aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2011-02-05 00:38:47 -0500
committerSage Weil <sage@newdream.net>2011-03-15 12:14:03 -0400
commit09adc80c611bb8902daa8ccfe34dbbc009d6befe (patch)
tree56d6096d2c4983a47acd7bb0a0f5d6e9c7fae331 /fs
parentb09734b1f4abd86e046777f0f268215b4ef1b523 (diff)
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')
-rw-r--r--fs/ceph/inode.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 193bfa5e9cb..60456361e07 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,
1030 dout("fill_trace doing d_move %p -> %p\n", 1030 dout("fill_trace doing d_move %p -> %p\n",
1031 req->r_old_dentry, dn); 1031 req->r_old_dentry, dn);
1032 1032
1033 /* d_move screws up d_subdirs order */
1034 ceph_i_clear(dir, CEPH_I_COMPLETE);
1035
1036 d_move(req->r_old_dentry, dn); 1033 d_move(req->r_old_dentry, dn);
1037 dout(" src %p '%.*s' dst %p '%.*s'\n", 1034 dout(" src %p '%.*s' dst %p '%.*s'\n",
1038 req->r_old_dentry, 1035 req->r_old_dentry,
@@ -1044,12 +1041,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
1044 rehashing bug in vfs_rename_dir */ 1041 rehashing bug in vfs_rename_dir */
1045 ceph_invalidate_dentry_lease(dn); 1042 ceph_invalidate_dentry_lease(dn);
1046 1043
1047 /* take overwritten dentry's readdir offset */ 1044 /*
1048 dout("dn %p gets %p offset %lld (old offset %lld)\n", 1045 * d_move() puts the renamed dentry at the end of
1049 req->r_old_dentry, dn, ceph_dentry(dn)->offset, 1046 * d_subdirs. We need to assign it an appropriate
1047 * directory offset so we can behave when holding
1048 * I_COMPLETE.
1049 */
1050 ceph_set_dentry_offset(req->r_old_dentry);
1051 dout("dn %p gets new offset %lld\n", req->r_old_dentry,
1050 ceph_dentry(req->r_old_dentry)->offset); 1052 ceph_dentry(req->r_old_dentry)->offset);
1051 ceph_dentry(req->r_old_dentry)->offset =
1052 ceph_dentry(dn)->offset;
1053 1053
1054 dn = req->r_old_dentry; /* use old_dentry */ 1054 dn = req->r_old_dentry; /* use old_dentry */
1055 in = dn->d_inode; 1055 in = dn->d_inode;