On Sun, May 21, 2023 at 07:08:43PM -0400, Jeff Layton wrote: > On Sat, 2023-05-20 at 14:36 -0700, Dai Ngo wrote: > > If the GETATTR request on a file that has write delegation in effect > > and the request attributes include the change info and size attribute > > then the write delegation is recalled and NFS4ERR_DELAY is returned > > for the GETATTR. > > > > Signed-off-by: Dai Ngo <dai.ngo@xxxxxxxxxx> > > --- > > fs/nfsd/nfs4xdr.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 45 insertions(+) > > > > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c > > index 76db2fe29624..e069b970f136 100644 > > --- a/fs/nfsd/nfs4xdr.c > > +++ b/fs/nfsd/nfs4xdr.c > > @@ -2920,6 +2920,46 @@ nfsd4_encode_bitmap(struct xdr_stream *xdr, u32 bmval0, u32 bmval1, u32 bmval2) > > return nfserr_resource; > > } > > > > +static struct file_lock * > > +nfs4_wrdeleg_filelock(struct svc_rqst *rqstp, struct inode *inode) > > +{ > > + struct file_lock_context *ctx; > > + struct file_lock *fl; > > + > > + ctx = locks_inode_context(inode); > > + if (!ctx) > > + return NULL; > > + spin_lock(&ctx->flc_lock); > > + if (!list_empty(&ctx->flc_lease)) { > > + fl = list_first_entry(&ctx->flc_lease, > > + struct file_lock, fl_list); > > + if (fl->fl_type == F_WRLCK) { > > + spin_unlock(&ctx->flc_lock); > > + return fl; > > + } > > + } > > + spin_unlock(&ctx->flc_lock); > > + return NULL; > > +} > > + > > +static __be32 > > +nfs4_handle_wrdeleg_conflict(struct svc_rqst *rqstp, struct inode *inode) > > +{ > > + __be32 status; > > + struct file_lock *fl; > > + struct nfs4_delegation *dp; > > + > > + fl = nfs4_wrdeleg_filelock(rqstp, inode); > > + if (!fl) > > + return 0; > > + dp = fl->fl_owner; > > + if (dp->dl_recall.cb_clp == *(rqstp->rq_lease_breaker)) > > + return 0; > > + refcount_inc(&dp->dl_stid.sc_count); > > Another question: Why are you taking a reference here at all? AFAICT, > you don't even look at the delegation again after that point, so it's > not clear to me who's responsible for putting that reference. I had the same thought, but I assumed I was missing something. > > + status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ)); > > + return status; > > +} > > + > > /* > > * Note: @fhp can be NULL; in this case, we might have to compose the filehandle > > * ourselves. > > @@ -2966,6 +3006,11 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, > > if (status) > > goto out; > > } > > + if (bmval0 & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) { > > + status = nfs4_handle_wrdeleg_conflict(rqstp, d_inode(dentry)); > > + if (status) > > + goto out; > > + } > > > > err = vfs_getattr(&path, &stat, > > STATX_BASIC_STATS | STATX_BTIME | STATX_CHANGE_COOKIE, > > -- > Jeff Layton <jlayton@xxxxxxxxxx>