Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ static int mdsc_show(struct seq_file *s, void *p)
				path = NULL;
			spin_lock(&req->r_old_dentry->d_lock);
			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.name,
				   path ? path : "");
+2 −0
Original line number Diff line number Diff line
@@ -811,6 +811,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
	req->r_dentry = dget(dentry);
	req->r_num_caps = 2;
	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_dentry_drop = CEPH_CAP_FILE_SHARED;
	req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
@@ -909,6 +910,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
	req->r_dentry = dget(new_dentry);
	req->r_num_caps = 2;
	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_old_dentry_drop = CEPH_CAP_FILE_SHARED;
	req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL;
+13 −10
Original line number Diff line number Diff line
@@ -483,22 +483,26 @@ void ceph_mdsc_release_request(struct kref *kref)
		destroy_reply_info(&req->r_reply_info);
	}
	if (req->r_inode) {
		ceph_put_cap_refs(ceph_inode(req->r_inode),
				  CEPH_CAP_PIN);
		ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
		iput(req->r_inode);
	}
	if (req->r_locked_dir)
		ceph_put_cap_refs(ceph_inode(req->r_locked_dir),
				  CEPH_CAP_PIN);
		ceph_put_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
	if (req->r_target_inode)
		iput(req->r_target_inode);
	if (req->r_dentry)
		dput(req->r_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);
		dput(req->r_old_dentry);
		iput(req->r_old_dentry_dir);
	}
	kfree(req->r_path1);
	kfree(req->r_path2);
@@ -1931,8 +1935,7 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
	if (req->r_locked_dir)
		ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
	if (req->r_old_dentry)
		ceph_get_cap_refs(
			ceph_inode(req->r_old_dentry->d_parent->d_inode),
		ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
				  CEPH_CAP_PIN);

	/* issue */
+1 −0
Original line number Diff line number Diff line
@@ -171,6 +171,7 @@ struct ceph_mds_request {
	struct inode *r_inode;              /* arg1 */
	struct dentry *r_dentry;            /* arg1 */
	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;
	struct ceph_vino r_ino1, r_ino2;