NFSD: Add encoders for NFSv4 clientids and verifiers
authorChuck Lever <chuck.lever@oracle.com>
Tue, 16 May 2023 14:26:09 +0000 (10:26 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 5 Jun 2023 13:01:44 +0000 (09:01 -0400)
Deduplicate some common code.

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

index 76db2fe..1488ce9 100644 (file)
@@ -3688,6 +3688,30 @@ fail:
        return -EINVAL;
 }
 
+static __be32
+nfsd4_encode_verifier4(struct xdr_stream *xdr, const nfs4_verifier *verf)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
+       if (!p)
+               return nfserr_resource;
+       memcpy(p, verf->data, sizeof(verf->data));
+       return nfs_ok;
+}
+
+static __be32
+nfsd4_encode_clientid4(struct xdr_stream *xdr, const clientid_t *clientid)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, sizeof(__be64));
+       if (!p)
+               return nfserr_resource;
+       memcpy(p, clientid, sizeof(*clientid));
+       return nfs_ok;
+}
+
 static __be32
 nfsd4_encode_stateid(struct xdr_stream *xdr, stateid_t *sid)
 {
@@ -3752,15 +3776,8 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr,
                    union nfsd4_op_u *u)
 {
        struct nfsd4_commit *commit = &u->commit;
-       struct xdr_stream *xdr = resp->xdr;
-       __be32 *p;
 
-       p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
-       if (!p)
-               return nfserr_resource;
-       p = xdr_encode_opaque_fixed(p, commit->co_verf.data,
-                                               NFS4_VERIFIER_SIZE);
-       return 0;
+       return nfsd4_encode_verifier4(resp->xdr, &commit->co_verf);
 }
 
 static __be32
@@ -4213,15 +4230,9 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr,
        int starting_len = xdr->buf->len;
        __be32 *p;
 
-       p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
-       if (!p)
-               return nfserr_resource;
-
-       /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
-       *p++ = cpu_to_be32(0);
-       *p++ = cpu_to_be32(0);
-       xdr->buf->head[0].iov_len = (char *)xdr->p -
-                                   (char *)xdr->buf->head[0].iov_base;
+       nfserr = nfsd4_encode_verifier4(xdr, &readdir->rd_verf);
+       if (nfserr != nfs_ok)
+               return nfserr;
 
        /*
         * Number of bytes left for directory entries allowing for the
@@ -4448,23 +4459,25 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr,
 {
        struct nfsd4_setclientid *scd = &u->setclientid;
        struct xdr_stream *xdr = resp->xdr;
-       __be32 *p;
 
        if (!nfserr) {
-               p = xdr_reserve_space(xdr, 8 + NFS4_VERIFIER_SIZE);
-               if (!p)
-                       return nfserr_resource;
-               p = xdr_encode_opaque_fixed(p, &scd->se_clientid, 8);
-               p = xdr_encode_opaque_fixed(p, &scd->se_confirm,
-                                               NFS4_VERIFIER_SIZE);
-       }
-       else if (nfserr == nfserr_clid_inuse) {
-               p = xdr_reserve_space(xdr, 8);
-               if (!p)
-                       return nfserr_resource;
-               *p++ = cpu_to_be32(0);
-               *p++ = cpu_to_be32(0);
+               nfserr = nfsd4_encode_clientid4(xdr, &scd->se_clientid);
+               if (nfserr != nfs_ok)
+                       goto out;
+               nfserr = nfsd4_encode_verifier4(xdr, &scd->se_confirm);
+       } else if (nfserr == nfserr_clid_inuse) {
+               /* empty network id */
+               if (xdr_stream_encode_u32(xdr, 0) < 0) {
+                       nfserr = nfserr_resource;
+                       goto out;
+               }
+               /* empty universal address */
+               if (xdr_stream_encode_u32(xdr, 0) < 0) {
+                       nfserr = nfserr_resource;
+                       goto out;
+               }
        }
+out:
        return nfserr;
 }
 
@@ -4473,17 +4486,12 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr,
                   union nfsd4_op_u *u)
 {
        struct nfsd4_write *write = &u->write;
-       struct xdr_stream *xdr = resp->xdr;
-       __be32 *p;
 
-       p = xdr_reserve_space(xdr, 16);
-       if (!p)
+       if (xdr_stream_encode_u32(resp->xdr, write->wr_bytes_written) < 0)
                return nfserr_resource;
-       *p++ = cpu_to_be32(write->wr_bytes_written);
-       *p++ = cpu_to_be32(write->wr_how_written);
-       p = xdr_encode_opaque_fixed(p, write->wr_verifier.data,
-                                               NFS4_VERIFIER_SIZE);
-       return 0;
+       if (xdr_stream_encode_u32(resp->xdr, write->wr_how_written) < 0)
+               return nfserr_resource;
+       return nfsd4_encode_verifier4(resp->xdr, &write->wr_verifier);
 }
 
 static __be32
@@ -4505,20 +4513,15 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
        server_scope = nn->nfsd_name;
        server_scope_sz = strlen(nn->nfsd_name);
 
-       p = xdr_reserve_space(xdr,
-               8 /* eir_clientid */ +
-               4 /* eir_sequenceid */ +
-               4 /* eir_flags */ +
-               4 /* spr_how */);
-       if (!p)
+       if (nfsd4_encode_clientid4(xdr, &exid->clientid) != nfs_ok)
+               return nfserr_resource;
+       if (xdr_stream_encode_u32(xdr, exid->seqid) < 0)
+               return nfserr_resource;
+       if (xdr_stream_encode_u32(xdr, exid->flags) < 0)
                return nfserr_resource;
 
-       p = xdr_encode_opaque_fixed(p, &exid->clientid, 8);
-       *p++ = cpu_to_be32(exid->seqid);
-       *p++ = cpu_to_be32(exid->flags);
-
-       *p++ = cpu_to_be32(exid->spa_how);
-
+       if (xdr_stream_encode_u32(xdr, exid->spa_how) < 0)
+               return nfserr_resource;
        switch (exid->spa_how) {
        case SP4_NONE:
                break;