From: Jeff Layton <jlayton@kernel.org>
To: Dai Ngo <dai.ngo@oracle.com>,
Chuck Lever <chuck.lever@oracle.com>, Neil Brown <neilb@suse.de>,
Olga Kornievskaia <kolga@netapp.com>, Tom Talpey <tom@talpey.com>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>
Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH] fs/nfsd: fix update of inode attrs in CB_GETATTR
Date: Mon, 26 Aug 2024 12:13:51 -0400 [thread overview]
Message-ID: <d438bc3a58fcb6bdbbf39b5ce585deef8d44c0eb.camel@kernel.org> (raw)
In-Reply-To: <8708e2e4-b9e9-45a7-8aa5-2f06234d3ae2@oracle.com>
On Mon, 2024-08-26 at 08:31 -0700, Dai Ngo wrote:
>
> On 8/24/24 5:46 AM, Jeff Layton wrote:
> > Currently, we copy the mtime and ctime to the in-core inode and then
> > mark the inode dirty. This is fine for certain types of filesystems, but
> > not all. Some require a real setattr to properly change these values
> > (e.g. ceph or reexported NFS).
> >
> > Fix this code to call notify_change() instead, which is the proper way
> > to effect a setattr. There is one problem though:
> >
> > In this case, the client is holding a write delegation and has sent us
> > attributes to update our cache. We don't want to break the delegation
> > for this since that would defeat the purpose.
>
> I think this won't happen with NFS since nfsd_breaker_owns_lease detects
> its own lease and won't break the delegation.
>
I don't think that works here. In this case, we've gotten a GETATTR
request from a different client than the lease holder. So the breaker
in this case does _not_ own the lease.
>
> > Add a new ATTR_DELEG flag
> > that makes notify_change bypass the try_break_deleg call.
> >
> > Fixes: c5967721e106 ("NFSD: handle GETATTR conflict with write delegation")
> > Signed-off-by: Jeff Layton <jlayton@kernel.org>
> > ---
> > One more CB_GETATTR fix. This one involves a little change at the VFS
> > layer to avoid breaking the delegation.
> >
> > Christian, unless you have objections, this should probably go in
> > via Chuck's tree as this patch depends on a nfsd patch [1] that I sent
> > yesterday. An A-b or R-b would be welcome though.
> >
> > [1]: https://lore.kernel.org/linux-nfs/20240823-nfsd-fixes-v1-1-fc99aa16f6a0@kernel.org/T/#u
> > ---
> > fs/attr.c | 9 ++++++---
> > fs/nfsd/nfs4state.c | 18 +++++++++++++-----
> > fs/nfsd/nfs4xdr.c | 2 +-
> > fs/nfsd/state.h | 2 +-
> > include/linux/fs.h | 1 +
> > 5 files changed, 22 insertions(+), 10 deletions(-)
> >
> > diff --git a/fs/attr.c b/fs/attr.c
> > index 960a310581eb..a40a2fb406f0 100644
> > --- a/fs/attr.c
> > +++ b/fs/attr.c
> > @@ -489,9 +489,12 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
> > error = security_inode_setattr(idmap, dentry, attr);
> > if (error)
> > return error;
> > - error = try_break_deleg(inode, delegated_inode);
> > - if (error)
> > - return error;
> > +
> > + if (!(ia_valid & ATTR_DELEG)) {
> > + error = try_break_deleg(inode, delegated_inode);
> > + if (error)
> > + return error;
> > + }
> >
> > if (inode->i_op->setattr)
> > error = inode->i_op->setattr(idmap, dentry, attr);
> > diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> > index dafff707e23a..e0e3d3ca0d45 100644
> > --- a/fs/nfsd/nfs4state.c
> > +++ b/fs/nfsd/nfs4state.c
> > @@ -8815,7 +8815,7 @@ nfsd4_get_writestateid(struct nfsd4_compound_state *cstate,
> > /**
> > * nfsd4_deleg_getattr_conflict - Recall if GETATTR causes conflict
> > * @rqstp: RPC transaction context
> > - * @inode: file to be checked for a conflict
> > + * @dentry: dentry of inode to be checked for a conflict
> > * @modified: return true if file was modified
> > * @size: new size of file if modified is true
> > *
> > @@ -8830,7 +8830,7 @@ nfsd4_get_writestateid(struct nfsd4_compound_state *cstate,
> > * code is returned.
> > */
> > __be32
> > -nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
> > +nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry,
> > bool *modified, u64 *size)
> > {
> > __be32 status;
> > @@ -8840,6 +8840,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
> > struct nfs4_delegation *dp;
> > struct iattr attrs;
> > struct nfs4_cb_fattr *ncf;
> > + struct inode *inode = d_inode(dentry);
> >
> > *modified = false;
> > ctx = locks_inode_context(inode);
> > @@ -8887,15 +8888,22 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
> > ncf->ncf_cur_fsize != ncf->ncf_cb_fsize))
> > ncf->ncf_file_modified = true;
> > if (ncf->ncf_file_modified) {
> > + int err;
> > +
> > /*
> > * Per section 10.4.3 of RFC 8881, the server would
> > * not update the file's metadata with the client's
> > * modified size
> > */
> > attrs.ia_mtime = attrs.ia_ctime = current_time(inode);
> > - attrs.ia_valid = ATTR_MTIME | ATTR_CTIME;
> > - setattr_copy(&nop_mnt_idmap, inode, &attrs);
> > - mark_inode_dirty(inode);
> > + attrs.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_DELEG;
> > + inode_lock(inode);
> > + err = notify_change(&nop_mnt_idmap, dentry, &attrs, NULL);
> > + inode_unlock(inode);
> > + if (err) {
> > + nfs4_put_stid(&dp->dl_stid);
> > + return nfserrno(err);
> > + }
> > ncf->ncf_cur_fsize = ncf->ncf_cb_fsize;
> > *size = ncf->ncf_cur_fsize;
> > *modified = true;
> > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> > index 43ccf6119cf1..97f583777972 100644
> > --- a/fs/nfsd/nfs4xdr.c
> > +++ b/fs/nfsd/nfs4xdr.c
> > @@ -3565,7 +3565,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
> > }
> > args.size = 0;
> > if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
> > - status = nfsd4_deleg_getattr_conflict(rqstp, d_inode(dentry),
> > + status = nfsd4_deleg_getattr_conflict(rqstp, dentry,
> > &file_modified, &size);
> > if (status)
> > goto out;
> > diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
> > index ffc217099d19..ec4559ecd193 100644
> > --- a/fs/nfsd/state.h
> > +++ b/fs/nfsd/state.h
> > @@ -781,5 +781,5 @@ static inline bool try_to_expire_client(struct nfs4_client *clp)
> > }
> >
> > extern __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp,
> > - struct inode *inode, bool *file_modified, u64 *size);
> > + struct dentry *dentry, bool *file_modified, u64 *size);
> > #endif /* NFSD4_STATE_H */
> > diff --git a/include/linux/fs.h b/include/linux/fs.h
> > index 0283cf366c2a..3fe289c74869 100644
> > --- a/include/linux/fs.h
> > +++ b/include/linux/fs.h
> > @@ -208,6 +208,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
> > #define ATTR_OPEN (1 << 15) /* Truncating from open(O_TRUNC) */
> > #define ATTR_TIMES_SET (1 << 16)
> > #define ATTR_TOUCH (1 << 17)
> > +#define ATTR_DELEG (1 << 18) /* Delegated attrs (don't break) */
> >
> > /*
> > * Whiteout is represented by a char device. The following constants define the
> >
> > ---
> > base-commit: a204501e1743d695ca2930ed25a2be9f8ced96d3
> > change-id: 20240823-nfsd-fixes-61f0c785d125
> >
> > Best regards,
--
Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2024-08-26 16:13 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-24 12:46 [PATCH] fs/nfsd: fix update of inode attrs in CB_GETATTR Jeff Layton
2024-08-24 17:58 ` Chuck Lever
2024-08-26 10:36 ` Christian Brauner
2024-08-26 12:27 ` Jeff Layton
2024-08-26 15:31 ` Dai Ngo
2024-08-26 16:13 ` Jeff Layton [this message]
2024-08-26 16:43 ` Dai Ngo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d438bc3a58fcb6bdbbf39b5ce585deef8d44c0eb.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=brauner@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=dai.ngo@oracle.com \
--cc=jack@suse.cz \
--cc=kolga@netapp.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@suse.de \
--cc=tom@talpey.com \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.