diff options
author | Sage Weil <sage@newdream.net> | 2011-02-04 21:38:47 -0800 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2011-03-15 09:14:03 -0700 |
commit | 09adc80c611bb8902daa8ccfe34dbbc009d6befe (patch) | |
tree | 56d6096d2c4983a47acd7bb0a0f5d6e9c7fae331 /fs/ceph/inode.c | |
parent | b09734b1f4abd86e046777f0f268215b4ef1b523 (diff) | |
download | op-kernel-dev-09adc80c611bb8902daa8ccfe34dbbc009d6befe.zip op-kernel-dev-09adc80c611bb8902daa8ccfe34dbbc009d6befe.tar.gz |
ceph: preserve I_COMPLETE across rename
d_move puts the renamed dentry at the end of d_subdirs, screwing with our
cached dentry directory offsets. We were just clearing I_COMPLETE to avoid
any possibility of trouble. However, assigning the renamed dentry an
offset at the end of the directory (to match it's new d_subdirs position)
is sufficient to maintain correct behavior and hold onto I_COMPLETE.
This is especially important for workloads like rsync, which renames files
into place. Before, we would lose I_COMPLETE and do MDS lookups for each
file. With this patch we only talk to the MDS on create and rename.
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 193bfa5..6045636 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1030,9 +1030,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, dout("fill_trace doing d_move %p -> %p\n", req->r_old_dentry, dn); - /* d_move screws up d_subdirs order */ - ceph_i_clear(dir, CEPH_I_COMPLETE); - d_move(req->r_old_dentry, dn); dout(" src %p '%.*s' dst %p '%.*s'\n", req->r_old_dentry, @@ -1044,12 +1041,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, rehashing bug in vfs_rename_dir */ ceph_invalidate_dentry_lease(dn); - /* take overwritten dentry's readdir offset */ - dout("dn %p gets %p offset %lld (old offset %lld)\n", - req->r_old_dentry, dn, ceph_dentry(dn)->offset, + /* + * d_move() puts the renamed dentry at the end of + * d_subdirs. We need to assign it an appropriate + * directory offset so we can behave when holding + * I_COMPLETE. + */ + ceph_set_dentry_offset(req->r_old_dentry); + dout("dn %p gets new offset %lld\n", req->r_old_dentry, ceph_dentry(req->r_old_dentry)->offset); - ceph_dentry(req->r_old_dentry)->offset = - ceph_dentry(dn)->offset; dn = req->r_old_dentry; /* use old_dentry */ in = dn->d_inode; |