Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nfsd: fix handling of delegated change attr in CB_GETATTR

RFC8881, section 10.4.3 has some specific guidance as to how the
delegated change attribute should be handled. We currently don't follow
that guidance properly.

In particular, when the file is modified, the server always reports the
initial change attribute + 1. Section 10.4.3 however indicates that it
should be incremented on every GETATTR request from other clients.

Only request the change attribute until the file has been modified. If
there is an outstanding delegation, then increment the cached change
attribute on every GETATTR.

Fixes: 6487a13b5c6b ("NFSD: add support for CB_GETATTR callback")
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

Jeff Layton and committed by
Chuck Lever
53150305 1196bdce

+14 -9
+5 -3
fs/nfsd/nfs4callback.c
··· 361 361 encode_cb_getattr4args(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr, 362 362 struct nfs4_cb_fattr *fattr) 363 363 { 364 - struct nfs4_delegation *dp = 365 - container_of(fattr, struct nfs4_delegation, dl_cb_fattr); 364 + struct nfs4_delegation *dp = container_of(fattr, struct nfs4_delegation, dl_cb_fattr); 366 365 struct knfsd_fh *fh = &dp->dl_stid.sc_file->fi_fhandle; 366 + struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr; 367 367 u32 bmap[1]; 368 368 369 - bmap[0] = FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE; 369 + bmap[0] = FATTR4_WORD0_SIZE; 370 + if (!ncf->ncf_file_modified) 371 + bmap[0] |= FATTR4_WORD0_CHANGE; 370 372 371 373 encode_nfs_cb_opnum4(xdr, OP_CB_GETATTR); 372 374 encode_nfs_fh4(xdr, fh);
+9 -6
fs/nfsd/nfs4xdr.c
··· 2920 2920 struct kstat stat; 2921 2921 struct kstatfs statfs; 2922 2922 struct nfs4_acl *acl; 2923 + u64 change_attr; 2923 2924 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL 2924 2925 void *context; 2925 2926 int contextlen; ··· 3020 3019 const struct nfsd4_fattr_args *args) 3021 3020 { 3022 3021 const struct svc_export *exp = args->exp; 3023 - u64 c; 3024 3022 3025 3023 if (unlikely(exp->ex_flags & NFSEXP_V4ROOT)) { 3026 3024 u32 flush_time = convert_to_wallclock(exp->cd->flush_time); ··· 3030 3030 return nfserr_resource; 3031 3031 return nfs_ok; 3032 3032 } 3033 - 3034 - c = nfsd4_change_attribute(&args->stat); 3035 - return nfsd4_encode_changeid4(xdr, c); 3033 + return nfsd4_encode_changeid4(xdr, args->change_attr); 3036 3034 } 3037 3035 3038 3036 static __be32 nfsd4_encode_fattr4_size(struct xdr_stream *xdr, ··· 3555 3557 if (dp) { 3556 3558 struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr; 3557 3559 3558 - if (ncf->ncf_file_modified) 3560 + if (ncf->ncf_file_modified) { 3561 + ++ncf->ncf_initial_cinfo; 3559 3562 args.stat.size = ncf->ncf_cur_fsize; 3560 - 3563 + } 3564 + args.change_attr = ncf->ncf_initial_cinfo; 3561 3565 nfs4_put_stid(&dp->dl_stid); 3566 + } else { 3567 + args.change_attr = nfsd4_change_attribute(&args.stat); 3562 3568 } 3569 + 3563 3570 if (err) 3564 3571 goto out_nfserr; 3565 3572