aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2011-07-26 14:31:14 -0400
committerSage Weil <sage@newdream.net>2011-07-26 14:31:14 -0400
commit41b02e1f9bb87b07d792b64aaeb7af3d00d69cd2 (patch)
tree87c9524ff96cbff2ff29d659cbefd516b553ca1f
parent4f1772645296a230e04f5c53e79cfb6f841ce634 (diff)
ceph: explicitly reference rename old_dentry parent dir in request
We carry a pin on the parent directory for the rename source and dest dentries. For the source it's r_locked_dir; we need to explicitly reference the old_dentry parent as well, since the dentry's d_parent may change between when the request was created and pinned and when it is freed. Reviewed-by: Yehuda Sadeh <yehuda@hq.newdream.net> Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--fs/ceph/debugfs.c2
-rw-r--r--fs/ceph/dir.c2
-rw-r--r--fs/ceph/mds_client.c23
-rw-r--r--fs/ceph/mds_client.h1
4 files changed, 17 insertions, 11 deletions
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index 0dba6915712b..fb962efdacee 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -102,7 +102,7 @@ static int mdsc_show(struct seq_file *s, void *p)
102 path = NULL; 102 path = NULL;
103 spin_lock(&req->r_old_dentry->d_lock); 103 spin_lock(&req->r_old_dentry->d_lock);
104 seq_printf(s, " #%llx/%.*s (%s)", 104 seq_printf(s, " #%llx/%.*s (%s)",
105 ceph_ino(req->r_old_dentry->d_parent->d_inode), 105 ceph_ino(req->r_old_dentry_dir),
106 req->r_old_dentry->d_name.len, 106 req->r_old_dentry->d_name.len,
107 req->r_old_dentry->d_name.name, 107 req->r_old_dentry->d_name.name,
108 path ? path : ""); 108 path ? path : "");
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 33a19df72288..7263f825d426 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -811,6 +811,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
811 req->r_dentry = dget(dentry); 811 req->r_dentry = dget(dentry);
812 req->r_num_caps = 2; 812 req->r_num_caps = 2;
813 req->r_old_dentry = dget(old_dentry); /* or inode? hrm. */ 813 req->r_old_dentry = dget(old_dentry); /* or inode? hrm. */
814 req->r_old_dentry_dir = ceph_get_dentry_parent_inode(old_dentry);
814 req->r_locked_dir = dir; 815 req->r_locked_dir = dir;
815 req->r_dentry_drop = CEPH_CAP_FILE_SHARED; 816 req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
816 req->r_dentry_unless = CEPH_CAP_FILE_EXCL; 817 req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
@@ -909,6 +910,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
909 req->r_dentry = dget(new_dentry); 910 req->r_dentry = dget(new_dentry);
910 req->r_num_caps = 2; 911 req->r_num_caps = 2;
911 req->r_old_dentry = dget(old_dentry); 912 req->r_old_dentry = dget(old_dentry);
913 req->r_old_dentry_dir = ceph_get_dentry_parent_inode(old_dentry);
912 req->r_locked_dir = new_dir; 914 req->r_locked_dir = new_dir;
913 req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED; 915 req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED;
914 req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL; 916 req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 8a09cd5a659e..66a8939cc518 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -483,22 +483,26 @@ void ceph_mdsc_release_request(struct kref *kref)
483 destroy_reply_info(&req->r_reply_info); 483 destroy_reply_info(&req->r_reply_info);
484 } 484 }
485 if (req->r_inode) { 485 if (req->r_inode) {
486 ceph_put_cap_refs(ceph_inode(req->r_inode), 486 ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
487 CEPH_CAP_PIN);
488 iput(req->r_inode); 487 iput(req->r_inode);
489 } 488 }
490 if (req->r_locked_dir) 489 if (req->r_locked_dir)
491 ceph_put_cap_refs(ceph_inode(req->r_locked_dir), 490 ceph_put_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
492 CEPH_CAP_PIN);
493 if (req->r_target_inode) 491 if (req->r_target_inode)
494 iput(req->r_target_inode); 492 iput(req->r_target_inode);
495 if (req->r_dentry) 493 if (req->r_dentry)
496 dput(req->r_dentry); 494 dput(req->r_dentry);
497 if (req->r_old_dentry) { 495 if (req->r_old_dentry) {
498 ceph_put_cap_refs( 496 /*
499 ceph_inode(req->r_old_dentry->d_parent->d_inode), 497 * track (and drop pins for) r_old_dentry_dir
500 CEPH_CAP_PIN); 498 * separately, since r_old_dentry's d_parent may have
499 * changed between the dir mutex being dropped and
500 * this request being freed.
501 */
502 ceph_put_cap_refs(ceph_inode(req->r_old_dentry_dir),
503 CEPH_CAP_PIN);
501 dput(req->r_old_dentry); 504 dput(req->r_old_dentry);
505 iput(req->r_old_dentry_dir);
502 } 506 }
503 kfree(req->r_path1); 507 kfree(req->r_path1);
504 kfree(req->r_path2); 508 kfree(req->r_path2);
@@ -1931,9 +1935,8 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
1931 if (req->r_locked_dir) 1935 if (req->r_locked_dir)
1932 ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN); 1936 ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
1933 if (req->r_old_dentry) 1937 if (req->r_old_dentry)
1934 ceph_get_cap_refs( 1938 ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
1935 ceph_inode(req->r_old_dentry->d_parent->d_inode), 1939 CEPH_CAP_PIN);
1936 CEPH_CAP_PIN);
1937 1940
1938 /* issue */ 1941 /* issue */
1939 mutex_lock(&mdsc->mutex); 1942 mutex_lock(&mdsc->mutex);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 8a40f0636ba9..4bb239921dbd 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -171,6 +171,7 @@ struct ceph_mds_request {
171 struct inode *r_inode; /* arg1 */ 171 struct inode *r_inode; /* arg1 */
172 struct dentry *r_dentry; /* arg1 */ 172 struct dentry *r_dentry; /* arg1 */
173 struct dentry *r_old_dentry; /* arg2: rename from or link from */ 173 struct dentry *r_old_dentry; /* arg2: rename from or link from */
174 struct inode *r_old_dentry_dir; /* arg2: old dentry's parent dir */
174 char *r_path1, *r_path2; 175 char *r_path1, *r_path2;
175 struct ceph_vino r_ino1, r_ino2; 176 struct ceph_vino r_ino1, r_ino2;
176 177