lkml.org 
[lkml]   [2022]   [Jan]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.16 12/28] NFSD: Fix zero-length NFSv3 WRITEs
    Date
    From: Chuck Lever <chuck.lever@oracle.com>

    commit 6a2f774424bfdcc2df3e17de0cefe74a4269cad5 upstream.

    The Linux NFS server currently responds to a zero-length NFSv3 WRITE
    request with NFS3ERR_IO. It responds to a zero-length NFSv4 WRITE
    with NFS4_OK and count of zero.

    RFC 1813 says of the WRITE procedure's @count argument:

    count
    The number of bytes of data to be written. If count is
    0, the WRITE will succeed and return a count of 0,
    barring errors due to permissions checking.

    RFC 8881 has similar language for NFSv4, though NFSv4 removed the
    explicit @count argument because that value is already contained in
    the opaque payload array.

    The synthetic client pynfs's WRT4 and WRT15 tests do emit zero-
    length WRITEs to exercise this spec requirement. Commit fdec6114ee1f
    ("nfsd4: zero-length WRITE should succeed") addressed the same
    problem there with the same fix.

    But interestingly the Linux NFS client does not appear to emit zero-
    length WRITEs, instead squelching them. I'm not aware of a test that
    can generate such WRITEs for NFSv3, so I wrote a naive C program to
    generate a zero-length WRITE and test this fix.

    Fixes: 8154ef2776aa ("NFSD: Clean up legacy NFS WRITE argument XDR decoders")
    Reported-by: Trond Myklebust <trond.myklebust@hammerspace.com>
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/nfsd/nfs3proc.c | 6 +-----
    fs/nfsd/nfsproc.c | 5 -----
    2 files changed, 1 insertion(+), 10 deletions(-)

    --- a/fs/nfsd/nfs3proc.c
    +++ b/fs/nfsd/nfs3proc.c
    @@ -202,15 +202,11 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
    fh_copy(&resp->fh, &argp->fh);
    resp->committed = argp->stable;
    nvecs = svc_fill_write_vector(rqstp, &argp->payload);
    - if (!nvecs) {
    - resp->status = nfserr_io;
    - goto out;
    - }
    +
    resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
    rqstp->rq_vec, nvecs, &cnt,
    resp->committed, resp->verf);
    resp->count = cnt;
    -out:
    return rpc_success;
    }

    --- a/fs/nfsd/nfsproc.c
    +++ b/fs/nfsd/nfsproc.c
    @@ -235,10 +235,6 @@ nfsd_proc_write(struct svc_rqst *rqstp)
    argp->len, argp->offset);

    nvecs = svc_fill_write_vector(rqstp, &argp->payload);
    - if (!nvecs) {
    - resp->status = nfserr_io;
    - goto out;
    - }

    resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
    argp->offset, rqstp->rq_vec, nvecs,
    @@ -247,7 +243,6 @@ nfsd_proc_write(struct svc_rqst *rqstp)
    resp->status = fh_getattr(&resp->fh, &resp->stat);
    else if (resp->status == nfserr_jukebox)
    return rpc_drop_reply;
    -out:
    return rpc_success;
    }


    \
     
     \ /
      Last update: 2022-01-18 17:13    [W:2.525 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site