Skip to content

Commit 5315030

Browse files
jtlaytonchucklever
authored andcommitted
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: 6487a13 ("NFSD: add support for CB_GETATTR callback") Signed-off-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 1196bdc commit 5315030

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

fs/nfsd/nfs4callback.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,12 +361,14 @@ static void
361361
encode_cb_getattr4args(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr,
362362
struct nfs4_cb_fattr *fattr)
363363
{
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);
366365
struct knfsd_fh *fh = &dp->dl_stid.sc_file->fi_fhandle;
366+
struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr;
367367
u32 bmap[1];
368368

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;
370372

371373
encode_nfs_cb_opnum4(xdr, OP_CB_GETATTR);
372374
encode_nfs_fh4(xdr, fh);

fs/nfsd/nfs4xdr.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2920,6 +2920,7 @@ struct nfsd4_fattr_args {
29202920
struct kstat stat;
29212921
struct kstatfs statfs;
29222922
struct nfs4_acl *acl;
2923+
u64 change_attr;
29232924
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
29242925
void *context;
29252926
int contextlen;
@@ -3019,7 +3020,6 @@ static __be32 nfsd4_encode_fattr4_change(struct xdr_stream *xdr,
30193020
const struct nfsd4_fattr_args *args)
30203021
{
30213022
const struct svc_export *exp = args->exp;
3022-
u64 c;
30233023

30243024
if (unlikely(exp->ex_flags & NFSEXP_V4ROOT)) {
30253025
u32 flush_time = convert_to_wallclock(exp->cd->flush_time);
@@ -3030,9 +3030,7 @@ static __be32 nfsd4_encode_fattr4_change(struct xdr_stream *xdr,
30303030
return nfserr_resource;
30313031
return nfs_ok;
30323032
}
3033-
3034-
c = nfsd4_change_attribute(&args->stat);
3035-
return nfsd4_encode_changeid4(xdr, c);
3033+
return nfsd4_encode_changeid4(xdr, args->change_attr);
30363034
}
30373035

30383036
static __be32 nfsd4_encode_fattr4_size(struct xdr_stream *xdr,
@@ -3557,11 +3555,16 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
35573555
if (dp) {
35583556
struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr;
35593557

3560-
if (ncf->ncf_file_modified)
3558+
if (ncf->ncf_file_modified) {
3559+
++ncf->ncf_initial_cinfo;
35613560
args.stat.size = ncf->ncf_cur_fsize;
3562-
3561+
}
3562+
args.change_attr = ncf->ncf_initial_cinfo;
35633563
nfs4_put_stid(&dp->dl_stid);
3564+
} else {
3565+
args.change_attr = nfsd4_change_attribute(&args.stat);
35643566
}
3567+
35653568
if (err)
35663569
goto out_nfserr;
35673570

0 commit comments

Comments
 (0)