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/module/zfs/blkptr.c

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  * CDDL HEADER START
    3  *
    4  * This file and its contents are supplied under the terms of the
    5  * Common Development and Distribution License ("CDDL"), version 1.0.
    6  * You may only use this file in accordance with the terms of version
    7  * 1.0 of the CDDL.
    8  *
    9  * A full copy of the text of the CDDL should have accompanied this
   10  * source.  A copy of the CDDL is also available via the Internet at
   11  * http://www.illumos.org/license/CDDL.
   12  *
   13  * CDDL HEADER END
   14  */
   15 
   16 /*
   17  * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
   18  */
   19 
   20 #include <sys/blkptr.h>
   21 #include <sys/zfs_context.h>
   22 #include <sys/zio.h>
   23 #include <sys/zio_compress.h>
   24 
   25 /*
   26  * Embedded-data Block Pointers
   27  *
   28  * Normally, block pointers point (via their DVAs) to a block which holds data.
   29  * If the data that we need to store is very small, this is an inefficient
   30  * use of space, because a block must be at minimum 1 sector (typically 512
   31  * bytes or 4KB).  Additionally, reading these small blocks tends to generate
   32  * more random reads.
   33  *
   34  * Embedded-data Block Pointers allow small pieces of data (the "payload",
   35  * up to 112 bytes) to be stored in the block pointer itself, instead of
   36  * being pointed to.  The "Pointer" part of this name is a bit of a
   37  * misnomer, as nothing is pointed to.
   38  *
   39  * BP_EMBEDDED_TYPE_DATA block pointers allow highly-compressible data to
   40  * be embedded in the block pointer.  The logic for this is handled in
   41  * the SPA, by the zio pipeline.  Therefore most code outside the zio
   42  * pipeline doesn't need special-cases to handle these block pointers.
   43  *
   44  * See spa.h for details on the exact layout of embedded block pointers.
   45  */
   46 
   47 void
   48 encode_embedded_bp_compressed(blkptr_t *bp, void *data,
   49     enum zio_compress comp, int uncompressed_size, int compressed_size)
   50 {
   51         uint64_t *bp64 = (uint64_t *)bp;
   52         uint64_t w = 0;
   53         uint8_t *data8 = data;
   54 
   55         ASSERT3U(compressed_size, <=, BPE_PAYLOAD_SIZE);
   56         ASSERT(uncompressed_size == compressed_size ||
   57             comp != ZIO_COMPRESS_OFF);
   58         ASSERT3U(comp, >=, ZIO_COMPRESS_OFF);
   59         ASSERT3U(comp, <, ZIO_COMPRESS_FUNCTIONS);
   60 
   61         memset(bp, 0, sizeof (*bp));
   62         BP_SET_EMBEDDED(bp, B_TRUE);
   63         BP_SET_COMPRESS(bp, comp);
   64         BP_SET_BYTEORDER(bp, ZFS_HOST_BYTEORDER);
   65         BPE_SET_LSIZE(bp, uncompressed_size);
   66         BPE_SET_PSIZE(bp, compressed_size);
   67 
   68         /*
   69          * Encode the byte array into the words of the block pointer.
   70          * First byte goes into low bits of first word (little endian).
   71          */
   72         for (int i = 0; i < compressed_size; i++) {
   73                 BF64_SET(w, (i % sizeof (w)) * NBBY, NBBY, data8[i]);
   74                 if (i % sizeof (w) == sizeof (w) - 1) {
   75                         /* we've reached the end of a word */
   76                         ASSERT3P(bp64, <, bp + 1);
   77                         *bp64 = w;
   78                         bp64++;
   79                         if (!BPE_IS_PAYLOADWORD(bp, bp64))
   80                                 bp64++;
   81                         w = 0;
   82                 }
   83         }
   84         /* write last partial word */
   85         if (bp64 < (uint64_t *)(bp + 1))
   86                 *bp64 = w;
   87 }
   88 
   89 /*
   90  * buf must be at least BPE_GET_PSIZE(bp) bytes long (which will never be
   91  * more than BPE_PAYLOAD_SIZE bytes).
   92  */
   93 void
   94 decode_embedded_bp_compressed(const blkptr_t *bp, void *buf)
   95 {
   96         int psize;
   97         uint8_t *buf8 = buf;
   98         uint64_t w = 0;
   99         const uint64_t *bp64 = (const uint64_t *)bp;
  100 
  101         ASSERT(BP_IS_EMBEDDED(bp));
  102 
  103         psize = BPE_GET_PSIZE(bp);
  104 
  105         /*
  106          * Decode the words of the block pointer into the byte array.
  107          * Low bits of first word are the first byte (little endian).
  108          */
  109         for (int i = 0; i < psize; i++) {
  110                 if (i % sizeof (w) == 0) {
  111                         /* beginning of a word */
  112                         ASSERT3P(bp64, <, bp + 1);
  113                         w = *bp64;
  114                         bp64++;
  115                         if (!BPE_IS_PAYLOADWORD(bp, bp64))
  116                                 bp64++;
  117                 }
  118                 buf8[i] = BF64_GET(w, (i % sizeof (w)) * NBBY, NBBY);
  119         }
  120 }
  121 
  122 /*
  123  * Fill in the buffer with the (decompressed) payload of the embedded
  124  * blkptr_t.  Takes into account compression and byteorder (the payload is
  125  * treated as a stream of bytes).
  126  * Return 0 on success, or ENOSPC if it won't fit in the buffer.
  127  */
  128 int
  129 decode_embedded_bp(const blkptr_t *bp, void *buf, int buflen)
  130 {
  131         int lsize, psize;
  132 
  133         ASSERT(BP_IS_EMBEDDED(bp));
  134 
  135         lsize = BPE_GET_LSIZE(bp);
  136         psize = BPE_GET_PSIZE(bp);
  137 
  138         if (lsize > buflen)
  139                 return (SET_ERROR(ENOSPC));
  140         ASSERT3U(lsize, ==, buflen);
  141 
  142         if (BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF) {
  143                 uint8_t dstbuf[BPE_PAYLOAD_SIZE];
  144                 decode_embedded_bp_compressed(bp, dstbuf);
  145                 VERIFY0(zio_decompress_data_buf(BP_GET_COMPRESS(bp),
  146                     dstbuf, buf, psize, buflen, NULL));
  147         } else {
  148                 ASSERT3U(lsize, ==, psize);
  149                 decode_embedded_bp_compressed(bp, buf);
  150         }
  151 
  152         return (0);
  153 }

Cache object: d94340d323e6d18a3f09b816f3ec8427


[ 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.