Skip to content

Commit

Permalink
ceph: fix __dcache_readdir()
Browse files Browse the repository at this point in the history
If directory is fragmented, readdir() read its dirfrags one by one.
After reading all dirfrags, the corresponding dentries are sorted in
(frag_t, off) order in the dcache. If dentries of a directory are all
cached, __dcache_readdir() can use the cached dentries to satisfy
readdir syscall. But when checking if a given dentry is after the
position of readdir, __dcache_readdir() compares numerical value of
frag_t directly. This is wrong, it should use ceph_frag_compare().

Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
  • Loading branch information
Yan, Zheng authored and Sage Weil committed Feb 17, 2014
1 parent 45195e4 commit 4d5f5df
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion fs/ceph/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ static unsigned fpos_off(loff_t p)
return p & 0xffffffff;
}

static int fpos_cmp(loff_t l, loff_t r)
{
int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r));
if (v)
return v;
return (int)(fpos_off(l) - fpos_off(r));
}

/*
* When possible, we try to satisfy a readdir by peeking at the
* dcache. We make this work by carefully ordering dentries on
Expand Down Expand Up @@ -156,7 +164,7 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx)
if (!d_unhashed(dentry) && dentry->d_inode &&
ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
ctx->pos <= di->offset)
fpos_cmp(ctx->pos, di->offset) <= 0)
break;
dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry,
dentry->d_name.len, dentry->d_name.name, di->offset,
Expand Down

0 comments on commit 4d5f5df

Please sign in to comment.