Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0494206 authored by Yan, Zheng's avatar Yan, Zheng
Browse files

ceph: fix ceph_dir_llseek()



Comparing offset with inode->i_sb->s_maxbytes doesn't make sense for
directory. For a fragmented directory, offset (frag_t, off) can be
larger than inode->i_sb->s_maxbytes.

At the very beginning of ceph_dir_llseek(), local variable old_offset
is initialized to parameter offset. This doesn't make sense neither.
Old_offset should be ceph_make_fpos(fi->frag, fi->next_offset).

Signed-off-by: default avatarYan, Zheng <zheng.z.yan@intel.com>
Reviewed-by: default avatarAlex Elder <elder@linaro.org>
parent 0ccd5926
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -190,7 +190,7 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx)
		if (last) {
			/* remember our position */
			fi->dentry = last;
			fi->next_offset = di->offset;
			fi->next_offset = fpos_off(di->offset);
		}
		dput(dentry);
		return 0;
@@ -369,9 +369,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
				fi->next_offset = 0;
			off = fi->next_offset;
		}
		fi->frag = frag;
		fi->offset = fi->next_offset;
		fi->last_readdir = req;
		fi->frag = frag;

		if (req->r_reply_info.dir_end) {
			kfree(fi->last_name);
@@ -474,7 +474,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
{
	struct ceph_file_info *fi = file->private_data;
	struct inode *inode = file->f_mapping->host;
	loff_t old_offset = offset;
	loff_t old_offset = ceph_make_fpos(fi->frag, fi->next_offset);
	loff_t retval;

	mutex_lock(&inode->i_mutex);
@@ -491,7 +491,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
		goto out;
	}

	if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) {
	if (offset >= 0) {
		if (offset != file->f_pos) {
			file->f_pos = offset;
			file->f_version = 0;
@@ -504,14 +504,14 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
		 * seek to new frag, or seek prior to current chunk.
		 */
		if (offset == 0 ||
		    fpos_frag(offset) != fpos_frag(old_offset) ||
		    fpos_frag(offset) != fi->frag ||
		    fpos_off(offset) < fi->offset) {
			dout("dir_llseek dropping %p content\n", file);
			reset_readdir(fi);
		}

		/* bump dir_release_count if we did a forward seek */
		if (offset > old_offset)
		if (fpos_cmp(offset, old_offset) > 0)
			fi->dir_release_count--;
	}
out:
+1 −1
Original line number Diff line number Diff line
@@ -577,7 +577,7 @@ struct ceph_file_info {

	/* readdir: position within a frag */
	unsigned offset;       /* offset of last chunk, adjusted for . and .. */
	u64 next_offset;       /* offset of next chunk (last_name's + 1) */
	unsigned next_offset;  /* offset of next chunk (last_name's + 1) */
	char *last_name;       /* last entry in previous chunk */
	struct dentry *dentry; /* next dentry (for dcache readdir) */
	int dir_release_count;