The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/include/sys/zstd/zstd.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * BSD 3-Clause New License (https://spdx.org/licenses/BSD-3-Clause.html)
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions are met:
    6  *
    7  * 1. Redistributions of source code must retain the above copyright notice,
    8  * this list of conditions and the following disclaimer.
    9  *
   10  * 2. Redistributions in binary form must reproduce the above copyright notice,
   11  * this list of conditions and the following disclaimer in the documentation
   12  * and/or other materials provided with the distribution.
   13  *
   14  * 3. Neither the name of the copyright holder nor the names of its
   15  * contributors may be used to endorse or promote products derived from this
   16  * software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   28  * POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * Copyright (c) 2016-2018, Klara Inc.
   33  * Copyright (c) 2016-2018, Allan Jude
   34  * Copyright (c) 2018-2020, Sebastian Gottschall
   35  * Copyright (c) 2019-2020, Michael Niewöhner
   36  * Copyright (c) 2020, The FreeBSD Foundation [1]
   37  *
   38  * [1] Portions of this software were developed by Allan Jude
   39  *     under sponsorship from the FreeBSD Foundation.
   40  */
   41 
   42 #ifndef _ZFS_ZSTD_H
   43 #define _ZFS_ZSTD_H
   44 
   45 #ifdef  __cplusplus
   46 extern "C" {
   47 #endif
   48 
   49 /*
   50  * ZSTD block header
   51  * NOTE: all fields in this header are in big endian order.
   52  */
   53 typedef struct zfs_zstd_header {
   54         /* Compressed size of data */
   55         uint32_t c_len;
   56 
   57         /*
   58          * Version and compression level
   59          * We used to use a union to reference compression level
   60          * and version easily, but as it turns out, relying on the
   61          * ordering of bitfields is not remotely portable.
   62          * So now we have get/set functions in zfs_zstd.c for
   63          * manipulating this in just the right way forever.
   64          */
   65         uint32_t raw_version_level;
   66         char data[];
   67 } zfs_zstdhdr_t;
   68 
   69 /*
   70  * Simple struct to pass the data from raw_version_level around.
   71  */
   72 typedef struct zfs_zstd_meta {
   73         uint8_t level;
   74         uint32_t version;
   75 } zfs_zstdmeta_t;
   76 
   77 /*
   78  * kstat helper macros
   79  */
   80 #define ZSTDSTAT(stat)          (zstd_stats.stat.value.ui64)
   81 #define ZSTDSTAT_ZERO(stat)     \
   82         atomic_store_64(&zstd_stats.stat.value.ui64, 0)
   83 #define ZSTDSTAT_ADD(stat, val) \
   84         atomic_add_64(&zstd_stats.stat.value.ui64, (val))
   85 #define ZSTDSTAT_SUB(stat, val) \
   86         atomic_sub_64(&zstd_stats.stat.value.ui64, (val))
   87 #define ZSTDSTAT_BUMP(stat)     ZSTDSTAT_ADD(stat, 1)
   88 
   89 /* (de)init for user space / kernel emulation */
   90 int zstd_init(void);
   91 void zstd_fini(void);
   92 
   93 size_t zfs_zstd_compress(void *s_start, void *d_start, size_t s_len,
   94     size_t d_len, int level);
   95 size_t zfs_zstd_compress_wrap(void *s_start, void *d_start, size_t s_len,
   96     size_t d_len, int level);
   97 int zfs_zstd_get_level(void *s_start, size_t s_len, uint8_t *level);
   98 int zfs_zstd_decompress_level(void *s_start, void *d_start, size_t s_len,
   99     size_t d_len, uint8_t *level);
  100 int zfs_zstd_decompress(void *s_start, void *d_start, size_t s_len,
  101     size_t d_len, int n);
  102 void zfs_zstd_cache_reap_now(void);
  103 
  104 /*
  105  * So, the reason we have all these complicated set/get functions is that
  106  * originally, in the zstd "header" we wrote out to disk, we used a 32-bit
  107  * bitfield to store the "level" (8 bits) and "version" (24 bits).
  108  *
  109  * Unfortunately, bitfields make few promises about how they're arranged in
  110  * memory...
  111  *
  112  * By way of example, if we were using version 1.4.5 and level 3, it'd be
  113  * level = 0x03, version = 10405/0x0028A5, which gets broken into Vhigh = 0x00,
  114  * Vmid = 0x28, Vlow = 0xA5. We include these positions below to help follow
  115  * which data winds up where.
  116  *
  117  * As a consequence, we wound up with little endian platforms with a layout
  118  * like this in memory:
  119  *
  120  *      0       8      16      24      32
  121  *      +-------+-------+-------+-------+
  122  *      | Vlow  | Vmid  | Vhigh | level |
  123  *      +-------+-------+-------+-------+
  124  *        =A5     =28     =00     =03
  125  *
  126  * ...and then, after being run through BE_32(), serializing this out to
  127  * disk:
  128  *
  129  *      0       8      16      24      32
  130  *      +-------+-------+-------+-------+
  131  *      | level | Vhigh | Vmid  | Vlow  |
  132  *      +-------+-------+-------+-------+
  133  *        =03     =00     =28     =A5
  134  *
  135  * while on big-endian systems, since BE_32() is a noop there, both in
  136  * memory and on disk, we wind up with:
  137  *
  138  *      0       8      16      24      32
  139  *      +-------+-------+-------+-------+
  140  *      | Vhigh | Vmid  | Vlow  | level |
  141  *      +-------+-------+-------+-------+
  142  *        =00     =28     =A5     =03
  143  *
  144  * (Vhigh is always 0 until version exceeds 6.55.35. Vmid and Vlow are the
  145  * other two bytes of the "version" data.)
  146  *
  147  * So now we use the BF32_SET macros to get consistent behavior (the
  148  * ondisk LE encoding, since x86 currently rules the world) across
  149  * platforms, but the "get" behavior requires that we check each of the
  150  * bytes in the aforementioned former-bitfield for 0x00, and from there,
  151  * we can know which possible layout we're dealing with. (Only the two
  152  * that have been observed in the wild are illustrated above, but handlers
  153  * for all 4 positions of 0x00 are implemented.
  154  */
  155 
  156 static inline void
  157 zfs_get_hdrmeta(const zfs_zstdhdr_t *blob, zfs_zstdmeta_t *res)
  158 {
  159         uint32_t raw = blob->raw_version_level;
  160         uint8_t findme = 0xff;
  161         int shift;
  162         for (shift = 0; shift < 4; shift++) {
  163                 findme = BF32_GET(raw, 8*shift, 8);
  164                 if (findme == 0)
  165                         break;
  166         }
  167         switch (shift) {
  168         case 0:
  169                 res->level = BF32_GET(raw, 24, 8);
  170                 res->version = BSWAP_32(raw);
  171                 res->version = BF32_GET(res->version, 8, 24);
  172                 break;
  173         case 1:
  174                 res->level = BF32_GET(raw, 0, 8);
  175                 res->version = BSWAP_32(raw);
  176                 res->version = BF32_GET(res->version, 0, 24);
  177                 break;
  178         case 2:
  179                 res->level = BF32_GET(raw, 24, 8);
  180                 res->version = BF32_GET(raw, 0, 24);
  181                 break;
  182         case 3:
  183                 res->level = BF32_GET(raw, 0, 8);
  184                 res->version = BF32_GET(raw, 8, 24);
  185                 break;
  186         default:
  187                 res->level = 0;
  188                 res->version = 0;
  189                 break;
  190         }
  191 }
  192 
  193 static inline uint8_t
  194 zfs_get_hdrlevel(const zfs_zstdhdr_t *blob)
  195 {
  196         uint8_t level = 0;
  197         zfs_zstdmeta_t res;
  198         zfs_get_hdrmeta(blob, &res);
  199         level = res.level;
  200         return (level);
  201 }
  202 
  203 static inline uint32_t
  204 zfs_get_hdrversion(const zfs_zstdhdr_t *blob)
  205 {
  206         uint32_t version = 0;
  207         zfs_zstdmeta_t res;
  208         zfs_get_hdrmeta(blob, &res);
  209         version = res.version;
  210         return (version);
  211 
  212 }
  213 
  214 static inline void
  215 zfs_set_hdrversion(zfs_zstdhdr_t *blob, uint32_t version)
  216 {
  217         /* cppcheck-suppress syntaxError */
  218         BF32_SET(blob->raw_version_level, 0, 24, version);
  219 }
  220 
  221 static inline void
  222 zfs_set_hdrlevel(zfs_zstdhdr_t *blob, uint8_t level)
  223 {
  224         /* cppcheck-suppress syntaxError */
  225         BF32_SET(blob->raw_version_level, 24, 8, level);
  226 }
  227 
  228 
  229 #ifdef  __cplusplus
  230 }
  231 #endif
  232 
  233 #endif /* _ZFS_ZSTD_H */

Cache object: d2e593430b362b4d63e4734cff926a8e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.