All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/5] zfs com.delphix:embedded_data feature support
@ 2015-04-16  5:23 Toomas Soome
  2015-04-19 15:37 ` Andrei Borzenkov
  2015-05-03 15:49 ` Andrei Borzenkov
  0 siblings, 2 replies; 4+ messages in thread
From: Toomas Soome @ 2015-04-16  5:23 UTC (permalink / raw)
  To: The development of GNU GRUB


---
 grub-core/fs/zfs/zfs.c |   84 ++++++++++++++++++++++++++++++++++++++++--------
 include/grub/zfs/spa.h |   27 +++++++++++++---
 2 files changed, 93 insertions(+), 18 deletions(-)

diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index a731c3d..da44131 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -282,6 +282,7 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key
 static const char *spa_feature_names[] = {
   "org.illumos:lz4_compress",
   "com.delphix:hole_birth",
+  "com.delphix:embedded_data",
   NULL
 };
 
@@ -1803,6 +1804,39 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf,
 }
 
 /*
+ * buf must be at least BPE_GET_PSIZE(bp) bytes long (which will never be
+ * more than BPE_PAYLOAD_SIZE bytes).
+ */
+static grub_err_t
+decode_embedded_bp_compressed(const blkptr_t *bp, void *buf)
+{
+  grub_size_t psize, i;
+  grub_uint8_t *buf8 = buf;
+  grub_uint64_t w = 0;
+  const grub_uint64_t *bp64 = (const grub_uint64_t *)bp;
+
+  psize = BPE_GET_PSIZE(bp);
+
+  /*
+   * Decode the words of the block pointer into the byte array.
+   * Low bits of first word are the first byte (little endian).
+   */
+  for (i = 0; i < psize; i++)
+    {
+      if (i % sizeof (w) == 0)
+       {
+         /* beginning of a word */
+         w = *bp64;
+         bp64++;
+         if (!BPE_IS_PAYLOADWORD(bp, bp64))
+         bp64++;
+       }
+      buf8[i] = BF64_GET(w, (i % sizeof (w)) * 8, 8);
+    }
+  return GRUB_ERR_NONE;
+}
+
+/*
  * Read in a block of data, verify its checksum, decompress if needed,
  * and put the uncompressed data in buf.
  */
@@ -1820,12 +1854,26 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf,
   *buf = NULL;
 
   checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
-  comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff;
+  comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7f;
   encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3);
-  lsize = (BP_IS_HOLE(bp) ? 0 :
-	   (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
-	    << SPA_MINBLOCKSHIFT));
-  psize = get_psize (bp, endian);
+  if (BP_IS_EMBEDDED(bp))
+    {
+      if (BPE_GET_ETYPE(bp) != BP_EMBEDDED_TYPE_DATA)
+	return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+			   "unsupported embedded BP (type=%u)\n",
+			   BPE_GET_ETYPE(bp));
+      lsize = BPE_GET_LSIZE(bp);
+      psize = BF64_GET_SB(grub_zfs_to_cpu64 ((bp)->blk_prop, endian), 25, 7, 0, 1);
+    }
+  else
+    {
+      lsize = (BP_IS_HOLE(bp) ? 0 :
+	       (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
+	        << SPA_MINBLOCKSHIFT));
+      psize = get_psize (bp, endian);
+    }
+  grub_dprintf("zfs", "zio_read: E %d: size %" PRIdGRUB_SSIZE "/%"
+	       PRIdGRUB_SSIZE "\n", (int)BP_IS_EMBEDDED(bp), lsize, psize);
 
   if (size)
     *size = lsize;
@@ -1849,23 +1897,31 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf,
     compbuf = *buf = grub_malloc (lsize);
 
   grub_dprintf ("zfs", "endian = %d\n", endian);
-  err = zio_read_data (bp, endian, compbuf, data);
+  if (BP_IS_EMBEDDED(bp))
+    err = decode_embedded_bp_compressed(bp, compbuf);
+  else
+    {
+      err = zio_read_data (bp, endian, compbuf, data);
+      grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize);
+    }
   if (err)
     {
       grub_free (compbuf);
       *buf = NULL;
       return err;
     }
-  grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize);
 
-  err = zio_checksum_verify (zc, checksum, endian,
-			     compbuf, psize);
-  if (err)
+  if (!BP_IS_EMBEDDED(bp))
     {
-      grub_dprintf ("zfs", "incorrect checksum\n");
-      grub_free (compbuf);
-      *buf = NULL;
-      return err;
+      err = zio_checksum_verify (zc, checksum, endian,
+			         compbuf, psize);
+      if (err)
+        {
+          grub_dprintf ("zfs", "incorrect checksum\n");
+          grub_free (compbuf);
+          *buf = NULL;
+          return err;
+        }
     }
 
   if (encrypted)
