diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-04-08 15:42:59 +0200 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2014-04-28 21:53:43 +0200 |
commit | 0081bd83c089ef3d0c9a4e4e869e2ab75f2cb379 (patch) | |
tree | 0405653138dd561f7f8d61b0e927384528f7438e /fs | |
parent | ceph: skip invalid dentry during dcache readdir (diff) | |
download | linux-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.c | 22 |
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); } |