summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2014-04-08 15:42:59 +0200
committerSage Weil <sage@inktank.com>2014-04-28 21:53:43 +0200
commit0081bd83c089ef3d0c9a4e4e869e2ab75f2cb379 (patch)
tree0405653138dd561f7f8d61b0e927384528f7438e /fs
parentceph: skip invalid dentry during dcache readdir (diff)
downloadlinux-0081bd83c089ef3d0c9a4e4e869e2ab75f2cb379.tar.xz
linux-0081bd83c089ef3d0c9a4e4e869e2ab75f2cb379.zip
ceph: check directory's completeness before emitting directory entry
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com> Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/dir.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 766410a12c2c..8c7f90b96913 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -182,9 +182,16 @@ more:
spin_unlock(&dentry->d_lock);
spin_unlock(&parent->d_lock);
+ /* make sure a dentry wasn't dropped while we didn't have parent lock */
+ if (!ceph_dir_is_complete(dir)) {
+ dout(" lost dir complete on %p; falling back to mds\n", dir);
+ dput(dentry);
+ err = -EAGAIN;
+ goto out;
+ }
+
dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, ctx->pos,
dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
- ctx->pos = di->offset;
if (!dir_emit(ctx, dentry->d_name.name,
dentry->d_name.len,
ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino),
@@ -198,19 +205,12 @@ more:
return 0;
}
+ ctx->pos = di->offset + 1;
+
if (last)
dput(last);
last = dentry;
- ctx->pos++;
-
- /* make sure a dentry wasn't dropped while we didn't have parent lock */
- if (!ceph_dir_is_complete(dir)) {
- dout(" lost dir complete on %p; falling back to mds\n", dir);
- err = -EAGAIN;
- goto out;
- }
-
spin_lock(&parent->d_lock);
p = p->prev; /* advance to next dentry */
goto more;
@@ -296,6 +296,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
err = __dcache_readdir(file, ctx, shared_gen);
if (err != -EAGAIN)
return err;
+ frag = fpos_frag(ctx->pos);
+ off = fpos_off(ctx->pos);
} else {
spin_unlock(&ci->i_ceph_lock);
}