NFSD: Add simple u32, u64, and bool encoders
authorChuck Lever <chuck.lever@oracle.com>
Mon, 18 Sep 2023 13:56:54 +0000 (09:56 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 16 Oct 2023 16:44:11 +0000 (12:44 -0400)
The generic XDR encoders return a length or a negative errno. NFSv4
encoders want to know simply whether the encode ran out of stream
buffer space. The return values for server-side encoding are either
nfs_ok or nfserr_resource.

So far I've found it adds a lot of duplicate code to try to use the
generic XDR encoder utilities when encoding the simple data types in
the NFSv4 operation encoders.

Add a set of NFSv4-specific utilities that handle the basic XDR data
types. These are added in xdr4.h so they might eventually be used by
the callback server and pNFS driver encoders too.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/xdr4.h

index 9d918a79dc1665f5b417c713c7bc538d27a5b1a1..5c3eb3691f8b829c1db4a84af555e9bb94d6086c 100644 (file)
 #define HAS_CSTATE_FLAG(c, f) ((c)->sid_flags & (f))
 #define CLEAR_CSTATE_FLAG(c, f) ((c)->sid_flags &= ~(f))
 
+/**
+ * nfsd4_encode_bool - Encode an XDR bool type result
+ * @xdr: target XDR stream
+ * @val: boolean value to encode
+ *
+ * Return values:
+ *    %nfs_ok: @val encoded; @xdr advanced to next position
+ *    %nfserr_resource: stream buffer space exhausted
+ */
+static __always_inline __be32
+nfsd4_encode_bool(struct xdr_stream *xdr, bool val)
+{
+       __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
+
+       if (unlikely(p == NULL))
+               return nfserr_resource;
+       *p = val ? xdr_one : xdr_zero;
+       return nfs_ok;
+}
+
+/**
+ * nfsd4_encode_uint32_t - Encode an XDR uint32_t type result
+ * @xdr: target XDR stream
+ * @val: integer value to encode
+ *
+ * Return values:
+ *    %nfs_ok: @val encoded; @xdr advanced to next position
+ *    %nfserr_resource: stream buffer space exhausted
+ */
+static __always_inline __be32
+nfsd4_encode_uint32_t(struct xdr_stream *xdr, u32 val)
+{
+       __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
+
+       if (unlikely(p == NULL))
+               return nfserr_resource;
+       *p = cpu_to_be32(val);
+       return nfs_ok;
+}
+
+/**
+ * nfsd4_encode_uint64_t - Encode an XDR uint64_t type result
+ * @xdr: target XDR stream
+ * @val: integer value to encode
+ *
+ * Return values:
+ *    %nfs_ok: @val encoded; @xdr advanced to next position
+ *    %nfserr_resource: stream buffer space exhausted
+ */
+static __always_inline __be32
+nfsd4_encode_uint64_t(struct xdr_stream *xdr, u64 val)
+{
+       __be32 *p = xdr_reserve_space(xdr, XDR_UNIT * 2);
+
+       if (unlikely(p == NULL))
+               return nfserr_resource;
+       put_unaligned_be64(val, p);
+       return nfs_ok;
+}
+
+/**
+ * nfsd4_encode_opaque_fixed - Encode a fixed-length XDR opaque type result
+ * @xdr: target XDR stream
+ * @data: pointer to data
+ * @size: length of data in bytes
+ *
+ * Return values:
+ *    %nfs_ok: @data encoded; @xdr advanced to next position
+ *    %nfserr_resource: stream buffer space exhausted
+ */
+static __always_inline __be32
+nfsd4_encode_opaque_fixed(struct xdr_stream *xdr, const void *data,
+                         size_t size)
+{
+       __be32 *p = xdr_reserve_space(xdr, xdr_align_size(size));
+       size_t pad = xdr_pad_size(size);
+
+       if (unlikely(p == NULL))
+               return nfserr_resource;
+       memcpy(p, data, size);
+       if (pad)
+               memset((char *)p + size, 0, pad);
+       return nfs_ok;
+}
+
+/**
+ * nfsd4_encode_opaque - Encode a variable-length XDR opaque type result
+ * @xdr: target XDR stream
+ * @data: pointer to data
+ * @size: length of data in bytes
+ *
+ * Return values:
+ *    %nfs_ok: @data encoded; @xdr advanced to next position
+ *    %nfserr_resource: stream buffer space exhausted
+ */
+static __always_inline __be32
+nfsd4_encode_opaque(struct xdr_stream *xdr, const void *data, size_t size)
+{
+       size_t pad = xdr_pad_size(size);
+       __be32 *p;
+
+       p = xdr_reserve_space(xdr, XDR_UNIT + xdr_align_size(size));
+       if (unlikely(p == NULL))
+               return nfserr_resource;
+       *p++ = cpu_to_be32(size);
+       memcpy(p, data, size);
+       if (pad)
+               memset((char *)p + size, 0, pad);
+       return nfs_ok;
+}
+
 struct nfsd4_compound_state {
        struct svc_fh           current_fh;
        struct svc_fh           save_fh;