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

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

Add updated grub2 port, and set some options when we build it.

Remove a defunct port from gnome-meta-utils

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