diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-04-14 13:13:02 +0800 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2014-04-28 12:54:44 -0700 |
commit | 0a8a70f96fe1bd3e07c15bb86fd247e76102398a (patch) | |
tree | 0d6f728345f3f4efa33896aab71dd24f611af011 /fs/ceph/dir.c | |
parent | 92b2e75158f6b8316b5a567c73dcf5b3d8f6bbce (diff) | |
download | linux-0a8a70f96fe1bd3e07c15bb86fd247e76102398a.tar.bz2 |
ceph: clear directory's completeness when creating file
When creating a file, ceph_set_dentry_offset() puts the new dentry
at the end of directory's d_subdirs, then set the dentry's offset
based on directory's max offset. The offset does not reflect the
real postion of the dentry in directory. Later readdir reply from
MDS may change the dentry's position/offset. This inconsistency
can cause missing/duplicate entries in readdir result if readdir
is partly satisfied by dcache_readdir().
The fix is clear directory's completeness after creating/renaming
file. It prevents later readdir from using dcache_readdir().
Fixes: http://tracker.ceph.com/issues/8025
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'fs/ceph/dir.c')
-rw-r--r-- | fs/ceph/dir.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index fb4f7a203eda..c29d6ae68874 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -448,7 +448,6 @@ more: if (atomic_read(&ci->i_release_count) == fi->dir_release_count) { dout(" marking %p complete\n", inode); __ceph_dir_set_complete(ci, fi->dir_release_count); - ci->i_max_offset = ctx->pos; } spin_unlock(&ci->i_ceph_lock); @@ -937,14 +936,16 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, * to do it here. */ - /* d_move screws up d_subdirs order */ - ceph_dir_clear_complete(new_dir); - d_move(old_dentry, new_dentry); /* ensure target dentry is invalidated, despite rehashing bug in vfs_rename_dir */ ceph_invalidate_dentry_lease(new_dentry); + + /* d_move screws up sibling dentries' offsets */ + ceph_dir_clear_complete(old_dir); + ceph_dir_clear_complete(new_dir); + } ceph_mdsc_put_request(req); return err; |