]> git.baikalelectronics.ru Git - kernel.git/commitdiff
nfsd: Ensure sampling of the write verifier is atomic with the write
authorTrond Myklebust <trondmy@gmail.com>
Mon, 6 Jan 2020 18:40:37 +0000 (13:40 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 22 Jan 2020 21:25:41 +0000 (16:25 -0500)
When doing an unstable write, we need to ensure that we sample the
write verifier before releasing the lock, and allowing a commit to
the same file to proceed.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs3proc.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfsproc.c
fs/nfsd/vfs.c
fs/nfsd/vfs.h
fs/nfsd/xdr3.h

index ffdc592868a6c6499e80261da598a628f03a0c47..288bc76b4574de1eb22b3754572a2d18cb756f0d 100644 (file)
@@ -203,7 +203,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
                RETURN_STATUS(nfserr_io);
        nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
                            rqstp->rq_vec, nvecs, &cnt,
-                           resp->committed);
+                           resp->committed, resp->verf);
        resp->count = cnt;
        RETURN_STATUS(nfserr);
 }
index 1ae4fc2eec0094440bc2b0e5119fd757906cba9a..aae514d40b641aba55d40c4431df41c56331cc5e 100644 (file)
@@ -747,17 +747,13 @@ int
 nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p)
 {
        struct nfsd3_writeres *resp = rqstp->rq_resp;
-       struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
-       __be32 verf[2];
 
        p = encode_wcc_data(rqstp, p, &resp->fh);
        if (resp->status == 0) {
                *p++ = htonl(resp->count);
                *p++ = htonl(resp->committed);
-               /* unique identifier, y2038 overflow can be ignored */
-               nfsd_copy_boot_verifier(verf, nn);
-               *p++ = verf[0];
-               *p++ = verf[1];
+               *p++ = resp->verf[0];
+               *p++ = resp->verf[1];
        }
        return xdr_ressize_check(rqstp, p);
 }
index c3455e1b0d507524f20cfb1c354f1dd9b340d126..e4ddaf87493ae4b961b8f10f48dac7c9973046ab 100644 (file)
@@ -1015,7 +1015,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        }
 
        write->wr_how_written = write->wr_stable_how;
-       gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp));
 
        nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
                                      &write->wr_head, write->wr_buflen);
@@ -1023,7 +1022,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf,
                                write->wr_offset, rqstp->rq_vec, nvecs, &cnt,
-                               write->wr_how_written);
+                               write->wr_how_written,
+                               (__be32 *)write->wr_verifier.data);
        nfsd_file_put(nf);
 
        write->wr_bytes_written = cnt;
index b25c90be29fbdecb8f0a993609936879b111ba87..543bbe0a556e7387c19e7aa40fd6400698766f86 100644 (file)
@@ -226,7 +226,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
                return nfserr_io;
        nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
                            argp->offset, rqstp->rq_vec, nvecs,
-                           &cnt, NFS_DATA_SYNC);
+                           &cnt, NFS_DATA_SYNC, NULL);
        return nfsd_return_attrs(nfserr, resp);
 }
 
index dc07d9797f115faea0b098dbfc980684d85c64eb..0aa02eb18bd3c5ca22301ac1c1ab4fd029878d0f 100644 (file)
@@ -962,7 +962,8 @@ static int wait_for_concurrent_writes(struct file *file)
 __be32
 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
                                loff_t offset, struct kvec *vec, int vlen,
-                               unsigned long *cnt, int stable)
+                               unsigned long *cnt, int stable,
+                               __be32 *verf)
 {
        struct file             *file = nf->nf_file;
        struct svc_export       *exp;
@@ -1004,6 +1005,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
                up_write(&nf->nf_rwsem);
        } else {
                down_read(&nf->nf_rwsem);
+               if (verf)
+                       nfsd_copy_boot_verifier(verf,
+                                       net_generic(SVC_NET(rqstp),
+                                       nfsd_net_id));
                host_err = vfs_iter_write(file, &iter, &pos, flags);
                up_read(&nf->nf_rwsem);
        }
@@ -1074,7 +1079,8 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
  */
 __be32
 nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
-          struct kvec *vec, int vlen, unsigned long *cnt, int stable)
+          struct kvec *vec, int vlen, unsigned long *cnt, int stable,
+          __be32 *verf)
 {
        struct nfsd_file *nf;
        __be32 err;
@@ -1086,7 +1092,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
                goto out;
 
        err = nfsd_vfs_write(rqstp, fhp, nf, offset, vec,
-                       vlen, cnt, stable);
+                       vlen, cnt, stable, verf);
        nfsd_file_put(nf);
 out:
        trace_nfsd_write_done(rqstp, fhp, offset, *cnt);
index d23d9daacc3db282e0bc123662594aaaa703580c..3eb660ad80d1c5bc8d54f833f0b9733e7fdd1c00 100644 (file)
@@ -94,11 +94,12 @@ __be32              nfsd_read(struct svc_rqst *, struct svc_fh *,
                                loff_t, struct kvec *, int, unsigned long *,
                                u32 *eof);
 __be32                 nfsd_write(struct svc_rqst *, struct svc_fh *, loff_t,
-                               struct kvec *, int, unsigned long *, int);
+                               struct kvec *, int, unsigned long *,
+                               int stable, __be32 *verf);
 __be32         nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp,
                                struct nfsd_file *nf, loff_t offset,
                                struct kvec *vec, int vlen, unsigned long *cnt,
-                               int stable);
+                               int stable, __be32 *verf);
 __be32         nfsd_readlink(struct svc_rqst *, struct svc_fh *,
                                char *, int *);
 __be32         nfsd_symlink(struct svc_rqst *, struct svc_fh *,
index fe6fd4556c2e58b3055328ac14c1f742363b87d2..4155fd71714c9c640a48b5a34e05f805132e48bb 100644 (file)
@@ -159,6 +159,7 @@ struct nfsd3_writeres {
        struct svc_fh           fh;
        unsigned long           count;
        int                     committed;
+       __be32                  verf[2];
 };
 
 struct nfsd3_renameres {