Message ID | 20190409194229.8247-5-jlayton@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [RFC,01/11] ceph: after an MDS request, do callback and completions | expand |
Jeff Layton <jlayton@kernel.org> 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,
On Wed, Apr 10, 2019 at 6:27 AM Luis Henriques <lhenriques@suse.com> wrote: > > Jeff Layton <jlayton@kernel.org> 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@kernel.org> > > --- > > 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); Yes, I think so. I'll make that change. Thanks,
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);
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. Signed-off-by: Jeff Layton <jlayton@kernel.org> --- 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(-)