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

nfsd: Ensure sampling of the commit verifier is atomic with the commit

When we have a successful commit, ensure we sample the commit verifier
before releasing the lock.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Trond Myklebust and committed by
J. Bruce Fields
524ff1af 809fe3c5

+14 -12
+2 -1
fs/nfsd/nfs3proc.c
··· 683 683 RETURN_STATUS(nfserr_inval); 684 684 685 685 fh_copy(&resp->fh, &argp->fh); 686 - nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count); 686 + nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count, 687 + resp->verf); 687 688 688 689 RETURN_STATUS(nfserr); 689 690 }
+2 -6
fs/nfsd/nfs3xdr.c
··· 1121 1121 nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p) 1122 1122 { 1123 1123 struct nfsd3_commitres *resp = rqstp->rq_resp; 1124 - struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 1125 - __be32 verf[2]; 1126 1124 1127 1125 p = encode_wcc_data(rqstp, p, &resp->fh); 1128 1126 /* Write verifier */ 1129 1127 if (resp->status == 0) { 1130 - /* unique identifier, y2038 overflow can be ignored */ 1131 - nfsd_copy_boot_verifier(verf, nn); 1132 - *p++ = verf[0]; 1133 - *p++ = verf[1]; 1128 + *p++ = resp->verf[0]; 1129 + *p++ = resp->verf[1]; 1134 1130 } 1135 1131 return xdr_ressize_check(rqstp, p); 1136 1132 }
+2 -2
fs/nfsd/nfs4proc.c
··· 590 590 { 591 591 struct nfsd4_commit *commit = &u->commit; 592 592 593 - gen_boot_verifier(&commit->co_verf, SVC_NET(rqstp)); 594 593 return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset, 595 - commit->co_count); 594 + commit->co_count, 595 + (__be32 *)commit->co_verf.data); 596 596 } 597 597 598 598 static __be32
+6 -2
fs/nfsd/vfs.c
··· 1105 1105 */ 1106 1106 __be32 1107 1107 nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, 1108 - loff_t offset, unsigned long count) 1108 + loff_t offset, unsigned long count, __be32 *verf) 1109 1109 { 1110 1110 struct nfsd_file *nf; 1111 1111 loff_t end = LLONG_MAX; ··· 1130 1130 err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); 1131 1131 switch (err2) { 1132 1132 case 0: 1133 + nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net, 1134 + nfsd_net_id)); 1133 1135 break; 1134 1136 case -EINVAL: 1135 1137 err = nfserr_notsupp; ··· 1142 1140 nfsd_net_id)); 1143 1141 } 1144 1142 up_write(&nf->nf_rwsem); 1145 - } 1143 + } else 1144 + nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net, 1145 + nfsd_net_id)); 1146 1146 1147 1147 nfsd_file_put(nf); 1148 1148 out:
+1 -1
fs/nfsd/vfs.h
··· 74 74 struct svc_fh *res, int createmode, 75 75 u32 *verifier, bool *truncp, bool *created); 76 76 __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, 77 - loff_t, unsigned long); 77 + loff_t, unsigned long, __be32 *verf); 78 78 #endif /* CONFIG_NFSD_V3 */ 79 79 int nfsd_open_break_lease(struct inode *, int); 80 80 __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t,
+1
fs/nfsd/xdr3.h
··· 223 223 struct nfsd3_commitres { 224 224 __be32 status; 225 225 struct svc_fh fh; 226 + __be32 verf[2]; 226 227 }; 227 228 228 229 struct nfsd3_getaclres {