source: build-files/ports-overlay/sysutils/grub2/files/patch-grub-2.00-zfs-feature-flag-support @ ff9dd98

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3
Last change on this file since ff9dd98 was ff9dd98, checked in by Kris Moore <kris@…>, 14 months ago

Update the ZFS feature flag support patch in grub2 from here:

http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/sys-boot/grub/files/grub-2.00-zfs-feature-flag-support-r1.patch

  • Property mode set to 100644
File size: 27.8 KB
Line 
1From
2
3        http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/sys-boot/grub/files/grub-2.00-zfs-feature-flag-support-r1.patch
4
5ZFS Feature Flag Support
6
7This is a monolithic version of the following commits:
8
9https://github.com/maxximino/grub2/commit/31a32560fd7948ae5ff5c63105d7c068de7890c8
10https://github.com/maxximino/grub2/commit/595d76e8ca0690a963f5533689de8db54ef07e75
11https://github.com/maxximino/grub2/commit/58344034e40218b20500fa2936eb4d7d019e1e88
12https://github.com/maxximino/grub2/commit/f98cb078abab2c14bb0766b5a0ceb055683dab81
13https://github.com/maxximino/grub2/commit/f12806f43a969a654dee7bb89b2e8fd5c42f0e2e
14
15A change was made to account for d8a0feb6 from upstream. This change prevents a
16compile time failure that is caused by a change in the callback interface used
17by mzap_interate(). Modifications to nvlist_find_value() were reverted to
18resolve Gentoo bug #462740. This eliminated the need for the new nvpair_type()
19and nvpair_value() functions. They have been removed to silence a compiler
20warning and reduce the size of the patch. Further adjustments were made to
21silence the following warnings:
22
23/var/tmp/portage/sys-boot/grub-2.00-r2/work/grub-2.00/grub-core/fs/zfs/zfs_lz4.c:77:5:
24warning: "__STDC_VERSION__" is not defined [-Wundef]
25/var/tmp/portage/sys-boot/grub-2.00-r2/work/grub-2.00/grub-core/fs/zfs/zfs.c:4079:3:
26warning: passing argument 4 of 'mzap_iterate' from incompatible pointer type
27[enabled by default]
28
29The initial feature flag support patches were written by Delphix while the LZ4
30support was written by Saso Kiselkov. The work porting this to GRUB2 was done
31by Massimo Maggi, while the adaption to Gentoo's GRUB2 package was done by
32Richard Yao.
33
34diff --git a/Makefile.util.def b/Makefile.util.def
35index b80187c..1bf3038 100644
36--- Makefile.util.def
37+++ Makefile.util.def
38@@ -95,6 +95,7 @@ library = {
39   common = grub-core/fs/zfs/zfs.c;
40   common = grub-core/fs/zfs/zfsinfo.c;
41   common = grub-core/fs/zfs/zfs_lzjb.c;
42+  common = grub-core/fs/zfs/zfs_lz4.c;
43   common = grub-core/fs/zfs/zfs_sha256.c;
44   common = grub-core/fs/zfs/zfs_fletcher.c;
45   common = grub-core/lib/envblk.c;
46diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
47index 39e77a4..1550b90 100644
48--- grub-core/Makefile.core.def
49+++ grub-core/Makefile.core.def
50@@ -1186,6 +1186,7 @@ module = {
51   name = zfs;
52   common = fs/zfs/zfs.c;
53   common = fs/zfs/zfs_lzjb.c;
54+  common = fs/zfs/zfs_lz4.c;
55   common = fs/zfs/zfs_sha256.c;
56   common = fs/zfs/zfs_fletcher.c;
57 };
58diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
59index ba0554a..811e3df 100644
60--- grub-core/fs/zfs/zfs.c
61+++ grub-core/fs/zfs/zfs.c
62@@ -2,6 +2,7 @@
63  *  GRUB  --  GRand Unified Bootloader
64  *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011  Free Software Foundation, Inc.
65  *  Copyright 2010  Sun Microsystems, Inc.
66+ *  Copyright (c) 2012 by Delphix. All rights reserved.
67  *
68  *  GRUB is free software; you can redistribute it and/or modify
69  *  it under the terms of the GNU General Public License as published by
70@@ -153,11 +154,13 @@ ZAP_LEAF_ENTRY(zap_leaf_phys_t *l, int bs, int idx)
71 
72 
73 /*
74- * Decompression Entry - lzjb
75+ * Decompression Entry - lzjb & lz4
76  */
77 
78 extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t);
79 
80+extern grub_err_t lz4_decompress (void *, void *, grub_size_t, grub_size_t);
81+
82 typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start,
83                                      grub_size_t s_len, grub_size_t d_len);
84 typedef struct decomp_entry
85@@ -263,6 +266,19 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key
86                                                  grub_size_t keysize,
87                                                  grub_uint64_t salt,
88                                                  grub_uint64_t algo) = NULL;
89+/*
90+ * List of pool features that the grub implementation of ZFS supports for
91+ * read. Note that features that are only required for write do not need
92+ * to be listed here since grub opens pools in read-only mode.
93+ */
94+static const char *spa_feature_names[] = {
95+       "org.illumos:lz4_compress",NULL
96+};
97+
98+static int NESTED_FUNC_ATTR
99+check_feature(const char *name, grub_uint64_t val);
100+static int
101+check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data );
102 
103 static grub_err_t
104 zlib_decompress (void *s, void *d,
105@@ -322,6 +338,7 @@ static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = {
106   {"gzip-8", zlib_decompress},  /* ZIO_COMPRESS_GZIP8 */
107   {"gzip-9", zlib_decompress},  /* ZIO_COMPRESS_GZIP9 */
108   {"zle", zle_decompress},      /* ZIO_COMPRESS_ZLE   */
109+  {"lz4", lz4_decompress},      /* ZIO_COMPRESS_LZ4   */
110 };
111 
112 static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
113@@ -482,15 +499,11 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset,
114 
115   if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_LITTLE_ENDIAN)
116       == UBERBLOCK_MAGIC
117-      && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) > 0
118-      && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN)
119-      <= SPA_VERSION)
120-    endian = GRUB_ZFS_LITTLE_ENDIAN;
121+      && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN)))
122+     endian = GRUB_ZFS_LITTLE_ENDIAN;
123 
124   if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_BIG_ENDIAN) == UBERBLOCK_MAGIC
125-      && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) > 0
126-      && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN)
127-      <= SPA_VERSION)
128+      && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN)))
129     endian = GRUB_ZFS_BIG_ENDIAN;
130 
131   if (endian == GRUB_ZFS_UNKNOWN_ENDIAN)
132@@ -764,6 +777,99 @@ fill_vdev_info (struct grub_zfs_data *data,
133 }
134 
135 /*
136+ * For a given XDR packed nvlist, verify the first 4 bytes and move on.
137+ *
138+ * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
139+ *
140+ *      encoding method/host endian     (4 bytes)
141+ *      nvl_version                     (4 bytes)
142+ *      nvl_nvflag                      (4 bytes)
143+ *     encoded nvpairs:
144+ *             encoded size of the nvpair      (4 bytes)
145+ *             decoded size of the nvpair      (4 bytes)
146+ *             name string size                (4 bytes)
147+ *             name string data                (sizeof(NV_ALIGN4(string))
148+ *             data type                       (4 bytes)
149+ *             # of elements in the nvpair     (4 bytes)
150+ *             data
151+ *      2 zero's for the last nvpair
152+ *             (end of the entire list)        (8 bytes)
153+ *
154+ */
155+
156+/*
157+ * The nvlist_next_nvpair() function returns a handle to the next nvpair in the
158+ * list following nvpair. If nvpair is NULL, the first pair is returned. If
159+ * nvpair is the last pair in the nvlist, NULL is returned.
160+ */
161+static const char *
162+nvlist_next_nvpair(const char *nvl, const char *nvpair)
163+{
164+       const char *nvp;
165+       int encode_size;
166+       int name_len;
167+       if (nvl == NULL)
168+               return (NULL);
169+
170+       if (nvpair == NULL) {
171+               /* skip over header, nvl_version and nvl_nvflag */
172+               nvpair = nvl + 4 * 3;
173+       } else {
174+               /* skip to the next nvpair */
175+               encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
176+               nvpair += encode_size;
177+       }
178+       /* 8 bytes of 0 marks the end of the list */
179+       if (*(grub_uint64_t*)nvpair == 0)
180+               return (NULL);
181+       /*consistency checks*/
182+       if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE)
183+       {
184+         grub_dprintf ("zfs", "nvlist overflow\n");
185+         grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
186+         return (NULL);
187+       }
188+       encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
189+
190+       nvp = nvpair + 4*2;
191+       name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
192+       nvp += 4;
193+
194+       nvp = nvp + ((name_len + 3) & ~3); // align
195+       if (nvp + 4 >= nvl + VDEV_PHYS_SIZE                       
196+           || encode_size < 0
197+           || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE)       
198+       {
199+         grub_dprintf ("zfs", "nvlist overflow\n");
200+         grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
201+         return (NULL);
202+       }
203+        /* end consistency checks */
204+
205+       return (nvpair);
206+}
207+/*
208+ * This function returns 0 on success and 1 on failure. On success, a string
209+ * containing the name of nvpair is saved in buf.
210+ */
211+static int
212+nvpair_name(const char *nvp, char **buf, int* buflen)
213+{
214+       int len;
215+
216+       /* skip over encode/decode size */
217+       nvp += 4 * 2;
218+
219+       len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
220+       nvp=nvp+4;
221+       
222+       *buf=(char*)nvp;
223+       *buflen=len;
224+
225+       return (0);
226+}
227+
228+/*
229  * Check the disk label information and retrieve needed vdev name-value pairs.
230  *
231  */
232@@ -773,7 +879,7 @@ check_pool_label (struct grub_zfs_data *data,
233                  int *inserted)
234 {
235   grub_uint64_t pool_state, txg = 0;
236-  char *nvlist;
237+  char *nvlist,*features;
238 #if 0
239   char *nv;
240 #endif
241@@ -837,13 +943,13 @@ check_pool_label (struct grub_zfs_data *data,
242     }
243   grub_dprintf ("zfs", "check 8 passed\n");
244 
245-  if (version > SPA_VERSION)
246+  if (!SPA_VERSION_IS_SUPPORTED(version))
247     {
248       grub_free (nvlist);
249       return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
250                         "too new version %llu > %llu",
251                         (unsigned long long) version,
252-                        (unsigned long long) SPA_VERSION);
253+                        (unsigned long long) SPA_VERSION_BEFORE_FEATURES);
254     }
255   grub_dprintf ("zfs", "check 9 passed\n");
256 
257@@ -893,7 +999,30 @@ check_pool_label (struct grub_zfs_data *data,
258     grub_free (nv);
259   }
260   grub_dprintf ("zfs", "check 10 passed\n");
261-
262+  if ((features=grub_zfs_nvlist_lookup_nvlist(nvlist, ZPOOL_CONFIG_FEATURES_FOR_READ)))
263+  {
264+    const char *nvp=NULL;
265+    char *name = grub_zalloc(51);
266+    char *nameptr;
267+    int namelen;
268+    while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL)
269+    {
270+      nvpair_name(nvp, &nameptr,&namelen);
271+      if(namelen > 50){namelen=50;}
272+      grub_strncpy(name,nameptr,namelen);
273+      name[namelen]=0;
274+      grub_dprintf("zfs","namelen=%u str=%s\n",namelen,name);
275+      if (check_feature(name,1) != 0)
276+      {
277+       grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name);
278+       err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name);
279+       grub_free(name);
280+       return err;
281+      }
282+    }
283+    grub_free(name);
284+  }
285+  grub_dprintf ("zfs", "check 12 passed (feature flags)\n");
286   grub_free (nvlist);
287 
288   return GRUB_ERR_NONE;
289@@ -3034,27 +3163,6 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
290   return err;
291 }
292 
293-/*
294- * For a given XDR packed nvlist, verify the first 4 bytes and move on.
295- *
296- * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
297- *
298- *      encoding method/host endian     (4 bytes)
299- *      nvl_version                     (4 bytes)
300- *      nvl_nvflag                      (4 bytes)
301- *     encoded nvpairs:
302- *             encoded size of the nvpair      (4 bytes)
303- *             decoded size of the nvpair      (4 bytes)
304- *             name string size                (4 bytes)
305- *             name string data                (sizeof(NV_ALIGN4(string))
306- *             data type                       (4 bytes)
307- *             # of elements in the nvpair     (4 bytes)
308- *             data
309- *      2 zero's for the last nvpair
310- *             (end of the entire list)        (8 bytes)
311- *
312- */
313-
314 static int
315 nvlist_find_value (const char *nvlist_in, const char *name,
316                   int valtype, char **val,
317@@ -3386,6 +3494,10 @@ zfs_mount (grub_device_t dev)
318       return NULL;
319     }
320 
321+    if (ub->ub_version >= SPA_VERSION_FEATURES &&
322+       check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian, data) != 0)
323+         return NULL;
324+       
325   /* Got the MOS. Save it at the memory addr MOS. */
326   grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode,
327                DNODE_SIZE);
328@@ -3910,6 +4022,64 @@ grub_zfs_dir (grub_device_t device, const char *path,
329   return grub_errno;
330 }
331 
332+static int NESTED_FUNC_ATTR
333+check_feature(const char *name, grub_uint64_t val)
334+{
335+  int i;
336+  if(val ==0) return 0;
337+  if(*name==0) return 0;
338+  for (i = 0; spa_feature_names[i] != NULL; i++)
339+  {
340+    if (grub_strcmp(name, spa_feature_names[i]) == 0)
341+        return 0;
342+  }
343+  grub_printf("missing feature for read '%s'\n",name);
344+  return 1;
345+}
346+
347+/*
348+ * Checks whether the MOS features that are active are supported by this
349+ * (GRUB's) implementation of ZFS.
350+ *
351+ * Return:
352+ *     0: Success.
353+ *     errnum: Failure.
354+ */
355+                 
356+static int
357+check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data )
358+{
359+  grub_uint64_t objnum;
360+  grub_uint8_t errnum = 0;
361+  dnode_end_t dn,mosmdn;
362+  mzap_phys_t* mzp;
363+  grub_zfs_endian_t endianzap;
364+  int size;
365+  grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t));
366+  mosmdn.endian=endian;
367+  if ((errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT,
368+         DMU_OT_OBJECT_DIRECTORY, &dn,data)) != 0)
369+      return (errnum);
370+
371+  /*
372+   * Find the object number for 'features_for_read' and retrieve its
373+   * corresponding dnode. Note that we don't check features_for_write
374+   * because GRUB is not opening the pool for write.
375+   */
376+  if ((errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0)) != 0)
377+      return (errnum);
378
379+  if ((errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data)) != 0)
380+      return (errnum);
381+
382+  if ((errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data)) != 0)
383+      return (errnum);
384+
385+  size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT;
386+  return (mzap_iterate(mzp,endianzap, size, check_feature));
387+}
388+
389+
390 #ifdef GRUB_UTIL
391 static grub_err_t
392 grub_zfs_embed (grub_device_t device __attribute__ ((unused)),
393diff --git a/grub-core/fs/zfs/zfs_lz4.c b/grub-core/fs/zfs/zfs_lz4.c
394new file mode 100644
395index 0000000..ff85a77
396--- /dev/null
397+++ grub-core/fs/zfs/zfs_lz4.c
398@@ -0,0 +1,321 @@
399+/*
400+ * LZ4 - Fast LZ compression algorithm
401+ * Header File
402+ * Copyright (C) 2011-2013, Yann Collet.
403+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
404+ *
405+ * Redistribution and use in source and binary forms, with or without
406+ * modification, are permitted provided that the following conditions are
407+ * met:
408+ *
409+ *     * Redistributions of source code must retain the above copyright
410+ * notice, this list of conditions and the following disclaimer.
411+ *     * Redistributions in binary form must reproduce the above
412+ * copyright notice, this list of conditions and the following disclaimer
413+ * in the documentation and/or other materials provided with the
414+ * distribution.
415+ *
416+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
417+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
418+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
419+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
420+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
421+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
422+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
423+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
424+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
425+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
426+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
427+ *
428+ * You can contact the author at :
429+ * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
430+ * - LZ4 source repository : http://code.google.com/p/lz4/
431+ */
432+
433+#include <grub/err.h>
434+#include <grub/mm.h>
435+#include <grub/misc.h>
436+#include <grub/types.h>
437+
438+static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
439+                                           int isize, int maxOutputSize);
440+
441+/*
442+ * CPU Feature Detection
443+ */
444+
445+/* 32 or 64 bits ? */
446+#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || \
447+       defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || \
448+       defined(__LP64__) || defined(_LP64))
449+#define        LZ4_ARCH64      1
450+#else
451+#define        LZ4_ARCH64      0
452+#endif
453+
454+/*
455+ * Little Endian or Big Endian?
456+ * Note: overwrite the below #define if you know your architecture endianess.
457+ */
458+#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || \
459+       defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || \
460+       defined(__PPC) || defined(PPC) || defined(__powerpc__) || \
461+       defined(__powerpc) || defined(powerpc) || \
462+       ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))))
463+#define        LZ4_BIG_ENDIAN  1
464+#else
465+       /*
466+        * Little Endian assumed. PDP Endian and other very rare endian format
467+        * are unsupported.
468+        */
469+#endif
470+
471+/*
472+ * Compiler Options
473+ */
474+
475+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L  /* C99 */
476+/* "restrict" is a known keyword */
477+#else
478+/* Disable restrict */
479+#ifndef restrict
480+#define        restrict /* Only if somebody already didn't take care of that.*/
481+#endif
482+#endif
483+
484+#define        GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
485+
486+#define        lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) \
487+       | (((x) & 0xffu) << 8)))
488+
489+#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
490+#define        expect(expr, value)    (__builtin_expect((expr), (value)))
491+#else
492+#define        expect(expr, value)    (expr)
493+#endif
494+
495+#define        likely(expr)    expect((expr) != 0, 1)
496+#define        unlikely(expr)  expect((expr) != 0, 0)
497+
498+/* Basic types */
499+#define        BYTE    grub_uint8_t
500+#define        U16     grub_uint16_t
501+#define        U32     grub_uint32_t
502+#define        S32     grub_int32_t
503+#define        U64     grub_uint64_t
504+typedef grub_size_t size_t;
505+
506+typedef struct _U16_S {
507+       U16 v;
508+} U16_S;
509+typedef struct _U32_S {
510+       U32 v;
511+} U32_S;
512+typedef struct _U64_S {
513+       U64 v;
514+} U64_S;
515+
516+#define        A64(x)  (((U64_S *)(x))->v)
517+#define        A32(x)  (((U32_S *)(x))->v)
518+#define        A16(x)  (((U16_S *)(x))->v)
519+
520+/*
521+ * Constants
522+ */
523+#define        MINMATCH 4
524+
525+#define        COPYLENGTH 8
526+#define        LASTLITERALS 5
527+
528+#define        ML_BITS 4
529+#define        ML_MASK ((1U<<ML_BITS)-1)
530+#define        RUN_BITS (8-ML_BITS)
531+#define        RUN_MASK ((1U<<RUN_BITS)-1)
532+
533+/*
534+ * Architecture-specific macros
535+ */
536+#if LZ4_ARCH64
537+#define        STEPSIZE 8
538+#define        UARCH U64
539+#define        AARCH A64
540+#define        LZ4_COPYSTEP(s, d)      A64(d) = A64(s); d += 8; s += 8;
541+#define        LZ4_COPYPACKET(s, d)    LZ4_COPYSTEP(s, d)
542+#define        LZ4_SECURECOPY(s, d, e) if (d < e) LZ4_WILDCOPY(s, d, e)
543+#define        HTYPE U32
544+#define        INITBASE(base)          const BYTE* const base = ip
545+#else
546+#define        STEPSIZE 4
547+#define        UARCH U32
548+#define        AARCH A32
549+#define        LZ4_COPYSTEP(s, d)      A32(d) = A32(s); d += 4; s += 4;
550+#define        LZ4_COPYPACKET(s, d)    LZ4_COPYSTEP(s, d); LZ4_COPYSTEP(s, d);
551+#define        LZ4_SECURECOPY          LZ4_WILDCOPY
552+#define        HTYPE const BYTE*
553+#define        INITBASE(base)          const int base = 0
554+#endif
555+
556+#if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE))
557+#define        LZ4_READ_LITTLEENDIAN_16(d, s, p) \
558+       { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }
559+#define        LZ4_WRITE_LITTLEENDIAN_16(p, i) \
560+       { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p += 2; }
561+#else
562+#define        LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - A16(p); }
563+#define        LZ4_WRITE_LITTLEENDIAN_16(p, v)  { A16(p) = v; p += 2; }
564+#endif
565+
566+/* Macros */
567+#define        LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e);
568+
569+/* Decompression functions */
570+grub_err_t
571+lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len);
572+
573+grub_err_t
574+lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len)
575+{
576+       const BYTE *src = s_start;
577+       U32 bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) |
578+           src[3];
579+
580+       /* invalid compressed buffer size encoded at start */
581+       if (bufsiz + 4 > s_len)
582+               return grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed.");
583+
584+       /*
585+        * Returns 0 on success (decompression function returned non-negative)
586+        * and appropriate error on failure (decompression function returned negative).
587+        */
588+       return (LZ4_uncompress_unknownOutputSize((char*)s_start + 4, d_start, bufsiz,
589+           d_len) < 0)?grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."):0;
590+}
591+
592+static int
593+LZ4_uncompress_unknownOutputSize(const char *source,
594+    char *dest, int isize, int maxOutputSize)
595+{
596+       /* Local Variables */
597+       const BYTE *restrict ip = (const BYTE *) source;
598+       const BYTE *const iend = ip + isize;
599+       const BYTE *restrict ref;
600+
601+       BYTE *restrict op = (BYTE *) dest;
602+       BYTE *const oend = op + maxOutputSize;
603+       BYTE *cpy;
604+
605+       size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
606+
607+       /* Main Loop */
608+       while (ip < iend) {
609+               BYTE token;
610+               int length;
611+
612+               /* get runlength */
613+               token = *ip++;
614+               if ((length = (token >> ML_BITS)) == RUN_MASK) {
615+                       int s = 255;
616+                       while ((ip < iend) && (s == 255)) {
617+                               s = *ip++;
618+                               length += s;
619+                       }
620+               }
621+               /* copy literals */
622+               cpy = op + length;
623+               if ((cpy > oend - COPYLENGTH) ||
624+                   (ip + length > iend - COPYLENGTH)) {
625+                       if (cpy > oend)
626+                               /*
627+                                * Error: request to write beyond destination
628+                                * buffer.
629+                                */
630+                               goto _output_error;
631+                       if (ip + length > iend)
632+                               /*
633+                                * Error : request to read beyond source
634+                                * buffer.
635+                                */
636+                               goto _output_error;
637+                       grub_memcpy(op, ip, length);
638+                       op += length;
639+                       ip += length;
640+                       if (ip < iend)
641+                               /* Error : LZ4 format violation */
642+                               goto _output_error;
643+                       /* Necessarily EOF, due to parsing restrictions. */
644+                       break;
645+               }
646+               LZ4_WILDCOPY(ip, op, cpy);
647+               ip -= (op - cpy);
648+               op = cpy;
649+
650+               /* get offset */
651+               LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
652+               ip += 2;
653+               if (ref < (BYTE * const) dest)
654+                       /*
655+                        * Error: offset creates reference outside of
656+                        * destination buffer.
657+                        */
658+                       goto _output_error;
659+
660+               /* get matchlength */
661+               if ((length = (token & ML_MASK)) == ML_MASK) {
662+                       while (ip < iend) {
663+                               int s = *ip++;
664+                               length += s;
665+                               if (s == 255)
666+                                       continue;
667+                               break;
668+                       }
669+               }
670+               /* copy repeated sequence */
671+               if unlikely(op - ref < STEPSIZE) {
672+#if LZ4_ARCH64
673+                       size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
674+                       size_t dec2 = dec2table[op - ref];
675+#else
676+                       const int dec2 = 0;
677+#endif
678+                       *op++ = *ref++;
679+                       *op++ = *ref++;
680+                       *op++ = *ref++;
681+                       *op++ = *ref++;
682+                       ref -= dec[op - ref];
683+                       A32(op) = A32(ref);
684+                       op += STEPSIZE - 4;
685+                       ref -= dec2;
686+               } else {
687+                       LZ4_COPYSTEP(ref, op);
688+               }
689+               cpy = op + length - (STEPSIZE - 4);
690+               if (cpy > oend - COPYLENGTH) {
691+                       if (cpy > oend)
692+                               /*
693+                                * Error: request to write outside of
694+                                * destination buffer.
695+                                */
696+                               goto _output_error;
697+                       LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
698+                       while (op < cpy)
699+                               *op++ = *ref++;
700+                       op = cpy;
701+                       if (op == oend)
702+                               /*
703+                                * Check EOF (should never happen, since last
704+                                * 5 bytes are supposed to be literals).
705+                                */
706+                               break;
707+                       continue;
708+               }
709+               LZ4_SECURECOPY(ref, op, cpy);
710+               op = cpy;       /* correction */
711+       }
712+
713+       /* end of decoding */
714+       return (int)(((char *)op) - dest);
715+
716+       /* write overflow error detected */
717+       _output_error:
718+       return (int)(-(((char *)ip) - source));
719+}
720diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c
721index fdb587a..c96bf21 100644
722--- grub-core/fs/zfs/zfsinfo.c
723+++ grub-core/fs/zfs/zfsinfo.c
724@@ -132,21 +132,31 @@ print_vdev_info (char *nvlist, int tab)
725       grub_free (path);
726       return GRUB_ERR_NONE;
727     }
728+  char is_mirror=(grub_strcmp(type,VDEV_TYPE_MIRROR) == 0);
729+  char is_raidz=(grub_strcmp(type,VDEV_TYPE_RAIDZ) == 0);
730 
731-  if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
732+  if (is_mirror || is_raidz)
733     {
734       int nelm, i;
735 
736       nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
737        (nvlist, ZPOOL_CONFIG_CHILDREN);
738 
739+      if(is_mirror){
740+        grub_puts_ (N_("This VDEV is a mirror"));
741+      }
742+      else if(is_raidz){
743+        grub_uint64_t parity;
744+        grub_zfs_nvlist_lookup_uint64(nvlist,"nparity",&parity);
745+        grub_printf_ (N_("This VDEV is a RAIDZ%llu\n"),(unsigned long long)parity);
746+      }
747       print_tabs (tab);
748       if (nelm <= 0)
749        {
750-         grub_puts_ (N_("Incorrect mirror"));
751+         grub_puts_ (N_("Incorrect VDEV"));
752          return GRUB_ERR_NONE;
753        }
754-      grub_printf_ (N_("Mirror with %d children\n"), nelm);
755+      grub_printf_ (N_("VDEV with %d children\n"), nelm);
756       print_state (nvlist, tab);
757       for (i = 0; i < nelm; i++)
758        {
759@@ -162,14 +172,14 @@ print_vdev_info (char *nvlist, int tab)
760                 total element number. And the number itself is fine,
761                 only the element isn't.
762              */
763-             grub_printf_ (N_("Mirror element number %d isn't correct\n"), i);
764+             grub_printf_ (N_("VDEV element number %d isn't correct\n"), i);
765              continue;
766            }
767 
768          /* TRANSLATORS: it's the element carying the number %d, not
769             total element number. This is used in enumeration
770             "Element number 1", "Element number 2", ... */
771-         grub_printf_ (N_("Mirror element number %d:\n"), i);
772+         grub_printf_ (N_("VDEV element number %d:\n"), i);
773          print_vdev_info (child, tab + 1);
774 
775          grub_free (child);
776diff --git a/include/grub/zfs/dmu.h b/include/grub/zfs/dmu.h
777index 8fc6dc5..4ad616c 100644
778--- include/grub/zfs/dmu.h
779+++ include/grub/zfs/dmu.h
780@@ -22,6 +22,39 @@
781 
782 #ifndef        _SYS_DMU_H
783 #define        _SYS_DMU_H
784+#define        B_FALSE 0
785+#define        B_TRUE  1
786+
787+#define        DMU_OT_NEWTYPE 0x80
788+#define        DMU_OT_METADATA 0x40
789+#define        DMU_OT_BYTESWAP_MASK 0x3f
790+
791+#define        DMU_OT(byteswap, metadata) \
792+       (DMU_OT_NEWTYPE | \
793+       ((metadata) ? DMU_OT_METADATA : 0) | \
794+       ((byteswap) & DMU_OT_BYTESWAP_MASK))
795+
796+#define        DMU_OT_IS_VALID(ot) (((ot) & DMU_OT_NEWTYPE) ? \
797+       ((ot) & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS : \
798+       (ot) < DMU_OT_NUMTYPES)
799+
800+#define        DMU_OT_IS_METADATA(ot) (((ot) & DMU_OT_NEWTYPE) ? \
801+       ((ot) & DMU_OT_METADATA) : \
802+       dmu_ot[(ot)].ot_metadata)
803+
804+typedef enum dmu_object_byteswap {
805+       DMU_BSWAP_UINT8,
806+       DMU_BSWAP_UINT16,
807+       DMU_BSWAP_UINT32,
808+       DMU_BSWAP_UINT64,
809+       DMU_BSWAP_ZAP,
810+       DMU_BSWAP_DNODE,
811+       DMU_BSWAP_OBJSET,
812+       DMU_BSWAP_ZNODE,
813+       DMU_BSWAP_OLDACL,
814+       DMU_BSWAP_ACL,
815+       DMU_BSWAP_NUMFUNCS
816+} dmu_object_byteswap_t;
817 
818 /*
819  * This file describes the interface that the DMU provides for its
820@@ -89,7 +122,17 @@ typedef enum dmu_object_type {
821        DMU_OT_SA_ATTR_REGISTRATION,    /* ZAP */
822        DMU_OT_SA_ATTR_LAYOUTS,         /* ZAP */
823        DMU_OT_DSL_KEYCHAIN = 54,
824-       DMU_OT_NUMTYPES
825+       DMU_OT_NUMTYPES,
826+       DMU_OTN_UINT8_DATA = DMU_OT(DMU_BSWAP_UINT8, B_FALSE),
827+       DMU_OTN_UINT8_METADATA = DMU_OT(DMU_BSWAP_UINT8, B_TRUE),
828+       DMU_OTN_UINT16_DATA = DMU_OT(DMU_BSWAP_UINT16, B_FALSE),
829+       DMU_OTN_UINT16_METADATA = DMU_OT(DMU_BSWAP_UINT16, B_TRUE),
830+       DMU_OTN_UINT32_DATA = DMU_OT(DMU_BSWAP_UINT32, B_FALSE),
831+       DMU_OTN_UINT32_METADATA = DMU_OT(DMU_BSWAP_UINT32, B_TRUE),
832+       DMU_OTN_UINT64_DATA = DMU_OT(DMU_BSWAP_UINT64, B_FALSE),
833+       DMU_OTN_UINT64_METADATA = DMU_OT(DMU_BSWAP_UINT64, B_TRUE),
834+       DMU_OTN_ZAP_DATA = DMU_OT(DMU_BSWAP_ZAP, B_FALSE),
835+       DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE),
836 } dmu_object_type_t;
837 
838 typedef enum dmu_objset_type {
839@@ -116,5 +159,6 @@ typedef enum dmu_objset_type {
840 #define        DMU_POOL_HISTORY                "history"
841 #define        DMU_POOL_PROPS                  "pool_props"
842 #define        DMU_POOL_L2CACHE                "l2cache"
843+#define        DMU_POOL_FEATURES_FOR_READ      "features_for_read"
844 
845 #endif /* _SYS_DMU_H */
846diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h
847index e326c8b..761ade7 100644
848--- include/grub/zfs/zfs.h
849+++ include/grub/zfs/zfs.h
850@@ -36,8 +36,13 @@ typedef enum grub_zfs_endian
851 /*
852  * On-disk version number.
853  */
854-#define        SPA_VERSION                     33ULL
855-
856+#define        SPA_VERSION_INITIAL             1ULL
857+#define        SPA_VERSION_BEFORE_FEATURES     33ULL
858+#define        SPA_VERSION                     5000ULL
859+#define        SPA_VERSION_FEATURES            5000ULL
860+#define        SPA_VERSION_IS_SUPPORTED(v) \
861+       (((v) >= SPA_VERSION_INITIAL && (v) <= SPA_VERSION_BEFORE_FEATURES) || \
862+       ((v) >= SPA_VERSION_FEATURES && (v) <= SPA_VERSION))
863 /*
864  * The following are configuration names used in the nvlist describing a pool's
865  * configuration.
866@@ -76,6 +81,7 @@ typedef enum grub_zfs_endian
867 #define        ZPOOL_CONFIG_DDT_HISTOGRAM      "ddt_histogram"
868 #define        ZPOOL_CONFIG_DDT_OBJ_STATS      "ddt_object_stats"
869 #define        ZPOOL_CONFIG_DDT_STATS          "ddt_stats"
870+#define        ZPOOL_CONFIG_FEATURES_FOR_READ  "features_for_read"
871 /*
872  * The persistent vdev state is stored as separate values rather than a single
873  * 'vdev_state' entry.  This is because a device can be in multiple states, such
874diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h
875index b1c46da..8fad2cc 100644
876--- include/grub/zfs/zio.h
877+++ include/grub/zfs/zio.h
878@@ -88,6 +88,7 @@ enum zio_compress {
879        ZIO_COMPRESS_GZIP8,
880        ZIO_COMPRESS_GZIP9,
881        ZIO_COMPRESS_ZLE,
882+       ZIO_COMPRESS_LZ4,
883        ZIO_COMPRESS_FUNCTIONS
884 };
885 
886diff --git a/po/POTFILES.in b/po/POTFILES.in
887index 987b37a..c55d9e3 100644
888--- po/POTFILES.in
889+++ po/POTFILES.in
890@@ -173,6 +173,7 @@
891 ./grub-core/fs/zfs/zfs_fletcher.c
892 ./grub-core/fs/zfs/zfsinfo.c
893 ./grub-core/fs/zfs/zfs_lzjb.c
894+./grub-core/fs/zfs/zfs_lz4.c
895 ./grub-core/fs/zfs/zfs_sha256.c
896 ./grub-core/gdb/cstub.c
897 ./grub-core/gdb/gdb.c
Note: See TracBrowser for help on using the repository browser.