]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFSD: Add COPY status code to OFFLOAD_STATUS response
authorChuck Lever <chuck.lever@oracle.com>
Tue, 30 Apr 2024 20:05:11 +0000 (16:05 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 6 May 2024 13:07:23 +0000 (09:07 -0400)
Clients that send an OFFLOAD_STATUS might want to distinguish
between an async COPY operation that is still running, has
completed successfully, or that has failed.

The intention of this patch is to make NFSD behave like this:

 * Copy still running:
OFFLOAD_STATUS returns NFS4_OK, the number of bytes copied
so far, and an empty osr_status array
 * Copy completed successfully:
OFFLOAD_STATUS returns NFS4_OK, the number of bytes copied,
and an osr_status of NFS4_OK
 * Copy failed:
OFFLOAD_STATUS returns NFS4_OK, the number of bytes copied,
and an osr_status other than NFS4_OK
 * Copy operation lost, canceled, or otherwise unrecognized:
OFFLOAD_STATUS returns NFS4ERR_BAD_STATEID

NB: Though RFC 7862 Section 11.2 lists a small set of NFS status
codes that are valid for OFFLOAD_STATUS, there do not seem to be any
explicit spec limits on the status codes that may be returned in the
osr_status field.

At this time we have no unit tests for COPY and its brethren, as
pynfs does not yet implement support for NFSv4.2.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4xdr.c
fs/nfsd/xdr4.h

index 7e6580384cdb6a83d03a337ced4808b5ac5b5344..ea3cc3e870a7f746ee4c39b754353d4c3387e0ec 100644 (file)
@@ -1793,6 +1793,7 @@ static int nfsd4_do_async_copy(void *data)
        }
 
 do_callback:
+       set_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags);
        nfsd4_send_cb_offload(copy);
        cleanup_async_copy(copy);
        return 0;
@@ -2002,11 +2003,16 @@ nfsd4_offload_status(struct svc_rqst *rqstp,
        struct nfsd4_copy *copy;
        struct nfs4_client *clp = cstate->clp;
 
+       os->completed = false;
        spin_lock(&clp->async_lock);
        copy = find_async_copy_locked(clp, &os->stateid);
-       if (copy)
+       if (copy) {
                os->count = copy->cp_res.wr_bytes_written;
-       else
+               if (test_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags)) {
+                       os->completed = true;
+                       os->status = copy->nfserr;
+               }
+       } else
                status = nfserr_bad_stateid;
        spin_unlock(&clp->async_lock);
 
index ea76100e50caa120907ba8f9e007537522416a93..c7bfd2180e3f27aa6eeb1db9b66af2267f84101b 100644 (file)
@@ -5271,7 +5271,12 @@ nfsd4_encode_offload_status(struct nfsd4_compoundres *resp, __be32 nfserr,
        if (nfserr != nfs_ok)
                return nfserr;
        /* osr_complete<1> */
-       if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
+       if (os->completed) {
+               if (xdr_stream_encode_u32(xdr, 1) != XDR_UNIT)
+                       return nfserr_resource;
+               if (xdr_stream_encode_be32(xdr, os->status) != XDR_UNIT)
+                       return nfserr_resource;
+       } else if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
                return nfserr_resource;
        return nfs_ok;
 }
index 62805931e8572253f6db79ae30fd9adee9020d51..fbdd42cde1fa5bc6ed7df1aec685dd111b50263c 100644 (file)
@@ -692,6 +692,7 @@ struct nfsd4_copy {
 #define NFSD4_COPY_F_INTRA             (1)
 #define NFSD4_COPY_F_SYNCHRONOUS       (2)
 #define NFSD4_COPY_F_COMMITTED         (3)
+#define NFSD4_COPY_F_COMPLETED         (4)
 
        /* response */
        __be32                  nfserr;
@@ -754,7 +755,8 @@ struct nfsd4_offload_status {
 
        /* response */
        u64             count;
-       u32             status;
+       __be32          status;
+       bool            completed;
 };
 
 struct nfsd4_copy_notify {