Skip to content

Commit 4c18347

Browse files
jtlaytonidryomov
authored andcommitted
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>
1 parent 23c2c76 commit 4c18347

4 files changed

Lines changed: 11 additions & 1 deletion

File tree

fs/ceph/dir.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
788788
mask |= CEPH_CAP_XATTR_SHARED;
789789
req->r_args.getattr.mask = cpu_to_le32(mask);
790790

791+
ihold(dir);
791792
req->r_parent = dir;
792793
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
793794
err = ceph_mdsc_do_request(mdsc, NULL, req);
@@ -868,6 +869,7 @@ static int ceph_mknod(struct user_namespace *mnt_userns, struct inode *dir,
868869
req->r_dentry = dget(dentry);
869870
req->r_num_caps = 2;
870871
req->r_parent = dir;
872+
ihold(dir);
871873
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
872874
req->r_args.mknod.mode = cpu_to_le32(mode);
873875
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,
929931
goto out;
930932
}
931933
req->r_parent = dir;
934+
ihold(dir);
935+
932936
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
933937
req->r_dentry = dget(dentry);
934938
req->r_num_caps = 2;
@@ -993,6 +997,7 @@ static int ceph_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
993997
req->r_dentry = dget(dentry);
994998
req->r_num_caps = 2;
995999
req->r_parent = dir;
1000+
ihold(dir);
9961001
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
9971002
req->r_args.mkdir.mode = cpu_to_le32(mode);
9981003
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,
10371042
req->r_num_caps = 2;
10381043
req->r_old_dentry = dget(old_dentry);
10391044
req->r_parent = dir;
1045+
ihold(dir);
10401046
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
10411047
req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
10421048
req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
@@ -1158,6 +1164,7 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
11581164
req->r_dentry = dget(dentry);
11591165
req->r_num_caps = 2;
11601166
req->r_parent = dir;
1167+
ihold(dir);
11611168
req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
11621169
req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
11631170
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,
12321239
req->r_old_dentry = dget(old_dentry);
12331240
req->r_old_dentry_dir = old_dir;
12341241
req->r_parent = new_dir;
1242+
ihold(new_dir);
12351243
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
12361244
req->r_old_dentry_drop = CEPH_CAP_FILE_SHARED;
12371245
req->r_old_dentry_unless = CEPH_CAP_FILE_EXCL;
@@ -1728,6 +1736,7 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
17281736
req->r_dentry = dget(dentry);
17291737
req->r_num_caps = 2;
17301738
req->r_parent = dir;
1739+
ihold(dir);
17311740

17321741
mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED;
17331742
if (ceph_security_xattr_wanted(dir))

fs/ceph/export.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ static int ceph_get_name(struct dentry *parent, char *name,
542542
ihold(inode);
543543
req->r_ino2 = ceph_vino(d_inode(parent));
544544
req->r_parent = d_inode(parent);
545+
ihold(req->r_parent);
545546
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
546547
req->r_num_caps = 2;
547548
err = ceph_mdsc_do_request(mdsc, NULL, req);

fs/ceph/file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
706706
mask |= CEPH_CAP_XATTR_SHARED;
707707
req->r_args.open.mask = cpu_to_le32(mask);
708708
req->r_parent = dir;
709+
ihold(dir);
709710

710711
if (flags & O_CREAT) {
711712
struct ceph_file_layout lo;

fs/ceph/mds_client.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2982,7 +2982,6 @@ int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
29822982
ceph_take_cap_refs(ci, CEPH_CAP_PIN, false);
29832983
__ceph_touch_fmode(ci, mdsc, fmode);
29842984
spin_unlock(&ci->i_ceph_lock);
2985-
ihold(req->r_parent);
29862985
}
29872986
if (req->r_old_dentry_dir)
29882987
ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),

0 commit comments

Comments
 (0)