1267565Sdelphij/*
2267565Sdelphij * CDDL HEADER START
3267565Sdelphij *
4267565Sdelphij * This file and its contents are supplied under the terms of the
5267565Sdelphij * Common Development and Distribution License ("CDDL"), version 1.0.
6267565Sdelphij * You may only use this file in accordance with the terms of version
7267565Sdelphij * 1.0 of the CDDL.
8267565Sdelphij *
9267565Sdelphij * A full copy of the text of the CDDL should have accompanied this
10267565Sdelphij * source.  A copy of the CDDL is also available via the Internet at
11267565Sdelphij * http://www.illumos.org/license/CDDL.
12267565Sdelphij *
13267565Sdelphij * CDDL HEADER END
14267565Sdelphij */
15267565Sdelphij
16267565Sdelphij/*
17267565Sdelphij * Copyright (c) 2013 by Delphix. All rights reserved.
18267565Sdelphij */
19267565Sdelphij
20267565Sdelphij/*
21267565Sdelphij * Embedded-data Block Pointers
22267565Sdelphij *
23267565Sdelphij * Normally, block pointers point (via their DVAs) to a block which holds data.
24267565Sdelphij * If the data that we need to store is very small, this is an inefficient
25267565Sdelphij * use of space, because a block must be at minimum 1 sector (typically 512
26267565Sdelphij * bytes or 4KB).  Additionally, reading these small blocks tends to generate
27267565Sdelphij * more random reads.
28267565Sdelphij *
29267565Sdelphij * Embedded-data Block Pointers allow small pieces of data (the "payload",
30267565Sdelphij * up to 112 bytes) to be stored in the block pointer itself, instead of
31267565Sdelphij * being pointed to.  The "Pointer" part of this name is a bit of a
32267565Sdelphij * misnomer, as nothing is pointed to.
33267565Sdelphij *
34267565Sdelphij * BP_EMBEDDED_TYPE_DATA block pointers allow highly-compressible data to
35267565Sdelphij * be embedded in the block pointer.  The logic for this is handled in
36267565Sdelphij * the SPA, by the zio pipeline.  Therefore most code outside the zio
37267565Sdelphij * pipeline doesn't need special-cases to handle these block pointers.
38267565Sdelphij *
39267565Sdelphij * See spa.h for details on the exact layout of embedded block pointers.
40267565Sdelphij */
41267565Sdelphij
42267565Sdelphij/*
43267565Sdelphij * buf must be at least BPE_GET_PSIZE(bp) bytes long (which will never be
44267565Sdelphij * more than BPE_PAYLOAD_SIZE bytes).
45267565Sdelphij */
46267565Sdelphijvoid
47267565Sdelphijdecode_embedded_bp_compressed(const blkptr_t *bp, void *buf)
48267565Sdelphij{
49267565Sdelphij	int psize;
50267565Sdelphij	uint8_t *buf8 = buf;
51267565Sdelphij	uint64_t w = 0;
52267565Sdelphij	const uint64_t *bp64 = (const uint64_t *)bp;
53267565Sdelphij
54267565Sdelphij	ASSERT(BP_IS_EMBEDDED(bp));
55267565Sdelphij
56267565Sdelphij	psize = BPE_GET_PSIZE(bp);
57267565Sdelphij
58267565Sdelphij	/*
59267565Sdelphij	 * Decode the words of the block pointer into the byte array.
60267565Sdelphij	 * Low bits of first word are the first byte (little endian).
61267565Sdelphij	 */
62267565Sdelphij	for (int i = 0; i < psize; i++) {
63267565Sdelphij		if (i % sizeof (w) == 0) {
64267565Sdelphij			/* beginning of a word */
65267565Sdelphij			ASSERT3P(bp64, <, bp + 1);
66267565Sdelphij			w = *bp64;
67267565Sdelphij			bp64++;
68267565Sdelphij			if (!BPE_IS_PAYLOADWORD(bp, bp64))
69267565Sdelphij				bp64++;
70267565Sdelphij		}
71267565Sdelphij		buf8[i] = BF64_GET(w, (i % sizeof (w)) * NBBY, NBBY);
72267565Sdelphij	}
73267565Sdelphij}
74