aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/dir.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2014-02-27 03:26:24 -0500
committerYan, Zheng <zheng.z.yan@intel.com>2014-04-02 22:33:52 -0400
commitf0494206076703aaa0c8005eff41c413216ae26b (patch)
treee12b390f7d458c085fb91b9ebe220e4147dbe41c /fs/ceph/dir.c
parent0ccd59266973047770d5160318561c9189b79c93 (diff)
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: Yan, Zheng <zheng.z.yan@intel.com> Reviewed-by: Alex Elder <elder@linaro.org>
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r--fs/ceph/dir.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 45eda6d7a40c..a7eaf9692aa6 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -190,7 +190,7 @@ more:
190 if (last) { 190 if (last) {
191 /* remember our position */ 191 /* remember our position */
192 fi->dentry = last; 192 fi->dentry = last;
193 fi->next_offset = di->offset; 193 fi->next_offset = fpos_off(di->offset);
194 } 194 }
195 dput(dentry); 195 dput(dentry);
196 return 0; 196 return 0;
@@ -369,9 +369,9 @@ more:
369 fi->next_offset = 0; 369 fi->next_offset = 0;
370 off = fi->next_offset; 370 off = fi->next_offset;
371 } 371 }
372 fi->frag = frag;
372 fi->offset = fi->next_offset; 373 fi->offset = fi->next_offset;
373 fi->last_readdir = req; 374 fi->last_readdir = req;
374 fi->frag = frag;
375 375
376 if (req->r_reply_info.dir_end) { 376 if (req->r_reply_info.dir_end) {
377 kfree(fi->last_name); 377 kfree(fi->last_name);
@@ -474,7 +474,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
474{ 474{
475 struct ceph_file_info *fi = file->private_data; 475 struct ceph_file_info *fi = file->private_data;
476 struct inode *inode = file->f_mapping->host; 476 struct inode *inode = file->f_mapping->host;
477 loff_t old_offset = offset; 477 loff_t old_offset = ceph_make_fpos(fi->frag, fi->next_offset);
478 loff_t retval; 478 loff_t retval;
479 479
480 mutex_lock(&inode->i_mutex); 480 mutex_lock(&inode->i_mutex);
@@ -491,7 +491,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
491 goto out; 491 goto out;
492 } 492 }
493 493
494 if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { 494 if (offset >= 0) {
495 if (offset != file->f_pos) { 495 if (offset != file->f_pos) {
496 file->f_pos = offset; 496 file->f_pos = offset;
497 file->f_version = 0; 497 file->f_version = 0;
@@ -504,14 +504,14 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
504 * seek to new frag, or seek prior to current chunk. 504 * seek to new frag, or seek prior to current chunk.
505 */ 505 */
506 if (offset == 0 || 506 if (offset == 0 ||
507 fpos_frag(offset) != fpos_frag(old_offset) || 507 fpos_frag(offset) != fi->frag ||
508 fpos_off(offset) < fi->offset) { 508 fpos_off(offset) < fi->offset) {
509 dout("dir_llseek dropping %p content\n", file); 509 dout("dir_llseek dropping %p content\n", file);
510 reset_readdir(fi); 510 reset_readdir(fi);
511 } 511 }
512 512
513 /* bump dir_release_count if we did a forward seek */ 513 /* bump dir_release_count if we did a forward seek */
514 if (offset > old_offset) 514 if (fpos_cmp(offset, old_offset) > 0)
515 fi->dir_release_count--; 515 fi->dir_release_count--;
516 } 516 }
517out: 517out: