]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - spl/module/spl/spl-xdr.c
UBUNTU: [Packaging] dkms -- drop zfs/spl source code from kernel
[mirror_ubuntu-bionic-kernel.git] / spl / module / spl / spl-xdr.c
diff --git a/spl/module/spl/spl-xdr.c b/spl/module/spl/spl-xdr.c
deleted file mode 100644 (file)
index 9405dc8..0000000
+++ /dev/null
@@ -1,514 +0,0 @@
-/*****************************************************************************\
- *  Copyright (c) 2008-2010 Sun Microsystems, Inc.
- *  Written by Ricardo Correia <Ricardo.M.Correia@Sun.COM>
- *
- *  This file is part of the SPL, Solaris Porting Layer.
- *  For details, see <http://zfsonlinux.org/>.
- *
- *  The SPL is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  The SPL is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with the SPL.  If not, see <http://www.gnu.org/licenses/>.
- *****************************************************************************
- *  Solaris Porting Layer (SPL) XDR Implementation.
-\*****************************************************************************/
-
-#include <linux/string.h>
-#include <sys/kmem.h>
-#include <sys/debug.h>
-#include <sys/types.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-
-/*
- * SPL's XDR mem implementation.
- *
- * This is used by libnvpair to serialize/deserialize the name-value pair data
- * structures into byte arrays in a well-defined and portable manner.
- *
- * These data structures are used by the DMU/ZFS to flexibly manipulate various
- * information in memory and later serialize it/deserialize it to disk.
- * Examples of usages include the pool configuration, lists of pool and dataset
- * properties, etc.
- *
- * Reference documentation for the XDR representation and XDR operations can be
- * found in RFC 1832 and xdr(3), respectively.
- *
- * ===  Implementation shortcomings ===
- *
- * It is assumed that the following C types have the following sizes:
- *
- * char/unsigned char:      1 byte
- * short/unsigned short:    2 bytes
- * int/unsigned int:        4 bytes
- * longlong_t/u_longlong_t: 8 bytes
- *
- * The C standard allows these types to be larger (and in the case of ints,
- * shorter), so if that is the case on some compiler/architecture, the build
- * will fail (on purpose).
- *
- * If someone wants to fix the code to work properly on such environments, then:
- *
- * 1) Preconditions should be added to xdrmem_enc functions to make sure the
- *    caller doesn't pass arguments which exceed the expected range.
- * 2) Functions which take signed integers should be changed to properly do
- *    sign extension.
- * 3) For ints with less than 32 bits, well.. I suspect you'll have bigger
- *    problems than this implementation.
- *
- * It is also assumed that:
- *
- * 1) Chars have 8 bits.
- * 2) We can always do 32-bit-aligned int memory accesses and byte-aligned
- *    memcpy, memset and memcmp.
- * 3) Arrays passed to xdr_array() are packed and the compiler/architecture
- *    supports element-sized-aligned memory accesses.
- * 4) Negative integers are natively stored in two's complement binary
- *    representation.
- *
- * No checks are done for the 4 assumptions above, though.
- *
- * === Caller expectations ===
- *
- * Existing documentation does not describe the semantics of XDR operations very
- * well.  Therefore, some assumptions about failure semantics will be made and
- * will be described below:
- *
- * 1) If any encoding operation fails (e.g., due to lack of buffer space), the
- * the stream should be considered valid only up to the encoding operation
- * previous to the one that first failed. However, the stream size as returned
- * by xdr_control() cannot be considered to be strictly correct (it may be
- * bigger).
- *
- * Putting it another way, if there is an encoding failure it's undefined
- * whether anything is added to the stream in that operation and therefore
- * neither xdr_control() nor future encoding operations on the same stream can
- * be relied upon to produce correct results.
- *
- * 2) If a decoding operation fails, it's undefined whether anything will be
- * decoded into passed buffers/pointers during that operation, or what the
- * values on those buffers will look like.
- *
- * Future decoding operations on the same stream will also have similar
- * undefined behavior.
- *
- * 3) When the first decoding operation fails it is OK to trust the results of
- * previous decoding operations on the same stream, as long as the caller
- * expects a failure to be possible (e.g. due to end-of-stream).
- *
- * However, this is highly discouraged because the caller should know the
- * stream size and should be coded to expect any decoding failure to be data
- * corruption due to hardware, accidental or even malicious causes, which should
- * be handled gracefully in all cases.
- *
- * In very rare situations where there are strong reasons to believe the data
- * can be trusted to be valid and non-tampered with, then the caller may assume
- * a decoding failure to be a bug (e.g. due to mismatched data types) and may
- * fail non-gracefully.
- *
- * 4) Non-zero padding bytes will cause the decoding operation to fail.
- *
- * 5) Zero bytes on string types will also cause the decoding operation to fail.
- *
- * 6) It is assumed that either the pointer to the stream buffer given by the
- * caller is 32-bit aligned or the architecture supports non-32-bit-aligned int
- * memory accesses.
- *
- * 7) The stream buffer and encoding/decoding buffers/ptrs should not overlap.
- *
- * 8) If a caller passes pointers to non-kernel memory (e.g., pointers to user
- * space or MMIO space), the computer may explode.
- */
-
-static struct xdr_ops xdrmem_encode_ops;
-static struct xdr_ops xdrmem_decode_ops;
-
-void
-xdrmem_create(XDR *xdrs, const caddr_t addr, const uint_t size,
-    const enum xdr_op op)
-{
-       switch (op) {
-               case XDR_ENCODE:
-                       xdrs->x_ops = &xdrmem_encode_ops;
-                       break;
-               case XDR_DECODE:
-                       xdrs->x_ops = &xdrmem_decode_ops;
-                       break;
-               default:
-                       xdrs->x_ops = NULL; /* Let the caller know we failed */
-                       return;
-       }
-
-       xdrs->x_op = op;
-       xdrs->x_addr = addr;
-       xdrs->x_addr_end = addr + size;
-
-       if (xdrs->x_addr_end < xdrs->x_addr) {
-               xdrs->x_ops = NULL;
-       }
-}
-EXPORT_SYMBOL(xdrmem_create);
-
-static bool_t
-xdrmem_control(XDR *xdrs, int req, void *info)
-{
-       struct xdr_bytesrec *rec = (struct xdr_bytesrec *) info;
-
-       if (req != XDR_GET_BYTES_AVAIL)
-               return FALSE;
-
-       rec->xc_is_last_record = TRUE; /* always TRUE in xdrmem streams */
-       rec->xc_num_avail = xdrs->x_addr_end - xdrs->x_addr;
-
-       return TRUE;
-}
-
-static bool_t
-xdrmem_enc_bytes(XDR *xdrs, caddr_t cp, const uint_t cnt)
-{
-       uint_t size = roundup(cnt, 4);
-       uint_t pad;
-
-       if (size < cnt)
-               return FALSE; /* Integer overflow */
-
-       if (xdrs->x_addr > xdrs->x_addr_end)
-               return FALSE;
-
-       if (xdrs->x_addr_end - xdrs->x_addr < size)
-               return FALSE;
-
-       memcpy(xdrs->x_addr, cp, cnt);
-
-       xdrs->x_addr += cnt;
-
-       pad = size - cnt;
-       if (pad > 0) {
-               memset(xdrs->x_addr, 0, pad);
-               xdrs->x_addr += pad;
-       }
-
-       return TRUE;
-}
-
-static bool_t
-xdrmem_dec_bytes(XDR *xdrs, caddr_t cp, const uint_t cnt)
-{
-       static uint32_t zero = 0;
-       uint_t size = roundup(cnt, 4);
-       uint_t pad;
-
-       if (size < cnt)
-               return FALSE; /* Integer overflow */
-
-       if (xdrs->x_addr > xdrs->x_addr_end)
-               return FALSE;
-
-       if (xdrs->x_addr_end - xdrs->x_addr < size)
-               return FALSE;
-
-       memcpy(cp, xdrs->x_addr, cnt);
-       xdrs->x_addr += cnt;
-
-       pad = size - cnt;
-       if (pad > 0) {
-               /* An inverted memchr() would be useful here... */
-               if (memcmp(&zero, xdrs->x_addr, pad) != 0)
-                       return FALSE;
-
-               xdrs->x_addr += pad;
-       }
-
-       return TRUE;
-}
-
-static bool_t
-xdrmem_enc_uint32(XDR *xdrs, uint32_t val)
-{
-       if (xdrs->x_addr + sizeof(uint32_t) > xdrs->x_addr_end)
-               return FALSE;
-
-       *((uint32_t *) xdrs->x_addr) = cpu_to_be32(val);
-
-       xdrs->x_addr += sizeof(uint32_t);
-
-       return TRUE;
-}
-
-static bool_t
-xdrmem_dec_uint32(XDR *xdrs, uint32_t *val)
-{
-       if (xdrs->x_addr + sizeof(uint32_t) > xdrs->x_addr_end)
-               return FALSE;
-
-       *val = be32_to_cpu(*((uint32_t *) xdrs->x_addr));
-
-       xdrs->x_addr += sizeof(uint32_t);
-
-       return TRUE;
-}
-
-static bool_t
-xdrmem_enc_char(XDR *xdrs, char *cp)
-{
-       uint32_t val;
-
-       BUILD_BUG_ON(sizeof(char) != 1);
-       val = *((unsigned char *) cp);
-
-       return xdrmem_enc_uint32(xdrs, val);
-}
-
-static bool_t
-xdrmem_dec_char(XDR *xdrs, char *cp)
-{
-       uint32_t val;
-
-       BUILD_BUG_ON(sizeof(char) != 1);
-
-       if (!xdrmem_dec_uint32(xdrs, &val))
-               return FALSE;
-
-       /*
-        * If any of the 3 other bytes are non-zero then val will be greater
-        * than 0xff and we fail because according to the RFC, this block does
-        * not have a char encoded in it.
-        */
-       if (val > 0xff)
-               return FALSE;
-
-       *((unsigned char *) cp) = val;
-
-       return TRUE;
-}
-
-static bool_t
-xdrmem_enc_ushort(XDR *xdrs, unsigned short *usp)
-{
-       BUILD_BUG_ON(sizeof(unsigned short) != 2);
-
-       return xdrmem_enc_uint32(xdrs, *usp);
-}
-
-static bool_t
-xdrmem_dec_ushort(XDR *xdrs, unsigned short *usp)
-{
-       uint32_t val;
-
-       BUILD_BUG_ON(sizeof(unsigned short) != 2);
-
-       if (!xdrmem_dec_uint32(xdrs, &val))
-               return FALSE;
-
-       /*
-        * Short ints are not in the RFC, but we assume similar logic as in
-        * xdrmem_dec_char().
-        */
-       if (val > 0xffff)
-               return FALSE;
-
-       *usp = val;
-
-       return TRUE;
-}
-
-static bool_t
-xdrmem_enc_uint(XDR *xdrs, unsigned *up)
-{
-       BUILD_BUG_ON(sizeof(unsigned) != 4);
-
-       return xdrmem_enc_uint32(xdrs, *up);
-}
-
-static bool_t
-xdrmem_dec_uint(XDR *xdrs, unsigned *up)
-{
-       BUILD_BUG_ON(sizeof(unsigned) != 4);
-
-       return xdrmem_dec_uint32(xdrs, (uint32_t *) up);
-}
-
-static bool_t
-xdrmem_enc_ulonglong(XDR *xdrs, u_longlong_t *ullp)
-{
-       BUILD_BUG_ON(sizeof(u_longlong_t) != 8);
-
-       if (!xdrmem_enc_uint32(xdrs, *ullp >> 32))
-               return FALSE;
-
-       return xdrmem_enc_uint32(xdrs, *ullp & 0xffffffff);
-}
-
-static bool_t
-xdrmem_dec_ulonglong(XDR *xdrs, u_longlong_t *ullp)
-{
-       uint32_t low, high;
-
-       BUILD_BUG_ON(sizeof(u_longlong_t) != 8);
-
-       if (!xdrmem_dec_uint32(xdrs, &high))
-               return FALSE;
-       if (!xdrmem_dec_uint32(xdrs, &low))
-               return FALSE;
-
-       *ullp = ((u_longlong_t) high << 32) | low;
-
-       return TRUE;
-}
-
-static bool_t
-xdr_enc_array(XDR *xdrs, caddr_t *arrp, uint_t *sizep, const uint_t maxsize,
-    const uint_t elsize, const xdrproc_t elproc)
-{
-       uint_t i;
-       caddr_t addr = *arrp;
-
-       if (*sizep > maxsize || *sizep > UINT_MAX / elsize)
-               return FALSE;
-
-       if (!xdrmem_enc_uint(xdrs, sizep))
-               return FALSE;
-
-       for (i = 0; i < *sizep; i++) {
-               if (!elproc(xdrs, addr))
-                       return FALSE;
-               addr += elsize;
-       }
-
-       return TRUE;
-}
-
-static bool_t
-xdr_dec_array(XDR *xdrs, caddr_t *arrp, uint_t *sizep, const uint_t maxsize,
-    const uint_t elsize, const xdrproc_t elproc)
-{
-       uint_t i, size;
-       bool_t alloc = FALSE;
-       caddr_t addr;
-
-       if (!xdrmem_dec_uint(xdrs, sizep))
-               return FALSE;
-
-       size = *sizep;
-
-       if (size > maxsize || size > UINT_MAX / elsize)
-               return FALSE;
-
-       /*
-        * The Solaris man page says: "If *arrp is NULL when decoding,
-        * xdr_array() allocates memory and *arrp points to it".
-        */
-       if (*arrp == NULL) {
-               BUILD_BUG_ON(sizeof(uint_t) > sizeof(size_t));
-
-               *arrp = kmem_alloc(size * elsize, KM_NOSLEEP);
-               if (*arrp == NULL)
-                       return FALSE;
-
-               alloc = TRUE;
-       }
-
-       addr = *arrp;
-
-       for (i = 0; i < size; i++) {
-               if (!elproc(xdrs, addr)) {
-                       if (alloc)
-                               kmem_free(*arrp, size * elsize);
-                       return FALSE;
-               }
-               addr += elsize;
-       }
-
-       return TRUE;
-}
-
-static bool_t
-xdr_enc_string(XDR *xdrs, char **sp, const uint_t maxsize)
-{
-       size_t slen = strlen(*sp);
-       uint_t len;
-
-       if (slen > maxsize)
-               return FALSE;
-
-       len = slen;
-
-       if (!xdrmem_enc_uint(xdrs, &len))
-               return FALSE;
-
-       return xdrmem_enc_bytes(xdrs, *sp, len);
-}
-
-static bool_t
-xdr_dec_string(XDR *xdrs, char **sp, const uint_t maxsize)
-{
-       uint_t size;
-       bool_t alloc = FALSE;
-
-       if (!xdrmem_dec_uint(xdrs, &size))
-               return FALSE;
-
-       if (size > maxsize || size > UINT_MAX - 1)
-               return FALSE;
-
-       /*
-        * Solaris man page: "If *sp is NULL when decoding, xdr_string()
-        * allocates memory and *sp points to it".
-        */
-       if (*sp == NULL) {
-               BUILD_BUG_ON(sizeof(uint_t) > sizeof(size_t));
-
-               *sp = kmem_alloc(size + 1, KM_NOSLEEP);
-               if (*sp == NULL)
-                       return FALSE;
-
-               alloc = TRUE;
-       }
-
-       if (!xdrmem_dec_bytes(xdrs, *sp, size))
-               goto fail;
-
-       if (memchr(*sp, 0, size) != NULL)
-               goto fail;
-
-       (*sp)[size] = '\0';
-
-       return TRUE;
-
-fail:
-       if (alloc)
-               kmem_free(*sp, size + 1);
-
-       return FALSE;
-}
-
-static struct xdr_ops xdrmem_encode_ops = {
-       .xdr_control      = xdrmem_control,
-       .xdr_char         = xdrmem_enc_char,
-       .xdr_u_short      = xdrmem_enc_ushort,
-       .xdr_u_int        = xdrmem_enc_uint,
-       .xdr_u_longlong_t = xdrmem_enc_ulonglong,
-       .xdr_opaque       = xdrmem_enc_bytes,
-       .xdr_string       = xdr_enc_string,
-       .xdr_array        = xdr_enc_array
-};
-
-static struct xdr_ops xdrmem_decode_ops = {
-       .xdr_control      = xdrmem_control,
-       .xdr_char         = xdrmem_dec_char,
-       .xdr_u_short      = xdrmem_dec_ushort,
-       .xdr_u_int        = xdrmem_dec_uint,
-       .xdr_u_longlong_t = xdrmem_dec_ulonglong,
-       .xdr_opaque       = xdrmem_dec_bytes,
-       .xdr_string       = xdr_dec_string,
-       .xdr_array        = xdr_dec_array
-};
-