Currently, we request a WR_STATE stateid for all SETATTR requests. If TIME_DELEG_ACCESS bit is set, set the RD_STATE bit in the mask as well so that we can use either sort of stateid. Also fix nfs4_check_delegmode to check for the absence of RD_STATE instead of the presence of the WR_STATE when testing for a read delegation. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/nfsd/nfs4proc.c | 7 ++++++- fs/nfsd/nfs4state.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 320c4f79662e65848dc824885566d48e696fe97c..f843b56b7b2056cbb69669e50c9ca9797cb91f0f 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1143,9 +1143,14 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, FATTR4_WORD2_TIME_DELEG_MODIFY); if (deleg_attrs || (setattr->sa_iattr.ia_valid & ATTR_SIZE)) { + int flags = WR_STATE; + + if (setattr->sa_bmval[2] & FATTR4_WORD2_TIME_DELEG_ACCESS) + flags |= RD_STATE; + status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh, &setattr->sa_stateid, - WR_STATE, NULL, &st); + flags, NULL, &st); if (status) return status; } diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 7905ab9d8bc6820dbb7ecb6f29c1e14b036e0de5..4ec58aab10410471bab25b3780facad4d77441e7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -5444,7 +5444,7 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate, static inline __be32 nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) { - if ((flags & WR_STATE) && deleg_is_read(dp->dl_type)) + if (!(flags & RD_STATE) && deleg_is_read(dp->dl_type)) return nfserr_openmode; else return nfs_ok; -- 2.47.0