ceph: take reference to req->r_parent at point of assignment
Currently, we set the r_parent pointer but then don't take a reference to it until we submit the request. If we end up freeing the req before that point, then we'll do a iput when we shouldn't. Instead, take the inode reference in the callers, so that it's always safe to call ceph_mdsc_put_request on the req, even before submission. Signed-off-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Luis Henriques <lhenriques@suse.de> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
23c2c76ead
commit
4c18347238
@ -788,6 +788,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
|
||||
mask |= CEPH_CAP_XATTR_SHARED;
|
||||
req->r_args.getattr.mask = cpu_to_le32(mask);
|
||||
|
||||
ihold(dir);
|
||||
req->r_parent = dir;
|
||||
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
|
||||
err = ceph_mdsc_do_request(mdsc, NULL, req);
|
||||
@ -868,6 +869,7 @@ static int ceph_mknod(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
req->r_dentry = dget(dentry);
|
||||
req->r_num_caps = 2;
|
||||
req->r_parent = dir;
|
||||
ihold(dir);
|
||||
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
|
||||
req->r_args.mknod.mode = cpu_to_le32(mode);
|
||||
req->r_args.mknod.rdev = cpu_to_le32(rdev);
|
||||
@ -929,6 +931,8 @@ static int ceph_symlink(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
goto out;
|
||||
}
|
||||
req->r_parent = dir;
|
||||
ihold(dir);
|
||||
|
||||
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
|
||||
req->r_dentry = dget(dentry);
|
||||
req->r_num_caps = 2;
|
||||
@ -993,6 +997,7 @@ static int ceph_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
|
||||
req->r_dentry = dget(dentry);
|
||||
req->r_num_caps = 2;
|
||||
req->r_parent = dir;
|
||||
ihold(dir);
|
||||
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
|
||||
req->r_args.mkdir.mode = cpu_to_le32(mode);
|
||||
req->r_dentry_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_AUTH_EXCL;
|
||||
@ -1037,6 +1042,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
|
||||
req->r_num_caps = 2;
|
||||
req->r_old_dentry = dget(old_dentry);
|
||||
req->r_parent = dir;
|
||||
ihold(dir);
|
||||
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
|
||||
req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
|
||||
req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
|
||||
@ -1158,6 +1164,7 @@ retry:
|
||||
req->r_dentry = dget(dentry);
|
||||
req->r_num_caps = 2;
|
||||
req->r_parent = dir;
|
||||
ihold(dir);
|
||||
req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
|
||||
req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
|
||||
req->r_inode_drop = ceph_drop_caps_for_unlink(inode);
|
||||
@ -1232,6 +1239,7 @@ static int ceph_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
||||
req->r_old_dentry = dget(old_dentry);
|
||||
req->r_old_dentry_dir = old_dir;
|
||||
req->r_parent = new_dir;
|
||||
ihold(new_dir);
|
||||
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
|
||||
req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED;
|
||||
req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL;
|
||||
@ -1728,6 +1736,7 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
req->r_dentry = dget(dentry);
|
||||
req->r_num_caps = 2;
|
||||
req->r_parent = dir;
|
||||
ihold(dir);
|
||||
|
||||
mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED;
|
||||
if (ceph_security_xattr_wanted(dir))
|
||||
|
@ -542,6 +542,7 @@ static int ceph_get_name(struct dentry *parent, char *name,
|
||||
ihold(inode);
|
||||
req->r_ino2 = ceph_vino(d_inode(parent));
|
||||
req->r_parent = d_inode(parent);
|
||||
ihold(req->r_parent);
|
||||
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
|
||||
req->r_num_caps = 2;
|
||||
err = ceph_mdsc_do_request(mdsc, NULL, req);
|
||||
|
@ -706,6 +706,7 @@ retry:
|
||||
mask |= CEPH_CAP_XATTR_SHARED;
|
||||
req->r_args.open.mask = cpu_to_le32(mask);
|
||||
req->r_parent = dir;
|
||||
ihold(dir);
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
struct ceph_file_layout lo;
|
||||
|
@ -2982,7 +2982,6 @@ int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
|
||||
ceph_take_cap_refs(ci, CEPH_CAP_PIN, false);
|
||||
__ceph_touch_fmode(ci, mdsc, fmode);
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
ihold(req->r_parent);
|
||||
}
|
||||
if (req->r_old_dentry_dir)
|
||||
ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
|
||||
|
Loading…
Reference in New Issue
Block a user