diff --git a/include/grub/zfs/spa.h b/include/grub/zfs/spa.h
index df43b6b..5d89250 100644
--- a/include/grub/zfs/spa.h
+++ b/include/grub/zfs/spa.h
@@ -126,7 +126,7 @@ typedef struct zio_cksum {
  *	+-------+-------+-------+-------+-------+-------+-------+-------+
  * 5	|G|			 offset3				|
  *	+-------+-------+-------+-------+-------+-------+-------+-------+
- * 6	|BDX|lvl| type	| cksum | comp	|     PSIZE	|     LSIZE	|
+ * 6	|BDX|lvl| type	| cksum |E| comp|    PSIZE	|     LSIZE	|
  *	+-------+-------+-------+-------+-------+-------+-------+-------+
  * 7	|			padding					|
  *	+-------+-------+-------+-------+-------+-------+-------+-------+
@@ -160,7 +160,8 @@ typedef struct zio_cksum {
  * G		gang block indicator
  * B		byteorder (endianness)
  * D		dedup
- * X		unused
+ * X		encryption
+ * E		blkptr_t contains embedded data
  * lvl		level of indirection
  * type		DMU object type
  * phys birth	txg of block allocation; zero if same as logical birth txg
@@ -203,8 +204,8 @@ typedef struct blkptr {
 #define	BP_SET_LSIZE(bp, x)	\
 	BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x)
 
-#define	BP_GET_COMPRESS(bp)		BF64_GET((bp)->blk_prop, 32, 8)
-#define	BP_SET_COMPRESS(bp, x)		BF64_SET((bp)->blk_prop, 32, 8, x)
+#define	BP_GET_COMPRESS(bp)		BF64_GET((bp)->blk_prop, 32, 7)
+#define	BP_SET_COMPRESS(bp, x)		BF64_SET((bp)->blk_prop, 32, 7, x)
 
 #define	BP_GET_CHECKSUM(bp)		BF64_GET((bp)->blk_prop, 40, 8)
 #define	BP_SET_CHECKSUM(bp, x)		BF64_SET((bp)->blk_prop, 40, 8, x)
@@ -215,6 +216,8 @@ typedef struct blkptr {
 #define	BP_GET_LEVEL(bp)		BF64_GET((bp)->blk_prop, 56, 5)
 #define	BP_SET_LEVEL(bp, x)		BF64_SET((bp)->blk_prop, 56, 5, x)
 
+#define	BP_IS_EMBEDDED(bp)		BF64_GET((bp)->blk_prop, 39, 1)
+
 #define	BP_GET_PROP_BIT_61(bp)		BF64_GET((bp)->blk_prop, 61, 1)
 #define	BP_SET_PROP_BIT_61(bp, x)	BF64_SET((bp)->blk_prop, 61, 1, x)
 
@@ -277,6 +280,22 @@ typedef struct blkptr {
 	(zcp)->zc_word[3] = w3;			\
 }
 
+#define	BPE_GET_ETYPE(bp)	BP_GET_CHECKSUM(bp)
+#define	BPE_GET_LSIZE(bp)	\
+	BF64_GET_SB((bp)->blk_prop, 0, 25, 0, 1)
+#define	BPE_GET_PSIZE(bp)	\
+	BF64_GET_SB((bp)->blk_prop, 25, 7, 0, 1)
+
+typedef enum bp_embedded_type {
+  BP_EMBEDDED_TYPE_DATA,
+  NUM_BP_EMBEDDED_TYPES
+} bp_embedded_type_t;
+
+#define	BPE_NUM_WORDS	14
+#define	BPE_PAYLOAD_SIZE	(BPE_NUM_WORDS * sizeof(grub_uint64_t))
+#define	BPE_IS_PAYLOADWORD(bp, wp)	\
+	((wp) != &(bp)->blk_prop && (wp) != &(bp)->blk_birth)
+
 #define	BP_IDENTITY(bp)		(&(bp)->blk_dva[0])
 #define	BP_IS_GANG(bp)		DVA_GET_GANG(BP_IDENTITY(bp))
 #define	DVA_IS_EMPTY(dva)	((dva)->dva_word[0] == 0ULL && \
-- 
1.7.9.2



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-05-03 15:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-16  5:23 [PATCH 4/5] zfs com.delphix:embedded_data feature support Toomas Soome
2015-04-19 15:37 ` Andrei Borzenkov
2015-04-19 17:43   ` Toomas Soome
2015-05-03 15:49 ` Andrei Borzenkov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.