Commit 41b02e1f authored by Sage Weil's avatar Sage Weil

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: default avatarYehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent 4f177264
...@@ -102,7 +102,7 @@ static int mdsc_show(struct seq_file *s, void *p) ...@@ -102,7 +102,7 @@ static int mdsc_show(struct seq_file *s, void *p)
path = NULL; path = NULL;
spin_lock(&req->r_old_dentry->d_lock); spin_lock(&req->r_old_dentry->d_lock);
seq_printf(s, " #%llx/%.*s (%s)", seq_printf(s, " #%llx/%.*s (%s)",
ceph_ino(req->r_old_dentry->d_parent->d_inode), ceph_ino(req->r_old_dentry_dir),
req->r_old_dentry->d_name.len, req->r_old_dentry->d_name.len,
req->r_old_dentry->d_name.name, req->r_old_dentry->d_name.name,
path ? path : ""); path ? path : "");
......
...@@ -811,6 +811,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir, ...@@ -811,6 +811,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
req->r_dentry = dget(dentry); req->r_dentry = dget(dentry);
req->r_num_caps = 2; req->r_num_caps = 2;
req->r_old_dentry = dget(old_dentry); /* or inode? hrm. */ req->r_old_dentry = dget(old_dentry); /* or inode? hrm. */
req->r_old_dentry_dir = ceph_get_dentry_parent_inode(old_dentry);
req->r_locked_dir = dir; req->r_locked_dir = dir;
req->r_dentry_drop = CEPH_CAP_FILE_SHARED; req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
req->r_dentry_unless = CEPH_CAP_FILE_EXCL; 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,6 +910,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
req->r_dentry = dget(new_dentry); req->r_dentry = dget(new_dentry);
req->r_num_caps = 2; req->r_num_caps = 2;
req->r_old_dentry = dget(old_dentry); req->r_old_dentry = dget(old_dentry);
req->r_old_dentry_dir = ceph_get_dentry_parent_inode(old_dentry);
req->r_locked_dir = new_dir; req->r_locked_dir = new_dir;
req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED; req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED;
req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL; req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL;
......
...@@ -483,22 +483,26 @@ void ceph_mdsc_release_request(struct kref *kref) ...@@ -483,22 +483,26 @@ void ceph_mdsc_release_request(struct kref *kref)
destroy_reply_info(&req->r_reply_info); destroy_reply_info(&req->r_reply_info);
} }
if (req->r_inode) { if (req->r_inode) {
ceph_put_cap_refs(ceph_inode(req->r_inode), ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
CEPH_CAP_PIN);
iput(req->r_inode); iput(req->r_inode);
} }
if (req->r_locked_dir) if (req->r_locked_dir)
ceph_put_cap_refs(ceph_inode(req->r_locked_dir), ceph_put_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
CEPH_CAP_PIN);
if (req->r_target_inode) if (req->r_target_inode)
iput(req->r_target_inode); iput(req->r_target_inode);
if (req->r_dentry) if (req->r_dentry)
dput(req->r_dentry); dput(req->r_dentry);
if (req->r_old_dentry) { if (req->r_old_dentry) {
ceph_put_cap_refs( /*
ceph_inode(req->r_old_dentry->d_parent->d_inode), * track (and drop pins for) r_old_dentry_dir
* separately, since r_old_dentry's d_parent may have
* changed between the dir mutex being dropped and
* this request being freed.
*/
ceph_put_cap_refs(ceph_inode(req->r_old_dentry_dir),
CEPH_CAP_PIN); CEPH_CAP_PIN);
dput(req->r_old_dentry); dput(req->r_old_dentry);
iput(req->r_old_dentry_dir);
} }
kfree(req->r_path1); kfree(req->r_path1);
kfree(req->r_path2); kfree(req->r_path2);
...@@ -1931,8 +1935,7 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc, ...@@ -1931,8 +1935,7 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
if (req->r_locked_dir) if (req->r_locked_dir)
ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN); ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
if (req->r_old_dentry) if (req->r_old_dentry)
ceph_get_cap_refs( ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
ceph_inode(req->r_old_dentry->d_parent->d_inode),
CEPH_CAP_PIN); CEPH_CAP_PIN);
/* issue */ /* issue */
......
...@@ -171,6 +171,7 @@ struct ceph_mds_request { ...@@ -171,6 +171,7 @@ struct ceph_mds_request {
struct inode *r_inode; /* arg1 */ struct inode *r_inode; /* arg1 */
struct dentry *r_dentry; /* arg1 */ struct dentry *r_dentry; /* arg1 */
struct dentry *r_old_dentry; /* arg2: rename from or link from */ struct dentry *r_old_dentry; /* arg2: rename from or link from */
struct inode *r_old_dentry_dir; /* arg2: old dentry's parent dir */
char *r_path1, *r_path2; char *r_path1, *r_path2;
struct ceph_vino r_ino1, r_ino2; struct ceph_vino r_ino1, r_ino2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment