Re: [RFC PATCH 04/11] ceph: hold extra reference to r_parent over life of request

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jeff Layton <jlayton@xxxxxxxxxx> writes:

> Currently, we just assume that it will stick around by virtue of the
> submitter's reference, but later patches will allow the syscall to
> return early and we can't rely on that reference at that point.
>
> Take an extra reference to the inode when setting r_parent and release
> it when releasing the request.

Couldn't you move all these ihold into ceph_mdsc_do_request?  I took a
quick look and it seems like it could use a logic similar to what's in
ceph_mdsc_release_request, i.e.:

	if (req->r_parent)
        	ihold(req->r_parent);

Cheers,
-- 
Luis

>
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
>  fs/ceph/dir.c        | 8 ++++++++
>  fs/ceph/export.c     | 1 +
>  fs/ceph/file.c       | 1 +
>  fs/ceph/mds_client.c | 4 +++-
>  4 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
> index a8f429882249..3eb9bc226b77 100644
> --- a/fs/ceph/dir.c
> +++ b/fs/ceph/dir.c
> @@ -783,6 +783,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
>  	req->r_args.getattr.mask = cpu_to_le32(mask);
>  
>  	req->r_parent = dir;
> +	ihold(dir);
>  	set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
>  	err = ceph_mdsc_do_request(mdsc, NULL, req);
>  	err = ceph_handle_snapdir(req, dentry, err);
> @@ -850,6 +851,7 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
>  	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);
> @@ -907,6 +909,7 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
>  		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;
> @@ -963,6 +966,7 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
>  	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;
> @@ -1008,6 +1012,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;
> @@ -1055,6 +1060,7 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
>  	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_dentry_drop = CEPH_CAP_FILE_SHARED;
>  	req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
> @@ -1104,6 +1110,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
>  	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;
> @@ -1586,6 +1593,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))
> diff --git a/fs/ceph/export.c b/fs/ceph/export.c
> index d3ef7ee429ec..e7804720549d 100644
> --- a/fs/ceph/export.c
> +++ b/fs/ceph/export.c
> @@ -519,6 +519,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);
> diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> index 0e505a5e09fe..f24d18f46715 100644
> --- a/fs/ceph/file.c
> +++ b/fs/ceph/file.c
> @@ -478,6 +478,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
>         req->r_args.open.mask = cpu_to_le32(mask);
>  
>  	req->r_parent = dir;
> +	ihold(dir);
>  	set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
>  	err = ceph_mdsc_do_request(mdsc,
>  				   (flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
> index 9d1ac87e5897..8c05cfe57adf 100644
> --- a/fs/ceph/mds_client.c
> +++ b/fs/ceph/mds_client.c
> @@ -696,8 +696,10 @@ void ceph_mdsc_release_request(struct kref *kref)
>  		ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
>  		iput(req->r_inode);
>  	}
> -	if (req->r_parent)
> +	if (req->r_parent) {
>  		ceph_put_cap_refs(ceph_inode(req->r_parent), CEPH_CAP_PIN);
> +		iput(req->r_parent);
> +	}
>  	iput(req->r_target_inode);
>  	if (req->r_dentry)
>  		dput(req->r_dentry);



[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux