Commit 6cc58291 authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Add simple u32, u64, and bool encoders



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: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 789ce196
Loading
Loading
Loading
Loading
+111 −0
Original line number Diff line number Diff line
@@ -50,6 +50,117 @@
#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;