Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 549274 | Differences between
and this patch

Collapse All | Expand All

(-)grub-2.02~beta2_/grub-core/fs/zfs/zfs.c (-1799 / +3695 lines)
Lines 1-8 Link Here
1
/*
1
/*
2
 *  GRUB  --  GRand Unified Bootloader
2
 *  GRUB  --  GRand Unified Bootloader
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011  Free Software Foundation, Inc.
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011  Free Software Foundation, Inc.
4
 *  Copyright 2010  Sun Microsystems, Inc.
4
 *  Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
5
 *  Copyright (c) 2012 by Delphix. All rights reserved.
5
 *  Copyright (c) 2012 by Delphix. All rights reserved.
6
 *  Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
7
 *  Copyright (c) 2015 by Toomas Soome.
6
 *
8
 *
7
 *  GRUB is free software; you can redistribute it and/or modify
9
 *  GRUB is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
10
 *  it under the terms of the GNU General Public License as published by
Lines 18-33 Link Here
18
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
20
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
19
 */
21
 */
20
/*
22
/*
21
 * The zfs plug-in routines for GRUB are:
23
 * This file and its contents are supplied under the terms of the
22
 *
24
 * Common Development and Distribution License ("CDDL"), version 1.0.
23
 * zfs_mount() - locates a valid uberblock of the root pool and reads
25
 * You may only use this file in accordance with the terms of version
24
 *		in its MOS at the memory address MOS.
26
 * 1.0 of the CDDL.
25
 *
26
 * zfs_open() - locates a plain file object by following the MOS
27
 *		and places its dnode at the memory address DNODE.
28
 *
29
 * zfs_read() - read in the data blocks pointed by the DNODE.
30
 *
27
 *
28
 * A full copy of the text of the CDDL should have accompanied this
29
 * source.  A copy of the CDDL is also available via the Internet at
30
 * http://www.illumos.org/license/CDDL.
31
 */
31
 */
32
32
33
#include <grub/err.h>
33
#include <grub/err.h>
Lines 59-64 Link Here
59
GRUB_MOD_LICENSE ("GPLv3+");
59
GRUB_MOD_LICENSE ("GPLv3+");
60
60
61
#define	ZPOOL_PROP_BOOTFS		"bootfs"
61
#define	ZPOOL_PROP_BOOTFS		"bootfs"
62
#define	BOOTFSNAME_SIZE			256
62
63
63
/*
64
/*
64
 * For nvlist manipulation. (from nvpair.h)
65
 * For nvlist manipulation. (from nvpair.h)
Lines 76-82 Link Here
76
static grub_dl_t my_mod;
77
static grub_dl_t my_mod;
77
#endif
78
#endif
78
79
80
#define	P2ALIGN_TYPED(x, align, type)	((type)(x) & -(type)(align))
79
#define	P2PHASE(x, align)		((x) & ((align) - 1))
81
#define	P2PHASE(x, align)		((x) & ((align) - 1))
82
#define	P2ROUNDUP(x, align)		(-(-(x) & -(align)))
83
#ifndef	NBBY
84
#define	NBBY	8
85
#endif
86
87
static grub_err_t vdev_disk_read_rootlabel(grub_device_t, char **);
88
static grub_err_t vdev_attach(struct grub_zfs_data *, grub_device_t, char *,
89
			      char *, int);
80
90
81
static inline grub_disk_addr_t
91
static inline grub_disk_addr_t
82
DVA_OFFSET_TO_PHYS_SECTOR (grub_disk_addr_t offset)
92
DVA_OFFSET_TO_PHYS_SECTOR (grub_disk_addr_t offset)
Lines 158-164 Link Here
158
 */
168
 */
159
169
160
extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t);
170
extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t);
161
162
extern grub_err_t lz4_decompress (void *, void *, grub_size_t, grub_size_t);
171
extern grub_err_t lz4_decompress (void *, void *, grub_size_t, grub_size_t);
163
172
164
typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start,
173
typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start,
Lines 179-188 Link Here
179
 * Information about each checksum function.
188
 * Information about each checksum function.
180
 */
189
 */
181
typedef struct zio_checksum_info {
190
typedef struct zio_checksum_info {
182
  zio_checksum_t	*ci_func; /* checksum function for each byteorder */
191
	zio_checksum_t	*ci_func; /* checksum function for each byteorder */
183
  int		ci_correctable;	/* number of correctable bits	*/
192
	int		ci_correctable;	/* number of correctable bits	*/
184
  int		ci_eck;		/* uses zio embedded checksum? */
193
	int		ci_eck;		/* uses zio embedded checksum? */
185
  const char		*ci_name;	/* descriptive name */
194
	const char		*ci_name;	/* descriptive name */
186
} zio_checksum_info_t;
195
} zio_checksum_info_t;
187
196
188
typedef struct dnode_end
197
typedef struct dnode_end
Lines 194-203 Link Here
194
struct grub_zfs_device_desc
203
struct grub_zfs_device_desc
195
{
204
{
196
  enum { DEVICE_LEAF, DEVICE_MIRROR, DEVICE_RAIDZ } type;
205
  enum { DEVICE_LEAF, DEVICE_MIRROR, DEVICE_RAIDZ } type;
206
  enum { DEVICE_OK, DEVICE_ERROR } dev_state;
197
  grub_uint64_t id;
207
  grub_uint64_t id;
198
  grub_uint64_t guid;
208
  grub_uint64_t guid;
199
  unsigned ashift;
209
  grub_uint64_t txg;			/* label transaction group */
200
  unsigned max_children_ashift;
210
  char *config;				/* nvlist from label */
201
211
202
  /* Valid only for non-leafs.  */
212
  /* Valid only for non-leafs.  */
203
  unsigned n_children;
213
  unsigned n_children;
Lines 206-216 Link Here
206
  /* Valid only for RAIDZ.  */
216
  /* Valid only for RAIDZ.  */
207
  unsigned nparity;
217
  unsigned nparity;
208
218
219
  /* Valid for all */
220
  unsigned ashift;
221
209
  /* Valid only for leaf devices.  */
222
  /* Valid only for leaf devices.  */
223
  struct grub_zfs_device_desc *top_vdev;
210
  grub_device_t dev;
224
  grub_device_t dev;
211
  grub_disk_addr_t vdev_phys_sector;
225
  char *dev_name;
226
  int original;			/* we dont close original */
212
  uberblock_t current_uberblock;
227
  uberblock_t current_uberblock;
213
  int original;
214
};
228
};
215
229
216
struct subvolume
230
struct subvolume
Lines 229-234 Link Here
229
243
230
struct grub_zfs_data
244
struct grub_zfs_data
231
{
245
{
246
  int zcached; /* the value should be zero if no cache available */
247
232
  /* cache for a file block of the currently zfs_open()-ed file */
248
  /* cache for a file block of the currently zfs_open()-ed file */
233
  char *file_buf;
249
  char *file_buf;
234
  grub_uint64_t file_start;
250
  grub_uint64_t file_start;
Lines 248-261 Link Here
248
  struct grub_zfs_device_desc *devices_attached;
264
  struct grub_zfs_device_desc *devices_attached;
249
  unsigned n_devices_attached;
265
  unsigned n_devices_attached;
250
  unsigned n_devices_allocated;
266
  unsigned n_devices_allocated;
251
  struct grub_zfs_device_desc *device_original;
252
267
253
  uberblock_t current_uberblock;
268
  uberblock_t current_uberblock;
254
269
255
  int mounted;
270
  int mounted;
256
  grub_uint64_t guid;
271
272
  grub_uint64_t guid;			/* pool guid */
273
  grub_uint64_t state;			/* pool state */
274
  char *label;				/* pool label name */
257
};
275
};
258
276
277
typedef struct mirror_child
278
{
279
  struct grub_zfs_device_desc	*mc_vd;
280
  grub_uint64_t			mc_offset;
281
  int				mc_error;
282
  grub_uint8_t			mc_tried;
283
  grub_uint8_t			mc_skipped;
284
  grub_uint8_t			mc_speculative;
285
} mirror_child_t;
286
287
typedef struct mirror_map
288
{
289
  void			*mm_buf;
290
  grub_size_t		mm_size;
291
  grub_uint64_t		mm_offset;
292
  int			mm_children;
293
  int			mm_replacing;
294
  int			mm_preferred;
295
  int			mm_root;
296
  mirror_child_t	mm_child[1];
297
} mirror_map_t;
298
299
/*
300
 * The following are taken straight from usr/src/uts/common/fs/zfs/vdev_raidz.c
301
 * If they change there, they need to be changed here.
302
 *
303
 * a map of columns returned for a given offset and size
304
 */
305
typedef struct raidz_col
306
{
307
  grub_uint64_t rc_devidx;	/* child device index for I/O */
308
  grub_uint64_t rc_offset;	/* device offset */
309
  grub_uint64_t rc_size;	/* I/O size */
310
  void *rc_data;		/* I/O data */
311
  void *rc_gdata;		/* used to store the "good" version */
312
  int rc_error;			/* I/O error for this device */
313
  grub_uint8_t rc_tried;	/* Did we attempt this I/O column? */
314
  grub_uint8_t rc_skipped;	/* Did we skip this I/O column? */
315
} raidz_col_t;
316
317
typedef struct raidz_map
318
{
319
  grub_uint64_t rm_cols;		/* Regular column count */
320
  grub_uint64_t rm_scols;		/* Count including skipped columns */
321
  grub_uint64_t rm_bigcols;		/* Number of oversized columns */
322
  grub_uint64_t rm_asize;		/* Actual total I/O size */
323
  grub_uint64_t rm_missingdata;		/* Count of missing data devices */
324
  grub_uint64_t rm_missingparity;	/* Count of missing parity devices */
325
  grub_uint64_t rm_firstdatacol;	/* First data column/parity count */
326
  grub_uint64_t rm_nskip;		/* Skipped sectors for padding */
327
  grub_uint64_t rm_skipstart;		/* Column index of padding start */
328
  void *rm_datacopy;			/* rm_asize-buffer of copied data */
329
  grub_addr_t rm_reports;		/* # of referencing checksum reports */
330
  grub_uint8_t rm_freed;		/* map no longer has referencing ZIO */
331
  grub_uint8_t rm_ecksuminjected;	/* checksum error was injected */
332
  raidz_col_t rm_col[1];		/* Flexible array of I/O columns */
333
} raidz_map_t;
334
335
#define	VDEV_RAIDZ_P	0
336
#define	VDEV_RAIDZ_Q	1
337
#define	VDEV_RAIDZ_R	2
338
/*
339
#define	VDEV_RAIDZ_MUL_2(x)	(((x) << 1) ^ (((x) & 0x80) ? 0x1d : 0))
340
#define	VDEV_RAIDZ_MUL_4(x)	(VDEV_RAIDZ_MUL_2(VDEV_RAIDZ_MUL_2(x)))
341
*/
342
#define	VDEV_RAIDZ_64MUL_2(x, mask)	\
343
{ \
344
  (mask) = (x) & 0x8080808080808080ULL; \
345
  (mask) = ((mask) << 1) - ((mask) >> 7); \
346
  (x) = (((x) << 1) & 0xfefefefefefefefeULL) ^ \
347
  ((mask) & 0x1d1d1d1d1d1d1d1dULL); \
348
}
349
350
#define VDEV_RAIDZ_64MUL_4(x, mask)	\
351
{ \
352
  VDEV_RAIDZ_64MUL_2((x), mask); \
353
  VDEV_RAIDZ_64MUL_2((x), mask); \
354
}
355
356
/* cache list for ZFS mount */
357
struct zfs_mount_cache
358
{
359
  char *zcache_pool_name;
360
  grub_uint64_t zcache_pool_guid;
361
  struct grub_zfs_data *zcache_zfs_data;
362
  struct zfs_mount_cache *next;
363
} *zfs_mount_cache_list;
364
365
/* cache list for non-zfs disk dev */
366
struct zfs_dev_notzfs
367
{
368
  char *dev_name;
369
  unsigned long dev_id;
370
  struct zfs_dev_notzfs *next;
371
} *zfs_dev_notzfs_list;
372
259
/* Context for grub_zfs_dir.  */
373
/* Context for grub_zfs_dir.  */
260
struct grub_zfs_dir_ctx
374
struct grub_zfs_dir_ctx
261
{
375
{
Lines 279-305 Link Here
279
 * read. Note that features that are only required for write do not need
393
 * read. Note that features that are only required for write do not need
280
 * to be listed here since grub opens pools in read-only mode.
394
 * to be listed here since grub opens pools in read-only mode.
281
 */
395
 */
282
#define MAX_SUPPORTED_FEATURE_STRLEN 50
283
static const char *spa_feature_names[] = {
396
static const char *spa_feature_names[] = {
284
  "org.illumos:lz4_compress",NULL
397
        "org.illumos:lz4_compress",
398
        "com.delphix:hole_birth",
399
        "com.delphix:extensible_dataset",
400
        "com.delphix:embedded_data",
401
	"org.open-zfs:large_blocks",
402
        NULL
285
};
403
};
286
404
287
static int
288
check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx);
289
static int
290
check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data );
291
292
static grub_err_t 
405
static grub_err_t 
293
zlib_decompress (void *s, void *d,
406
zlib_decompress (void *s, void *d,
294
		 grub_size_t slen, grub_size_t dlen)
407
		 grub_size_t slen, grub_size_t dlen)
295
{
408
{
296
  if (grub_zlib_decompress (s, slen, 0, d, dlen) == (grub_ssize_t) dlen)
409
  if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0)
297
    return GRUB_ERR_NONE;
410
    return grub_errno;
298
411
  return GRUB_ERR_NONE;
299
  if (!grub_errno)
300
    grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
301
		"premature end of compressed");
302
  return grub_errno;
303
}
412
}
304
413
305
static grub_err_t 
414
static grub_err_t 
Lines 356-361 Link Here
356
465
357
static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
466
static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
358
				 void *buf, struct grub_zfs_data *data);
467
				 void *buf, struct grub_zfs_data *data);
468
static grub_err_t zio_read_common (blkptr_t * bp, dva_t *dva,
469
				 grub_zfs_endian_t endian, void *buf,
470
				 struct grub_zfs_data *data);
471
static const char * nvlist_next_nvpair (const char *nvl, const char *nvpair);
472
static char *nvpair_name (const char *nvp);
473
static grub_err_t scan_devices (struct grub_zfs_data *, char *, grub_device_t);
359
474
360
/*
475
/*
361
 * Our own version of log2().  Same thing as highbit()-1.
476
 * Our own version of log2().  Same thing as highbit()-1.
Lines 371-377 Link Here
371
      num = num >> 1;
486
      num = num >> 1;
372
    }
487
    }
373
488
374
  return i;
489
  return (i);
375
}
490
}
376
491
377
/* Checksum Functions */
492
/* Checksum Functions */
Lines 391-401 Link Here
391
  {zio_checksum_off, 0, 0, "off"},
506
  {zio_checksum_off, 0, 0, "off"},
392
  {zio_checksum_SHA256, 1, 1, "label"},
507
  {zio_checksum_SHA256, 1, 1, "label"},
393
  {zio_checksum_SHA256, 1, 1, "gang_header"},
508
  {zio_checksum_SHA256, 1, 1, "gang_header"},
394
  {NULL, 0, 0, "zilog"},
509
  {fletcher_2, 0, 1, "zilog"},
395
  {fletcher_2, 0, 0, "fletcher2"},
510
  {fletcher_2, 0, 0, "fletcher2"},
396
  {fletcher_4, 1, 0, "fletcher4"},
511
  {fletcher_4, 1, 0, "fletcher4"},
397
  {zio_checksum_SHA256, 1, 0, "SHA256"},
512
  {zio_checksum_SHA256, 1, 0, "SHA256"},
398
  {NULL, 0, 0, "zilog2"},
513
  {fletcher_4, 0, 1, "zilog2"},
399
  {zio_checksum_SHA256, 1, 0, "SHA256+MAC"},
514
  {zio_checksum_SHA256, 1, 0, "SHA256+MAC"},
400
};
515
};
401
516
Lines 418-424 Link Here
418
    {
533
    {
419
      grub_dprintf ("zfs", "unknown checksum function %d\n", checksum);
534
      grub_dprintf ("zfs", "unknown checksum function %d\n", checksum);
420
      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
535
      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
421
			 "unknown checksum function %d", checksum);
536
			 N_("unknown checksum function %d"), checksum);
422
    }
537
    }
423
538
424
  if (ci->ci_eck)
539
  if (ci->ci_eck)
Lines 479-497 Link Here
479
594
480
  if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) 
595
  if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) 
481
      < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
596
      < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
482
    return -1;
597
    return (1);
483
  if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) 
598
  if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) 
484
      > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
599
      > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
485
    return 1;
600
    return (-1);
486
601
487
  if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) 
602
  if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) 
488
      < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
603
      < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
489
    return -1;
604
    return (1);
490
  if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) 
605
  if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) 
491
      > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
606
      > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
492
    return 1;
607
    return (-1);
493
608
494
  return 0;
609
  return (0);
495
}
610
}
496
611
497
/*
612
/*
Lines 502-511 Link Here
502
 *
617
 *
503
 */
618
 */
504
static grub_err_t
619
static grub_err_t
505
uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset,
620
uberblock_verify (uberblock_t *uber, grub_uint64_t offset, int ashift)
506
		  grub_size_t s)
507
{
621
{
508
  uberblock_t *uber = &ub->ubp_uberblock;
509
  grub_err_t err;
622
  grub_err_t err;
510
  grub_zfs_endian_t endian = GRUB_ZFS_UNKNOWN_ENDIAN;
623
  grub_zfs_endian_t endian = GRUB_ZFS_UNKNOWN_ENDIAN;
511
  zio_cksum_t zc;
624
  zio_cksum_t zc;
Lines 520-1835 Link Here
520
    endian = GRUB_ZFS_BIG_ENDIAN;
633
    endian = GRUB_ZFS_BIG_ENDIAN;
521
634
522
  if (endian == GRUB_ZFS_UNKNOWN_ENDIAN)
635
  if (endian == GRUB_ZFS_UNKNOWN_ENDIAN)
523
    return grub_error (GRUB_ERR_BAD_FS, "invalid uberblock magic");
636
    return grub_error (GRUB_ERR_BAD_FS, N_("invalid uberblock magic"));
524
637
525
  grub_memset (&zc, 0, sizeof (zc));
638
  grub_memset (&zc, 0, sizeof (zc));
526
639
527
  zc.zc_word[0] = grub_cpu_to_zfs64 (offset, endian);
640
  zc.zc_word[0] = grub_cpu_to_zfs64 (offset, endian);
528
  err = zio_checksum_verify (zc, ZIO_CHECKSUM_LABEL, endian,
641
  err = zio_checksum_verify (zc, ZIO_CHECKSUM_LABEL, endian,
529
			     (char *) ub, s);
642
			     (char *) uber, VDEV_UBERBLOCK_SIZE(ashift));
530
643
531
  return err;
644
  return err;
532
}
645
}
533
646
534
/*
647
/*
535
 * Find the best uberblock.
648
 * Check if this vdev is online and is in a good state.
536
 * Return:
537
 *    Success - Pointer to the best uberblock.
538
 *    Failure - NULL
539
 */
649
 */
540
static uberblock_phys_t *
650
int
541
find_bestub (uberblock_phys_t * ub_array,
651
grub_zfs_vdev_validate (const char *nv)
542
	     const struct grub_zfs_device_desc *desc)
543
{
652
{
544
  uberblock_phys_t *ubbest = NULL, *ubptr;
653
  grub_uint64_t ival = 0;
545
  int i;
546
  grub_disk_addr_t offset;
547
  grub_err_t err = GRUB_ERR_NONE;
548
  int ub_shift;
549
550
  ub_shift = desc->ashift;
551
  if (ub_shift < VDEV_UBERBLOCK_SHIFT)
552
    ub_shift = VDEV_UBERBLOCK_SHIFT;
553
654
554
  for (i = 0; i < (VDEV_UBERBLOCK_RING >> ub_shift); i++)
655
  if (grub_zfs_nvlist_lookup_uint64 (nv, ZPOOL_CONFIG_OFFLINE, &ival) && ival)
656
    {
657
      grub_dprintf ("zfs", "vdev_validate: ZPOOL_CONFIG_OFFLINE\n");
658
      return (1);
659
    }
660
  if ((grub_zfs_nvlist_lookup_uint64 (nv, ZPOOL_CONFIG_FAULTED, &ival) && ival) &&
661
      !(grub_zfs_nvlist_lookup_uint64 (nv, ZPOOL_CONFIG_DEGRADED, &ival) && ival))
662
    {
663
      grub_dprintf ("zfs", "vdev_validate: ZPOOL_CONFIG_FAULTED\n");
664
      return (1);
665
    }
666
  if (grub_zfs_nvlist_lookup_uint64 (nv, ZPOOL_CONFIG_REMOVED, &ival) && ival)
555
    {
667
    {
556
      offset = (desc->vdev_phys_sector << SPA_MINBLOCKSHIFT) + VDEV_PHYS_SIZE
668
      grub_dprintf ("zfs", "vdev_validate: ZPOOL_CONFIG_REMOVED\n");
557
	+ (i << ub_shift);
669
      return (1);
558
670
559
      ubptr = (uberblock_phys_t *) ((grub_properly_aligned_t *) ub_array
560
				    + ((i << ub_shift)
561
				       / sizeof (grub_properly_aligned_t)));
562
      err = uberblock_verify (ubptr, offset, 1 << ub_shift);
563
      if (err)
564
	{
565
	  grub_errno = GRUB_ERR_NONE;
566
	  continue;
567
	}
568
      if (ubbest == NULL 
569
	  || vdev_uberblock_compare (&(ubptr->ubp_uberblock),
570
				     &(ubbest->ubp_uberblock)) > 0)
571
	ubbest = ubptr;
572
    }
671
    }
573
  if (!ubbest)
574
    grub_errno = err;
575
672
576
  return ubbest;
673
    return (0);
577
}
674
}
578
675
579
static inline grub_size_t
676
static int
580
get_psize (blkptr_t * bp, grub_zfs_endian_t endian)
677
check_feature(const char *name, grub_uint64_t val,
678
	      struct grub_zfs_dir_ctx *ctx __attribute__((unused)))
581
{
679
{
582
  return ((((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) >> 16) & 0xffff) + 1)
680
  int i;
583
	  << SPA_MINBLOCKSHIFT);
584
}
585
681
586
static grub_uint64_t
682
  if (val == 0)	/* value is not set */
587
dva_get_offset (const dva_t *dva, grub_zfs_endian_t endian)
683
    return (0);
588
{
684
  if(name[0] == 0)  /* empty name */
589
  grub_dprintf ("zfs", "dva=%llx, %llx\n", 
685
    return (0);
590
		(unsigned long long) dva->dva_word[0], 
686
591
		(unsigned long long) dva->dva_word[1]);
687
  for (i = 0; spa_feature_names[i] != NULL; i++ )
592
  return grub_zfs_to_cpu64 ((dva)->dva_word[1], 
688
    if (grub_strcmp(name, spa_feature_names[i]) == 0)
593
			    endian) << SPA_MINBLOCKSHIFT;
689
      {
690
	grub_dprintf ("zfs", "check_feature: %s ok\n", name);
691
	return (0);
692
      }
693
  return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "unknown feature: %s", name);
594
}
694
}
595
695
596
static grub_err_t
696
struct scan_devices_ctx {
597
zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist)
697
	struct grub_zfs_data *data;
698
	char *name;
699
	grub_device_t dev;
700
	int missing_vdev;
701
	int missing_children;
702
};
703
704
static int
705
scan_devices_iter(const char *name, void *hook_data)
598
{
706
{
707
  struct scan_devices_ctx *ctx = hook_data;
708
  struct grub_zfs_data *data = ctx->data;
709
  struct zfs_dev_notzfs *dev_notzfs;
710
  grub_device_t dev;
711
  grub_uint64_t u;
712
  unsigned i, j;
713
  int original = 0;
714
  char *dev_name;
715
  char *config;
599
  grub_err_t err;
716
  grub_err_t err;
600
717
601
  *nvlist = 0;
718
  grub_dprintf("zfs", "scan_devices: %s\n", name);
602
603
  if (!diskdesc->dev)
604
    return grub_error (GRUB_ERR_BUG, "member drive unknown");
605
719
606
  *nvlist = grub_malloc (VDEV_PHYS_SIZE);
720
  /* scan our config first */
607
721
  ctx->missing_vdev = data->n_devices_allocated - data->n_devices_attached;
608
  /* Read in the vdev name-value pair list (112K). */
722
  ctx->missing_children = 0;
609
  err = grub_disk_read (diskdesc->dev->disk, diskdesc->vdev_phys_sector, 0,
723
  for (i = 0; i<data->n_devices_allocated; i++)
610
			VDEV_PHYS_SIZE, *nvlist);
611
  if (err)
612
    {
724
    {
613
      grub_free (*nvlist);
725
      if (data->devices_attached[i].guid == 0) /* not attached */
614
      *nvlist = 0;
726
	continue;
615
      return err;
616
    }
617
  return GRUB_ERR_NONE;
618
}
619
620
static grub_err_t
621
fill_vdev_info_real (struct grub_zfs_data *data,
622
		     const char *nvlist,
623
		     struct grub_zfs_device_desc *fill,
624
		     struct grub_zfs_device_desc *insert,
625
		     int *inserted,
626
		     unsigned ashift)
627
{
628
  char *type;
629
630
  type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
631
632
  if (!type)
633
    return grub_errno;
634
727
635
  if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &(fill->id)))
728
      for (j = 0; j < data->devices_attached[i].n_children; j++)
636
    {
729
	{
637
      grub_free (type);
730
	  if (data->devices_attached[i].children[j].guid == 0)
638
      return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
731
	    ctx->missing_children++;
732
	}
639
    }
733
    }
640
734
641
  if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "guid", &(fill->guid)))
735
  if (ctx->missing_vdev == 0 && ctx->missing_children == 0)
642
    {
736
    {
643
      grub_free (type);
737
      /* nothing to do */
644
      return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
738
      return 1;
645
    }
739
    }
646
740
647
  {
741
  for (dev_notzfs = zfs_dev_notzfs_list;
648
    grub_uint64_t par;
742
       dev_notzfs != NULL; dev_notzfs = dev_notzfs->next)
649
    if (grub_zfs_nvlist_lookup_uint64 (nvlist, "ashift", &par))
743
    if (grub_strcmp(name, dev_notzfs->dev_name) == 0)
650
      fill->ashift = par;
651
    else if (ashift != 0xffffffff)
652
      fill->ashift = ashift;
653
    else
654
      {
744
      {
655
	grub_free (type);
745
	grub_dprintf("zfs", "scan_devices_iter: found cached non-zfs "
656
	return grub_error (GRUB_ERR_BAD_FS, "couldn't find ashift");
746
		     "disk dev: %s\n", dev_notzfs->dev_name);
747
	return 0;
657
      }
748
      }
658
  }
659
749
660
  fill->max_children_ashift = 0;
750
  if (grub_strcmp(name, ctx->name) == 0)
661
751
662
  if (grub_strcmp (type, VDEV_TYPE_DISK) == 0
663
      || grub_strcmp (type, VDEV_TYPE_FILE) == 0)
664
    {
752
    {
665
      fill->type = DEVICE_LEAF;
753
      dev = ctx->dev;
754
      dev_name = ctx->name;
755
      original = 1;
756
    }
757
  else
758
    {
759
      dev = grub_device_open (name);
760
      if (!dev)
761
	return 0;
762
      if (!dev->disk)
666
763
667
      if (!fill->dev && fill->guid == insert->guid)
668
	{
764
	{
669
	  fill->dev = insert->dev;
765
	  grub_device_close (dev);
670
	  fill->vdev_phys_sector = insert->vdev_phys_sector;
766
	  return 0;
671
	  fill->current_uberblock = insert->current_uberblock;
672
	  fill->original = insert->original;
673
	  if (!data->device_original)
674
	    data->device_original = fill;
675
	  insert->ashift = fill->ashift;
676
	  *inserted = 1;
677
	}
767
	}
768
      dev_name = grub_strdup(name);
678
769
679
      grub_free (type);
680
770
681
      return GRUB_ERR_NONE;
682
    }
771
    }
683
772
684
  if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0
773
  if ((err = vdev_disk_read_rootlabel (dev, &config)) != GRUB_ERR_NONE)
685
      || grub_strcmp (type, VDEV_TYPE_RAIDZ) == 0)
686
    {
774
    {
687
      int nelm, i;
775
      dev_notzfs = grub_malloc(sizeof (struct zfs_dev_notzfs));
776
      if (dev_notzfs)
688
777
689
      if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
690
	fill->type = DEVICE_MIRROR;
691
      else
692
	{
778
	{
693
	  grub_uint64_t par;
779
	  dev_notzfs->dev_name = grub_strdup(name);
694
	  fill->type = DEVICE_RAIDZ;
780
	  dev_notzfs->dev_id = dev->disk->id;
695
	  if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "nparity", &par))
781
	  if (zfs_dev_notzfs_list)
696
	    {
782
	    dev_notzfs->next = zfs_dev_notzfs_list;
697
	      grub_free (type);
783
	  else
698
	      return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz parity");
784
	    dev_notzfs->next = NULL;
699
	    }
785
	  zfs_dev_notzfs_list = dev_notzfs;
700
	  fill->nparity = par;
701
	}
786
	}
787
      if (!original) 
702
788
703
      nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist,
704
							   ZPOOL_CONFIG_CHILDREN);
705
706
      if (nelm <= 0)
707
	{
789
	{
708
	  grub_free (type);
790
          grub_device_close (dev);
709
	  return grub_error (GRUB_ERR_BAD_FS, "incorrect mirror VDEV");
791
	  grub_free (dev_name);
710
	}
792
	}
793
      return 0;
794
    }
711
795
712
      if (!fill->children)
796
  u = 0;
797
  if (grub_zfs_nvlist_lookup_uint64 (config, ZPOOL_CONFIG_POOL_GUID, &u)
798
      && data->guid != u)
799
    {
800
      grub_free (config);
801
      if (!original)
713
	{
802
	{
714
	  fill->n_children = nelm;
803
	  grub_device_close (dev);
715
	  
804
	  grub_free (dev_name);
716
	  fill->children = grub_zalloc (fill->n_children
717
					* sizeof (fill->children[0]));
718
	}
805
	}
719
806
720
      for (i = 0; i < nelm; i++)
807
      return 0;
721
	{
808
    }
722
	  char *child;
723
	  grub_err_t err;
724
809
725
	  child = grub_zfs_nvlist_lookup_nvlist_array
810
  grub_dprintf ("zfs", "disk from our pool: %s\n", name);
726
	    (nvlist, ZPOOL_CONFIG_CHILDREN, i);
727
811
728
	  err = fill_vdev_info_real (data, child, &fill->children[i], insert,
812
  err = vdev_attach(data, dev, config, dev_name, original);
729
				     inserted, fill->ashift);
813
  grub_free (config);
730
814
731
	  grub_free (child);
815
  /* check the vdev tree again */
816
  ctx->missing_vdev = data->n_devices_allocated - data->n_devices_attached;
817
  ctx->missing_children = 0;
818
  for (i = 0; i<data->n_devices_allocated; i++)
819
    {
820
      if (data->devices_attached[i].guid == 0) /* not attached */
821
	continue;
732
822
733
	  if (err)
823
      for (j = 0; j < data->devices_attached[i].n_children; j++)
734
	    {
824
	{
735
	      grub_free (type);
825
	  if (data->devices_attached[i].children[j].guid == 0)
736
	      return err;
826
	    ctx->missing_children++;
737
	    }
738
	  if (fill->children[i].ashift > fill->max_children_ashift)
739
	    fill->max_children_ashift = fill->children[i].ashift;
740
	}
827
	}
741
      grub_free (type);
742
      return GRUB_ERR_NONE;
743
    }
828
    }
744
829
745
  grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported", type);
830
  if (ctx->missing_vdev == 0 && ctx->missing_children == 0)
746
  grub_free (type);
831
    {
747
  return grub_errno;
832
      /* done */
833
      return 1;
834
    }
835
836
  return 0;
748
}
837
}
749
838
839
/*
840
 * we iterate over all disks grub_device_iterate() will provide, till
841
 * we have filled all vdevs and children.
842
 */
750
static grub_err_t
843
static grub_err_t
751
fill_vdev_info (struct grub_zfs_data *data,
844
scan_devices (struct grub_zfs_data *data, char *name, grub_device_t dev)
752
		char *nvlist, struct grub_zfs_device_desc *diskdesc,
753
		int *inserted)
754
{
845
{
755
  grub_uint64_t id;
846
  struct scan_devices_ctx ctx;
756
  unsigned i;
757
847
758
  *inserted = 0;
848
  ctx.data = data;
849
  ctx.name = name;		/* disk name from zfs_mount() caller */
850
  ctx.dev = dev;		/* disk device from zfs_mount() caller */
851
  ctx.missing_vdev = 0;
852
  ctx.missing_children = 0;
759
853
760
  if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &id))
854
  grub_device_iterate (scan_devices_iter, (void *) &ctx);
761
    return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id");
762
855
763
  for (i = 0; i < data->n_devices_attached; i++)
856
  /* scan is done, fix device states in vdevs */
764
    if (data->devices_attached[i].id == id)
765
      return fill_vdev_info_real (data, nvlist, &data->devices_attached[i],
766
				  diskdesc, inserted, 0xffffffff);
767
768
  data->n_devices_attached++;
769
  if (data->n_devices_attached > data->n_devices_allocated)
770
    {
771
      void *tmp;
772
      data->n_devices_allocated = 2 * data->n_devices_attached + 1;
773
      data->devices_attached
774
	= grub_realloc (tmp = data->devices_attached,
775
			data->n_devices_allocated
776
			* sizeof (data->devices_attached[0]));
777
      if (!data->devices_attached)
778
	{
779
	  data->devices_attached = tmp;
780
	  return grub_errno;
781
	}
782
    }
783
857
784
  grub_memset (&data->devices_attached[data->n_devices_attached - 1],
858
  if (ctx.missing_vdev != 0 || ctx.missing_children != 0)
785
	       0, sizeof (data->devices_attached[data->n_devices_attached - 1]));
859
    {
860
      return GRUB_ERR_BAD_FS;
861
    }
786
862
787
  return fill_vdev_info_real (data, nvlist,
863
  return GRUB_ERR_NONE;
788
			      &data->devices_attached[data->n_devices_attached - 1],
789
			      diskdesc, inserted, 0xffffffff);
790
}
864
}
791
865
866
/* Powers of 2 in the Galois field. */
867
static const grub_uint8_t vdev_raidz_pow2[256] = {
868
        0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
869
        0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
870
        0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9,
871
        0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
872
        0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35,
873
        0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
874
        0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0,
875
        0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
876
        0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc,
877
        0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
878
        0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f,
879
        0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
880
        0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88,
881
        0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
882
        0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93,
883
        0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
884
        0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9,
885
        0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
886
        0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa,
887
        0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
888
        0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e,
889
        0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
890
        0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4,
891
        0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
892
        0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e,
893
        0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
894
        0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef,
895
        0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
896
        0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5,
897
        0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
898
        0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83,
899
        0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01
900
};
901
902
/* Logs of 2 in the Galois field. */
903
static const grub_uint8_t vdev_raidz_log2[256] = {
904
        0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6,
905
        0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
906
        0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81,
907
        0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
908
        0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21,
909
        0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
910
        0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9,
911
        0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
912
        0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd,
913
        0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
914
        0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd,
915
        0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
916
        0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e,
917
        0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
918
        0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b,
919
        0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
920
        0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d,
921
        0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
922
        0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c,
923
        0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
924
        0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd,
925
        0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
926
        0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e,
927
        0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
928
        0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76,
929
        0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
930
        0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa,
931
        0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
932
        0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51,
933
        0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
934
        0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8,
935
        0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf,
936
};
937
792
/*
938
/*
793
 * For a given XDR packed nvlist, verify the first 4 bytes and move on.
939
 * Multiply a given number by 2 raised to the given power.
794
 *
795
 * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
796
 *
797
 *      encoding method/host endian     (4 bytes)
798
 *      nvl_version                     (4 bytes)
799
 *      nvl_nvflag                      (4 bytes)
800
 *	encoded nvpairs:
801
 *		encoded size of the nvpair      (4 bytes)
802
 *		decoded size of the nvpair      (4 bytes)
803
 *		name string size                (4 bytes)
804
 *		name string data                (sizeof(NV_ALIGN4(string))
805
 *		data type                       (4 bytes)
806
 *		# of elements in the nvpair     (4 bytes)
807
 *		data
808
 *      2 zero's for the last nvpair
809
 *		(end of the entire list)	(8 bytes)
810
 *
811
 */
940
 */
941
static grub_uint8_t
942
vdev_raidz_exp2(unsigned a, int exp)
943
{
944
  if (a == 0)
945
    return (0);
946
947
  exp += vdev_raidz_log2[a];
948
  if (exp > 255)
949
    exp -= 255;
950
951
  return (vdev_raidz_pow2[exp]);
952
}
812
953
813
/*
954
/*
814
 * The nvlist_next_nvpair() function returns a handle to the next nvpair in the
955
 *  vdev_raidz_map_get() is hacked from vdev_raidz_map_alloc() in
815
 * list following nvpair. If nvpair is NULL, the first pair is returned. If
956
 *  usr/src/uts/common/fs/zfs/vdev_raidz.c.  If that routine changes,
816
 * nvpair is the last pair in the nvlist, NULL is returned.
957
 *  this might also need changing.
817
 */
958
 */
818
static const char *
819
nvlist_next_nvpair (const char *nvl, const char *nvpair)
820
{
821
  const char *nvp;
822
  int encode_size;
823
  int name_len;
824
  if (nvl == NULL)
825
    return NULL;
826
959
827
  if (nvpair == NULL)
960
#ifndef MIN
828
    {
961
#define	MIN(a, b)	((a) < (b) ? (a) : (b))
829
      /* skip over header, nvl_version and nvl_nvflag */
962
#endif
830
      nvpair = nvl + 4 * 3;
963
#ifndef roundup
831
    } 
964
#define	roundup(x, y)	(grub_divmod64 ( (x)+((y)-1), (y), NULL) *(y))
832
  else
965
#endif
966
#ifndef offsetof
967
#define	offsetof(s, m)	((grub_size_t)(&(((s *)0)->m)))
968
#endif
969
970
static raidz_map_t *
971
vdev_raidz_map_alloc(void *data, grub_uint64_t size, grub_uint64_t offset,
972
		   grub_uint64_t unit_shift, grub_uint64_t dcols,
973
		   grub_uint64_t nparity)
974
{
975
  raidz_map_t *rm;
976
  grub_uint64_t b = offset >> unit_shift;
977
  grub_uint64_t s = size >> unit_shift;
978
  grub_uint64_t f, o, q, r, c, bc, col, acols, scols, coff, devidx, asize, tot;
979
980
  o = grub_divmod64(b, dcols, NULL) << unit_shift;
981
  (void) grub_divmod64(b, dcols, &f);
982
  q = grub_divmod64(s, dcols - nparity, NULL);
983
  r = s - q * (dcols - nparity);
984
  bc = (r == 0 ? 0 : r + nparity);
985
  tot = s + nparity * (q + (r == 0 ? 0 : 1));
986
987
  if (q == 0)
833
    {
988
    {
834
      /* skip to the next nvpair */
989
      acols = bc;
835
      encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
990
      scols = MIN(dcols, roundup(bc, nparity + 1));
836
      nvpair += encode_size;
837
      /*If encode_size equals 0 nvlist_next_nvpair would return
838
       * the same pair received in input, leading to an infinite loop.
839
       * If encode_size is less than 0, this will move the pointer
840
       * backwards, *possibly* examinining two times the same nvpair
841
       * and potentially getting into an infinite loop. */
842
      if(encode_size <= 0)
843
	{
844
	  grub_dprintf ("zfs", "nvpair with size <= 0\n");
845
	  grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
846
	  return NULL;
847
	}
848
    }
991
    }
849
  /* 8 bytes of 0 marks the end of the list */
992
  else
850
  if (grub_get_unaligned64 (nvpair) == 0)
851
    return NULL;
852
  /*consistency checks*/
853
  if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE)
854
    {
993
    {
855
      grub_dprintf ("zfs", "nvlist overflow\n");
994
      acols = dcols;
856
      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
995
      scols = dcols;
857
      return NULL;
858
    }
996
    }
859
  encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
860
997
861
  nvp = nvpair + 4*2;
998
  rm = grub_malloc(offsetof(raidz_map_t, rm_col[scols]));
862
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
863
  nvp += 4;
864
999
865
  nvp = nvp + ((name_len + 3) & ~3); // align 
1000
  if (rm == NULL)
866
  if (nvp + 4 >= nvl + VDEV_PHYS_SIZE                        
867
      || encode_size < 0
868
      || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE)       
869
    {
1001
    {
870
      grub_dprintf ("zfs", "nvlist overflow\n");
871
      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
872
      return NULL;
1002
      return NULL;
873
    }
1003
    }
874
  /* end consistency checks */
875
1004
876
  return nvpair;
1005
  rm->rm_cols = acols;
877
}
1006
  rm->rm_scols = scols;
1007
  rm->rm_bigcols = bc;
1008
  rm->rm_skipstart = bc;
1009
  rm->rm_missingdata = 0;
1010
  rm->rm_missingparity = 0;
1011
  rm->rm_firstdatacol = nparity;
1012
  rm->rm_datacopy = NULL;
1013
  rm->rm_reports = 0;
1014
  rm->rm_freed = 0;
1015
  rm->rm_ecksuminjected = 0;
1016
1017
  asize = 0;
1018
1019
  for (c = 0; c < scols; c++)
1020
    {
1021
      col = f + c;
1022
      coff = o;
1023
      if (col >= dcols)
1024
	{
1025
	  col -= dcols;
1026
	  coff += 1ULL << unit_shift;
1027
	}
1028
      rm->rm_col[c].rc_devidx = col;
1029
      rm->rm_col[c].rc_offset = coff;
1030
      rm->rm_col[c].rc_data = NULL;
1031
      rm->rm_col[c].rc_gdata = NULL;
1032
      rm->rm_col[c].rc_error = 0;
1033
      rm->rm_col[c].rc_tried = 0;
1034
      rm->rm_col[c].rc_skipped = 0;
1035
1036
      if (c >= acols)
1037
	rm->rm_col[c].rc_size = 0;
1038
      else if (c < bc)
1039
	rm->rm_col[c].rc_size = (q + 1) << unit_shift;
1040
      else
1041
	rm->rm_col[c].rc_size = q << unit_shift;
878
1042
879
/*
1043
      asize += rm->rm_col[c].rc_size;
880
 * This function returns 0 on success and 1 on failure. On success, a string
1044
    }
881
 * containing the name of nvpair is saved in buf.
882
 */
883
static int
884
nvpair_name (const char *nvp, char **buf, grub_size_t *buflen)
885
{
886
  /* skip over encode/decode size */
887
  nvp += 4 * 2;
888
	
889
  *buf = (char *) (nvp + 4);
890
  *buflen = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
891
1045
892
  return 0;
1046
  rm->rm_asize = roundup(asize, (nparity + 1) << unit_shift);
893
}
1047
  rm->rm_nskip = roundup(tot, nparity + 1) - tot;
894
1048
895
/*
1049
  for (c = 0; c < rm->rm_firstdatacol; c++)
896
 * This function retrieves the value of the nvpair in the form of enumerated
1050
    rm->rm_col[c].rc_data = grub_malloc (rm->rm_col[c].rc_size);
897
 * type data_type_t.
898
 */
899
static int
900
nvpair_type (const char *nvp)
901
{
902
  int name_len, type;
903
1051
904
  /* skip over encode/decode size */
1052
  rm->rm_col[c].rc_data = data;
905
  nvp += 4 * 2;
906
1053
907
  /* skip over name_len */
1054
  for (c = c + 1; c < acols; c++)
908
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
1055
    rm->rm_col[c].rc_data = (char *)rm->rm_col[c - 1].rc_data +
909
  nvp += 4;
1056
				    rm->rm_col[c - 1].rc_size;
910
1057
911
  /* skip over name */
1058
  /*
912
  nvp = nvp + ((name_len + 3) & ~3); /* align */
1059
   * If all data stored spans all columns, there's a danger that parity
1060
   * will always be on the same device and, since parity isn't read
1061
   * during normal operation, that that device's I/O bandwidth won't be
1062
   * used effectively. We therefore switch the parity every 1MB.
1063
   *
1064
   * ... at least that was, ostensibly, the theory. As a practical
1065
   * matter unless we juggle the parity between all devices evenly, we
1066
   * won't see any benefit. Further, occasional writes that aren't a
1067
   * multiple of the LCM of the number of children and the minimum
1068
   * stripe width are sufficient to avoid pessimal behavior.
1069
   * Unfortunately, this decision created an implicit on-disk format
1070
   * requirement that we need to support for all eternity, but only
1071
   * for single-parity RAID-Z.
1072
   *
1073
   * If we intend to skip a sector in the zeroth column for padding
1074
   * we must make sure to note this swap. We will never intend to
1075
   * skip the first column since at least one data and one parity
1076
   * column must appear in each row.
1077
   */
913
1078
914
  type = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
1079
  if (rm->rm_firstdatacol == 1 && (offset & (1ULL << 20)))
1080
    {
1081
       devidx = rm->rm_col[0].rc_devidx;
1082
       o = rm->rm_col[0].rc_offset;
1083
       rm->rm_col[0].rc_devidx = rm->rm_col[1].rc_devidx;
1084
       rm->rm_col[0].rc_offset = rm->rm_col[1].rc_offset;
1085
       rm->rm_col[1].rc_devidx = devidx;
1086
       rm->rm_col[1].rc_offset = o;
915
1087
916
  return type;
1088
       if (rm->rm_skipstart == 0)
1089
	 rm->rm_skipstart = 1;
1090
    }
1091
1092
  return (rm);
917
}
1093
}
918
1094
919
static int
1095
static void
920
nvpair_value (const char *nvp,char **val,
1096
vdev_raidz_map_free(raidz_map_t *rm)
921
	      grub_size_t *size_out, grub_size_t *nelm_out)
922
{
1097
{
923
  int name_len,nelm,encode_size;
1098
  grub_uint64_t c;
924
1099
925
  /* skip over encode/decode size */
1100
  for (c = 0; c < rm->rm_firstdatacol; c++)
926
  encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvp));
1101
    {
927
  nvp += 8;
1102
      grub_free (rm->rm_col[c].rc_data);
928
1103
929
  /* skip over name_len */
1104
      if (rm->rm_col[c].rc_gdata != NULL)
930
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
1105
	grub_free (rm->rm_col[c].rc_gdata);
931
  nvp += 4;
932
933
  /* skip over name */
934
  nvp = nvp + ((name_len + 3) & ~3); /* align */
935
	
936
  /* skip over type */
937
  nvp += 4;
938
  nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
939
  nvp +=4;
940
  if (nelm < 1)
941
    {
942
      grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
943
      return 0;
944
    }
1106
    }
945
  *val = (char *) nvp;
1107
946
  *size_out = encode_size;
1108
  if (rm->rm_datacopy != NULL)
947
  if (nelm_out)
1109
    grub_free (rm->rm_datacopy);
948
    *nelm_out = nelm;
1110
  grub_free (rm);
949
	    
950
  return 1;
951
}
1111
}
952
1112
953
/*
954
 * Check the disk label information and retrieve needed vdev name-value pairs.
955
 *
956
 */
957
static grub_err_t
1113
static grub_err_t
958
check_pool_label (struct grub_zfs_data *data,
1114
zio_checksum_error(blkptr_t *bp, grub_zfs_endian_t endian, void *buf)
959
		  struct grub_zfs_device_desc *diskdesc,
960
		  int *inserted)
961
{
1115
{
962
  grub_uint64_t pool_state, txg = 0;
1116
  zio_cksum_t zc;
963
  char *nvlist,*features;
1117
  grub_uint32_t checksum;
964
#if 0
1118
  grub_size_t size;
965
  char *nv;
1119
  grub_uint64_t offset;
966
#endif
967
  grub_uint64_t poolguid;
968
  grub_uint64_t version;
969
  int found;
970
  grub_err_t err;
971
  grub_zfs_endian_t endian;
972
  vdev_phys_t *phys;
973
  zio_cksum_t emptycksum;
974
975
  *inserted = 0;
976
977
  err = zfs_fetch_nvlist (diskdesc, &nvlist);
978
  if (err)
979
    return err;
980
981
  phys = (vdev_phys_t*) nvlist;
982
  if (grub_zfs_to_cpu64 (phys->vp_zbt.zec_magic,
983
			 GRUB_ZFS_LITTLE_ENDIAN)
984
      == ZEC_MAGIC)
985
    endian = GRUB_ZFS_LITTLE_ENDIAN;
986
  else if (grub_zfs_to_cpu64 (phys->vp_zbt.zec_magic,
987
			      GRUB_ZFS_BIG_ENDIAN)
988
	   == ZEC_MAGIC)
989
    endian = GRUB_ZFS_BIG_ENDIAN;
990
  else
991
    {
992
      grub_free (nvlist);
993
      return grub_error (GRUB_ERR_BAD_FS,
994
			 "bad vdev_phys_t.vp_zbt.zec_magic number");
995
    }
996
  /* Now check the integrity of the vdev_phys_t structure though checksum.  */
997
  ZIO_SET_CHECKSUM(&emptycksum, diskdesc->vdev_phys_sector << 9, 0, 0, 0);
998
  err = zio_checksum_verify (emptycksum, ZIO_CHECKSUM_LABEL, endian,
999
			     nvlist, VDEV_PHYS_SIZE);
1000
  if (err)
1001
    return err;
1002
1120
1003
  grub_dprintf ("zfs", "check 2 passed\n");
1121
  grub_memset (&zc, 0, sizeof (zc));
1004
1122
1005
  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
1123
  if (BP_IS_GANG(bp, endian))
1006
					 &pool_state);
1007
  if (! found)
1008
    {
1124
    {
1009
      grub_free (nvlist);
1125
      dva_t *dva = BP_IDENTITY(bp);
1010
      if (! grub_errno)
1126
      grub_uint64_t txg = BP_PHYSICAL_BIRTH(bp);
1011
	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_STATE " not found");
1127
      checksum = ZIO_CHECKSUM_GANG_HEADER;
1012
      return grub_errno;
1128
      size = SPA_GANGBLOCKSIZE;
1129
      offset = DVA_GET_OFFSET (dva, endian);
1130
      ZIO_SET_CHECKSUM (&zc, DVA_GET_VDEV(dva), offset, txg, 0);
1013
    }
1131
    }
1014
  grub_dprintf ("zfs", "check 3 passed\n");
1132
  else
1015
1016
  if (pool_state == POOL_STATE_DESTROYED)
1017
    {
1133
    {
1018
      grub_free (nvlist);
1134
      checksum = BP_GET_CHECKSUM(bp, endian);
1019
      return grub_error (GRUB_ERR_BAD_FS, "zpool is marked as destroyed");
1135
      size = BP_GET_PSIZE(bp, endian);
1136
      zc = bp->blk_cksum;
1020
    }
1137
    }
1021
  grub_dprintf ("zfs", "check 4 passed\n");
1138
  return zio_checksum_verify (zc, checksum, endian, buf, size);
1139
}
1022
1140
1023
  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_TXG, &txg);
1141
static void
1024
  if (!found)
1142
vdev_raidz_generate_parity_pq(raidz_map_t *rm)
1025
    {
1143
{
1026
      grub_free (nvlist);
1144
  grub_uint64_t *p, *q, *src, pcnt, ccnt, mask, i;
1027
      if (! grub_errno)
1145
  int c;
1028
	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_TXG " not found");
1029
      return grub_errno;
1030
    }
1031
  grub_dprintf ("zfs", "check 6 passed\n");
1032
1146
1033
  /* not an active device */
1147
  pcnt = grub_divmod64(rm->rm_col[VDEV_RAIDZ_P].rc_size, sizeof (src[0]), NULL);
1034
  if (txg == 0)
1035
    {
1036
      grub_free (nvlist);
1037
      return grub_error (GRUB_ERR_BAD_FS, "zpool isn't active");
1038
    }
1039
  grub_dprintf ("zfs", "check 7 passed\n");
1040
1148
1041
  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_VERSION,
1149
  for (c = rm->rm_firstdatacol; c < (int) rm->rm_cols; c++)
1042
					 &version);
1043
  if (! found)
1044
    {
1150
    {
1045
      grub_free (nvlist);
1151
      src = rm->rm_col[c].rc_data;
1046
      if (! grub_errno)
1152
      p = rm->rm_col[VDEV_RAIDZ_P].rc_data;
1047
	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_VERSION " not found");
1153
      q = rm->rm_col[VDEV_RAIDZ_Q].rc_data;
1048
      return grub_errno;
1049
    }
1050
  grub_dprintf ("zfs", "check 8 passed\n");
1051
1154
1052
  if (!SPA_VERSION_IS_SUPPORTED(version))
1155
      ccnt = grub_divmod64(rm->rm_col[c].rc_size, sizeof (src[0]), NULL);
1053
    {
1054
      grub_free (nvlist);
1055
      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
1056
			 "too new version %llu > %llu",
1057
			 (unsigned long long) version,
1058
			 (unsigned long long) SPA_VERSION_BEFORE_FEATURES);
1059
    }
1060
  grub_dprintf ("zfs", "check 9 passed\n");
1061
1156
1062
  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID,
1157
      if (c == (int) rm->rm_firstdatacol)
1063
					 &(diskdesc->guid));
1158
	{
1064
  if (! found)
1159
	  for (i = 0; i < ccnt; i++, src++, p++, q++)
1065
    {
1160
	    {
1066
      grub_free (nvlist);
1161
	      *p = *src;
1067
      if (! grub_errno)
1162
	      *q = *src;
1068
	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_GUID " not found");
1163
	    }
1069
      return grub_errno;
1164
	  for (; i < pcnt; i++, src++, p++, q++)
1070
    }
1165
	    {
1166
	      *p = 0;
1167
	      *q = 0;
1168
	    }
1169
	}
1170
      else
1171
	{
1172
	  for (i = 0; i < ccnt; i++, src++, p++, q++)
1173
	    {
1174
	      *p ^= *src;
1071
1175
1072
  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID,
1176
	      VDEV_RAIDZ_64MUL_2(*q, mask);
1073
					 &poolguid);
1177
	      *q ^= *src;
1074
  if (! found)
1178
	    }
1075
    {
1076
      grub_free (nvlist);
1077
      if (! grub_errno)
1078
	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_GUID " not found");
1079
      return grub_errno;
1080
    }
1081
1179
1082
  grub_dprintf ("zfs", "check 11 passed\n");
1180
	  /*
1181
	   * Treat short columns as though they are full of 0s.
1182
	   * Note that there's therefore nothing needed for P.
1183
	   */
1184
	  for (; i < pcnt; i++, q++)
1185
	    VDEV_RAIDZ_64MUL_2(*q, mask);
1186
	}
1187
    }
1188
}
1083
1189
1084
  if (data->mounted && data->guid != poolguid)
1190
static int
1085
    return grub_error (GRUB_ERR_BAD_FS, "another zpool");
1191
vdev_raidz_reconstruct_p(raidz_map_t *rm, int *tgts)
1086
  else
1192
{
1087
    data->guid = poolguid;
1193
  grub_uint64_t *dst, *src, xcount, ccount, count, i;
1194
  int x = tgts[0];
1195
  int c;
1088
1196
1089
  {
1197
  xcount = grub_divmod64(rm->rm_col[x].rc_size, sizeof (src[0]), NULL);
1090
    char *nv;
1091
    nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
1092
1198
1093
    if (!nv)
1199
  src = rm->rm_col[VDEV_RAIDZ_P].rc_data;
1094
      {
1200
  dst = rm->rm_col[x].rc_data;
1095
	grub_free (nvlist);
1201
  for (i = 0; i < xcount; i++, dst++, src++)
1096
	return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev tree");
1202
    *dst = *src;
1097
      }
1203
  for (c = rm->rm_firstdatacol; c < (int) rm->rm_cols; c++)
1098
    err = fill_vdev_info (data, nv, diskdesc, inserted);
1099
    if (err)
1100
      {
1101
	grub_free (nv);
1102
	grub_free (nvlist);
1103
	return err;
1104
      }
1105
    grub_free (nv);
1106
  }
1107
  grub_dprintf ("zfs", "check 10 passed\n");
1108
  features = grub_zfs_nvlist_lookup_nvlist(nvlist,
1109
					   ZPOOL_CONFIG_FEATURES_FOR_READ);
1110
  if (features)
1111
    {
1204
    {
1112
      const char *nvp=NULL;
1205
      src = rm->rm_col[c].rc_data;
1113
      char name[MAX_SUPPORTED_FEATURE_STRLEN + 1];
1206
      dst = rm->rm_col[x].rc_data;
1114
      char *nameptr;
1207
      if (c == x)
1115
      grub_size_t namelen;
1208
        continue;
1116
      while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL)
1209
1117
	{
1210
      ccount = grub_divmod64(rm->rm_col[c].rc_size, sizeof (src[0]), NULL);
1118
	  nvpair_name (nvp, &nameptr, &namelen);
1211
      count = MIN(ccount, xcount);
1119
	  if(namelen > MAX_SUPPORTED_FEATURE_STRLEN)
1212
1120
	    namelen = MAX_SUPPORTED_FEATURE_STRLEN;
1213
      for (i = 0; i < count; i++, dst++, src++)
1121
	  grub_memcpy (name, nameptr, namelen);
1214
	{
1122
	  name[namelen] = '\0';
1215
	  *dst ^= *src;
1123
	  grub_dprintf("zfs","str=%s\n",name);
1124
	  if (check_feature(name,1, NULL) != 0)
1125
	    {
1126
	      grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name);
1127
	      err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name);
1128
	      return err;
1129
	    }
1130
	}
1216
	}
1131
    }
1217
    }
1132
  grub_dprintf ("zfs", "check 12 passed (feature flags)\n");
1133
  grub_free (nvlist);
1134
1218
1135
  return GRUB_ERR_NONE;
1219
  return (1 << VDEV_RAIDZ_P);
1136
}
1220
}
1137
1221
1138
static grub_err_t
1222
static int
1139
scan_disk (grub_device_t dev, struct grub_zfs_data *data,
1223
vdev_raidz_reconstruct_q(raidz_map_t *rm, int *tgts)
1140
	   int original, int *inserted)
1141
{
1224
{
1142
  int label = 0;
1225
  grub_uint64_t *dst, *src, xcount, ccount, count, mask, i;
1143
  uberblock_phys_t *ub_array, *ubbest = NULL;
1226
  grub_uint8_t *b;
1144
  vdev_boot_header_t *bh;
1227
  int x = tgts[0];
1145
  grub_err_t err;
1228
  int c, j, exp;
1146
  int vdevnum;
1147
  struct grub_zfs_device_desc desc;
1148
1229
1149
  ub_array = grub_malloc (VDEV_UBERBLOCK_RING);
1230
  xcount = grub_divmod64(rm->rm_col[x].rc_size, sizeof (src[0]), NULL);
1150
  if (!ub_array)
1151
    return grub_errno;
1152
1231
1153
  bh = grub_malloc (VDEV_BOOT_HEADER_SIZE);
1232
  for (c = rm->rm_firstdatacol; c < (int) rm->rm_cols; c++)
1154
  if (!bh)
1155
    {
1233
    {
1156
      grub_free (ub_array);
1234
      src = rm->rm_col[c].rc_data;
1157
      return grub_errno;
1235
      dst = rm->rm_col[x].rc_data;
1158
    }
1159
1160
  vdevnum = VDEV_LABELS;
1161
1162
  desc.dev = dev;
1163
  desc.original = original;
1164
1236
1165
  /* Don't check back labels on CDROM.  */
1237
      if (c == x)
1166
  if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
1238
	ccount = 0;
1167
    vdevnum = VDEV_LABELS / 2;
1239
      else
1240
	ccount = grub_divmod64(rm->rm_col[c].rc_size, sizeof (src[0]), NULL);
1168
1241
1169
  for (label = 0; ubbest == NULL && label < vdevnum; label++)
1242
      count = MIN(ccount, xcount);
1170
    {
1243
      if (c == (int) rm->rm_firstdatacol)
1171
      desc.vdev_phys_sector
1172
	= label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)
1173
	+ ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT)
1174
	+ (label < VDEV_LABELS / 2 ? 0 : 
1175
	   ALIGN_DOWN (grub_disk_get_size (dev->disk), sizeof (vdev_label_t))
1176
	   - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT));
1177
1178
      /* Read in the uberblock ring (128K). */
1179
      err = grub_disk_read (dev->disk, desc.vdev_phys_sector
1180
			    + (VDEV_PHYS_SIZE >> SPA_MINBLOCKSHIFT),
1181
			    0, VDEV_UBERBLOCK_RING, (char *) ub_array);
1182
      if (err)
1183
	{
1244
	{
1184
	  grub_errno = GRUB_ERR_NONE;
1245
	  for (i = 0; i < count; i++, dst++, src++)
1185
	  continue;
1246
	    *dst = *src;
1186
	}
1187
      grub_dprintf ("zfs", "label ok %d\n", label);
1188
1247
1189
      err = check_pool_label (data, &desc, inserted);
1248
	  for (; i < xcount; i++, dst++)
1190
      if (err || !*inserted)
1249
	    *dst = 0;
1191
	{
1192
	  grub_errno = GRUB_ERR_NONE;
1193
	  continue;
1194
	}
1250
	}
1195
1251
      else
1196
      ubbest = find_bestub (ub_array, &desc);
1197
      if (!ubbest)
1198
	{
1252
	{
1199
	  grub_dprintf ("zfs", "No uberblock found\n");
1253
	  for (i = 0; i < count; i++, dst++, src++)
1200
	  grub_errno = GRUB_ERR_NONE;
1254
	    {
1201
	  continue;
1255
	      VDEV_RAIDZ_64MUL_2(*dst, mask);
1256
	      *dst ^= *src;
1257
	    }
1258
1259
	  for (; i < xcount; i++, dst++)
1260
	    VDEV_RAIDZ_64MUL_2(*dst, mask);
1202
	}
1261
	}
1262
    }
1203
1263
1204
      grub_memmove (&(desc.current_uberblock),
1264
  src = rm->rm_col[VDEV_RAIDZ_Q].rc_data;
1205
		    &ubbest->ubp_uberblock, sizeof (uberblock_t));
1265
  dst = rm->rm_col[x].rc_data;
1206
      if (original)
1266
  exp = 255 - (rm->rm_cols - 1 - x);
1207
	grub_memmove (&(data->current_uberblock),
1208
		      &ubbest->ubp_uberblock, sizeof (uberblock_t));
1209
1267
1210
#if 0
1268
  for (i = 0; i < xcount; i++, dst++, src++)
1211
      if (find_best_root &&
1269
    {
1212
	  vdev_uberblock_compare (&ubbest->ubp_uberblock,
1270
      *dst ^= *src;
1213
				  &(current_uberblock)) <= 0)
1271
      for (j = 0, b = (grub_uint8_t *)dst; j < 8; j++, b++)
1214
	continue;
1272
	*b = vdev_raidz_exp2(*b, exp);
1215
#endif
1216
      grub_free (ub_array);
1217
      grub_free (bh);
1218
      return GRUB_ERR_NONE;
1219
    }
1273
    }
1220
  
1221
  grub_free (ub_array);
1222
  grub_free (bh);
1223
1274
1224
  return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label");
1275
  return (1 << VDEV_RAIDZ_Q);
1225
}
1276
}
1226
1277
1227
/* Helper for scan_devices.  */
1228
static int
1278
static int
1229
scan_devices_iter (const char *name, void *hook_data)
1279
vdev_raidz_reconstruct_pq(raidz_map_t *rm, int *tgts)
1230
{
1280
{
1231
  struct grub_zfs_data *data = hook_data;
1281
  grub_uint8_t *p, *q, *pxy, *qxy, *xd, *yd, tmp, a, b, aexp, bexp;
1232
  grub_device_t dev;
1282
  void *pdata, *qdata;
1233
  grub_err_t err;
1283
  grub_uint64_t xsize, ysize, i;
1234
  int inserted;
1284
  int x = tgts[0];
1285
  int y = tgts[1];
1235
1286
1236
  dev = grub_device_open (name);
1287
  /*
1237
  if (!dev)
1288
   * Move the parity data aside -- we're going to compute parity as
1238
    return 0;
1289
   * though columns x and y were full of zeros -- Pxy and Qxy. We want to
1239
  if (!dev->disk)
1290
   * reuse the parity generation mechanism without trashing the actual
1240
    {
1291
   * parity so we make those columns appear to be full of zeros by
1241
      grub_device_close (dev);
1292
   * setting their lengths to zero.
1242
      return 0;
1293
   */
1243
    }
1294
  pdata = rm->rm_col[VDEV_RAIDZ_P].rc_data;
1244
  err = scan_disk (dev, data, 0, &inserted);
1295
  qdata = rm->rm_col[VDEV_RAIDZ_Q].rc_data;
1245
  if (err == GRUB_ERR_BAD_FS)
1296
  xsize = rm->rm_col[x].rc_size;
1246
    {
1297
  ysize = rm->rm_col[y].rc_size;
1247
      grub_device_close (dev);
1298
1248
      grub_errno = GRUB_ERR_NONE;
1299
  rm->rm_col[VDEV_RAIDZ_P].rc_data =
1249
      return 0;
1300
    grub_malloc(rm->rm_col[VDEV_RAIDZ_P].rc_size);
1250
    }
1301
  rm->rm_col[VDEV_RAIDZ_Q].rc_data =
1251
  if (err)
1302
    grub_malloc(rm->rm_col[VDEV_RAIDZ_Q].rc_size);
1303
  rm->rm_col[x].rc_size = 0;
1304
  rm->rm_col[y].rc_size = 0;
1305
1306
  vdev_raidz_generate_parity_pq(rm);
1307
1308
  rm->rm_col[x].rc_size = xsize;
1309
  rm->rm_col[y].rc_size = ysize;
1310
1311
  p = pdata;
1312
  q = qdata;
1313
  pxy = rm->rm_col[VDEV_RAIDZ_P].rc_data;
1314
  qxy = rm->rm_col[VDEV_RAIDZ_Q].rc_data;
1315
  xd = rm->rm_col[x].rc_data;
1316
  yd = rm->rm_col[y].rc_data;
1317
1318
  /*
1319
   * We now have:
1320
   *      Pxy = P + D_x + D_y
1321
   *      Qxy = Q + 2^(ndevs - 1 - x) * D_x + 2^(ndevs - 1 - y) * D_y
1322
   *
1323
   * We can then solve for D_x:
1324
   *      D_x = A * (P + Pxy) + B * (Q + Qxy)
1325
   * where
1326
   *      A = 2^(x - y) * (2^(x - y) + 1)^-1
1327
   *      B = 2^(ndevs - 1 - x) * (2^(x - y) + 1)^-1
1328
   *
1329
   * With D_x in hand, we can easily solve for D_y:
1330
   *      D_y = P + Pxy + D_x
1331
   */
1332
1333
  a = vdev_raidz_pow2[255 + x - y];
1334
  b = vdev_raidz_pow2[255 - (rm->rm_cols - 1 - x)];
1335
  tmp = 255 - vdev_raidz_log2[a ^ 1];
1336
1337
  aexp = vdev_raidz_log2[vdev_raidz_exp2(a, tmp)];
1338
  bexp = vdev_raidz_log2[vdev_raidz_exp2(b, tmp)];
1339
1340
  for (i = 0; i < xsize; i++, p++, q++, pxy++, qxy++, xd++, yd++)
1252
    {
1341
    {
1253
      grub_device_close (dev);
1342
      *xd = vdev_raidz_exp2(*p ^ *pxy, aexp) ^ vdev_raidz_exp2(*q ^ *qxy, bexp);
1254
      grub_print_error ();
1343
1255
      return 0;
1344
      if (i < ysize)
1345
        *yd = *p ^ *pxy ^ *xd;
1256
    }
1346
    }
1257
1347
1258
  if (!inserted)
1348
  grub_free(rm->rm_col[VDEV_RAIDZ_P].rc_data);
1259
    grub_device_close (dev);
1349
  grub_free(rm->rm_col[VDEV_RAIDZ_Q].rc_data);
1260
  
1350
1261
  return 0;
1351
  /*
1352
   * Restore the saved parity data.
1353
   */
1354
  rm->rm_col[VDEV_RAIDZ_P].rc_data = pdata;
1355
  rm->rm_col[VDEV_RAIDZ_Q].rc_data = qdata;
1356
1357
  return ((1 << VDEV_RAIDZ_P) | (1 << VDEV_RAIDZ_Q));
1262
}
1358
}
1263
1359
1264
static grub_err_t
1360
static void
1265
scan_devices (struct grub_zfs_data *data)
1361
vdev_raidz_matrix_init(int n, int nmap, int *map, grub_uint8_t **rows)
1266
{
1362
{
1267
  grub_device_iterate (scan_devices_iter, data);
1363
  int i, j;
1268
  return GRUB_ERR_NONE;
1364
  int pow;
1365
1366
  /*
1367
   * Fill in the missing rows of interest.
1368
   */
1369
  for (i = 0; i < nmap; i++)
1370
    {
1371
      pow = map[i] * n;
1372
      if (pow > 255)
1373
	pow -= 255;
1374
1375
      for (j = 0; j < n; j++)
1376
	{
1377
	  pow -= map[i];
1378
	  if (pow < 0)
1379
	    pow += 255;
1380
	  rows[i][j] = vdev_raidz_pow2[pow];
1381
	}
1382
    }
1269
}
1383
}
1270
1384
1271
/* x**y.  */
1385
static void
1272
static grub_uint8_t powx[255 * 2];
1386
vdev_raidz_matrix_invert(raidz_map_t *rm, int n, int nmissing, int *missing,
1273
/* Such an s that x**s = y */
1387
    grub_uint8_t **rows, grub_uint8_t **invrows, const grub_uint8_t *used)
1274
static int powx_inv[256];
1275
static const grub_uint8_t poly = 0x1d;
1276
1277
/* perform the operation a ^= b * (x ** (known_idx * recovery_pow) ) */
1278
static inline void
1279
xor_out (grub_uint8_t *a, const grub_uint8_t *b, grub_size_t s,
1280
	 unsigned known_idx, unsigned recovery_pow)
1281
{
1388
{
1282
  unsigned add;
1389
  int i, j, ii, jj;
1390
  grub_uint8_t log;
1283
1391
1284
  /* Simple xor.  */
1392
  /*
1285
  if (known_idx == 0 || recovery_pow == 0)
1393
   * First initialize the storage where we'll compute the inverse rows.
1394
   */
1395
  for (i = 0; i < nmissing; i++)
1286
    {
1396
    {
1287
      grub_crypto_xor (a, a, b, s);
1397
      for (j = 0; j < n; j++)
1288
      return;
1398
	invrows[i][j] = (i == j) ? 1 : 0;
1399
    }
1400
1401
  /*
1402
   * Subtract all trivial rows from the rows of consequence.
1403
   */
1404
  for (i = 0; i < nmissing; i++)
1405
    {
1406
      for (j = nmissing; j < n; j++)
1407
	{
1408
	   jj = used[j] - rm->rm_firstdatacol;
1409
	   invrows[i][j] = rows[i][jj];
1410
	   rows[i][jj] = 0;
1411
        }
1412
    }
1413
1414
  /*
1415
   * For each of the rows of interest, we must normalize it and subtract
1416
   * a multiple of it from the other rows.
1417
   */
1418
  for (i = 0; i < nmissing; i++)
1419
    {
1420
      /*
1421
       * Compute the inverse of the first element and multiply each
1422
       * element in the row by that value.
1423
       */
1424
      log = 255 - vdev_raidz_log2[rows[i][missing[i]]];
1425
1426
      for (j = 0; j < n; j++)
1427
	{
1428
	   rows[i][j] = vdev_raidz_exp2(rows[i][j], log);
1429
	   invrows[i][j] = vdev_raidz_exp2(invrows[i][j], log);
1430
	}
1431
1432
      for (ii = 0; ii < nmissing; ii++)
1433
	{
1434
	   if (i == ii)
1435
	     continue;
1436
1437
	   log = vdev_raidz_log2[rows[ii][missing[i]]];
1438
1439
	   for (j = 0; j < n; j++)
1440
	     {
1441
		rows[ii][j] ^= vdev_raidz_exp2(rows[i][j], log);
1442
		invrows[ii][j] ^= vdev_raidz_exp2(invrows[i][j], log);
1443
	     }
1444
	}
1289
    }
1445
    }
1290
  add = (known_idx * recovery_pow) % 255;
1291
  for (;s--; b++, a++)
1292
    if (*b)
1293
      *a ^= powx[powx_inv[*b] + add];
1294
}
1446
}
1295
1447
1296
static inline grub_uint8_t
1448
static void
1297
gf_mul (grub_uint8_t a, grub_uint8_t b)
1449
vdev_raidz_matrix_reconstruct(raidz_map_t *rm, int n, int nmissing,
1450
    int *missing, grub_uint8_t **invrows, const grub_uint8_t *used)
1298
{
1451
{
1299
  if (a == 0 || b == 0)
1452
  int i, j, x, cc, c;
1300
    return 0;
1453
  grub_uint8_t *src;
1301
  return powx[powx_inv[a] + powx_inv[b]];
1454
  grub_uint64_t ccount;
1302
}
1455
  grub_uint8_t *dst[VDEV_RAIDZ_MAXPARITY];
1456
  grub_uint64_t dcount[VDEV_RAIDZ_MAXPARITY];
1457
  grub_uint8_t log = 0;
1458
  grub_uint8_t val;
1459
  int ll;
1460
  grub_uint8_t *invlog[VDEV_RAIDZ_MAXPARITY];
1461
  grub_uint8_t *p, *pp;
1462
  grub_size_t psize;
1303
1463
1304
#define MAX_NBUFS 4
1464
  psize = sizeof (invlog[0][0]) * n * nmissing;
1465
  p = grub_malloc(psize);
1305
1466
1306
static grub_err_t
1467
  for (pp = p, i = 0; i < nmissing; i++)
1307
recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs,
1308
	  const unsigned *powers,
1309
	  const unsigned *idx)
1310
{
1311
  grub_dprintf ("zfs", "recovering %u buffers\n", nbufs);
1312
  /* Now we have */
1313
  /* b_i = sum (r_j* (x ** (powers[i] * idx[j])))*/
1314
  /* Let's invert the matrix in question. */
1315
  switch (nbufs)
1316
    {
1468
    {
1317
      /* Easy: r_0 = bufs[0] / (x << (powers[i] * idx[j])).  */
1469
      invlog[i] = pp;
1318
    case 1:
1470
      pp += n;
1319
      {
1471
    }
1320
	int add;
1472
1321
	grub_uint8_t *a;
1473
  for (i = 0; i < nmissing; i++)
1322
	if (powers[0] == 0 || idx[0] == 0)
1474
    {
1323
	  return GRUB_ERR_NONE;
1475
      for (j = 0; j < n; j++)
1324
	add = 255 - ((powers[0] * idx[0]) % 255);
1476
	invlog[i][j] = vdev_raidz_log2[invrows[i][j]];
1325
	for (a = bufs[0]; s--; a++)
1477
    }
1326
	  if (*a)
1478
1327
	    *a = powx[powx_inv[*a] + add];
1479
  for (i = 0; i < n; i++)
1328
	return GRUB_ERR_NONE;
1480
    {
1329
      }
1481
      c = used[i];
1330
      /* Case 2x2: Let's use the determinant formula.  */
1331
    case 2:
1332
      {
1333
	grub_uint8_t det, det_inv;
1334
	grub_uint8_t matrixinv[2][2];
1335
	unsigned i;
1336
	/* The determinant is: */
1337
	det = (powx[(powers[0] * idx[0] + powers[1] * idx[1]) % 255]
1338
	       ^ powx[(powers[0] * idx[1] + powers[1] * idx[0]) % 255]);
1339
	if (det == 0)
1340
	  return grub_error (GRUB_ERR_BAD_FS, "singular recovery matrix");
1341
	det_inv = powx[255 - powx_inv[det]];
1342
	matrixinv[0][0] = gf_mul (powx[(powers[1] * idx[1]) % 255], det_inv);
1343
	matrixinv[1][1] = gf_mul (powx[(powers[0] * idx[0]) % 255], det_inv);
1344
	matrixinv[0][1] = gf_mul (powx[(powers[0] * idx[1]) % 255], det_inv);
1345
	matrixinv[1][0] = gf_mul (powx[(powers[1] * idx[0]) % 255], det_inv);
1346
	for (i = 0; i < s; i++)
1347
	  {
1348
	    grub_uint8_t b0, b1;
1349
	    b0 = bufs[0][i];
1350
	    b1 = bufs[1][i];
1351
1352
	    bufs[0][i] = (gf_mul (b0, matrixinv[0][0])
1353
			  ^ gf_mul (b1, matrixinv[0][1]));
1354
	    bufs[1][i] = (gf_mul (b0, matrixinv[1][0])
1355
			  ^ gf_mul (b1, matrixinv[1][1]));
1356
	  }
1357
	return GRUB_ERR_NONE;
1358
      }
1359
      /* Otherwise use Gauss.  */
1360
    case 3:
1361
      {
1362
	grub_uint8_t matrix1[MAX_NBUFS][MAX_NBUFS], matrix2[MAX_NBUFS][MAX_NBUFS];
1363
	int i, j, k;
1364
1482
1365
	for (i = 0; i < nbufs; i++)
1483
      src = rm->rm_col[c].rc_data;
1366
	  for (j = 0; j < nbufs; j++)
1484
      ccount = rm->rm_col[c].rc_size;
1367
	    matrix1[i][j] = powx[(powers[i] * idx[j]) % 255];
1485
      for (j = 0; j < nmissing; j++)
1368
	for (i = 0; i < nbufs; i++)
1486
	{
1369
	  for (j = 0; j < nbufs; j++)
1487
	  cc = missing[j] + rm->rm_firstdatacol;
1370
	    matrix2[i][j] = 0;
1488
1371
	for (i = 0; i < nbufs; i++)
1489
	  dst[j] = rm->rm_col[cc].rc_data;
1372
	  matrix2[i][i] = 1;
1490
	  dcount[j] = rm->rm_col[cc].rc_size;
1491
	}
1373
1492
1374
	for (i = 0; i < nbufs; i++)
1493
	for (x = 0; x < (int) ccount; x++, src++)
1375
	  {
1494
	  {
1376
	    grub_uint8_t mul;
1495
	    if (*src != 0)
1377
	    for (j = i; j < nbufs; j++)	    
1496
	      log = vdev_raidz_log2[*src];
1378
	      if (matrix1[i][j])
1497
1379
		break;
1498
	    for (cc = 0; cc < nmissing; cc++)
1380
	    if (j == nbufs)
1381
	      return grub_error (GRUB_ERR_BAD_FS, "singular recovery matrix");
1382
	    if (j != i)
1383
	      {
1499
	      {
1384
		int xchng;
1500
		if (x >= (int) dcount[cc])
1385
		xchng = j;
1501
		  continue;
1386
		for (j = 0; j < nbufs; j++)
1502
1387
		  {
1503
		if (*src == 0)
1388
		    grub_uint8_t t;
1504
		  val = 0;
1389
		    t = matrix1[xchng][j];
1505
		else
1390
		    matrix1[xchng][j] = matrix1[i][j];
1391
		    matrix1[i][j] = t;
1392
		  }
1393
		for (j = 0; j < nbufs; j++)
1394
		  {
1506
		  {
1395
		    grub_uint8_t t;
1507
		    if ((ll = log + invlog[cc][i]) >= 255)
1396
		    t = matrix2[xchng][j];
1508
		      ll -= 255;
1397
		    matrix2[xchng][j] = matrix2[i][j];
1509
		    val = vdev_raidz_pow2[ll];
1398
		    matrix2[i][j] = t;
1399
		  }
1510
		  }
1400
	      }
1401
	    mul = powx[255 - powx_inv[matrix1[i][i]]];
1402
	    for (j = 0; j < nbufs; j++)
1403
	      matrix1[i][j] = gf_mul (matrix1[i][j], mul);
1404
	    for (j = 0; j < nbufs; j++)
1405
	      matrix2[i][j] = gf_mul (matrix2[i][j], mul);
1406
	    for (j = i + 1; j < nbufs; j++)
1407
	      {
1408
		mul = matrix1[j][i];
1409
		for (k = 0; k < nbufs; k++)
1410
		  matrix1[j][k] ^= gf_mul (matrix1[i][k], mul);
1411
		for (k = 0; k < nbufs; k++)
1412
		  matrix2[j][k] ^= gf_mul (matrix2[i][k], mul);
1413
	      }
1414
	  }
1415
	for (i = nbufs - 1; i >= 0; i--)
1416
	  {
1417
	    for (j = 0; j < i; j++)
1418
	      {
1419
		grub_uint8_t mul;
1420
		mul = matrix1[j][i];
1421
		for (k = 0; k < nbufs; k++)
1422
		  matrix1[j][k] ^= gf_mul (matrix1[i][k], mul);
1423
		for (k = 0; k < nbufs; k++)
1424
		  matrix2[j][k] ^= gf_mul (matrix2[i][k], mul);
1425
	      }
1426
	  }
1427
1511
1428
	for (i = 0; i < (int) s; i++)
1512
		if (i == 0)
1429
	  {
1513
		  dst[cc][x] = val;
1430
	    grub_uint8_t b[MAX_NBUFS];
1514
		else
1431
	    for (j = 0; j < nbufs; j++)
1515
		  dst[cc][x] ^= val;
1432
	      b[j] = bufs[j][i];
1433
	    for (j = 0; j < nbufs; j++)
1434
	      {
1435
		bufs[j][i] = 0;
1436
		for (k = 0; k < nbufs; k++)
1437
		  bufs[j][i] ^= gf_mul (matrix2[j][k], b[k]);
1438
	      }
1516
	      }
1439
	  }
1517
	  }
1440
	return GRUB_ERR_NONE;
1518
    }
1441
      }
1519
1442
    default:
1520
  grub_free(p);
1443
      return grub_error (GRUB_ERR_BUG, "too big matrix");
1444
    }      
1445
}
1521
}
1446
1522
1447
static grub_err_t
1523
static int
1448
read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
1524
vdev_raidz_reconstruct_general(raidz_map_t *rm, int *tgts, int ntgts)
1449
	     grub_size_t len, void *buf)
1450
{
1525
{
1451
  switch (desc->type)
1526
  int n, i, c, t, tt;
1527
  int nmissing_rows;
1528
  int missing_rows[VDEV_RAIDZ_MAXPARITY];
1529
  int parity_map[VDEV_RAIDZ_MAXPARITY];
1530
1531
  grub_uint8_t *p, *pp;
1532
  grub_size_t psize;
1533
1534
  grub_uint8_t *rows[VDEV_RAIDZ_MAXPARITY];
1535
  grub_uint8_t *invrows[VDEV_RAIDZ_MAXPARITY];
1536
  grub_uint8_t *used;
1537
1538
  int code = 0;
1539
1540
1541
  n = rm->rm_cols - rm->rm_firstdatacol;
1542
1543
  /*
1544
   * Figure out which data columns are missing.
1545
   */
1546
  nmissing_rows = 0;
1547
  for (t = 0; t < ntgts; t++)
1452
    {
1548
    {
1453
    case DEVICE_LEAF:
1549
      if (tgts[t] >= (int) rm->rm_firstdatacol)
1454
      {
1550
	missing_rows[nmissing_rows++] = tgts[t] - rm->rm_firstdatacol;
1455
	grub_uint64_t sector;
1551
    }
1456
	sector = DVA_OFFSET_TO_PHYS_SECTOR (offset);
1552
1457
	if (!desc->dev)
1553
  /*
1458
	  {
1554
   * Figure out which parity columns to use to help generate the missing
1459
	    return grub_error (GRUB_ERR_BAD_FS,
1555
   * data columns.
1556
   */
1557
  for (tt = 0, c = 0, i = 0; i < nmissing_rows; c++)
1558
    {
1559
      /*
1560
       * Skip any targeted parity columns.
1561
       */
1562
      if (c == tgts[tt])
1563
	{
1564
	  tt++;
1565
	  continue;
1566
	}
1567
1568
      code |= 1 << c;
1569
1570
      parity_map[i] = c;
1571
      i++;
1572
    }
1573
1574
  psize = (sizeof (rows[0][0]) + sizeof (invrows[0][0])) *
1575
           nmissing_rows * n + sizeof (used[0]) * n;
1576
  p = grub_malloc(psize);
1577
1578
  for (pp = p, i = 0; i < nmissing_rows; i++)
1579
    {
1580
       rows[i] = pp;
1581
       pp += n;
1582
       invrows[i] = pp;
1583
       pp += n;
1584
    }
1585
  used = pp;
1586
1587
  for (i = 0; i < nmissing_rows; i++)
1588
    used[i] = parity_map[i];
1589
1590
  for (tt = 0, c = rm->rm_firstdatacol; c < (int) rm->rm_cols; c++)
1591
    {
1592
      if (tt < (int) nmissing_rows &&
1593
	  c == missing_rows[tt] + (int) rm->rm_firstdatacol)
1594
	{
1595
	  tt++;
1596
	  continue;
1597
	}
1598
1599
      used[i] = c;
1600
      i++;
1601
    }
1602
1603
  /*
1604
   * Initialize the interesting rows of the matrix.
1605
   */
1606
  vdev_raidz_matrix_init(n, nmissing_rows, parity_map, rows);
1607
1608
  /*
1609
   * Invert the matrix.
1610
   */
1611
  vdev_raidz_matrix_invert(rm, n, nmissing_rows, missing_rows, rows,
1612
			   invrows, used);
1613
1614
  /*
1615
   * Reconstruct the missing data using the generated matrix.
1616
   */
1617
  vdev_raidz_matrix_reconstruct(rm, n, nmissing_rows, missing_rows,
1618
				invrows, used);
1619
1620
  grub_free(p);
1621
1622
  return (code);
1623
}
1624
1625
static int
1626
vdev_raidz_reconstruct(raidz_map_t *rm, int *t, int nt)
1627
{
1628
  int tgts[VDEV_RAIDZ_MAXPARITY], *dt;
1629
  int ntgts;
1630
  int i, c;
1631
  int code;
1632
  int nbadparity, nbaddata;
1633
  int parity_valid[VDEV_RAIDZ_MAXPARITY];
1634
1635
  nbadparity = rm->rm_firstdatacol;
1636
  nbaddata = rm->rm_cols - nbadparity;
1637
  ntgts = 0;
1638
  for (i = 0, c = 0; c < (int) rm->rm_cols; c++)
1639
    {
1640
      if (c < (int) rm->rm_firstdatacol)
1641
        parity_valid[c] = B_FALSE;
1642
1643
      if (i < nt && c == t[i])
1644
	{
1645
	  tgts[ntgts++] = c;
1646
	  i++;
1647
	}
1648
      else if (rm->rm_col[c].rc_error != 0)
1649
	{
1650
	  tgts[ntgts++] = c;
1651
	}
1652
      else if (c >= (int) rm->rm_firstdatacol)
1653
	{
1654
	  nbaddata--;
1655
	}
1656
      else
1657
	{
1658
	  parity_valid[c] = B_TRUE;
1659
	  nbadparity--;
1660
	}
1661
   }
1662
1663
   dt = &tgts[nbadparity];
1664
1665
   switch (nbaddata)
1666
     {
1667
     case 1:
1668
       if (parity_valid[VDEV_RAIDZ_P])
1669
         return (vdev_raidz_reconstruct_p(rm, dt));
1670
1671
       if (parity_valid[VDEV_RAIDZ_Q])
1672
         return (vdev_raidz_reconstruct_q(rm, dt));
1673
1674
       break;
1675
     case 2:
1676
       if (parity_valid[VDEV_RAIDZ_P] && parity_valid[VDEV_RAIDZ_Q])
1677
         return (vdev_raidz_reconstruct_pq(rm, dt));
1678
1679
       break;
1680
     }
1681
1682
  code = vdev_raidz_reconstruct_general(rm, tgts, ntgts);
1683
  return (code);
1684
}
1685
1686
static mirror_map_t *
1687
vdev_mirror_map_alloc(struct grub_zfs_device_desc *vd, grub_uint64_t offset,
1688
		      grub_uint64_t children)
1689
{
1690
  mirror_map_t *mm = NULL;
1691
  mirror_child_t *mc;
1692
  int c;
1693
1694
  c = (int) children;
1695
  mm = grub_zalloc(offsetof(mirror_map_t, mm_child[c]));
1696
  mm->mm_children = c;
1697
  mm->mm_replacing = B_FALSE;
1698
  mm->mm_preferred = ((int)offset >> 21) % c;
1699
  mm->mm_root = B_TRUE;
1700
  mm->mm_offset = offset;
1701
1702
  for (c = 0; c < mm->mm_children; c++)
1703
    {
1704
      mc = &mm->mm_child[c];
1705
      mc->mc_vd = &vd->children[c];
1706
      mc->mc_offset = offset;
1707
    }
1708
1709
  return (mm);
1710
}
1711
1712
static int
1713
vdev_mirror_child_select(mirror_map_t *mm)
1714
{
1715
  mirror_child_t *mc = NULL;
1716
  int c, i;
1717
1718
  for (i = 0, c = mm->mm_preferred; i < mm->mm_children; i++, c++)
1719
    {
1720
       if (c >= mm->mm_children)
1721
	  c = 0;
1722
       mc = &mm->mm_child[c];
1723
       if (mc->mc_tried || mc->mc_skipped)
1724
	 continue;
1725
       if (mc->mc_vd->dev_state == DEVICE_ERROR)
1726
	 {
1727
	    mc->mc_error = GRUB_ERR_IO;
1728
	    mc->mc_tried = 1;       /* don't even try */
1729
	    mc->mc_skipped = 1;
1730
	    continue;
1731
	 }
1732
      return (c);
1733
    }
1734
  for (c = 0; c < mm->mm_children; c++)
1735
    if (!mm->mm_child[c].mc_tried)
1736
      return (c);
1737
1738
  return -1;
1739
}
1740
1741
static grub_err_t
1742
read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
1743
	     grub_size_t len, void *buf, void **priv)
1744
{
1745
  grub_err_t err = GRUB_ERR_NONE;
1746
1747
  if (priv != NULL)
1748
    *priv = NULL;
1749
1750
  switch (desc->type)
1751
    {
1752
    case DEVICE_LEAF:
1753
      {
1754
	grub_uint64_t sector;
1755
	sector = DVA_OFFSET_TO_PHYS_SECTOR (offset);
1756
	grub_dprintf("zfs", "read_device: offset %llx sector %llx\n",
1757
		   (unsigned long long) offset,
1758
		   (unsigned long long) sector);
1759
	if (!desc->dev)
1760
	  {
1761
	    return grub_error (GRUB_ERR_BAD_FS,
1460
			       N_("couldn't find a necessary member device "
1762
			       N_("couldn't find a necessary member device "
1461
				  "of multi-device filesystem"));
1763
				  "of multi-device filesystem"));
1462
	  }
1764
	  }
1765
	if (desc->dev_state == DEVICE_ERROR)
1766
	  {
1767
	    return grub_error (GRUB_ERR_BAD_DEVICE, "dev state is NOT OK.\n");
1768
	  }
1463
	/* read in a data block */
1769
	/* read in a data block */
1464
	return grub_disk_read (desc->dev->disk, sector, 0, len, buf);
1770
	return grub_disk_read (desc->dev->disk, sector, 0, len, buf);
1465
      }
1771
      }
1466
    case DEVICE_MIRROR:
1772
    case DEVICE_MIRROR:
1467
      {
1773
      {
1468
	grub_err_t err = GRUB_ERR_NONE;
1774
	mirror_map_t *mm = NULL;
1469
	unsigned i;
1775
1470
	if (desc->n_children <= 0)
1776
	if (desc->n_children <= 0)
1471
	  return grub_error (GRUB_ERR_BAD_FS,
1777
	  return grub_error (GRUB_ERR_BAD_FS,
1472
			     "non-positive number of mirror children");
1778
			     "non-positive number of mirror children");
1473
	for (i = 0; i < desc->n_children; i++)
1779
1780
	mm = vdev_mirror_map_alloc(desc, offset, desc->n_children);
1781
	if (mm == NULL)
1782
	   err = grub_errno;
1783
	else
1474
	  {
1784
	  {
1475
	    err = read_device (offset, &desc->children[i],
1785
	    mm->mm_buf = buf;
1476
			       len, buf);
1786
	    mm->mm_size = len;
1477
	    if (!err)
1478
	      break;
1479
	    grub_errno = GRUB_ERR_NONE;
1480
	  }
1787
	  }
1481
	grub_errno = err;
1482
1788
1789
	*priv = mm;
1483
	return err;
1790
	return err;
1484
      }
1791
      }
1485
    case DEVICE_RAIDZ:
1792
    case DEVICE_RAIDZ:
1486
      {
1793
      {
1487
	unsigned c = 0;
1794
	raidz_map_t *rm;
1488
	grub_uint64_t high;
1795
	raidz_col_t *rc;
1489
	grub_uint64_t devn;
1796
	grub_int64_t c;
1490
	grub_uint64_t m;
1797
	struct grub_zfs_device_desc *cvd;
1491
	grub_uint32_t s, orig_s;
1492
	void *orig_buf = buf;
1493
	grub_size_t orig_len = len;
1494
	grub_uint8_t *recovery_buf[4];
1495
	grub_size_t recovery_len[4];
1496
	unsigned recovery_idx[4];
1497
	unsigned failed_devices = 0;
1498
	int idx, orig_idx;
1499
1798
1500
	if (desc->nparity < 1 || desc->nparity > 3)
1799
	if (desc->nparity < 1 || desc->nparity > 3)
1501
	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
1800
	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
1502
			     "raidz%d is not supported", desc->nparity);
1801
			     "raidz%d is not supported", desc->nparity);
1503
1802
1504
	orig_s = (((len + (1 << desc->ashift) - 1) >> desc->ashift)
1803
	  return grub_error(GRUB_ERR_BAD_FS,
1505
		  + (desc->n_children - desc->nparity) - 1);
1804
			    "too little devices for given parity");
1506
	s = orig_s;
1805
	rm = vdev_raidz_map_alloc(buf, len, offset, desc->ashift,
1507
1806
				 desc->n_children, desc->nparity);
1508
	high = grub_divmod64 ((offset >> desc->ashift),
1807
	if (rm == NULL)
1509
			      desc->n_children, &m);
1808
	  return grub_errno; 
1510
	if (desc->nparity == 2)
1809
1511
	  c = 2;
1810
	grub_dprintf("zfs", "read_device: cols = %" PRIuGRUB_UINT64_T
1512
	if (desc->nparity == 3)
1811
		     ", firstdatacol = %" PRIuGRUB_UINT64_T "\n",
1513
	  c = 3;
1812
		     rm->rm_cols, rm->rm_firstdatacol);
1514
	if (((len + (1 << desc->ashift) - 1) >> desc->ashift)
1813
1515
	    >= (desc->n_children - desc->nparity))
1814
	/*
1516
	  idx = (desc->n_children - desc->nparity - 1);
1815
	 * Iterate over the columns in reverse order so that we hit the parity
1517
	else
1816
	 * last -- any errors along the way will force us to read the parity.
1518
	  idx = ((len + (1 << desc->ashift) - 1) >> desc->ashift) - 1;
1817
	 */
1519
	orig_idx = idx;
1818
	for (c = rm->rm_cols - 1; c >= 0; c--)
1520
	while (len > 0)
1521
	  {
1819
	  {
1522
	    grub_size_t csize;
1820
	    rc = &rm->rm_col[c];
1523
	    grub_uint32_t bsize;
1821
	    cvd = &desc->children[rc->rc_devidx];
1524
	    grub_err_t err;
1822
	    if(cvd->dev_state == DEVICE_ERROR)
1525
	    bsize = s / (desc->n_children - desc->nparity);
1526
1527
	    if (desc->nparity == 1
1528
		&& ((offset >> (desc->ashift + 20 - desc->max_children_ashift))
1529
		    & 1) == c)
1530
	      c++;
1531
1532
	    high = grub_divmod64 ((offset >> desc->ashift) + c,
1533
				  desc->n_children, &devn);
1534
	    csize = bsize << desc->ashift;
1535
	    if (csize > len)
1536
	      csize = len;
1537
1538
	    grub_dprintf ("zfs", "RAIDZ mapping 0x%" PRIxGRUB_UINT64_T
1539
			  "+%u (%" PRIxGRUB_SIZE ", %" PRIxGRUB_UINT32_T
1540
			  ") -> (0x%" PRIxGRUB_UINT64_T ", 0x%"
1541
			  PRIxGRUB_UINT64_T ")\n",
1542
			  offset >> desc->ashift, c, len, bsize, high,
1543
			  devn);
1544
	    err = read_device ((high << desc->ashift)
1545
			       | (offset & ((1 << desc->ashift) - 1)),
1546
			       &desc->children[devn],
1547
			       csize, buf);
1548
	    if (err && failed_devices < desc->nparity)
1549
	      {
1823
	      {
1550
		recovery_buf[failed_devices] = buf;
1824
		if ((grub_uint64_t)c >= rm->rm_firstdatacol)
1551
		recovery_len[failed_devices] = csize;
1825
		  rm->rm_missingdata++;
1552
		recovery_idx[failed_devices] = idx;
1826
		else
1553
		failed_devices++;
1827
		  rm->rm_missingparity++;
1554
		grub_errno = err = 0;
1828
		rc->rc_error = GRUB_ERR_IO;
1555
	      }
1829
		rc->rc_tried = 1;       /* don't even try */
1556
	    if (err)
1830
		rc->rc_skipped = 1;
1557
	      return err;
1831
		continue;
1558
1832
              }
1559
	    c++;
1833
	    grub_dprintf("zfs", "%" PRIuGRUB_UINT64_T ":%" PRIxGRUB_UINT64_T
1560
	    idx--;
1834
			 ":%" PRIxGRUB_UINT64_T "\n", rc->rc_devidx,
1561
	    s--;
1835
			 rc->rc_offset, rc->rc_size);
1562
	    buf = (char *) buf + csize;
1836
	    if ((grub_uint64_t)c >= rm->rm_firstdatacol ||
1563
	    len -= csize;
1837
		rm->rm_missingdata > 0)
1564
	  }
1565
	if (failed_devices)
1566
	  {
1567
	    unsigned redundancy_pow[4];
1568
	    unsigned cur_redundancy_pow = 0;
1569
	    unsigned n_redundancy = 0;
1570
	    unsigned i, j;
1571
	    grub_err_t err;
1572
1573
	    /* Compute mul. x**s has a period of 255.  */
1574
	    if (powx[0] == 0)
1575
	      {
1838
	      {
1576
		grub_uint8_t cur = 1;
1839
	        err = read_device (rc->rc_offset, cvd, rc->rc_size,
1577
		for (i = 0; i < 255; i++)
1840
				   rc->rc_data, NULL);
1841
		rc->rc_error = err;
1842
		rc->rc_tried = 1;
1843
		rc->rc_skipped = 0;
1844
		if (err)
1578
		  {
1845
		  {
1579
		    powx[i] = cur;
1846
		    /* missing data will trigger parity read */
1580
		    powx[i + 255] = cur;
1847
		    if ((grub_uint64_t)c >= rm->rm_firstdatacol)
1581
		    powx_inv[cur] = i;
1848
		      rm->rm_missingdata++;
1582
		    if (cur & 0x80)
1583
		      cur = (cur << 1) ^ poly;
1584
		    else
1849
		    else
1585
		      cur <<= 1;
1850
		      rm->rm_missingparity++;
1586
		  }
1587
	      }
1588
1589
	    /* Read redundancy data.  */
1590
	    for (n_redundancy = 0, cur_redundancy_pow = 0;
1591
		 n_redundancy < failed_devices;
1592
		 cur_redundancy_pow++)
1593
	      {
1594
		high = grub_divmod64 ((offset >> desc->ashift)
1595
				      + cur_redundancy_pow
1596
				      + ((desc->nparity == 1)
1597
					 && ((offset >> (desc->ashift + 20
1598
							 - desc->max_children_ashift))
1599
					     & 1)),
1600
				      desc->n_children, &devn);
1601
		err = read_device ((high << desc->ashift)
1602
				   | (offset & ((1 << desc->ashift) - 1)),
1603
				   &desc->children[devn],
1604
				   recovery_len[n_redundancy],
1605
				   recovery_buf[n_redundancy]);
1606
		/* Ignore error if we may still have enough devices.  */
1607
		if (err && n_redundancy + desc->nparity - cur_redundancy_pow - 1
1608
		    >= failed_devices)
1609
		  {
1610
		    grub_errno = GRUB_ERR_NONE;
1611
		    continue;
1612
		  }
1851
		  }
1613
		if (err)
1614
		  return err;
1615
		redundancy_pow[n_redundancy] = cur_redundancy_pow;
1616
		n_redundancy++;
1617
	      }
1618
	    /* Now xor-our the parts we already know.  */
1619
	    buf = orig_buf;
1620
	    len = orig_len;
1621
	    s = orig_s;
1622
	    idx = orig_idx;
1623
1624
	    while (len > 0)
1625
	      {
1626
		grub_size_t csize;
1627
		csize = ((s / (desc->n_children - desc->nparity))
1628
			 << desc->ashift);
1629
		if (csize > len)
1630
		  csize = len;
1631
1632
		for (j = 0; j < failed_devices; j++)
1633
		  if (buf == recovery_buf[j])
1634
		    break;
1635
1636
		if (j == failed_devices)
1637
		  for (j = 0; j < failed_devices; j++)
1638
		    xor_out (recovery_buf[j], buf,
1639
			     csize < recovery_len[j] ? csize : recovery_len[j],
1640
			     idx, redundancy_pow[j]);
1641
1642
		s--;
1643
		buf = (char *) buf + csize;
1644
		len -= csize;
1645
		idx--;
1646
	      }
1647
	    for (i = 0; i < failed_devices 
1648
		   && recovery_len[i] == recovery_len[0];
1649
		 i++);
1650
	    /* Since the chunks have variable length handle the last block
1651
	       separately.  */
1652
	    if (i != failed_devices)
1653
	      {
1654
		grub_uint8_t *tmp_recovery_buf[4];
1655
		for (j = 0; j < i; j++)
1656
		  tmp_recovery_buf[j] = recovery_buf[j] + recovery_len[failed_devices - 1];
1657
		err = recovery (tmp_recovery_buf, recovery_len[0] - recovery_len[failed_devices - 1], i, redundancy_pow,
1658
				recovery_idx);
1659
		if (err)
1660
		  return err;
1661
	      }
1852
	      }
1662
	    err = recovery (recovery_buf, recovery_len[failed_devices - 1],
1663
			    failed_devices, redundancy_pow, recovery_idx);
1664
	    if (err)
1665
	      return err;
1666
	  }
1853
	  }
1854
	*priv = rm;
1855
1667
	return GRUB_ERR_NONE;
1856
	return GRUB_ERR_NONE;
1668
      }
1857
      }
1669
    }
1858
    }
1670
  return grub_error (GRUB_ERR_BAD_FS, "unsupported device type");
1859
  return grub_error (GRUB_ERR_BAD_FS, "unsupported device type");
1671
}
1860
}
1672
1861
1673
static grub_err_t
1862
static int
1674
read_dva (const dva_t *dva,
1863
vdev_raidz_combrec(blkptr_t *bp, grub_zfs_endian_t endian, raidz_map_t *rm,
1675
	  grub_zfs_endian_t endian, struct grub_zfs_data *data,
1864
		   int total_errors, int data_errors)
1676
	  void *buf, grub_size_t len)
1677
{
1865
{
1678
  grub_uint64_t offset;
1866
  raidz_col_t *rc;
1679
  unsigned i;
1867
  void *orig[VDEV_RAIDZ_MAXPARITY];
1680
  grub_err_t err = 0;
1868
  int tstore[VDEV_RAIDZ_MAXPARITY + 2];
1681
  int try = 0;
1869
  int *tgts = &tstore[1];
1682
  offset = dva_get_offset (dva, endian);
1870
  int current, next, i, c, n;
1871
  int code, ret = 0;
1683
1872
1684
  for (try = 0; try < 2; try++)
1873
  /*
1874
   * This simplifies one edge condition.
1875
   */
1876
  tgts[-1] = -1;
1877
1878
  for (n = 1; n <= (int) rm->rm_firstdatacol - total_errors; n++)
1685
    {
1879
    {
1686
      for (i = 0; i < data->n_devices_attached; i++)
1880
      /*
1687
	if (data->devices_attached[i].id == DVA_GET_VDEV (dva))
1881
       * Initialize the targets array by finding the first n columns
1688
	  {
1882
       * that contain no error.
1689
	    err = read_device (offset, &data->devices_attached[i], len, buf);
1883
       *
1690
	    if (!err)
1884
       * If there were no data errors, we need to ensure that we're
1691
	      return GRUB_ERR_NONE;
1885
       * always explicitly attempting to reconstruct at least one
1692
	    break;
1886
       * data column. To do this, we simply push the highest target
1693
	  }
1887
       * up into the data columns.
1694
      if (try == 1)
1888
       */
1695
	break;
1889
      for (c = 0, i = 0; i < n; i++)
1696
      err = scan_devices (data);
1890
	{
1697
      if (err)
1891
	  if (i == n - 1 && data_errors == 0 && c < (int) rm->rm_firstdatacol)
1698
	return err;
1892
	    {
1699
    }
1893
	      c = rm->rm_firstdatacol;
1700
  if (!err)
1894
	    }
1701
    return grub_error (GRUB_ERR_BAD_FS, "unknown device %d",
1702
		       (int) DVA_GET_VDEV (dva));
1703
  return err;
1704
}
1705
1895
1706
/*
1896
	  while (rm->rm_col[c].rc_error != 0)
1707
 * Read a block of data based on the gang block address dva,
1897
	    c++;
1708
 * and put its data in buf.
1709
 *
1710
 */
1711
static grub_err_t
1712
zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf,
1713
	       struct grub_zfs_data *data)
1714
{
1715
  zio_gbh_phys_t *zio_gb;
1716
  unsigned i;
1717
  grub_err_t err;
1718
  zio_cksum_t zc;
1719
1898
1720
  grub_memset (&zc, 0, sizeof (zc));
1899
	  tgts[i] = c++;
1900
	}
1721
1901
1722
  zio_gb = grub_malloc (SPA_GANGBLOCKSIZE);
1902
      /*
1723
  if (!zio_gb)
1903
       * Setting tgts[n] simplifies the other edge condition.
1724
    return grub_errno;
1904
       */
1725
  grub_dprintf ("zfs", endian == GRUB_ZFS_LITTLE_ENDIAN ? "little-endian gang\n"
1905
      tgts[n] = rm->rm_cols;
1726
		:"big-endian gang\n");
1727
1906
1728
  err = read_dva (dva, endian, data, zio_gb, SPA_GANGBLOCKSIZE);
1907
      orig[n - 1] = grub_malloc(rm->rm_col[0].rc_size);
1729
  if (err)
1730
    {
1731
      grub_free (zio_gb);
1732
      return err;
1733
    }
1734
1908
1735
  /* XXX */
1909
      current = 0;
1736
  /* self checksuming the gang block header */
1910
      next = tgts[current];
1737
  ZIO_SET_CHECKSUM (&zc, DVA_GET_VDEV (dva),
1738
		    dva_get_offset (dva, endian), bp->blk_birth, 0);
1739
  err = zio_checksum_verify (zc, ZIO_CHECKSUM_GANG_HEADER, endian,
1740
			     (char *) zio_gb, SPA_GANGBLOCKSIZE);
1741
  if (err)
1742
    {
1743
      grub_free (zio_gb);
1744
      return err;
1745
    }
1746
1911
1747
  endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
1912
      while (current != n)
1913
	{
1914
	  tgts[current] = next;
1915
	  current = 0;
1748
1916
1749
  for (i = 0; i < SPA_GBH_NBLKPTRS; i++)
1917
	  /*
1750
    {
1918
	   * Save off the original data that we're going to
1751
      if (zio_gb->zg_blkptr[i].blk_birth == 0)
1919
	   * attempt to reconstruct.
1752
	continue;
1920
	   */
1921
	  for (i = 0; i < n; i++)
1922
	    {
1923
	      c = tgts[i];
1924
	      rc = &rm->rm_col[c];
1925
	      grub_memcpy(orig[i], rc->rc_data, rc->rc_size);
1926
	    }
1753
1927
1754
      err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data);
1928
	  /*
1755
      if (err)
1929
	   * Attempt a reconstruction and exit the outer loop on
1756
	{
1930
	   * success.
1757
	  grub_free (zio_gb);
1931
	   */
1758
	  return err;
1932
	  code = vdev_raidz_reconstruct(rm, tgts, n);
1759
	}
1933
	  if (zio_checksum_error(bp, endian,
1760
      buf = (char *) buf + get_psize (&zio_gb->zg_blkptr[i], endian);
1934
				 rm->rm_col[rm->rm_firstdatacol].rc_data) == 0)
1761
    }
1935
	    {
1762
  grub_free (zio_gb);
1936
	      for (i = 0; i < n; i++)
1763
  return GRUB_ERR_NONE;
1937
		{
1764
}
1938
		  c = tgts[i];
1939
		  rc = &rm->rm_col[c];
1940
		  rc->rc_error = GRUB_ERR_IO;
1941
		}
1765
1942
1766
/*
1943
	      ret = code;
1767
 * Read in a block of raw data to buf.
1944
	      goto done;
1768
 */
1945
	    }
1769
static grub_err_t
1770
zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, 
1771
	       struct grub_zfs_data *data)
1772
{
1773
  int i, psize;
1774
  grub_err_t err = GRUB_ERR_NONE;
1775
1946
1776
  psize = get_psize (bp, endian);
1947
	  /*
1948
	   * Restore the original data.
1949
	   */
1950
	  for (i = 0; i < n; i++)
1951
	    {
1952
	      c = tgts[i];
1953
	      rc = &rm->rm_col[c];
1954
	      grub_memcpy(rc->rc_data, orig[i], rc->rc_size);
1955
	    }
1777
1956
1778
  /* pick a good dva from the block pointer */
1957
	  do {
1779
  for (i = 0; i < SPA_DVAS_PER_BP; i++)
1958
	    /*
1780
    {
1959
	     * Find the next valid column after the current
1781
      if (bp->blk_dva[i].dva_word[0] == 0 && bp->blk_dva[i].dva_word[1] == 0)
1960
	     * position..
1782
	continue;
1961
	     */
1962
	    for (next = tgts[current] + 1;
1963
		 next < (int) rm->rm_cols && rm->rm_col[next].rc_error != 0;
1964
		 next++)
1965
	      continue;
1783
1966
1784
      if ((grub_zfs_to_cpu64 (bp->blk_dva[i].dva_word[1], endian)>>63) & 1)
1967
	    /*
1785
	err = zio_read_gang (bp, endian, &bp->blk_dva[i], buf, data);
1968
	     * If that spot is available, we're done here.
1786
      else
1969
	     */
1787
	err = read_dva (&bp->blk_dva[i], endian, data, buf, psize);
1970
	    if (next != tgts[current + 1])
1788
      if (!err)
1971
	      break;
1789
	return GRUB_ERR_NONE;
1972
1790
      grub_errno = GRUB_ERR_NONE;
1973
	    /*
1974
	     * Otherwise, find the next valid column after
1975
	     * the previous position.
1976
	     */
1977
	    for (c = tgts[current - 1] + 1; rm->rm_col[c].rc_error != 0; c++)
1978
	      continue;
1979
1980
	    tgts[current] = c;
1981
	    current++;
1982
1983
	  } while (current != n);
1984
	}
1791
    }
1985
    }
1986
  n--;
1792
1987
1793
  if (!err)
1988
done:
1794
    err = grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid DVA");
1989
  for (i = 0; i < n; i++)
1795
  grub_errno = err;
1990
    grub_free(orig[i]);
1796
1991
1797
  return err;
1992
  return (ret);
1798
}
1993
}
1799
1994
1800
/*
1801
 * Read in a block of data, verify its checksum, decompress if needed,
1802
 * and put the uncompressed data in buf.
1803
 */
1804
static grub_err_t
1995
static grub_err_t
1805
zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, 
1996
vdev_raidz_io_done(blkptr_t *bp, struct grub_zfs_device_desc *desc,
1806
	  grub_size_t *size, struct grub_zfs_data *data)
1997
		   grub_zfs_endian_t endian, raidz_map_t *rm)
1807
{
1998
{
1808
  grub_size_t lsize, psize;
1999
  raidz_col_t *rc;
1809
  unsigned int comp, encrypted;
2000
  int unexpected_errors = 0;
1810
  char *compbuf = NULL;
2001
  int parity_errors = 0;
1811
  grub_err_t err;
2002
  int parity_untried = 0;
1812
  zio_cksum_t zc = bp->blk_cksum;
2003
  int data_errors = 0;
1813
  grub_uint32_t checksum;
2004
  int total_errors = 0;
1814
2005
  int n, c;
1815
  *buf = NULL;
2006
  int tgts[VDEV_RAIDZ_MAXPARITY];
2007
  int code;
2008
  grub_err_t err = GRUB_ERR_NONE;
1816
2009
1817
  checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
2010
  for (c = 0; c < (int)rm->rm_cols; c++)
1818
  comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff;
2011
    {
1819
  encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3);
2012
      rc = &rm->rm_col[c];
1820
  lsize = (BP_IS_HOLE(bp) ? 0 :
2013
      if (rc->rc_error)
1821
	   (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
2014
	{
1822
	    << SPA_MINBLOCKSHIFT));
2015
	  if (c < (int)rm->rm_firstdatacol)
1823
  psize = get_psize (bp, endian);
2016
	    parity_errors++;
2017
	  else
2018
	    data_errors++;
1824
2019
1825
  if (size)
2020
	  if (!rc->rc_skipped)
1826
    *size = lsize;
2021
	    unexpected_errors++;
1827
2022
1828
  if (comp >= ZIO_COMPRESS_FUNCTIONS)
2023
	  total_errors++;
1829
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
2024
	}
1830
		       "compression algorithm %u not supported\n", (unsigned int) comp);
2025
      else if (c < (int)rm->rm_firstdatacol && !rc->rc_tried)
2026
        {
2027
	  parity_untried++;
2028
	}
2029
    }
2030
  /*
2031
   * There are three potential phases for a read:
2032
   *      1. produce valid data from the columns read
2033
   *      2. read all disks and try again
2034
   *      3. perform combinatorial reconstruction
2035
   *
2036
   * Each phase is progressively both more expensive and less likely to
2037
   * occur. If we encounter more errors than we can repair or all phases
2038
   * fail, we have no choice but to return an error.
2039
   */
1831
2040
1832
  if (comp != ZIO_COMPRESS_OFF && decomp_table[comp].decomp_func == NULL)
2041
  /*
2042
   * If the number of errors we saw was correctable -- less than or equal
2043
   * to the number of parity disks read -- attempt to produce data that
2044
   * has a valid checksum. Naturally, this case applies in the absence of
2045
   * any errors.
2046
   */
2047
  if (total_errors <= (int)rm->rm_firstdatacol - parity_untried)
2048
    {
2049
      if (data_errors == 0)
2050
	{
2051
	  rc = &rm->rm_col[rm->rm_firstdatacol];
2052
	  if ((err = zio_checksum_error(bp, endian, rc->rc_data)) == 0)
2053
	    {
2054
	      goto done;
2055
	    }
2056
	  else
2057
	    rm->rm_ecksuminjected = 1;
2058
	}
2059
      else
2060
	{
2061
	  n = 0;
2062
	  for (c = rm->rm_firstdatacol; c < (int)rm->rm_cols; c++)
2063
	    {
2064
	      rc = &rm->rm_col[c];
2065
	      if (rc->rc_error != 0)
2066
		tgts[n++] = c;
2067
	    }
2068
	  code = vdev_raidz_reconstruct(rm, tgts, n);
2069
	  rc = &rm->rm_col[rm->rm_firstdatacol];
2070
	  if ((err = zio_checksum_error(bp, endian, rc->rc_data)) == 0)
2071
	    {
2072
	      goto done;
2073
	    }
2074
	  else
2075
	    rm->rm_ecksuminjected = 1;
2076
	}
2077
    }
2078
  /*
2079
   * if all else fails. make sure we have read all columns and
2080
   * check again.
2081
   */
2082
  unexpected_errors = 1;
2083
  rm->rm_missingdata = 0;
2084
  rm->rm_missingparity = 0;
2085
2086
  for (c = 0; c < (int) rm->rm_cols; c++)
2087
    {
2088
      struct grub_zfs_device_desc *cvd;
2089
      if (rm->rm_col[c].rc_tried)
2090
	continue;
2091
2092
      do {
2093
	rc = &rm->rm_col[c];
2094
	if (rc->rc_tried)
2095
	  continue;
2096
2097
	cvd = &desc->children[rc->rc_devidx];
2098
	err = read_device (rc->rc_offset, cvd, rc->rc_size,
2099
				   rc->rc_data, NULL);
2100
	rc->rc_error = err;
2101
	rc->rc_tried = 1;
2102
	rc->rc_skipped = 0;
2103
      } while (++c < (int) rm->rm_cols);
2104
2105
      /* and repeat the check */
2106
      return vdev_raidz_io_done(bp, desc, endian, rm);
2107
    }
2108
2109
  /*
2110
   * all columns are read, it could still be the silent data corruption.
2111
   */
2112
  err = GRUB_ERR_IO;
2113
2114
  if (total_errors < (int) rm->rm_firstdatacol)
2115
    {
2116
       code = vdev_raidz_combrec(bp, endian, rm, total_errors, data_errors);
2117
       if (code != 0)
2118
	 err = GRUB_ERR_NONE;
2119
    }
2120
2121
done:
2122
  grub_dprintf("zfs", "vdev_raidz_io_done (%d):\n"
2123
	       "\tdata errors: %d\n"
2124
	       "\tparity errors: %d\n"
2125
	       "\tparity untried: %d\n"
2126
	       "\tunexpected errors: %d\n"
2127
	       "\ttotal errors: %d\n", err, data_errors, parity_errors,
2128
	       parity_untried, unexpected_errors, total_errors);
2129
2130
  vdev_raidz_map_free(rm);
2131
  return err;
2132
}
2133
2134
static grub_err_t
2135
vdev_mirror_io_done(blkptr_t *bp, grub_zfs_endian_t endian, mirror_map_t *mm)
2136
{
2137
  mirror_child_t *mc = NULL;
2138
  int c;
2139
  grub_err_t err = GRUB_ERR_NONE;
2140
2141
  while ((c = vdev_mirror_child_select(mm)) >= 0)
2142
    {
2143
      grub_dprintf("zfs", "reading mirror child: %d\n", c);
2144
      mc = &mm->mm_child[c];
2145
      err = read_device (mm->mm_offset, mc->mc_vd, mm->mm_size,
2146
			 mm->mm_buf, NULL);
2147
      mc->mc_tried = 1;
2148
      mc->mc_skipped = 0;
2149
      if (err == GRUB_ERR_NONE)
2150
	{
2151
	  err = zio_checksum_error(bp, endian, mm->mm_buf);
2152
	  if (err == GRUB_ERR_NONE)
2153
	    break;
2154
	}
2155
      mc->mc_error = err;
2156
    }
2157
2158
  grub_free(mm);
2159
  return err;
2160
}
2161
2162
static grub_err_t
2163
read_dva (blkptr_t *bp, const dva_t *dva, grub_zfs_endian_t endian,
2164
	  struct grub_zfs_data *data, void *buf, grub_size_t len)
2165
{
2166
  grub_uint64_t offset;
2167
  grub_size_t align;
2168
  grub_size_t asize;
2169
  void *abuf = NULL, *orig_buf = NULL;
2170
  unsigned i;
2171
  void *priv;
2172
  grub_err_t err = GRUB_ERR_NONE;
2173
  offset = DVA_GET_OFFSET (dva, endian);
2174
  struct grub_zfs_device_desc *desc;
2175
2176
  for (i = 0; i < data->n_devices_attached; i++)
2177
    if (data->devices_attached[i].id == DVA_GET_VDEV (dva))
2178
      {
2179
	desc = &data->devices_attached[i];
2180
	align = 1 << desc->ashift;
2181
2182
	if (P2PHASE(len, align) != 0) {
2183
	   grub_dprintf("zfs", "read_dva: unaligned read: %"
2184
			PRIdGRUB_SSIZE "(%" PRIdGRUB_SSIZE ")\n",
2185
			len, P2ROUNDUP(len, align));
2186
	  asize = P2ROUNDUP(len, align);
2187
	  abuf = grub_malloc(asize);
2188
	  orig_buf = buf;
2189
	} else {
2190
	  asize = len;
2191
	  abuf = buf;
2192
	}
2193
2194
	grub_dprintf("zfs", "read_dva vdev: %d\n", i);
2195
	err = read_device (offset, desc, asize, abuf, &priv);
2196
	if (err != GRUB_ERR_NONE)
2197
	  break;
2198
2199
	if (data->devices_attached[i].type == DEVICE_MIRROR)
2200
	  {
2201
	    mirror_map_t *mm = priv;
2202
	    err = vdev_mirror_io_done(bp, endian, mm);
2203
	  }
2204
	if (data->devices_attached[i].type == DEVICE_RAIDZ)
2205
	  {
2206
	    raidz_map_t *rm = priv;
2207
	    err = vdev_raidz_io_done(bp, desc, endian, rm);
2208
	  }
2209
	if (data->devices_attached[i].type == DEVICE_LEAF)
2210
	  {
2211
	    err = zio_checksum_error(bp, endian, abuf);
2212
	  }
2213
2214
	if (err == GRUB_ERR_NONE)
2215
	  {
2216
	    if (orig_buf != NULL)
2217
	      {
2218
		grub_memcpy(buf, abuf, len);
2219
		grub_free(abuf);
2220
	      }
2221
	    return err;
2222
	  }
2223
	break;
2224
     }
2225
2226
  if (orig_buf != NULL)
2227
    grub_free(abuf);
2228
2229
  if (!err)
2230
    return grub_error (GRUB_ERR_BAD_FS, "unknown device %d",
2231
		       (int) DVA_GET_VDEV (dva));
2232
  return err;
2233
}
2234
2235
/*
2236
 * Read a block of data based on the gang block address dva,
2237
 * and put its data in buf.
2238
 */
2239
static grub_err_t
2240
zio_read_gang_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf,
2241
	       struct grub_zfs_data *data)
2242
{
2243
  int i;
2244
2245
  /* pick a good dva from the block pointer */
2246
  for (i = 0; i < BP_GET_NDVAS(bp); i++)
2247
    {
2248
      if (zio_read_common(bp, &bp->blk_dva[i], endian, buf, data) == GRUB_ERR_NONE)
2249
	return GRUB_ERR_NONE;
2250
    }
2251
  return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid DVA");
2252
}
2253
2254
/*
2255
 * Read gang block header, verify its checksum, loop through all gang blocks
2256
 * to collect its data based on the gang block address dva and put it in buf.
2257
 *
2258
 */
2259
static grub_err_t
2260
zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf,
2261
	       struct grub_zfs_data *data)
2262
{
2263
  zio_gbh_phys_t *zio_gb;
2264
  unsigned i;
2265
  grub_err_t err;
2266
2267
  zio_gb = grub_malloc (SPA_GANGBLOCKSIZE);
2268
  if (!zio_gb)
2269
    return grub_errno;
2270
  grub_dprintf ("zfs", endian == GRUB_ZFS_LITTLE_ENDIAN ? "little-endian gang\n"
2271
		:"big-endian gang\n");
2272
2273
  err = read_dva (bp, dva, endian, data, zio_gb, SPA_GANGBLOCKSIZE);
2274
  if (err)
2275
    {
2276
      grub_free (zio_gb);
2277
      return err;
2278
    }
2279
2280
  endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
2281
2282
  for (i = 0; i < SPA_GBH_NBLKPTRS; i++)
2283
    {
2284
      if (zio_gb->zg_blkptr[i].blk_birth == 0)
2285
	continue;
2286
2287
      err = zio_read_gang_data (&zio_gb->zg_blkptr[i], endian, buf, data);
2288
      if (err)
2289
	{
2290
	  grub_free (zio_gb);
2291
	  return err;
2292
	}
2293
      buf = (char *) buf + BP_GET_PSIZE (&zio_gb->zg_blkptr[i], endian);
2294
    }
2295
  grub_free (zio_gb);
2296
  return GRUB_ERR_NONE;
2297
}
2298
2299
/*
2300
 * Read in a block of raw data to buf.
2301
 */
2302
static grub_err_t
2303
zio_read_common (blkptr_t * bp, dva_t *dva, grub_zfs_endian_t endian,
2304
		void *buf, struct grub_zfs_data *data)
2305
{
2306
  int psize;
2307
  grub_err_t err = GRUB_ERR_NONE;
2308
2309
  psize = BP_GET_PSIZE (bp, endian);
2310
2311
  if (dva->dva_word[0] == 0 && dva->dva_word[1] == 0)
2312
    return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid DVA");
2313
2314
  if (BP_IS_GANG(bp, endian))
2315
    err = zio_read_gang (bp, endian, dva, buf, data);
2316
  else
2317
    err = read_dva (bp, dva, endian, data, buf, psize);
2318
2319
  return err;
2320
2321
}
2322
2323
/*
2324
 * Loop through DVAs to read in a block of raw data to buf and verify
2325
 * the checksum.
2326
 */
2327
static grub_err_t
2328
zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf,
2329
	       struct grub_zfs_data *data)
2330
{
2331
  int i;
2332
  grub_err_t err = GRUB_ERR_NONE;
2333
2334
  /* pick a good dva from the block pointer */
2335
  for (i = 0; i < BP_GET_NDVAS(bp); i++)
2336
    {
2337
      if (zio_read_common(bp, &bp->blk_dva[i], endian, buf, data) != GRUB_ERR_NONE)
2338
	{
2339
	  grub_errno = GRUB_ERR_NONE;
2340
	  continue;
2341
	}
2342
      /* if no errors, return from here */
2343
      return GRUB_ERR_NONE;
2344
    }
2345
2346
  err = grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid DVA");
2347
  grub_errno = err;
2348
2349
  return err;
2350
}
2351
2352
/*
2353
 * buf must be at least BPE_GET_PSIZE(bp) bytes long (which will never be
2354
 * more than BPE_PAYLOAD_SIZE bytes).
2355
 */
2356
static grub_err_t
2357
decode_embedded_bp_compressed(const blkptr_t *bp, grub_zfs_endian_t endian,
2358
    void *buf)
2359
{
2360
       grub_size_t psize, i;
2361
       grub_uint8_t *buf8 = buf;
2362
       grub_uint64_t w = 0;
2363
       const grub_uint64_t *bp64 = (const grub_uint64_t *)bp;
2364
2365
       psize = BPE_GET_PSIZE(bp, endian);
2366
2367
       /*
2368
        * Decode the words of the block pointer into the byte array.
2369
        * Low bits of first word are the first byte (little endian).
2370
        */
2371
       for (i = 0; i < psize; i++) {
2372
               if (i % sizeof (w) == 0) {
2373
                       /* beginning of a word */
2374
                       w = grub_zfs_to_cpu64(*bp64, endian);
2375
                       bp64++;
2376
                       if (!BPE_IS_PAYLOADWORD(bp, bp64))
2377
                               bp64++;
2378
               }
2379
               buf8[i] = BF64_GET(w, (i % sizeof (w)) * NBBY, NBBY);
2380
       }
2381
       return GRUB_ERR_NONE;
2382
}
2383
2384
/*
2385
 * Read in a block of data, verify its checksum, decompress if needed,
2386
 * and put the uncompressed data in buf.
2387
 */
2388
static grub_err_t
2389
zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf,
2390
	  grub_size_t *size, struct grub_zfs_data *data)
2391
{
2392
  grub_size_t lsize, psize;
2393
  unsigned int comp, encrypted;
2394
  char *compbuf = NULL;
2395
  zio_cksum_t zc = bp->blk_cksum;
2396
  grub_err_t err;
2397
2398
  *buf = NULL;
2399
2400
  comp = BP_GET_COMPRESS(bp, endian);
2401
  encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3);
2402
2403
  grub_dprintf("zfs", "zio_read compress %d\n", (unsigned int) comp);
2404
  if (BP_IS_EMBEDDED(bp, endian)) {
2405
	if(BPE_GET_ETYPE(bp, endian) != BP_EMBEDDED_TYPE_DATA) {
2406
		return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
2407
			"unsupported embedded BP (type=%u)\n",
2408
			(int) BPE_GET_ETYPE(bp, endian));
2409
	}
2410
	lsize = BPE_GET_LSIZE(bp, endian);
2411
	psize = BPE_GET_PSIZE(bp, endian);
2412
  } else {
2413
	lsize = BP_GET_LSIZE(bp, endian);
2414
	psize = BP_GET_PSIZE(bp, endian);
2415
  }
2416
2417
  grub_dprintf("zfs", "zio_read: size %" PRIdGRUB_SSIZE "/%"
2418
	       PRIdGRUB_SSIZE "\n", lsize, psize);
2419
  if (comp >= ZIO_COMPRESS_FUNCTIONS)
2420
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
2421
		       "compression algorithm %u not supported\n", (unsigned int) comp);
2422
2423
  if (comp != ZIO_COMPRESS_OFF && decomp_table[comp].decomp_func == NULL)
1833
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
2424
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
1834
		       "compression algorithm %s not supported\n", decomp_table[comp].name);
2425
		       "compression algorithm %s not supported\n", decomp_table[comp].name);
1835
2426
Lines 1841-1863 Link Here
1841
	return grub_errno;
2432
	return grub_errno;
1842
    }
2433
    }
1843
  else
2434
  else
1844
    compbuf = *buf = grub_malloc (lsize);
1845
1846
  grub_dprintf ("zfs", "endian = %d\n", endian);
1847
  err = zio_read_data (bp, endian, compbuf, data);
1848
  if (err)
1849
    {
2435
    {
1850
      grub_free (compbuf);
2436
      compbuf = *buf = grub_malloc (lsize);
1851
      *buf = NULL;
2437
	if (! compbuf)
1852
      return err;
2438
	  return grub_errno;
1853
    }
2439
    }
1854
  grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize);
1855
2440
1856
  err = zio_checksum_verify (zc, checksum, endian,
2441
  if (size)
1857
			     compbuf, psize);
2442
     *size = lsize;
2443
2444
  grub_dprintf ("zfs", "endian = %d\n", endian);
2445
  if (BP_IS_EMBEDDED(bp, endian)) {
2446
    err = decode_embedded_bp_compressed(bp, endian, compbuf);
2447
  } else {
2448
    err = zio_read_data (bp, endian, compbuf, data);
2449
    grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize);
2450
  }
2451
1858
  if (err)
2452
  if (err)
1859
    {
2453
    {
1860
      grub_dprintf ("zfs", "incorrect checksum\n");
1861
      grub_free (compbuf);
2454
      grub_free (compbuf);
1862
      *buf = NULL;
2455
      *buf = NULL;
1863
      return err;
2456
      return err;
Lines 1950-1972 Link Here
1950
  grub_zfs_endian_t endian;
2543
  grub_zfs_endian_t endian;
1951
  grub_err_t err = GRUB_ERR_NONE;
2544
  grub_err_t err = GRUB_ERR_NONE;
1952
2545
1953
  bp = grub_malloc (sizeof (blkptr_t));
1954
  if (!bp)
1955
    return grub_errno;
1956
1957
  endian = dn->endian;
2546
  endian = dn->endian;
1958
  for (level = dn->dn.dn_nlevels - 1; level >= 0; level--)
2547
  for (level = dn->dn.dn_nlevels - 1; level >= 0; level--)
1959
    {
2548
    {
1960
      grub_dprintf ("zfs", "endian = %d\n", endian);
2549
      grub_dprintf ("zfs", "endian = %d\n", endian);
1961
      idx = (blkid >> (epbs * level)) & ((1 << epbs) - 1);
2550
      idx = (blkid >> (epbs * level)) & ((1 << epbs) - 1);
1962
      *bp = bp_array[idx];
2551
      bp = &bp_array[idx];
1963
      if (bp_array != dn->dn.dn_blkptr)
2552
      if (BP_IS_HOLE (bp, endian))
1964
	{
1965
	  grub_free (bp_array);
1966
	  bp_array = 0;
1967
	}
1968
1969
      if (BP_IS_HOLE (bp))
1970
	{
2553
	{
1971
	  grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, 
2554
	  grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, 
1972
						dn->endian) 
2555
						dn->endian) 
Lines 1993-1998 Link Here
1993
      endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
2576
      endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
1994
      if (err)
2577
      if (err)
1995
	break;
2578
	break;
2579
      if (bp_array != dn->dn.dn_blkptr)
2580
        grub_free (bp_array);
1996
      bp_array = tmpbuf;
2581
      bp_array = tmpbuf;
1997
    }
2582
    }
1998
  if (bp_array != dn->dn.dn_blkptr)
2583
  if (bp_array != dn->dn.dn_blkptr)
Lines 2000-2006 Link Here
2000
  if (endian_out)
2585
  if (endian_out)
2001
    *endian_out = endian;
2586
    *endian_out = endian;
2002
2587
2003
  grub_free (bp);
2004
  return err;
2588
  return err;
2005
}
2589
}
2006
2590
Lines 2030-2040 Link Here
2030
  return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name);
2614
  return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name);
2031
}
2615
}
2032
2616
2617
/*
2618
 * mzap_value_search: Looks up value and returns property name.
2619
 */
2620
static grub_err_t
2621
mzap_value_search (mzap_phys_t *zapobj, grub_zfs_endian_t endian,
2622
	     int objsize, char *name, grub_uint64_t *value)
2623
{
2624
  int i, chunks;
2625
  mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
2626
  grub_uint64_t mze_val;
2627
2628
  chunks = objsize / MZAP_ENT_LEN - 1;
2629
  for (i = 0; i < chunks; i++)
2630
    {
2631
	mze_val = grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian);
2632
	if (mze_val == *value)
2633
	  {
2634
	    grub_memcpy (name, mzap_ent[i].mze_name, grub_strlen
2635
			 (mzap_ent[i].mze_name) + 1);
2636
	    return GRUB_ERR_NONE;
2637
	  }
2638
    }
2639
2640
  return grub_error (GRUB_ERR_FILE_NOT_FOUND,
2641
			"mzap_value_search: couldn't find %s", value);
2642
}
2643
2033
static int
2644
static int
2034
mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, 
2645
mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, 
2035
	      int (*hook) (const char *name, grub_uint64_t val,
2646
    int (*hook) (const char *name, grub_uint64_t val,
2036
			   struct grub_zfs_dir_ctx *ctx),
2647
	struct grub_zfs_dir_ctx *ctx),
2037
	      struct grub_zfs_dir_ctx *ctx)
2648
    struct grub_zfs_dir_ctx *ctx)
2038
{
2649
{
2039
  int i, chunks;
2650
  int i, chunks;
2040
  mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
2651
  mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
Lines 2088-2094 Link Here
2088
   */
2699
   */
2089
  crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1);
2700
  crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1);
2090
2701
2091
  return crc;
2702
  return (crc);
2092
}
2703
}
2093
2704
2094
/*
2705
/*
Lines 2110-2116 Link Here
2110
  while (n--)
2721
  while (n--)
2111
    {
2722
    {
2112
      if (grub_toupper (*t1) != grub_toupper (*t2))
2723
      if (grub_toupper (*t1) != grub_toupper (*t2))
2113
	return (int) grub_toupper (*t1) - (int) grub_toupper (*t2);
2724
	  return (int) grub_toupper (*t1) - (int) grub_toupper (*t2);
2114
	  
2725
	  
2115
      t1++;
2726
      t1++;
2116
      t2++;
2727
      t2++;
Lines 2298-2306 Link Here
2298
fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
2909
fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
2299
	      grub_size_t name_elem_length,
2910
	      grub_size_t name_elem_length,
2300
	      int (*hook) (const void *name, grub_size_t name_length,
2911
	      int (*hook) (const void *name, grub_size_t name_length,
2301
			   const void *val_in,
2912
			    const void *val_in, grub_size_t nelem,
2302
			   grub_size_t nelem, grub_size_t elemsize,
2913
			    grub_size_t elemsize, void *data),
2303
			   void *data),
2304
	      void *hook_data, struct grub_zfs_data *data)
2914
	      void *hook_data, struct grub_zfs_data *data)
2305
{
2915
{
2306
  zap_leaf_phys_t *l;
2916
  zap_leaf_phys_t *l;
Lines 2331-2341 Link Here
2331
  for (idx = 0; idx < (1ULL << zap->zap_ptrtbl.zt_shift); idx++)
2941
  for (idx = 0; idx < (1ULL << zap->zap_ptrtbl.zt_shift); idx++)
2332
    {
2942
    {
2333
      blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))],
2943
      blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))],
2334
				 zap_dnode->endian);
2944
					 zap_dnode->endian);
2335
2945
2336
      for (idx2 = 0; idx2 < idx; idx2++)
2946
      for (idx2 = 0; idx2 < idx; idx2++)
2337
	if (blkid == grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))],
2947
	if (blkid == grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))],
2338
					zap_dnode->endian))
2948
					 zap_dnode->endian))
2339
	  break;
2949
	  break;
2340
      if (idx2 != idx)
2950
      if (idx2 != idx)
2341
	continue;
2951
	continue;
Lines 2361-2415 Link Here
2361
	}
2971
	}
2362
2972
2363
      for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++)
2973
      for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++)
2364
	{
2974
	  {
2365
	  char *buf;
2975
	    char *buf;
2366
	  struct zap_leaf_entry *le;
2976
	    struct zap_leaf_entry *le;
2367
	  char *val;
2977
	    char *val;
2368
	  grub_size_t val_length;
2978
	    grub_size_t val_length;
2369
	  le = ZAP_LEAF_ENTRY (l, blksft, chunk);
2979
	    le = ZAP_LEAF_ENTRY (l, blksft, chunk);
2370
2371
	  /* Verify the chunk entry */
2372
	  if (le->le_type != ZAP_CHUNK_ENTRY)
2373
	    continue;
2374
2980
2375
	  buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
2981
	    /* Verify the chunk entry */
2376
			     * name_elem_length + 1);
2982
	    if (le->le_type != ZAP_CHUNK_ENTRY)
2377
	  if (zap_leaf_array_get (l, endian, blksft,
2378
				  grub_zfs_to_cpu16 (le->le_name_chunk,
2379
						     endian),
2380
				  grub_zfs_to_cpu16 (le->le_name_length,
2381
						     endian)
2382
				  * name_elem_length, buf))
2383
	    {
2384
	      grub_free (buf);
2385
	      continue;
2983
	      continue;
2386
	    }
2387
	  buf[le->le_name_length * name_elem_length] = 0;
2388
2984
2389
	  val_length = ((int) le->le_value_length
2985
	    buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
2390
			* (int) le->le_int_size);
2986
			       * name_elem_length + 1);
2391
	  val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
2987
	    if (zap_leaf_array_get (l, endian, blksft,
2392
	  if (zap_leaf_array_get (l, endian, blksft,
2988
				    grub_zfs_to_cpu16 (le->le_name_chunk,
2393
				  grub_zfs_to_cpu16 (le->le_value_chunk,
2989
						       endian),
2394
						     endian),
2990
				    grub_zfs_to_cpu16 (le->le_name_length,
2395
				  val_length, val))
2991
						       endian)
2396
	    {
2992
				    * name_elem_length, buf))
2397
	      grub_free (buf);
2993
	      {
2398
	      grub_free (val);
2994
		grub_free (buf);
2399
	      continue;
2995
		continue;
2400
	    }
2996
	      }
2997
	    buf[le->le_name_length * name_elem_length] = 0;
2401
2998
2402
	  if (hook (buf, le->le_name_length,
2999
	    val_length = ((int) le->le_value_length
2403
		    val, le->le_value_length, le->le_int_size, hook_data))
3000
			  * (int) le->le_int_size);
2404
	    {
3001
	    val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
2405
	      grub_free (l);
3002
	    if (zap_leaf_array_get (l, endian, blksft,
2406
	      return 1;
3003
				    grub_zfs_to_cpu16 (le->le_value_chunk,
2407
	    }
3004
						       endian),
2408
	  grub_free (buf);
3005
				    val_length, val))
2409
	  grub_free (val);
3006
	      {
2410
	}
3007
		grub_free (buf);
2411
      grub_free (l);
3008
		grub_free (val);
2412
    }
3009
		continue;
3010
	      }
3011
3012
	    if (hook (buf, le->le_name_length,
3013
		      val, le->le_value_length, le->le_int_size, hook_data))
3014
	      {
3015
		grub_free (l);
3016
		return 1;
3017
	      }
3018
	    grub_free (buf);
3019
	    grub_free (val);
3020
	  }
3021
      grub_free (l);
3022
    }
2413
  return 0;
3023
  return 0;
2414
}
3024
}
2415
3025
Lines 2463-2578 Link Here
2463
  return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
3073
  return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
2464
}
3074
}
2465
3075
2466
/* Context for zap_iterate_u64.  */
3076
/*
2467
struct zap_iterate_u64_ctx
3077
 * Read in the data of a zap object and find the property name for a
2468
{
3078
 * matching value.
2469
  int (*hook) (const char *, grub_uint64_t, struct grub_zfs_dir_ctx *);
3079
 *
2470
  struct grub_zfs_dir_ctx *dir_ctx;
3080
 */
2471
};
3081
static grub_err_t
2472
3082
zap_value_search (dnode_end_t *zap_dnode, char *name, grub_uint64_t *val,
2473
/* Helper for zap_iterate_u64.  */
3083
	    struct grub_zfs_data *data)
2474
static int
2475
zap_iterate_u64_transform (const void *name,
2476
			   grub_size_t namelen __attribute__ ((unused)),
2477
			   const void *val_in,
2478
			   grub_size_t nelem,
2479
			   grub_size_t elemsize,
2480
			   void *data)
2481
{
2482
  struct zap_iterate_u64_ctx *ctx = data;
2483
2484
  if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
2485
    return 0;
2486
  return ctx->hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in),
2487
		    ctx->dir_ctx);
2488
}
2489
2490
static int
2491
zap_iterate_u64 (dnode_end_t * zap_dnode, 
2492
		 int (*hook) (const char *name, grub_uint64_t val,
2493
			      struct grub_zfs_dir_ctx *ctx),
2494
		 struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx)
2495
{
3084
{
2496
  grub_uint64_t block_type;
3085
  grub_uint64_t block_type;
2497
  int size;
3086
  int size;
2498
  void *zapbuf;
3087
  void *zapbuf;
2499
  grub_err_t err;
3088
  grub_err_t err;
2500
  int ret;
2501
  grub_zfs_endian_t endian;
3089
  grub_zfs_endian_t endian;
2502
3090
3091
  grub_dprintf ("zfs", "zap_value_search: looking for '%lld'\n", (unsigned long long)*val);
3092
2503
  /* Read in the first block of the zap object data. */
3093
  /* Read in the first block of the zap object data. */
2504
  size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT;
3094
  size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec,
3095
			    zap_dnode->endian) << SPA_MINBLOCKSHIFT;
2505
  err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
3096
  err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
2506
  if (err)
3097
  if (err)
2507
    return 0;
3098
    return err;
2508
  block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
3099
  block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
2509
3100
2510
  grub_dprintf ("zfs", "zap iterate\n");
3101
  grub_dprintf ("zfs", "zap_value_search: zap read\n");
2511
3102
2512
  if (block_type == ZBT_MICRO)
3103
  if (block_type == ZBT_MICRO)
2513
    {
3104
    {
2514
      grub_dprintf ("zfs", "micro zap\n");
3105
      grub_dprintf ("zfs", "zap_value_search: micro zap value search\n");
2515
      ret = mzap_iterate (zapbuf, endian, size, hook, ctx);
3106
      err = (mzap_value_search (zapbuf, endian, size, name, val));
3107
      grub_dprintf ("zfs", "zap_value_search: returned %d\n", err);
2516
      grub_free (zapbuf);
3108
      grub_free (zapbuf);
2517
      return ret;
3109
      return err;
2518
    }
3110
    }
2519
  else if (block_type == ZBT_HEADER)
3111
  else if (block_type == ZBT_HEADER)
2520
    {
3112
    {
2521
      struct zap_iterate_u64_ctx transform_ctx = {
2522
	.hook = hook,
2523
	.dir_ctx = ctx
2524
      };
2525
2526
      grub_dprintf ("zfs", "fat zap\n");
2527
      /* this is a fat zap */
3113
      /* this is a fat zap */
2528
      ret = fzap_iterate (zap_dnode, zapbuf, 1,
3114
      grub_dprintf ("zfs", "fat zap value search not supported\n");
2529
			  zap_iterate_u64_transform, &transform_ctx, data);
2530
      grub_free (zapbuf);
3115
      grub_free (zapbuf);
2531
      return ret;
3116
      return grub_error (GRUB_ERR_BAD_FS, "fat zap value search not supported");
2532
    }
3117
    }
2533
  grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
3118
2534
  return 0;
3119
  return grub_error (GRUB_ERR_BAD_FS, "zap_value_search: unknown ZAP type");
2535
}
3120
}
2536
3121
2537
static int
3122
/* Context for zap_iterate_u64.  */
2538
zap_iterate (dnode_end_t * zap_dnode, 
3123
struct zap_iterate_u64_ctx
2539
	     grub_size_t nameelemlen,
2540
	     int (*hook) (const void *name, grub_size_t namelen,
2541
			  const void *val_in,
2542
			  grub_size_t nelem, grub_size_t elemsize,
2543
			  void *data),
2544
	     void *hook_data, struct grub_zfs_data *data)
2545
{
3124
{
2546
  grub_uint64_t block_type;
3125
	int (*hook) (const char *, grub_uint64_t, struct grub_zfs_dir_ctx *);
2547
  void *zapbuf;
3126
	struct grub_zfs_dir_ctx *dir_ctx;
2548
  grub_err_t err;
3127
};
2549
  int ret;
2550
  grub_zfs_endian_t endian;
2551
3128
2552
  /* Read in the first block of the zap object data. */
3129
/* Helper for zap_iterate_u64.  */
2553
  err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
3130
static int
2554
  if (err)
3131
zap_iterate_u64_transform (const void *name,
2555
    return 0;
3132
                           grub_size_t namelen __attribute__ ((unused)),
2556
  block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
3133
                           const void *val_in,
3134
                           grub_size_t nelem,
3135
                           grub_size_t elemsize,
3136
                           void *data)
3137
{
3138
	struct zap_iterate_u64_ctx *ctx = data;
3139
3140
	if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
3141
		return 0;
3142
	return ctx->hook(name,
3143
	    grub_be_to_cpu64 (*(const grub_uint64_t *) val_in), ctx->dir_ctx);
3144
}
2557
3145
2558
  grub_dprintf ("zfs", "zap iterate\n");
3146
static int
3147
zap_iterate_u64 (dnode_end_t * zap_dnode,
3148
    int (*hook) (const char *name, grub_uint64_t val,
3149
	struct grub_zfs_dir_ctx *ctx),
3150
    struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx)
3151
{
3152
	grub_uint64_t block_type;
3153
	int size;
3154
	void *zapbuf;
3155
	grub_err_t err;
3156
	int ret;
3157
	grub_zfs_endian_t endian;
3158
3159
	/* Read in the first block of the zap object data. */
3160
	size = grub_zfs_to_cpu16(zap_dnode->dn.dn_datablkszsec,
3161
	    zap_dnode->endian) << SPA_MINBLOCKSHIFT;
3162
	err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
3163
	if (err)
3164
		return 0;
3165
	block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
3166
3167
	grub_dprintf ("zfs", "zap iterate\n");
3168
3169
	if (block_type == ZBT_MICRO) {
3170
		grub_dprintf ("zfs", "micro zap\n");
3171
		ret = mzap_iterate (zapbuf, endian, size, hook, ctx);
3172
		grub_free (zapbuf);
3173
		return ret;
3174
	} else if (block_type == ZBT_HEADER) {
3175
		struct zap_iterate_u64_ctx transform_ctx = {
3176
			.hook = hook,
3177
			.dir_ctx = ctx
3178
		};
3179
		grub_dprintf ("zfs", "fat zap\n");
3180
		/* this is a fat zap */
3181
		ret = fzap_iterate (zap_dnode, zapbuf, 1,
3182
		    zap_iterate_u64_transform, &transform_ctx, data);
3183
		grub_free (zapbuf);
3184
		return ret;
3185
	}
3186
	grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
3187
	return 0;
3188
}
2559
3189
2560
  if (block_type == ZBT_MICRO)
3190
static int
2561
    {
3191
zap_iterate (dnode_end_t * zap_dnode, grub_size_t nameelemlen,
2562
      grub_error (GRUB_ERR_BAD_FS, "micro ZAP where FAT ZAP expected");
3192
    int (*hook) (const void *name, grub_size_t namelen, const void *val_in,
2563
      return 0;
3193
	grub_size_t nelem, grub_size_t elemsize, void *data),
2564
    }
3194
    void *hook_data, struct grub_zfs_data *data)
2565
  if (block_type == ZBT_HEADER)
3195
{
2566
    {
3196
	grub_uint64_t block_type;
2567
      grub_dprintf ("zfs", "fat zap\n");
3197
	void *zapbuf;
2568
      /* this is a fat zap */
3198
	grub_err_t err;
2569
      ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, hook_data,
3199
	int ret;
2570
			  data);
3200
	grub_zfs_endian_t endian;
2571
      grub_free (zapbuf);
3201
2572
      return ret;
3202
	/* Read in the first block of the zap object data. */
2573
    }
3203
	err = dmu_read(zap_dnode, 0, &zapbuf, &endian, data);
2574
  grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
3204
	if (err)
2575
  return 0;
3205
		return 0;
3206
	block_type = grub_zfs_to_cpu64(*((grub_uint64_t *) zapbuf), endian);
3207
3208
	grub_dprintf("zfs", "zap iterate\n");
3209
3210
	if (block_type == ZBT_MICRO) {
3211
		grub_error(GRUB_ERR_BAD_FS, "micro ZAP where FAT ZAP expected");
3212
		return 0;
3213
	}
3214
	if (block_type == ZBT_HEADER) {
3215
		grub_dprintf ("zfs", "fat zap\n");
3216
		/* this is a fat zap */
3217
		ret = fzap_iterate(zap_dnode, zapbuf, nameelemlen, hook,
3218
		    hook_data, data);
3219
		grub_free(zapbuf);
3220
		return ret;
3221
	}
3222
	grub_error(GRUB_ERR_BAD_FS, "unknown ZAP type");
3223
	return 0;
2576
}
3224
}
2577
3225
2578
3226
Lines 2608-2614 Link Here
2608
      grub_memmove (&(buf->dn), &(data->dnode_buf)[idx], DNODE_SIZE);
3256
      grub_memmove (&(buf->dn), &(data->dnode_buf)[idx], DNODE_SIZE);
2609
      buf->endian = data->dnode_endian;
3257
      buf->endian = data->dnode_endian;
2610
      if (type && buf->dn.dn_type != type) 
3258
      if (type && buf->dn.dn_type != type) 
2611
	return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); 
3259
	return grub_error(GRUB_ERR_BAD_FS, "[1] incorrect dnode type: %d != %d\n", buf->dn.dn_type, type);
2612
      return GRUB_ERR_NONE;
3260
      return GRUB_ERR_NONE;
2613
    }
3261
    }
2614
3262
Lines 2620-2625 Link Here
2620
  grub_dprintf ("zfs", "alive\n");
3268
  grub_dprintf ("zfs", "alive\n");
2621
3269
2622
  grub_free (data->dnode_buf);
3270
  grub_free (data->dnode_buf);
3271
  data->dnode_buf = NULL;
2623
  grub_free (data->dnode_mdn);
3272
  grub_free (data->dnode_mdn);
2624
  data->dnode_mdn = grub_malloc (sizeof (*mdn));
3273
  data->dnode_mdn = grub_malloc (sizeof (*mdn));
2625
  if (! data->dnode_mdn)
3274
  if (! data->dnode_mdn)
Lines 2639-2645 Link Here
2639
  grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE);
3288
  grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE);
2640
  buf->endian = endian;
3289
  buf->endian = endian;
2641
  if (type && buf->dn.dn_type != type) 
3290
  if (type && buf->dn.dn_type != type) 
2642
    return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); 
3291
    return grub_error(GRUB_ERR_BAD_FS, "[2] incorrect dnode type: %d != %d\n", buf->dn.dn_type, type);
2643
3292
2644
  return GRUB_ERR_NONE;
3293
  return GRUB_ERR_NONE;
2645
}
3294
}
Lines 2801-2807 Link Here
2801
	      grub_size_t block;
3450
	      grub_size_t block;
2802
	      grub_size_t blksz;
3451
	      grub_size_t blksz;
2803
	      blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, 
3452
	      blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, 
2804
					  dnode_path->dn.endian)
3453
					 dnode_path->dn.endian)
2805
		       << SPA_MINBLOCKSHIFT);
3454
		       << SPA_MINBLOCKSHIFT);
2806
3455
2807
	      sym_value = grub_malloc (sym_sz);
3456
	      sym_value = grub_malloc (sym_sz);
Lines 2846-2856 Link Here
2846
	      grub_free (dn_new);
3495
	      grub_free (dn_new);
2847
	    }
3496
	    }
2848
	  else while (dnode_path != root)
3497
	  else while (dnode_path != root)
2849
		 {
3498
	    {
2850
		   dn_new = dnode_path;
3499
	      dn_new = dnode_path;
2851
		   dnode_path = dn_new->next;
3500
	      dnode_path = dn_new->next;
2852
		   grub_free (dn_new);
3501
	      grub_free (dn_new);
2853
		 }
3502
	    }
2854
	}
3503
	}
2855
      if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA)
3504
      if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA)
2856
	{
3505
	{
Lines 2907-2917 Link Here
2907
		  grub_free (dn_new);
3556
		  grub_free (dn_new);
2908
		}
3557
		}
2909
	      else while (dnode_path != root)
3558
	      else while (dnode_path != root)
2910
		     {
3559
		{
2911
		       dn_new = dnode_path;
3560
		  dn_new = dnode_path;
2912
		       dnode_path = dn_new->next;
3561
		  dnode_path = dn_new->next;
2913
		       grub_free (dn_new);
3562
		  grub_free (dn_new);
2914
		     }
3563
		}
2915
	    }
3564
	    }
2916
	}
3565
	}
2917
    }
3566
    }
Lines 2929-2985 Link Here
2929
  return err;
3578
  return err;
2930
}
3579
}
2931
3580
2932
#if 0
3581
/*
3582
 * Get the default 'bootfs' dataset name using rootfs object number
3583
 *
3584
 */
3585
static grub_err_t
3586
get_default_bootfsname (dnode_end_t * mosmdn, grub_uint64_t bootfsobj,
3587
		       struct grub_zfs_data *data, char **bootfsname)
3588
{
3589
  dnode_end_t dn;
3590
  dnode_end_t mdn;
3591
  grub_uint64_t dirobj;
3592
  grub_uint64_t parentobj;
3593
  grub_uint64_t childobj;
3594
  grub_uint64_t rootobj;
3595
  grub_size_t	buf_size;
3596
  grub_err_t err = GRUB_ERR_NONE;
3597
  char *bootfs;
3598
3599
  *bootfsname = 0;
3600
  if ((grub_errno = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT,
3601
			       DMU_OT_OBJECT_DIRECTORY, &mdn, data)))
3602
      return (grub_errno);
3603
3604
  err = zap_lookup (&mdn, DMU_POOL_ROOT_DATASET, &rootobj, data, 0);
3605
  if (err)
3606
       return err;
3607
3608
  if ((grub_errno = dnode_get (mosmdn, bootfsobj, DMU_OT_DSL_DATASET, &dn, data)))
3609
       return (grub_errno);
3610
3611
  dirobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *)
3612
			DN_BONUS (&dn.dn))->ds_dir_obj, dn.endian);
3613
3614
  buf_size = BOOTFSNAME_SIZE;
3615
  bootfs = grub_zalloc(buf_size);
3616
  do
3617
    {
3618
      if ((grub_errno = dnode_get (mosmdn, dirobj, DMU_OT_DSL_DIR, &dn, data)))
3619
	{
3620
	  grub_free (bootfs);
3621
          return (grub_errno);
3622
	}
3623
3624
      parentobj = grub_zfs_to_cpu64 ((((dsl_dir_phys_t *)
3625
			    DN_BONUS (&dn.dn)))->dd_parent_obj, dn.endian);
3626
3627
      if ((grub_errno = dnode_get (mosmdn, parentobj, DMU_OT_DSL_DIR, &dn, data)))
3628
	{
3629
	  grub_free (bootfs);
3630
          return (grub_errno);
3631
	}
3632
3633
      childobj = grub_zfs_to_cpu64 ((((dsl_dir_phys_t *)
3634
			   DN_BONUS (&dn.dn)))->dd_child_dir_zapobj, dn.endian);
3635
3636
      if ((grub_errno = dnode_get (mosmdn, childobj,
3637
				   DMU_OT_DSL_DIR_CHILD_MAP, &dn, data)))
3638
	{
3639
	  grub_free (bootfs);
3640
          return (grub_errno);
3641
	}
3642
3643
      char cname[64];
3644
      grub_memset (cname, 0, sizeof(cname));
3645
3646
      if (zap_value_search (&dn, cname, &dirobj, data))
3647
	{
3648
	  grub_free (bootfs);
3649
          return (GRUB_ERR_BAD_FS);
3650
	}
3651
3652
      grub_size_t cname_len = grub_strlen(cname);
3653
      cname[cname_len++] = '/';
3654
3655
      grub_size_t bootfs_len= grub_strlen(bootfs);
3656
      grub_size_t expected_len = bootfs_len + cname_len;
3657
      if (expected_len >= buf_size)
3658
	{
3659
	    while((buf_size = buf_size * 2) < expected_len);
3660
	    char *tmp = grub_realloc (bootfs, buf_size);
3661
	    if (! tmp)
3662
	      {
3663
		grub_free (bootfs);
3664
		return (grub_errno);
3665
	      }
3666
	    bootfs = tmp;
3667
	    grub_memset((bootfs + bootfs_len), 0, (buf_size - bootfs_len));
3668
	}
3669
3670
      /* create space for parent dataset name */
3671
      grub_memmove((bootfs + cname_len), bootfs, bootfs_len);
3672
      grub_memmove(bootfs, cname, cname_len);
3673
3674
    } while ((dirobj = parentobj) != rootobj);
3675
3676
  /* remove trailing slash */
3677
  *(bootfs + grub_strlen(bootfs) - 1) = '\0';
3678
  *bootfsname = bootfs;
3679
3680
  grub_dprintf ("zfs", "get_default_bootfsname: %s\n", *bootfsname);
3681
  return (0);
3682
}
3683
2933
/*
3684
/*
2934
 * Get the default 'bootfs' property value from the rootpool.
3685
 * Get the default 'bootfs' property value from the rootpool.
2935
 *
3686
 *
2936
 */
3687
 */
2937
static grub_err_t
3688
static grub_err_t
2938
get_default_bootfsobj (dnode_phys_t * mosmdn, grub_uint64_t * obj,
3689
get_default_bootfsobj (dnode_end_t * mosmdn, grub_uint64_t * obj,
2939
		       struct grub_zfs_data *data)
3690
		       struct grub_zfs_data *data)
2940
{
3691
{
2941
  grub_uint64_t objnum = 0;
3692
  grub_uint64_t objnum = 0;
2942
  dnode_phys_t *dn;
3693
  dnode_end_t dn;
2943
  if (!dn)
2944
    return grub_errno;
2945
3694
3695
  grub_dprintf ("zfs", "get_default_bootfsobj called\n");
2946
  if ((grub_errno = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT,
3696
  if ((grub_errno = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT,
2947
			       DMU_OT_OBJECT_DIRECTORY, dn, data)))
3697
			       DMU_OT_OBJECT_DIRECTORY, &dn, data)))
2948
    {
2949
      grub_free (dn);
2950
      return (grub_errno);
3698
      return (grub_errno);
2951
    }
2952
3699
2953
  /*
3700
  /*
2954
   * find the object number for 'pool_props', and get the dnode
3701
   * find the object number for 'pool_props', and get the dnode
2955
   * of the 'pool_props'.
3702
   * of the 'pool_props'.
2956
   */
3703
   */
2957
  if (zap_lookup (dn, DMU_POOL_PROPS, &objnum, data))
3704
  if (zap_lookup (&dn, DMU_POOL_PROPS, &objnum, data, 0))
2958
    {
2959
      grub_free (dn);
2960
      return (GRUB_ERR_BAD_FS);
3705
      return (GRUB_ERR_BAD_FS);
2961
    }
3706
2962
  if ((grub_errno = dnode_get (mosmdn, objnum, DMU_OT_POOL_PROPS, dn, data)))
3707
  if ((grub_errno = dnode_get (mosmdn, objnum, DMU_OT_POOL_PROPS, &dn, data)))
2963
    {
2964
      grub_free (dn);
2965
      return (grub_errno);
3708
      return (grub_errno);
2966
    }
3709
2967
  if (zap_lookup (dn, ZPOOL_PROP_BOOTFS, &objnum, data))
3710
  if (zap_lookup (&dn, ZPOOL_PROP_BOOTFS, &objnum, data, 0))
2968
    {
2969
      grub_free (dn);
2970
      return (GRUB_ERR_BAD_FS);
3711
      return (GRUB_ERR_BAD_FS);
2971
    }
2972
3712
2973
  if (!objnum)
3713
  if (!objnum)
2974
    {
2975
      grub_free (dn);
2976
      return (GRUB_ERR_BAD_FS);
3714
      return (GRUB_ERR_BAD_FS);
2977
    }
2978
3715
2979
  *obj = objnum;
3716
  *obj = objnum;
3717
2980
  return (0);
3718
  return (0);
2981
}
3719
}
2982
#endif
3720
2983
/*
3721
/*
2984
 * Given a MOS metadnode, get the metadnode of a given filesystem name (fsname),
3722
 * Given a MOS metadnode, get the metadnode of a given filesystem name (fsname),
2985
 * e.g. pool/rootfs, or a given object number (obj), e.g. the object number
3723
 * e.g. pool/rootfs, or a given object number (obj), e.g. the object number
Lines 3036-3041 Link Here
3036
      *fsname = 0;
3774
      *fsname = 0;
3037
3775
3038
      childobj = grub_zfs_to_cpu64 ((((dsl_dir_phys_t *) DN_BONUS (&mdn->dn)))->dd_child_dir_zapobj, mdn->endian);
3776
      childobj = grub_zfs_to_cpu64 ((((dsl_dir_phys_t *) DN_BONUS (&mdn->dn)))->dd_child_dir_zapobj, mdn->endian);
3777
      if (childobj == 0)
3778
	return grub_error(GRUB_ERR_BAD_FS, "file system not found");
3779
3039
      err = dnode_get (mosmdn, childobj,
3780
      err = dnode_get (mosmdn, childobj,
3040
		       DMU_OT_DSL_DIR_CHILD_MAP, mdn, data);
3781
		       DMU_OT_DSL_DIR_CHILD_MAP, mdn, data);
3041
      if (err)
3782
      if (err)
Lines 3084-3344 Link Here
3084
/* Context for dnode_get_fullpath.  */
3825
/* Context for dnode_get_fullpath.  */
3085
struct dnode_get_fullpath_ctx
3826
struct dnode_get_fullpath_ctx
3086
{
3827
{
3087
  struct subvolume *subvol;
3828
	struct subvolume *subvol;
3088
  grub_uint64_t salt;
3829
	grub_uint64_t salt;
3089
  int keyn;
3830
	int keyn;
3090
};
3831
};
3091
3832
3092
/* Helper for dnode_get_fullpath.  */
3833
/* Helper for dnode_get_fullpath.  */
3093
static int
3834
static int
3094
count_zap_keys (const void *name __attribute__ ((unused)),
3835
count_zap_keys (const void *name __attribute__ ((unused)),
3095
		grub_size_t namelen __attribute__ ((unused)),
3836
    grub_size_t namelen __attribute__ ((unused)),
3096
		const void *val_in __attribute__ ((unused)),
3837
    const void *val_in __attribute__ ((unused)),
3097
		grub_size_t nelem __attribute__ ((unused)),
3838
    grub_size_t nelem __attribute__ ((unused)),
3098
		grub_size_t elemsize __attribute__ ((unused)),
3839
    grub_size_t elemsize __attribute__ ((unused)),
3099
		void *data)
3840
    void *data)
3100
{
3841
{
3101
  struct dnode_get_fullpath_ctx *ctx = data;
3842
	struct dnode_get_fullpath_ctx *ctx = data;
3102
3843
3103
  ctx->subvol->nkeys++;
3844
	ctx->subvol->nkeys++;
3104
  return 0;
3845
	return 0;
3105
}
3846
}
3106
3847
3107
/* Helper for dnode_get_fullpath.  */
3848
/* Helper for dnode_get_fullpath. */
3108
static int
3849
static int
3109
load_zap_key (const void *name, grub_size_t namelen, const void *val_in,
3850
load_zap_key (const void *name, grub_size_t namelen, const void *val_in,
3110
	      grub_size_t nelem, grub_size_t elemsize, void *data)
3851
    grub_size_t nelem, grub_size_t elemsize, void *data)
3111
{
3852
{
3112
  struct dnode_get_fullpath_ctx *ctx = data;
3853
	struct dnode_get_fullpath_ctx *ctx = data;
3113
3854
3114
  if (namelen != 1)
3855
	if (namelen != 1) {
3115
    {
3856
		grub_dprintf("zfs",
3116
      grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
3857
		    "Unexpected key index size %" PRIuGRUB_SIZE "\n", namelen);
3117
		    namelen);
3858
		return 0;
3118
      return 0;
3859
	}
3119
    }
3120
3860
3121
  if (elemsize != 1)
3861
	if (elemsize != 1) {
3122
    {
3862
		grub_dprintf("zfs",
3123
      grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
3863
		    "Unexpected key element size %" PRIuGRUB_SIZE "\n",
3124
		    elemsize);
3864
		    elemsize);
3125
      return 0;
3865
		return 0;
3126
    }
3866
	}
3127
3867
3128
  ctx->subvol->keyring[ctx->keyn].txg =
3868
	ctx->subvol->keyring[ctx->keyn].txg =
3129
    grub_be_to_cpu64 (*(grub_uint64_t *) name);
3869
	    grub_be_to_cpu64(*(grub_uint64_t *) name);
3130
  ctx->subvol->keyring[ctx->keyn].algo =
3870
	ctx->subvol->keyring[ctx->keyn].algo =
3131
    grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
3871
	    grub_le_to_cpu64(*(grub_uint64_t *) val_in);
3132
  ctx->subvol->keyring[ctx->keyn].cipher =
3872
	ctx->subvol->keyring[ctx->keyn].cipher =
3133
    grub_zfs_load_key (val_in, nelem, ctx->salt,
3873
	    grub_zfs_load_key(val_in, nelem, ctx->salt,
3134
		       ctx->subvol->keyring[ctx->keyn].algo);
3874
	    ctx->subvol->keyring[ctx->keyn].algo);
3135
  ctx->keyn++;
3875
	ctx->keyn++;
3136
  return 0;
3876
	return 0;
3137
}
3877
}
3138
3878
3139
static grub_err_t
3879
static grub_err_t
3140
dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
3880
dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
3141
		    dnode_end_t * dn, int *isfs,
3881
    dnode_end_t *dn, int *isfs, struct grub_zfs_data *data)
3142
		    struct grub_zfs_data *data)
3143
{
3882
{
3144
  char *fsname, *snapname;
3883
	char *fsname, *snapname;
3145
  const char *ptr_at, *filename;
3884
	const char *ptr_at, *filename;
3146
  grub_uint64_t headobj;
3885
	grub_uint64_t headobj;
3147
  grub_uint64_t keychainobj;
3886
	grub_uint64_t keychainobj;
3148
  grub_err_t err;
3887
	grub_err_t err;
3149
3888
3150
  ptr_at = grub_strchr (fullpath, '@');
3889
	ptr_at = grub_strchr(fullpath, '@');
3151
  if (! ptr_at)
3890
	if (!ptr_at) {
3152
    {
3891
		*isfs = 1;
3153
      *isfs = 1;
3892
		filename = 0;
3154
      filename = 0;
3893
		snapname = 0;
3155
      snapname = 0;
3894
		fsname = grub_strdup(fullpath);
3156
      fsname = grub_strdup (fullpath);
3895
	} else {
3157
    }
3896
		const char *ptr_slash = grub_strchr(ptr_at, '/');
3158
  else
3897
3159
    {
3898
		*isfs = 0;
3160
      const char *ptr_slash = grub_strchr (ptr_at, '/');
3899
		fsname = grub_malloc(ptr_at - fullpath + 1);
3161
3900
		if (!fsname)
3162
      *isfs = 0;
3901
			return grub_errno;
3163
      fsname = grub_malloc (ptr_at - fullpath + 1);
3902
		grub_memcpy(fsname, fullpath, ptr_at - fullpath);
3164
      if (!fsname)
3903
		fsname[ptr_at - fullpath] = 0;
3165
	return grub_errno;
3904
		if (ptr_at[1] && ptr_at[1] != '/') {
3166
      grub_memcpy (fsname, fullpath, ptr_at - fullpath);
3905
			snapname = grub_malloc(ptr_slash - ptr_at);
3167
      fsname[ptr_at - fullpath] = 0;
3906
			if (!snapname) {
3168
      if (ptr_at[1] && ptr_at[1] != '/')
3907
				grub_free(fsname);
3169
	{
3908
				return grub_errno;
3170
	  snapname = grub_malloc (ptr_slash - ptr_at);
3909
			}
3171
	  if (!snapname)
3910
			grub_memcpy(snapname, ptr_at + 1,
3172
	    {
3911
			    ptr_slash - ptr_at - 1);
3173
	      grub_free (fsname);
3912
			snapname[ptr_slash - ptr_at - 1] = 0;
3174
	      return grub_errno;
3913
		} else
3175
	    }
3914
			snapname = 0;
3176
	  grub_memcpy (snapname, ptr_at + 1, ptr_slash - ptr_at - 1);
3915
		if (ptr_slash)
3177
	  snapname[ptr_slash - ptr_at - 1] = 0;
3916
			filename = ptr_slash;
3178
	}
3917
		else
3179
      else
3918
			filename = "/";
3180
	snapname = 0;
3919
		grub_dprintf("zfs",
3181
      if (ptr_slash)
3920
		    "fsname = '%s' snapname='%s' filename = '%s'\n",
3182
	filename = ptr_slash;
3183
      else
3184
	filename = "/";
3185
      grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n", 
3186
		    fsname, snapname, filename);
3921
		    fsname, snapname, filename);
3187
    }
3922
	}
3188
  grub_dprintf ("zfs", "alive\n");
3923
	grub_dprintf ("zfs", "alive\n");
3189
  err = get_filesystem_dnode (&(data->mos), fsname, dn, data);
3924
	err = get_filesystem_dnode(&(data->mos), fsname, dn, data);
3190
  if (err)
3925
	if (err) {
3191
    {
3926
		grub_free(fsname);
3192
      grub_free (fsname);
3927
		grub_free(snapname);
3193
      grub_free (snapname);
3928
		return err;
3194
      return err;
3929
	}
3195
    }
3196
3197
  grub_dprintf ("zfs", "alive\n");
3198
3930
3199
  headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_head_dataset_obj, dn->endian);
3931
	grub_dprintf("zfs", "alive\n");
3200
3932
3201
  grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian);
3933
	headobj = grub_zfs_to_cpu64(
3934
	    ((dsl_dir_phys_t *) DN_BONUS(&dn->dn))->dd_head_dataset_obj,
3935
	    dn->endian);
3936
3937
	grub_dprintf("zfs", "endian = %d\n", subvol->mdn.endian);
3938
3939
	err = dnode_get(&(data->mos), headobj, DMU_OT_DSL_DATASET,
3940
	    &subvol->mdn, data);
3941
	if (err) {
3942
		grub_free(fsname);
3943
		grub_free(snapname);
3944
		return err;
3945
	}
3946
	grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian);
3202
3947
3203
  err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &subvol->mdn,
3948
	keychainobj = grub_zfs_to_cpu64 (
3204
		   data);
3949
	    ((dsl_dir_phys_t *) DN_BONUS(&dn->dn))->keychain, dn->endian);
3205
  if (err)
3950
	if (grub_zfs_load_key && keychainobj) {
3206
    {
3951
		struct dnode_get_fullpath_ctx ctx = {
3207
      grub_free (fsname);
3952
			.subvol = subvol,
3208
      grub_free (snapname);
3953
			.keyn = 0
3209
      return err;
3954
		};
3210
    }
3955
		dnode_end_t keychain_dn, props_dn;
3211
  grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian);
3956
		grub_uint64_t propsobj;
3957
		propsobj = grub_zfs_to_cpu64(
3958
		    ((dsl_dir_phys_t *) DN_BONUS(&dn->dn))->dd_props_zapobj,
3959
		    dn->endian);
3960
3961
		err = dnode_get(&(data->mos), propsobj, DMU_OT_DSL_PROPS,
3962
		    &props_dn, data);
3963
		if (err) {
3964
			grub_free(fsname);
3965
			grub_free(snapname);
3966
			return err;
3967
		}
3212
3968
3213
  keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian);
3969
		err = zap_lookup (&props_dn, "salt", &ctx.salt, data, 0);
3214
  if (grub_zfs_load_key && keychainobj)
3970
		if (err == GRUB_ERR_FILE_NOT_FOUND) {
3215
    {
3971
			err = 0;
3216
      struct dnode_get_fullpath_ctx ctx = {
3972
			grub_errno = 0;
3217
	.subvol = subvol,
3973
			ctx.salt = 0;
3218
	.keyn = 0
3974
		}
3219
      };
3975
		if (err) {
3220
      dnode_end_t keychain_dn, props_dn;
3976
			grub_dprintf("zfs", "failed here\n");
3221
      grub_uint64_t propsobj;
3977
			return err;
3222
      propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian);
3978
		}
3223
3979
3224
      err = dnode_get (&(data->mos), propsobj, DMU_OT_DSL_PROPS,
3980
		err = dnode_get(&(data->mos), keychainobj, DMU_OT_DSL_KEYCHAIN,
3225
		       &props_dn, data);
3981
		    &keychain_dn, data);
3226
      if (err)
3982
		if (err) {
3227
	{
3983
			grub_free(fsname);
3228
	  grub_free (fsname);
3984
			grub_free(snapname);
3229
	  grub_free (snapname);
3985
			return err;
3230
	  return err;
3986
		}
3987
		subvol->nkeys = 0;
3988
		zap_iterate(&keychain_dn, 8, count_zap_keys, &ctx, data);
3989
		subvol->keyring = grub_zalloc(subvol->nkeys *
3990
		    sizeof (subvol->keyring[0]));
3991
		if (!subvol->keyring) {
3992
			grub_free(fsname);
3993
			grub_free(snapname);
3994
			return err;
3995
		}
3996
		zap_iterate(&keychain_dn, 8, load_zap_key, &ctx, data);
3231
	}
3997
	}
3232
3998
3233
      err = zap_lookup (&props_dn, "salt", &ctx.salt, data, 0);
3999
	if (snapname) {
3234
      if (err == GRUB_ERR_FILE_NOT_FOUND)
4000
		grub_uint64_t snapobj;
3235
	{
3236
	  err = 0;
3237
	  grub_errno = 0;
3238
	  ctx.salt = 0;
3239
	}
3240
      if (err)
3241
	{
3242
	  grub_dprintf ("zfs", "failed here\n");
3243
	  return err;
3244
	}
3245
4001
3246
      err = dnode_get (&(data->mos), keychainobj, DMU_OT_DSL_KEYCHAIN,
4002
		snapobj = grub_zfs_to_cpu64(
3247
		       &keychain_dn, data);
4003
		    ((dsl_dataset_phys_t *)
3248
      if (err)
4004
		    DN_BONUS(&subvol->mdn.dn))->ds_snapnames_zapobj,
3249
	{
4005
		    subvol->mdn.endian);
3250
	  grub_free (fsname);
4006
3251
	  grub_free (snapname);
4007
		err = dnode_get(&(data->mos), snapobj,
3252
	  return err;
4008
		    DMU_OT_DSL_DS_SNAP_MAP, &subvol->mdn, data);
3253
	}
4009
		if (!err)
3254
      subvol->nkeys = 0;
4010
			err = zap_lookup(&subvol->mdn, snapname,
3255
      zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data);
4011
			    &headobj, data, 0);
3256
      subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0]));
4012
		if (!err)
3257
      if (!subvol->keyring)
4013
			err = dnode_get(&(data->mos), headobj,
3258
	{
4014
			    DMU_OT_DSL_DATASET, &subvol->mdn, data);
3259
	  grub_free (fsname);
4015
		if (err) {
3260
	  grub_free (snapname);
4016
			grub_free(fsname);
3261
	  return err;
4017
			grub_free(snapname);
4018
			return err;
4019
		}
3262
	}
4020
	}
3263
      zap_iterate (&keychain_dn, 8, load_zap_key, &ctx, data);
3264
    }
3265
3266
  if (snapname)
3267
    {
3268
      grub_uint64_t snapobj;
3269
3270
      snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&subvol->mdn.dn))->ds_snapnames_zapobj, subvol->mdn.endian);
3271
4021
3272
      err = dnode_get (&(data->mos), snapobj, 
4022
	subvol->obj = headobj;
3273
		       DMU_OT_DSL_DS_SNAP_MAP, &subvol->mdn, data);
3274
      if (!err)
3275
	err = zap_lookup (&subvol->mdn, snapname, &headobj, data, 0);
3276
      if (!err)
3277
	err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET,
3278
			 &subvol->mdn, data);
3279
      if (err)
3280
	{
3281
	  grub_free (fsname);
3282
	  grub_free (snapname);
3283
	  return err;
3284
	}
3285
    }
3286
4023
3287
  subvol->obj = headobj;
4024
	make_mdn(&subvol->mdn, data);
3288
4025
3289
  make_mdn (&subvol->mdn, data);
4026
	grub_dprintf("zfs", "endian = %d\n", subvol->mdn.endian);
3290
  
3291
  grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian);
3292
4027
3293
  if (*isfs)
4028
	if (*isfs) {
3294
    {
4029
		grub_free(fsname);
3295
      grub_free (fsname);
4030
		grub_free(snapname);
3296
      grub_free (snapname);      
4031
		return GRUB_ERR_NONE;
3297
      return GRUB_ERR_NONE;
4032
	}
3298
    }
4033
	err = dnode_get_path(subvol, filename, dn, data);
3299
  err = dnode_get_path (subvol, filename, dn, data);
4034
	grub_free(fsname);
3300
  grub_free (fsname);
4035
	grub_free(snapname);
3301
  grub_free (snapname);
4036
	return err;
3302
  return err;
3303
}
4037
}
3304
4038
3305
static int
4039
/*
3306
nvlist_find_value (const char *nvlist_in, const char *name,
4040
 * Checks whether the MOS features that are active are supported by this
3307
		   int valtype, char **val,
4041
 * (GRUB's) implementation of ZFS.
3308
		   grub_size_t *size_out, grub_size_t *nelm_out)
4042
 *
4043
 * Return:
4044
 *      0: Success.
4045
 *      errnum: Failure.
4046
 */
4047
static grub_err_t
4048
check_mos_features(dnode_end_t *mosmdn, struct grub_zfs_data *data)
3309
{
4049
{
3310
  grub_size_t nvp_name_len, name_len = grub_strlen(name);
4050
        dnode_end_t dn;
3311
  int type;
4051
        grub_uint64_t objnum;
3312
  const char *nvpair=NULL,*nvlist=nvlist_in;
4052
        grub_err_t errnum = GRUB_ERR_NONE;
3313
  char *nvp_name;
4053
4054
        if ((errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
4055
            DMU_OT_OBJECT_DIRECTORY, &dn, data)) != 0)
4056
                return (errnum);
4057
4058
        /*
4059
         * Find the object number for 'features_for_read' and retrieve its
4060
         * corresponding dnode. Note that we don't check features_for_write
4061
         * because GRUB is not opening the pool for write.
4062
         */
4063
        errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data, 0);
4064
	if(errnum != 0) {
4065
	  /* this pool does not support features */
4066
	  if(errnum == GRUB_ERR_FILE_NOT_FOUND)
4067
		errnum = GRUB_ERR_NONE;
4068
4069
          return (errnum);
4070
	}
4071
4072
        if ((errnum = dnode_get(mosmdn, objnum, DMU_OTN_ZAP_METADATA,
4073
            &dn, data)) != 0)
4074
                return (errnum);
3314
4075
3315
  /* Verify if the 1st and 2nd byte in the nvlist are valid. */
4076
        return (zap_iterate_u64(&dn, check_feature, data, NULL));
3316
  /* NOTE: independently of what endianness header announces all 
4077
}
3317
     subsequent values are big-endian.  */
3318
  if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN 
3319
				     && nvlist[1] != NV_BIG_ENDIAN))
3320
    {
3321
      grub_dprintf ("zfs", "incorrect nvlist header\n");
3322
      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
3323
      return 0;
3324
    }
3325
4078
3326
  /*
4079
/*
3327
   * Loop thru the nvpair list
4080
 * For a given XDR packed nvlist, verify the first 4 bytes and move on.
3328
   * The XDR representation of an integer is in big-endian byte order.
4081
 *
3329
   */
4082
 * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
3330
  while ((nvpair=nvlist_next_nvpair(nvlist,nvpair)))
4083
 *
3331
    {
4084
 *      encoding method/host endian     (4 bytes)
3332
      nvpair_name(nvpair,&nvp_name, &nvp_name_len);
4085
 *      nvl_version                     (4 bytes)
3333
      type = nvpair_type(nvpair);
4086
 *      nvl_nvflag                      (4 bytes)
3334
      if (type == valtype
4087
 *	encoded nvpairs:
3335
	  && (nvp_name_len == name_len
4088
 *		encoded size of the nvpair      (4 bytes)
3336
	      || (nvp_name_len > name_len && nvp_name[name_len] == '\0'))
4089
 *		decoded size of the nvpair      (4 bytes)
3337
	  && grub_memcmp (nvp_name, name, name_len) == 0)
4090
 *		name string size                (4 bytes)
3338
	{
4091
 *		name string data                (sizeof(NV_ALIGN4(string))
3339
	  return nvpair_value(nvpair,val,size_out,nelm_out);
4092
 *		data type                       (4 bytes)
3340
	}
4093
 *		# of elements in the nvpair     (4 bytes)
3341
    }
4094
 *		data
4095
 *      2 zero's for the last nvpair
4096
 *		(end of the entire list)	(8 bytes)
4097
 *
4098
 */
4099
4100
/*
4101
 * The nvlist_next_nvpair() function returns a handle to the next nvpair in the
4102
 * list following nvpair. If nvpair is NULL, the first pair is returned. If
4103
 * nvpair is the last pair in the nvlist, NULL is returned.
4104
 */
4105
static const char *
4106
nvlist_next_nvpair (const char *nvl, const char *nvpair)
4107
{
4108
  const char *nvp;
4109
  int encode_size;
4110
  int name_len;
4111
  if (nvl == NULL)
4112
    return NULL;
4113
4114
  if (nvpair == NULL)
4115
    {
4116
      /* skip over header, nvl_version and nvl_nvflag */
4117
      nvpair = nvl + 4 * 3;
4118
    }
4119
  else
4120
    {
4121
      /* skip to the next nvpair */
4122
      encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
4123
      nvpair += encode_size;
4124
      /*If encode_size equals 0 nvlist_next_nvpair would return
4125
       * the same pair received in input, leading to an infinite loop.
4126
       * If encode_size is less than 0, this will move the pointer
4127
       * backwards, *possibly* examinining two times the same nvpair
4128
       * and potentially getting into an infinite loop. */
4129
      if(encode_size <= 0)
4130
	{
4131
	  grub_dprintf ("zfs", "nvpair with size <= 0\n");
4132
	  grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
4133
	  return NULL;
4134
	}
4135
    }
4136
  /* 8 bytes of 0 marks the end of the list */
4137
  if (grub_get_unaligned64 (nvpair) == 0)
4138
    return NULL;
4139
  /*consistency checks*/
4140
  if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE)
4141
    {
4142
      grub_dprintf ("zfs", "nvlist overflow\n");
4143
      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
4144
      return NULL;
4145
    }
4146
  encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
4147
4148
  nvp = nvpair + 4*2;
4149
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
4150
  nvp += 4;
4151
4152
  nvp = nvp + ((name_len + 3) & ~3); /* align */
4153
  if (nvp + 4 >= nvl + VDEV_PHYS_SIZE
4154
      || encode_size < 0
4155
      || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE)
4156
    {
4157
      grub_dprintf ("zfs", "nvlist overflow\n");
4158
      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
4159
      return NULL;
4160
    }
4161
  /* end consistency checks */
4162
4163
  return nvpair;
4164
}
4165
4166
/*
4167
 * This function returns 0 on success and 1 on failure. On success, a string
4168
 * containing the name of nvpair is saved in buf.
4169
 */
4170
static char *
4171
nvpair_name(const char *nvp)
4172
{
4173
	int len;
4174
	char *buf = NULL;
4175
4176
	/* skip over encode/decode size */
4177
	nvp += 4 * 2;
4178
	len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
4179
	buf = grub_malloc(len + 1);
4180
	if (buf ) {
4181
		grub_memmove(buf, nvp + 4, len);
4182
		buf[len] = '\0';
4183
	}
4184
	return buf;
4185
}
4186
4187
#if 0
4188
/*
4189
 * This function retrieves the value of the nvpair in the form of enumerated
4190
 * type data_type_t.
4191
 */
4192
static int
4193
nvpair_type (const char *nvp)
4194
{
4195
  int name_len, type;
4196
4197
  /* skip over encode/decode size */
4198
  nvp += 4 * 2;
4199
4200
  /* skip over name_len */
4201
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
4202
  nvp += 4;
4203
4204
  /* skip over name */
4205
  nvp = nvp + ((name_len + 3) & ~3); /* align */
4206
4207
  type = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
4208
4209
  return type;
4210
}
4211
4212
static int
4213
nvpair_value (const char *nvp,char **val,
4214
	      grub_size_t *size_out, grub_size_t *nelm_out)
4215
{
4216
  int name_len,nelm,encode_size;
4217
4218
  /* skip over encode/decode size */
4219
  encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvp));
4220
  nvp += 8;
4221
4222
  /* skip over name_len */
4223
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
4224
  nvp += 4;
4225
4226
  /* skip over name */
4227
  nvp = nvp + ((name_len + 3) & ~3); /* align */
4228
4229
  /* skip over type */
4230
  nvp += 4;
4231
  nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
4232
  nvp +=4;
4233
  if (nelm < 1)
4234
    {
4235
      grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
4236
      return 0;
4237
    }
4238
  *val = (char *) nvp;
4239
  *size_out = encode_size;
4240
  if (nelm_out)
4241
    *nelm_out = nelm;
4242
4243
  return 1;
4244
}
4245
#endif
4246
4247
static int
4248
nvlist_find_value (const char *nvlist_in, const char *name,
4249
		   int valtype, char **val,
4250
		   grub_size_t *size_out, grub_size_t *nelm_out)
4251
{
4252
  int name_len, type, encode_size;
4253
  const char *nvpair, *nvp_name, *nvlist = nvlist_in;
4254
4255
  /* Verify if the 1st and 2nd byte in the nvlist are valid. */
4256
  /* NOTE: independently of what endianness header announces all
4257
     subsequent values are big-endian.  */
4258
  if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN
4259
				     && nvlist[1] != NV_BIG_ENDIAN))
4260
    {
4261
      grub_dprintf ("zfs", "incorrect nvlist header\n");
4262
      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
4263
      return 0;
4264
    }
4265
4266
  /* skip the header, nvl_version, and nvl_nvflag */
4267
  nvlist = nvlist + 4 * 3;
4268
  /*
4269
   * Loop thru the nvpair list
4270
   * The XDR representation of an integer is in big-endian byte order.
4271
   */
4272
  while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist))))
4273
    {
4274
      int nelm;
4275
4276
      if (nvlist + 4 * 4 >= nvlist_in + VDEV_PHYS_SIZE)
4277
	{
4278
	  grub_dprintf("zfs", "nvlist overflow\n");
4279
	  grub_error(GRUB_ERR_BAD_FS, "incorrect nvlist");
4280
	  return 0;
4281
	}
4282
4283
      nvpair = nvlist + 4 * 2;	/* skip the encode/decode size */
4284
4285
      name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
4286
      nvpair += 4;
4287
4288
      nvp_name = nvpair;
4289
      nvpair = nvpair + ((name_len + 3) & ~3);	/* align */
4290
4291
      if (nvpair + 8 >= nvlist_in + VDEV_PHYS_SIZE
4292
	  || encode_size < 0
4293
	  || nvpair + 8 + encode_size > nvlist_in + VDEV_PHYS_SIZE)
4294
	{
4295
	  grub_dprintf("zfs", "nvlist overflow\n");
4296
	  grub_error(GRUB_ERR_BAD_FS, "incorrect nvlist");
4297
	  return 0;
4298
	}
4299
4300
      type = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
4301
      nvpair += 4;
4302
4303
      nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
4304
      if (nelm < 1)
4305
	return grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
4306
4307
      nvpair += 4;
4308
4309
      if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype)
4310
	{
4311
	  *val = (char *) nvpair;
4312
	  *size_out = encode_size;
4313
	  if (nelm_out)
4314
	    *nelm_out = nelm;
4315
	  return 1;
4316
	}
4317
4318
      nvlist += encode_size;	/* goto the next nvpair */
4319
    }
3342
  return 0;
4320
  return 0;
3343
}
4321
}
3344
4322
Lines 3497-3588 Link Here
3497
}
4475
}
3498
4476
3499
static void
4477
static void
3500
unmount_device (struct grub_zfs_device_desc *desc)
4478
mount_device (struct grub_zfs_device_desc *desc, grub_device_t dev, char *name)
4479
{
4480
  unsigned i;
4481
  switch (desc->type)
4482
    {
4483
    case DEVICE_LEAF:
4484
      if (desc->dev_name)
4485
	{
4486
	  if (grub_strcmp(desc->dev_name, name) == 0)
4487
	    {
4488
	      grub_dprintf ("zfs", "mount_device: using device %s\n", name);
4489
	      desc->dev = dev;
4490
	      desc->original = 1;
4491
	    }
4492
	  else
4493
	    {
4494
	      desc->original = 0; /* just to be safe */
4495
	      grub_dprintf ("zfs", "mount_device: open device %s\n", name);
4496
	      if (desc->dev == NULL)
4497
	        desc->dev = grub_device_open (desc->dev_name);
4498
	    }
4499
	}
4500
      return;
4501
    case DEVICE_RAIDZ:
4502
    case DEVICE_MIRROR:
4503
      for (i = 0; i < desc->n_children; i++)
4504
	mount_device (&desc->children[i], dev, name);
4505
      return;
4506
    }
4507
}
4508
4509
static void
4510
unmount_device (struct grub_zfs_device_desc *desc, int zcached)
3501
{
4511
{
3502
  unsigned i;
4512
  unsigned i;
4513
4514
  if (desc->config)
4515
    grub_free (desc->config);
4516
3503
  switch (desc->type)
4517
  switch (desc->type)
3504
    {
4518
    {
3505
    case DEVICE_LEAF:
4519
    case DEVICE_LEAF:
3506
      if (!desc->original && desc->dev)
4520
      if (desc->dev)
3507
	grub_device_close (desc->dev);
4521
	{
4522
	  /*
4523
	   * make sure we dont close dev provided by caller of zfs_mount()
4524
	   */
4525
	  if (!desc->original)
4526
	    {
4527
	      grub_dprintf ("zfs", "unmount_device: closing device %s\n",
4528
			    desc->dev_name);
4529
	      grub_device_close (desc->dev);
4530
	    }
4531
	  desc->dev = NULL;
4532
	}
4533
      desc->original = 0; /* next caller may use different device */
4534
      if (! zcached)
4535
	  grub_free (desc->dev_name);
3508
      return;
4536
      return;
3509
    case DEVICE_RAIDZ:
4537
    case DEVICE_RAIDZ:
3510
    case DEVICE_MIRROR:
4538
    case DEVICE_MIRROR:
3511
      for (i = 0; i < desc->n_children; i++)
4539
      for (i = 0; i < desc->n_children; i++)
3512
	unmount_device (&desc->children[i]);
4540
	unmount_device (&desc->children[i], zcached);
3513
      grub_free (desc->children);
3514
      return;
4541
      return;
3515
    }
4542
    }
3516
}
4543
}
4544
4545
static void
4546
zfs_unmount (struct grub_zfs_data *data)
4547
{
4548
  unsigned i;
4549
4550
  grub_dprintf("zfs", "zfs_unmount: %p\n", data);
4551
4552
  if (data == NULL)
4553
	return;
4554
4555
  grub_free (data->label);
4556
  data->label = NULL;
4557
  grub_free (data->dnode_buf);
4558
  data->dnode_buf = NULL;
4559
  grub_free (data->dnode_mdn);
4560
  data->dnode_mdn = NULL;
4561
  grub_free (data->file_buf);
4562
  data->file_buf = NULL;
4563
  data->file_start = 0;
4564
  data->file_end = 0;
4565
  data->dnode_start = 0;
4566
  data->dnode_end = 0;
4567
4568
  for (i = 0; i < data->subvol.nkeys; i++)
4569
    grub_crypto_cipher_close (data->subvol.keyring[i].cipher);
4570
  grub_free (data->subvol.keyring);
4571
  data->subvol.nkeys = 0;
4572
  data->subvol.keyring = NULL;
4573
4574
  for (i = 0; i < data->n_devices_attached; i++)
4575
    {
4576
      unmount_device (&data->devices_attached[i], data->zcached);
4577
      if (! data->zcached)
4578
        grub_free (data->devices_attached[i].children);
4579
    }
4580
  if (! data->zcached)
4581
    {
4582
      grub_free (data->devices_attached);
4583
      grub_free (data);
4584
    }
4585
}
4586
4587
/*
4588
 * Free all the caches
4589
 */
4590
static void
4591
zfs_free_caches (void)
4592
{
4593
  unsigned int i;
4594
  struct grub_zfs_data *data;
4595
  struct zfs_mount_cache *zcache, *zcache_next;
4596
  struct zfs_dev_notzfs *dev_notzfs, *dev_notzfs_next;
4597
4598
  /* free the zfs mount cache list */
4599
  zcache = zfs_mount_cache_list;
4600
  while (zcache != NULL)
4601
    {
4602
      data = zcache->zcache_zfs_data;
4603
      if (data)
4604
      {
4605
        for (i = 0; i < data->n_devices_attached; i++)
4606
          {
4607
            unmount_device (&data->devices_attached[i], 0);
4608
            grub_free (data->devices_attached[i].children);
4609
          }
4610
        grub_free (data->devices_attached);
4611
4612
        for (i = 0; i < data->subvol.nkeys; i++)
4613
          grub_crypto_cipher_close (data->subvol.keyring[i].cipher);
4614
        grub_free (data->subvol.keyring);
4615
4616
        grub_free (data);
4617
        zcache->zcache_zfs_data = NULL;
4618
      }
4619
4620
      grub_free (zcache->zcache_pool_name);
4621
      zcache->zcache_pool_name = NULL;
4622
      zcache->zcache_pool_guid = 0;
4623
4624
      zcache_next = zcache->next;
4625
      grub_free (zcache);
4626
      zcache = zcache_next;
4627
    }
4628
  zfs_mount_cache_list = NULL;
4629
4630
  /* free the cache list for non-zfs disk dev */
4631
  dev_notzfs = zfs_dev_notzfs_list;
4632
  while (dev_notzfs != NULL)
4633
    {
4634
      grub_free (dev_notzfs->dev_name);
4635
      dev_notzfs_next = dev_notzfs->next;
4636
      grub_free (dev_notzfs);
4637
      dev_notzfs = dev_notzfs_next;
4638
    }
4639
  zfs_dev_notzfs_list = NULL;
4640
}
4641
4642
static grub_off_t
4643
vdev_label_offset(grub_uint64_t psize, int l, grub_uint64_t offset)
4644
{
4645
  return (offset + l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
4646
	  0 : psize - VDEV_LABELS * sizeof (vdev_label_t)));
4647
}
4648
4649
static grub_err_t
4650
vdev_disk_read_rootlabel(grub_device_t dev, char **config)
4651
{
4652
  int vdevnum;
4653
  int l;
4654
  vdev_phys_t *vp;
4655
  grub_uint64_t s, size;
4656
  grub_err_t err;
4657
4658
  vdevnum = VDEV_LABELS;
4659
4660
  vp = grub_malloc (VDEV_PHYS_SIZE);
4661
  *config = NULL;
4662
4663
  if (!vp)
4664
  {
4665
    grub_dprintf("zfs", "vdev_phys_t allocation failed.\n");
4666
    return grub_errno;
4667
  }
4668
4669
  size = s = grub_disk_get_size (dev->disk);
4670
4671
  /* Don't check back labels on CDROM. */
4672
  if (s == GRUB_DISK_SIZE_UNKNOWN)
4673
    vdevnum = VDEV_LABELS / 2;
4674
  else
4675
   {
4676
     /* grub_disk_get_size() returns sector count */
4677
     s = s << dev->disk->log_sector_size;
4678
     size = P2ALIGN_TYPED(s, sizeof (vdev_label_t), grub_uint64_t);
4679
   }
4680
4681
  for (l = 0; l < vdevnum; l++)
4682
    {
4683
      grub_uint64_t state, txg;
4684
      grub_off_t offset;
4685
      char *nvl;
4686
4687
      offset = vdev_label_offset(size, l, 0);
4688
      offset += VDEV_SKIP_SIZE;		/* pad1 */
4689
      offset += VDEV_BOOT_HEADER_SIZE;	/* boot header */
4690
4691
      /* Read in the vdev_phys. */
4692
      grub_dprintf ("zfs", "vdev_disk_read_rootlabel: label[%d] %"
4693
		    PRIuGRUB_UINT64_T "\n", l, offset);
4694
4695
      err = grub_disk_read (dev->disk, 0, offset,
4696
			    VDEV_PHYS_SIZE, (char *) vp);
4697
      if (err)
4698
	{
4699
	  grub_errno = GRUB_ERR_NONE;
4700
	  continue;
4701
	}
4702
      else
4703
	{
4704
	  zio_cksum_t zc;
4705
	  grub_zfs_endian_t endian;
4706
4707
	  if (grub_zfs_to_cpu64 (vp->vp_zbt.zec_magic,
4708
				 GRUB_ZFS_LITTLE_ENDIAN) == ZEC_MAGIC)
4709
	    endian = GRUB_ZFS_LITTLE_ENDIAN;
4710
	  else if (grub_zfs_to_cpu64 (vp->vp_zbt.zec_magic,
4711
				      GRUB_ZFS_BIG_ENDIAN) == ZEC_MAGIC)
4712
	    endian = GRUB_ZFS_BIG_ENDIAN;
4713
	  else
4714
	      continue;
4715
4716
	  ZIO_SET_CHECKSUM (&zc, offset, 0, 0, 0);
4717
	  err = zio_checksum_verify (zc, ZIO_CHECKSUM_LABEL, endian,
4718
				     (char *)vp, VDEV_PHYS_SIZE);
4719
	  if (err)
4720
	    {
4721
	      grub_errno = GRUB_ERR_NONE;
4722
	      continue;
4723
	    }
4724
	}
4725
4726
      nvl = vp->vp_nvlist;
4727
      if (!grub_zfs_nvlist_lookup_uint64 (nvl, ZPOOL_CONFIG_POOL_STATE,
4728
	&state) && state >= POOL_STATE_DESTROYED)
4729
	{
4730
	  continue;
4731
	}
4732
4733
      if (!grub_zfs_nvlist_lookup_uint64 (nvl, ZPOOL_CONFIG_POOL_TXG,
4734
	&txg) && txg == 0)
4735
	{
4736
	  continue;
4737
	}
4738
4739
      *config = grub_malloc(VDEV_PHYS_SIZE - sizeof (zio_eck_t));
4740
      if (!*config)
4741
	{
4742
	  grub_dprintf("zfs", "nvlist allocation failed.\n");
4743
	  grub_free(vp);
4744
	  return grub_errno;
4745
	}
4746
      grub_memcpy(*config, nvl, VDEV_PHYS_SIZE - sizeof (zio_eck_t));
4747
      break;
4748
    }
4749
4750
  grub_free(vp);
4751
  if (*config == NULL)
4752
    err = GRUB_ERR_BAD_FS;
4753
4754
  return err;
4755
}
4756
4757
/* add device to grub_zfs_device_desc */
4758
static grub_err_t
4759
vdev_add(struct grub_zfs_device_desc *desc, grub_device_t dev, char *nv,
4760
	 char *dev_name, int original)
4761
{
4762
  char *type;
4763
  grub_uint64_t u;
4764
4765
  type = grub_zfs_nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE);
4766
4767
  if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
4768
    desc->type = DEVICE_MIRROR;
4769
  else if (grub_strcmp (type, VDEV_TYPE_RAIDZ) == 0)
4770
    desc->type = DEVICE_RAIDZ;
4771
  else if (grub_strcmp (type, VDEV_TYPE_DISK) == 0 ||
4772
	   grub_strcmp (type, VDEV_TYPE_FILE) == 0)
4773
    desc->type = DEVICE_LEAF;
4774
  else
4775
    {
4776
      grub_dprintf("zfs", "vdev_add: vdev %d unknown type %s\n",
4777
		   (int)desc->id, type);
4778
      grub_free (type);
4779
      return GRUB_ERR_BAD_FS;
4780
    }
4781
  grub_free (type);
4782
4783
  if (desc->type > DEVICE_LEAF)
4784
    {
4785
      unsigned i;
4786
      desc->n_children = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
4787
				(nv, ZPOOL_CONFIG_CHILDREN);
4788
      desc->children = grub_zalloc (sizeof (desc->children[0])
4789
				    * desc->n_children);
4790
      if (! desc->children)
4791
	{
4792
	  grub_dprintf("zfs", "vdev_add: out of memory\n");
4793
	  return GRUB_ERR_OUT_OF_MEMORY;
4794
	}
4795
      /* set children state to DEVICE_ERROR */
4796
      for (i = 0; i < desc->n_children; i++)
4797
	desc->children[i].dev_state = DEVICE_ERROR;
4798
    }
4799
  else
4800
    {
4801
      desc->n_children = 0;
4802
      if (grub_zfs_vdev_validate(nv) || dev == NULL)
4803
	desc->dev_state = DEVICE_ERROR;
4804
      else
4805
	desc->dev_state = DEVICE_OK;
4806
      desc->dev = dev;
4807
      desc->dev_name = dev_name;
4808
      desc->original = original;
4809
      desc->ashift = dev->disk->log_sector_size;
4810
      grub_dprintf("zfs", "vdev_add: added disk %s, state: %d original: %d\n",
4811
		   desc->dev_name, desc->dev_state, desc->original);
4812
    }
4813
4814
  if (desc->type == DEVICE_RAIDZ)
4815
    {
4816
      if (!grub_zfs_nvlist_lookup_uint64 (nv, ZPOOL_CONFIG_NPARITY, &u))
4817
	{
4818
	  grub_dprintf("zfs", "vdev_add: can't get parity\n");
4819
	  return GRUB_ERR_BAD_FS;
4820
	}
4821
      desc->nparity = u;
4822
    }
4823
4824
  if (grub_zfs_nvlist_lookup_uint64 (nv, ZPOOL_CONFIG_ASHIFT, &u))
4825
      desc->ashift = u;
4826
4827
  grub_dprintf("zfs", "vdev_add: ashift: %d\n", desc->ashift);
4828
4829
  return GRUB_ERR_NONE;
4830
}
4831
4832
/* attach device to vdev tree */
4833
static grub_err_t
4834
vdev_attach(struct grub_zfs_data *data, grub_device_t dev, char *config,
4835
	    char *dev_name, int original)
4836
{
4837
  grub_uint64_t id, guid, txg, n_children = 0;
4838
  struct grub_zfs_device_desc *desc;
4839
  char *nvtop;
4840
  unsigned i;
4841
  grub_err_t err = GRUB_ERR_NONE;
4842
4843
  if (!grub_zfs_nvlist_lookup_uint64 (config, ZPOOL_CONFIG_POOL_TXG, &txg))
4844
    {
4845
      grub_dprintf ("zfs", "can't read vdev txg\n");
4846
      return GRUB_ERR_BAD_FS;
4847
    }
4848
  if (!grub_zfs_nvlist_lookup_uint64 (config, ZPOOL_CONFIG_TOP_GUID, &guid))
4849
    {
4850
      grub_dprintf ("zfs", "vdev_attach: can't read top guid\n");
4851
      return GRUB_ERR_BAD_FS;
4852
    }
4853
4854
  nvtop = grub_zfs_nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4855
  if (!nvtop)
4856
    {
4857
      grub_dprintf("zfs", "read vdev tree failed\n");
4858
      return GRUB_ERR_BAD_FS;
4859
    }
4860
4861
  if (!grub_zfs_nvlist_lookup_uint64 (nvtop, ZPOOL_CONFIG_ID, &id))
4862
    {
4863
      grub_dprintf ("zfs", "can't read vdev id\n");
4864
      grub_free (nvtop);
4865
      return GRUB_ERR_BAD_FS;
4866
    }
4867
  grub_dprintf ("zfs", "vdev id: %" PRIxGRUB_UINT64_T " guid: %"
4868
		PRIxGRUB_UINT64_T "\n", id, guid);
4869
4870
  if (id > data->n_devices_allocated)
4871
    {
4872
	data->devices_attached = grub_realloc(data->devices_attached,
4873
					      sizeof (data->devices_attached[0])
4874
					      * (id + 1));
4875
	for (i = data->n_devices_allocated; i < (id + 1); i++)
4876
	  grub_memset(&data->devices_attached[i], 0,
4877
		      sizeof (data->devices_attached[0]));
4878
	data->n_devices_allocated = id + 1;
4879
    }
4880
4881
  desc = &data->devices_attached[id];
4882
4883
  /* is it new vdev? */
4884
  if (desc->guid == 0)
4885
    {
4886
      grub_dprintf ("zfs", "adding vdev: %d guid: %"
4887
		    PRIxGRUB_UINT64_T "\n", (int)id, guid);
4888
      desc->id = id;
4889
      desc->guid = guid;
4890
      desc->txg = txg;
4891
      err = vdev_add(desc, dev, nvtop, dev_name, original);
4892
      if (err)
4893
	{
4894
	  grub_dprintf ("zfs", "vdev_add failed\n");
4895
          grub_free (nvtop);
4896
	  return err;
4897
	}
4898
4899
      data->n_devices_attached++;
4900
    }
4901
  else
4902
    {
4903
      /* this vdev is set up, so the top guid must match with vdev guid */
4904
      if (desc->guid != guid)
4905
	{
4906
	  grub_dprintf ("zfs", "vdev_attach: the top vdev guid mismatch\n");
4907
          grub_free (nvtop);
4908
	  return GRUB_ERR_BAD_FS;
4909
	}
4910
    }
4911
4912
  /* add us in child list if needed */
4913
  if (!grub_zfs_nvlist_lookup_uint64 (config, ZPOOL_CONFIG_GUID, &guid))
4914
    {
4915
      grub_dprintf ("zfs", "vdev_attach: can't read guid\n");
4916
      grub_free (nvtop);
4917
      return GRUB_ERR_BAD_FS;
4918
    }
4919
4920
  if (desc->type > DEVICE_LEAF)
4921
    {
4922
      n_children = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
4923
				(nvtop, ZPOOL_CONFIG_CHILDREN);
4924
      if (n_children > desc->n_children)
4925
	{
4926
	  desc->children = grub_realloc(desc->children,
4927
					sizeof (desc->children[0])
4928
					* n_children);
4929
	  for (i = desc->n_children; i < n_children; i++)
4930
	    grub_memset(&desc->children[i], 0, sizeof (desc->children[0]));
4931
	  desc->n_children = n_children;
4932
	}
4933
    }
4934
4935
  for (i = 0; i < desc->n_children; i++)
4936
    {
4937
      grub_uint64_t cguid;
4938
      struct grub_zfs_device_desc *cdesc;
4939
      char *child;
4940
4941
      child = grub_zfs_nvlist_lookup_nvlist_array(nvtop,
4942
						  ZPOOL_CONFIG_CHILDREN, i);
4943
4944
      if (!grub_zfs_nvlist_lookup_uint64 (child, ZPOOL_CONFIG_ID, &id))
4945
	{
4946
	  grub_dprintf ("zfs", "vdev_attach: can't read id\n");
4947
	  grub_free (child);
4948
          grub_free (nvtop);
4949
	  return GRUB_ERR_BAD_FS;
4950
	}
4951
4952
      if (!grub_zfs_nvlist_lookup_uint64 (child, ZPOOL_CONFIG_GUID, &cguid))
4953
	{
4954
	  grub_dprintf ("zfs", "vdev_attach: can't read guid\n");
4955
	  grub_free (child);
4956
          grub_free (nvtop);
4957
	  return GRUB_ERR_BAD_FS;
4958
	}
4959
4960
      cdesc = &desc->children[id];
4961
      if (cguid == guid && i == id && cdesc->guid == 0)
4962
	{
4963
	  grub_dprintf ("zfs", "adding child: %d guid: %"
4964
			PRIxGRUB_UINT64_T "\n", i, guid);
4965
4966
	  cdesc->id = id;
4967
	  cdesc->guid = guid;
4968
	  if (cdesc->txg < txg)
4969
	    {
4970
	      cdesc->txg = txg;
4971
	      if (cdesc->config != NULL)
4972
		grub_free (cdesc->config);
4973
	      cdesc->config = child;
4974
	    }
4975
4976
	  err = vdev_add(cdesc, dev, child, dev_name, original);
4977
	  if (err)
4978
	    {
4979
	      grub_dprintf ("zfs", "vdev_add failed\n");
4980
	      if (cdesc->config == child)
4981
		cdesc->config = NULL;
4982
	      grub_free (child);
4983
              grub_free (nvtop);
4984
	      return err;
4985
	    }
4986
	  cdesc->top_vdev = desc;
4987
	  if (desc->ashift < cdesc->ashift)
4988
	    desc->ashift = cdesc->ashift;
4989
	}
4990
      /* update child dev_state if needed */
4991
      if (cdesc->txg < txg)
4992
	{
4993
	  cdesc->txg = txg;
4994
	  if (cdesc->config != NULL)
4995
	    grub_free (cdesc->config);
4996
	  cdesc->config = child;
4997
	}
4998
      if (cdesc->dev == NULL)
4999
	cdesc->dev_state = DEVICE_ERROR;
5000
      else if (grub_zfs_vdev_validate(cdesc->config))
5001
	cdesc->dev_state = DEVICE_ERROR;
5002
      if (cdesc->config != child)
5003
	grub_free (child);
5004
    }
5005
5006
  grub_free (nvtop);
5007
  return err;
5008
}
5009
5010
/*
5011
 * read 'best' uberblock from disk. so we read UB array from each label
5012
 * from each vdev and looking for highest txg.
5013
 */
5014
static void
5015
vdev_uberblock_load(struct grub_zfs_data *data,
5016
		    struct grub_zfs_device_desc *desc)
5017
{
5018
  int vdevnum, l, ashift;
5019
  grub_uint64_t s, size;
5020
  grub_uint8_t *ub_array;
5021
  grub_err_t err;
5022
5023
  if (desc->dev == NULL)
5024
    return;
5025
5026
  if (desc->top_vdev)
5027
    ashift = desc->top_vdev->ashift;
5028
  else
5029
    ashift = desc->ashift;
5030
5031
  grub_dprintf("zfs", "vdev_uberblock_load: %s ashift: %d\n",
5032
	       desc->dev_name, ashift);
5033
  vdevnum = VDEV_LABELS;
5034
5035
  ub_array = grub_zalloc (VDEV_UBERBLOCK_SIZE(ashift));
5036
  if (!ub_array)
5037
    {
5038
      grub_dprintf("zfs", "ub_array allocation failed.\n");
5039
      return;
5040
    }
5041
5042
  size = s = grub_disk_get_size (desc->dev->disk);
5043
  /* Don't check back labels on CDROM. */
5044
  if (s == GRUB_DISK_SIZE_UNKNOWN)
5045
    vdevnum = VDEV_LABELS / 2;
5046
  else
5047
   {
5048
     /* grub_disk_get_size() returns sector count */
5049
     s = s << desc->dev->disk->log_sector_size;
5050
     size = P2ALIGN_TYPED(s, sizeof (vdev_label_t), grub_uint64_t);
5051
   }
5052
5053
  for (l = 0; l < vdevnum; l++)
5054
    {
5055
      grub_off_t offset;
5056
      int n;
5057
5058
      for (n = 0; n < VDEV_UBERBLOCK_COUNT(ashift); n++)
5059
	{
5060
	  offset = vdev_label_offset(size, l, VDEV_UBERBLOCK_OFFSET(ashift, n));
5061
	  err = grub_disk_read (desc->dev->disk, 0, offset,
5062
				VDEV_UBERBLOCK_SIZE(ashift), (char *)ub_array);
5063
	  if (err)
5064
	    {
5065
	      grub_dprintf ("zfs", "grub_disk_read() failed\n");
5066
	      grub_errno = GRUB_ERR_NONE;
5067
	      continue;
5068
	    }
5069
	  err = uberblock_verify ((uberblock_t *)ub_array, offset, ashift);
5070
	  if (err)
5071
	    {
5072
	      grub_errno = GRUB_ERR_NONE;
5073
	      continue;
5074
	    }
5075
	  if (data->current_uberblock.ub_magic == 0 ||
5076
	      vdev_uberblock_compare(&data->current_uberblock,
5077
				     (uberblock_t *)ub_array) > 0)
5078
	    {
5079
	      grub_memmove(&(data->current_uberblock), ub_array,
5080
			   sizeof (uberblock_t));
5081
	    }
5082
	}
5083
    }
5084
  grub_free (ub_array);
5085
}
5086
5087
/*
5088
 * zfs_mount() locates a valid uberblock of the root pool and
5089
 * read in its MOS to the device grub_zfs_data structure.
5090
 *
5091
 * zfs_mount() is called frequently by GRUB2 zfs interfaces, so
5092
 * a cache mechanism is implemented to save the successful zfs
5093
 * mount data for devices. This is good for zfs mount performance.
5094
 *
5095
 */
5096
static struct grub_zfs_data *
5097
zfs_mount (grub_device_t dev)
5098
{
5099
  struct grub_zfs_data *data = NULL;
5100
  struct zfs_mount_cache *zcache = NULL;
5101
  objset_phys_t *osp = 0;
5102
  grub_size_t ospsize;
5103
  grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN;
5104
  uberblock_t *ub;
5105
  unsigned int i, j;
5106
  char *diskname, *partname, *fullname, *pname;
5107
  char *features, *config = NULL;
5108
  grub_uint64_t u;
5109
  grub_err_t err;
5110
5111
  grub_errno = GRUB_ERR_NONE;
5112
  if (! dev->disk)
5113
    {
5114
      grub_error (GRUB_ERR_BAD_DEVICE, "not a disk");
5115
      grub_errno = GRUB_ERR_BAD_DEVICE;
5116
      return NULL;
5117
    }
5118
5119
  diskname = (char *)dev->disk->name;
5120
  partname = grub_partition_get_name(dev->disk->partition);
5121
  if (partname[0] != 0)
5122
    {
5123
      fullname = grub_xasprintf("%s,%s", diskname, partname);
5124
    }
5125
  else
5126
    fullname = grub_strdup (diskname);
5127
  grub_free (partname);
5128
5129
  if ((err = vdev_disk_read_rootlabel(dev, &config)) != GRUB_ERR_NONE)
5130
    {
5131
      grub_error (err, "Cannot read the pool label from '%s'", fullname);
5132
      grub_free (fullname);
5133
      if (grub_errno == GRUB_ERR_NONE)
5134
	grub_errno = err;
5135
      return NULL;
5136
    }
5137
5138
  pname = grub_zfs_nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
5139
  if (!pname)
5140
    {
5141
      grub_error (err, "Incorrect pool label from '%s'", fullname);
5142
      grub_free (fullname);
5143
      grub_free (config);
5144
      if (grub_errno == GRUB_ERR_NONE)
5145
	grub_errno = GRUB_ERR_BAD_FS;
5146
      return NULL;
5147
    }
5148
5149
  if (!grub_zfs_nvlist_lookup_uint64 (config, ZPOOL_CONFIG_VERSION, &u))
5150
    {
5151
      grub_free (fullname);
5152
      grub_free (config);
5153
      grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_VERSION " not found");
5154
      if (grub_errno == GRUB_ERR_NONE)
5155
	grub_errno = GRUB_ERR_BAD_FS;
5156
5157
      return NULL;
5158
    }
5159
5160
  if (!SPA_VERSION_IS_SUPPORTED(u))
5161
    {
5162
      grub_free (fullname);
5163
      grub_free (config);
5164
5165
      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
5166
	"ZFS SPA version %" PRIuGRUB_UINT64_T "is not compatible with this "
5167
	"GRUB2 ZFS reader code.\nSupported Oracle ZFS is %" PRIuGRUB_UINT64_T
5168
	"\nSupported OpenZFS version is %" PRIuGRUB_UINT64_T "\n",
5169
	(unsigned long long) u,
5170
	(unsigned long long) SPA_VERSION_ORACLE,
5171
	(unsigned long long) SPA_VERSION);
5172
      if (grub_errno == GRUB_ERR_NONE)
5173
	grub_errno = GRUB_ERR_NOT_IMPLEMENTED_YET;
5174
5175
      return NULL;
5176
    }
5177
5178
  features = grub_zfs_nvlist_lookup_nvlist (config,
5179
					    ZPOOL_CONFIG_FEATURES_FOR_READ);
5180
  if (features)
5181
    {
5182
      const char *nvp;
5183
      char *name;
5184
5185
      for (nvp = nvlist_next_nvpair(features, NULL); nvp != NULL;
5186
           nvp = nvlist_next_nvpair(features, nvp)) {
5187
        name = nvpair_name(nvp);
5188
        if (name) {
5189
          err = check_feature(name, 1, NULL);
5190
          if (err) {
5191
            grub_free (name);
5192
            grub_free (features);
5193
	    grub_free (fullname);
5194
	    grub_free (config);
5195
	    grub_errno = err;
5196
            return NULL;
5197
          }
5198
          grub_free (name);
5199
	}
5200
      }
5201
      grub_free (features);
5202
    }
5203
  grub_dprintf ("zfs", "zfs_mount: attempting to mount \"%s\" from %s\n",
5204
	       pname, fullname);
5205
5206
  /* check the zfs mount cache list first */
5207
  for (zcache = zfs_mount_cache_list; zcache != NULL; zcache = zcache->next)
5208
    {
5209
      grub_dprintf ("zfs", "zfs_mount: zcached %s\n", zcache->zcache_pool_name);
5210
      if (grub_strcmp (pname, zcache->zcache_pool_name) != 0)
5211
	continue;
5212
5213
      data = zcache->zcache_zfs_data;
5214
      data->file_buf = 0;
5215
      data->file_start = 0;
5216
      data->file_end = 0;
5217
      data->dnode_buf = 0;
5218
      data->dnode_mdn = 0;
5219
      data->dnode_start = 0;
5220
      data->dnode_end = 0;
5221
      data->dnode_endian = 0;
5222
      data->label = pname;
5223
      grub_memset(&data->dnode, 0, sizeof (data->dnode));
5224
      grub_memset(&data->subvol, 0, sizeof (data->subvol));
5225
5226
      grub_free (config);
5227
5228
      for (i = 0; i < data->n_devices_attached; i++)
5229
	{
5230
	  mount_device (&data->devices_attached[i], dev, fullname);
5231
	}
5232
      grub_free (fullname);
5233
      /* need to check if dev is actually usable */
5234
      return data;
5235
    }
5236
5237
  /* allocate the zfs mount data structure */
5238
  data = grub_zalloc (sizeof (*data));
5239
  if (! data)
5240
    {
5241
      grub_error (GRUB_ERR_OUT_OF_MEMORY, "zfs data allocation failed");
5242
      grub_free (pname);
5243
      grub_free (config);
5244
      grub_free (fullname);
5245
      grub_errno = GRUB_ERR_OUT_OF_MEMORY;
5246
      return 0;
5247
    }
5248
5249
  /* need to do a new mount */
5250
  data->label = pname;
5251
5252
  if (!grub_zfs_nvlist_lookup_uint64 (config, ZPOOL_CONFIG_POOL_GUID, &u))
5253
    {
5254
      grub_dprintf ("zfs", "can't read pool guid\n");
5255
      grub_free (config);
5256
      zfs_unmount (data);
5257
      grub_free (fullname);
5258
      if (grub_errno == GRUB_ERR_NONE)
5259
	grub_errno = GRUB_ERR_BAD_FS;
5260
      return NULL;
5261
    }
5262
  data->guid = u;
5263
  grub_dprintf ("zfs", "pool guid: %" PRIxGRUB_UINT64_T "\n", u);
5264
5265
  if (!grub_zfs_nvlist_lookup_uint64 (config, ZPOOL_CONFIG_POOL_STATE, &u))
5266
    {
5267
      grub_dprintf ("zfs", "can't read pool state\n");
5268
      grub_free (config);
5269
      zfs_unmount (data);
5270
      grub_free (fullname);
5271
      if (grub_errno == GRUB_ERR_NONE)
5272
	grub_errno = GRUB_ERR_BAD_FS;
5273
      return NULL;
5274
    }
5275
  data->state = u;
5276
5277
  if (!grub_zfs_nvlist_lookup_uint64 (config, ZPOOL_CONFIG_VDEV_CHILDREN, &u))
5278
    {
5279
      grub_dprintf ("zfs", "can't read vdev children count\n");
5280
      grub_free (config);
5281
      grub_free (fullname);
5282
      zfs_unmount (data);
5283
      if (grub_errno == GRUB_ERR_NONE)
5284
	grub_errno = GRUB_ERR_BAD_FS;
5285
      return NULL;
5286
    }
5287
5288
  /* set up memory for top level vdevs */
5289
  data->n_devices_allocated = u;
5290
  data->devices_attached = grub_zalloc (sizeof (data->devices_attached[0])
5291
					* data->n_devices_allocated);
5292
  if (! data->devices_attached)
5293
    {
5294
      grub_dprintf ("zfs", "can't allocate top level vdevs\n");
5295
      grub_free (config);
5296
      grub_free (fullname);
5297
      zfs_unmount (data);
5298
      if (grub_errno == GRUB_ERR_NONE)
5299
	grub_errno = GRUB_ERR_BAD_FS;
5300
      return NULL;
5301
    }
5302
5303
  data->n_devices_attached = 0;
5304
5305
  /*
5306
   * check if the pool has multiple vdevs/children, add the disks.
5307
   * as the zfs_mount() caller provides us open "dev" and will close it,
5308
   * we dont wanna store this descriptor, but instead we open new instance.
5309
   */
5310
  err = scan_devices(data, fullname, dev);
5311
  if (err)
5312
    {
5313
      /* we are missing disks, check if we have enough parity to continue */
5314
      if (data->n_devices_attached == data->n_devices_allocated)
5315
	{
5316
	  unsigned missing = 0;
5317
	  struct grub_zfs_device_desc *desc;
5318
	  /*
5319
           * only need to check raidz, as missing leaf can't get here
5320
	   * and mirror means we have at least 1 disk in mirror
5321
	   */
5322
	  err = GRUB_ERR_NONE;
5323
	  for (i = 0; i < data->n_devices_attached; i++)
5324
	    {
5325
	      desc = &data->devices_attached[i];
5326
	      if (desc->type == DEVICE_RAIDZ)
5327
		{
5328
		  for (j = 0; j < desc->n_children; j++)
5329
		    if (desc->children[j].dev == NULL)
5330
		      missing++;
5331
		  if (missing > desc->nparity)
5332
		    err = grub_error (GRUB_ERR_BAD_FS,
5333
				      N_("pool %s is missing too many devices"),
5334
				      data->label);
5335
		}
5336
	    }
5337
	}
5338
    }
3517
5339
3518
static void
5340
  /* if dev_state is DEVICE_ERROR, we need to use another device for mount */
3519
zfs_unmount (struct grub_zfs_data *data)
3520
{
3521
  unsigned i;
3522
  for (i = 0; i < data->n_devices_attached; i++)
5341
  for (i = 0; i < data->n_devices_attached; i++)
3523
    unmount_device (&data->devices_attached[i]);
5342
    {
3524
  grub_free (data->devices_attached);
5343
      struct grub_zfs_device_desc *desc;
3525
  grub_free (data->dnode_buf);
5344
      desc = &data->devices_attached[i];
3526
  grub_free (data->dnode_mdn);
5345
      if (err)
3527
  grub_free (data->file_buf);
5346
	break;
3528
  for (i = 0; i < data->subvol.nkeys; i++)
3529
    grub_crypto_cipher_close (data->subvol.keyring[i].cipher);
3530
  grub_free (data->subvol.keyring);
3531
  grub_free (data);
3532
}
3533
5347
3534
/*
5348
      if (desc->type == DEVICE_LEAF)
3535
 * zfs_mount() locates a valid uberblock of the root pool and read in its MOS
5349
	{
3536
 * to the memory address MOS.
5350
	  if (desc->original && desc->dev_state == DEVICE_ERROR)
3537
 *
5351
	    {
3538
 */
5352
	      err = GRUB_ERR_BAD_DEVICE;
3539
static struct grub_zfs_data *
5353
	      break;
3540
zfs_mount (grub_device_t dev)
5354
	    }
3541
{
5355
	}
3542
  struct grub_zfs_data *data = 0;
5356
      for (j = 0; j < desc->n_children; j++)
3543
  grub_err_t err;
5357
	{
3544
  void *osp = 0;
5358
	  if (desc->children[j].original &&
3545
  grub_size_t ospsize;
5359
	      desc->children[j].dev_state == DEVICE_ERROR)
3546
  grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN;
5360
	    {
3547
  uberblock_t *ub;
5361
	      err = GRUB_ERR_BAD_DEVICE;
3548
  int inserted;
5362
	      break;
5363
	    }
5364
	}
5365
    }
3549
5366
3550
  if (! dev->disk)
5367
  if (err)
3551
    {
5368
    {
3552
      grub_error (GRUB_ERR_BAD_DEVICE, "not a disk");
5369
      grub_errno = err;
3553
      return 0;
5370
      grub_dprintf("zfs", "zfs_mount failed: missing devices\n");
5371
      grub_free (config);
5372
      zfs_unmount (data);
5373
      return NULL;
3554
    }
5374
    }
3555
5375
3556
  data = grub_zalloc (sizeof (*data));
5376
  /*
3557
  if (!data)
5377
   * load the UB now. the obvious issue here is that we should load
3558
    return 0;
5378
   * an config based on this UB, so instead we just hope the pool
3559
#if 0
5379
   * current config is ok. from bootloader point of view, it just may
3560
  /* if it's our first time here, zero the best uberblock out */
5380
   * be "good enough", as we will output the disk with best ub with
3561
  if (data->best_drive == 0 && data->best_part == 0 && find_best_root)
5381
   * "search" command to be set for root, and so subsequent pool access
3562
    grub_memset (&current_uberblock, 0, sizeof (uberblock_t));
5382
   * will load the best config. same for "zfs-bootfs", to inform kernel
3563
#endif
5383
   * to start from best disk - even if the kernel is able to deal better
5384
   * with pool config, there are cases where kernel will drop out and
5385
   * asks to use another disk to boot from...
5386
   */
5387
  grub_dprintf("zfs", "pool: %s\n", data->label);
5388
  for (i = 0; i < data->n_devices_attached; i++)
5389
    if (data->devices_attached[i].type == DEVICE_LEAF)
5390
      {
5391
        grub_dprintf("zfs", "  %s\n",
5392
		     data->devices_attached[i].dev_name);
5393
	vdev_uberblock_load(data, &data->devices_attached[i]);
5394
      }
5395
    else
5396
      {
5397
	 grub_dprintf("zfs", "  %s-%u\n",
5398
		      data->devices_attached[i].type == DEVICE_MIRROR?
5399
		      "mirror" : "raidz", i);
5400
	 for (j = 0; j < data->devices_attached[i].n_children; j++)
5401
	   {
5402
	     struct grub_zfs_device_desc *desc;
5403
	     desc = &data->devices_attached[i].children[j];
5404
	     grub_dprintf("zfs", "    %s\n", desc->dev_name == NULL?
5405
	     		  "[missing]" : desc->dev_name);
5406
	     vdev_uberblock_load(data, desc);
5407
	   }
5408
      }
3564
5409
3565
  data->n_devices_allocated = 16;
5410
  grub_free (config);
3566
  data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
5411
3567
					* data->n_devices_allocated);
5412
  ub = &(data->current_uberblock);
3568
  data->n_devices_attached = 0;
5413
3569
  err = scan_disk (dev, data, 1, &inserted);
5414
  /* did we got UB from any of the disks? */
3570
  if (err)
5415
  if (ub->ub_magic == 0)
3571
    {
5416
    {
5417
      grub_dprintf("zfs", "we have no uberblock, can not continue\n");
3572
      zfs_unmount (data);
5418
      zfs_unmount (data);
5419
      if (grub_errno == GRUB_ERR_NONE)
5420
	grub_errno = GRUB_ERR_BAD_FS;
3573
      return NULL;
5421
      return NULL;
3574
    }
5422
    }
3575
5423
3576
  ub = &(data->current_uberblock);
3577
  ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, 
5424
  ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, 
3578
				  GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC 
5425
				  GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC 
3579
	       ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN);
5426
	       ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN);
3580
5427
3581
  err = zio_read (&ub->ub_rootbp, ub_endian,
5428
  err = zio_read (&ub->ub_rootbp, ub_endian,
3582
		  &osp, &ospsize, data);
5429
		  (void **) &osp, &ospsize, data);
3583
  if (err)
5430
  if (err)
3584
    {
5431
    {
5432
      grub_dprintf("zfs", "zio_read failed: %s\n", grub_errmsg );
3585
      zfs_unmount (data);
5433
      zfs_unmount (data);
5434
      if (grub_errno == GRUB_ERR_NONE)
5435
	grub_errno = err;
3586
      return NULL;
5436
      return NULL;
3587
    }
5437
    }
3588
5438
Lines 3591-3605 Link Here
3591
      grub_error (GRUB_ERR_BAD_FS, "OSP too small");
5441
      grub_error (GRUB_ERR_BAD_FS, "OSP too small");
3592
      grub_free (osp);
5442
      grub_free (osp);
3593
      zfs_unmount (data);
5443
      zfs_unmount (data);
5444
      if (grub_errno == GRUB_ERR_NONE)
5445
	grub_errno = GRUB_ERR_BAD_FS;
3594
      return NULL;
5446
      return NULL;
3595
    }
5447
    }
3596
5448
3597
  if (ub->ub_version >= SPA_VERSION_FEATURES &&
5449
  /* Got the MOS. Save it to data->mos. */
3598
      check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian,
3599
			 data) != 0)
3600
    return NULL;
3601
	
3602
  /* Got the MOS. Save it at the memory addr MOS. */
3603
  grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode,
5450
  grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode,
3604
		DNODE_SIZE);
5451
		DNODE_SIZE);
3605
  data->mos.endian = (grub_zfs_to_cpu64 (ub->ub_rootbp.blk_prop,
5452
  data->mos.endian = (grub_zfs_to_cpu64 (ub->ub_rootbp.blk_prop,
Lines 3608-3613 Link Here
3608
5455
3609
  data->mounted = 1;
5456
  data->mounted = 1;
3610
5457
5458
  if(ub->ub_version >= SPA_VERSION_FEATURES &&
5459
     check_mos_features(&data->mos, data) != 0)
5460
    {
5461
      zfs_unmount (data);
5462
      if (grub_errno == GRUB_ERR_NONE)
5463
	grub_errno = GRUB_ERR_BAD_FS;
5464
      return NULL;
5465
    }
5466
5467
  data->mounted = 1;	/* mount succeeded */
5468
#if 0
5469
  /*
5470
   * zfs_mount cache is currently disabled, as it was causing
5471
   * artefacts with gfx menu - so there must be some bugs in it.
5472
   */
5473
  if (zcache == NULL)   /* allocate the zfs mount cache structure */
5474
    zcache = grub_zalloc (sizeof (*zcache));
5475
  else
5476
    zcache = NULL;      /* intend for a non-cached mount */
5477
#endif
5478
5479
  if (zcache != NULL)   /* cache this OK zfs mount */
5480
    {
5481
      zcache->zcache_zfs_data = data;
5482
      zcache->zcache_pool_guid = data->guid;
5483
      zcache->zcache_pool_name = grub_strdup(data->label);
5484
      zcache->next = zfs_mount_cache_list;
5485
      if (zcache->zcache_pool_name)
5486
	{
5487
	  zfs_mount_cache_list = zcache;
5488
	  data->zcached = 1;
5489
	}
5490
      else
5491
	grub_free(zcache);
5492
    }
5493
3611
  return data;
5494
  return data;
3612
}
5495
}
3613
5496
Lines 3615-3654 Link Here
3615
grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist)
5498
grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist)
3616
{
5499
{
3617
  struct grub_zfs_data *zfs;
5500
  struct grub_zfs_data *zfs;
3618
  grub_err_t err;
5501
  grub_err_t err = GRUB_ERR_NONE;
5502
  unsigned i, j;
5503
  char *diskname, *partname, *fullname;
3619
5504
3620
  zfs = zfs_mount (dev);
5505
  zfs = zfs_mount (dev);
3621
  if (!zfs)
5506
  if (!zfs)
3622
    return grub_errno;
5507
    return grub_errno;
3623
  err = zfs_fetch_nvlist (zfs->device_original, nvlist);
5508
5509
  diskname = (char *)dev->disk->name;
5510
  partname = grub_partition_get_name(dev->disk->partition);
5511
  if (partname[0] != 0)
5512
    {
5513
      fullname = grub_xasprintf("%s,%s", diskname, partname);
5514
    }
5515
  else
5516
    fullname = grub_strdup (diskname);
5517
  grub_free (partname);
5518
5519
  for (i = 0; i < zfs->n_devices_attached; i++)
5520
    {
5521
      struct grub_zfs_device_desc *desc;
5522
      desc = &zfs->devices_attached[i];
5523
      if (desc->type == DEVICE_LEAF)
5524
	{
5525
	  if (grub_strcmp(fullname, desc->dev_name) == 0)
5526
	    err = vdev_disk_read_rootlabel (desc->dev, nvlist);
5527
	}
5528
      else
5529
	{
5530
	  for (j = 0; j < desc->n_children; j++)
5531
	    if (grub_strcmp(fullname, desc->children[j].dev_name) == 0)
5532
	      err = vdev_disk_read_rootlabel (desc->children[j].dev, nvlist);
5533
	}
5534
    }
5535
5536
  if (err)
5537
    grub_dprintf("zfs", "zfs_fetch_nvlist failed: device:%s\n", fullname);
5538
  grub_free (fullname);
3624
  zfs_unmount (zfs);
5539
  zfs_unmount (zfs);
3625
  return err;
5540
  return err;
3626
}
5541
}
3627
5542
5543
/*
5544
 * Returns the pool name.
5545
 */
3628
static grub_err_t 
5546
static grub_err_t 
3629
zfs_label (grub_device_t device, char **label)
5547
zfs_label (grub_device_t device, char **label)
3630
{
5548
{
3631
  char *nvlist;
3632
  grub_err_t err;
3633
  struct grub_zfs_data *data;
5549
  struct grub_zfs_data *data;
3634
5550
5551
  *label = NULL;
5552
3635
  data = zfs_mount (device);
5553
  data = zfs_mount (device);
3636
  if (! data)
5554
  if (! data)
3637
    return grub_errno;
5555
    return grub_errno;
3638
5556
3639
  err = zfs_fetch_nvlist (data->device_original, &nvlist);
5557
  *label = grub_strdup(data->label);
3640
  if (err)      
5558
  if (*label == NULL)
3641
    {
5559
    grub_errno = GRUB_ERR_OUT_OF_MEMORY;
3642
      zfs_unmount (data);
3643
      return err;
3644
    }
3645
3646
  *label = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
3647
  grub_free (nvlist);
3648
  zfs_unmount (data);
5560
  zfs_unmount (data);
3649
  return grub_errno;
5561
  return grub_errno;
3650
}
5562
}
3651
5563
5564
/*
5565
 * Returns the pool GUID.
5566
 */
3652
static grub_err_t 
5567
static grub_err_t 
3653
zfs_uuid (grub_device_t device, char **uuid)
5568
zfs_uuid (grub_device_t device, char **uuid)
3654
{
5569
{
Lines 3663-3669 Link Here
3663
  *uuid = grub_xasprintf ("%016llx", (long long unsigned) data->guid);
5578
  *uuid = grub_xasprintf ("%016llx", (long long unsigned) data->guid);
3664
  zfs_unmount (data);
5579
  zfs_unmount (data);
3665
  if (! *uuid)
5580
  if (! *uuid)
3666
    return grub_errno;
5581
    {
5582
      if (grub_errno == GRUB_ERR_NONE)
5583
	grub_errno = GRUB_ERR_OUT_OF_MEMORY;
5584
      return grub_errno;
5585
    }
3667
  return GRUB_ERR_NONE;
5586
  return GRUB_ERR_NONE;
3668
}
5587
}
3669
5588
Lines 3692-3698 Link Here
3692
5611
3693
/*
5612
/*
3694
 * zfs_open() locates a file in the rootpool by following the
5613
 * zfs_open() locates a file in the rootpool by following the
3695
 * MOS and places the dnode of the file in the memory address DNODE.
5614
 * MOS and places the dnode of the file in the device
5615
 * grub_zfs_data structure.
3696
 */
5616
 */
3697
static grub_err_t
5617
static grub_err_t
3698
grub_zfs_open (struct grub_file *file, const char *fsfilename)
5618
grub_zfs_open (struct grub_file *file, const char *fsfilename)
Lines 3815-3823 Link Here
3815
      grub_uint64_t blkid = grub_divmod64 (file->offset + read, blksz, 0);
5735
      grub_uint64_t blkid = grub_divmod64 (file->offset + read, blksz, 0);
3816
      grub_free (data->file_buf);
5736
      grub_free (data->file_buf);
3817
      data->file_buf = 0;
5737
      data->file_buf = 0;
5738
      data->file_start = data->file_end = 0;
3818
5739
3819
      err = dmu_read (&(data->dnode), blkid, &t,
5740
      err = dmu_read (&(data->dnode), blkid, &t, 0, data);
3820
		      0, data);
3821
      data->file_buf = t;
5741
      data->file_buf = t;
3822
      if (err)
5742
      if (err)
3823
	{
5743
	{
Lines 3874-3879 Link Here
3874
  return err;
5794
  return err;
3875
}
5795
}
3876
5796
5797
grub_err_t
5798
grub_zfs_defaultbootfsobj (grub_device_t dev, grub_uint64_t *mdnobj)
5799
{
5800
  struct grub_zfs_data *data;
5801
  grub_err_t err;
5802
5803
  data = zfs_mount (dev);
5804
  if (! data)
5805
    return grub_errno;
5806
5807
  err = get_default_bootfsobj (&(data->mos), mdnobj, data);
5808
  zfs_unmount (data);
5809
5810
  return err;
5811
}
5812
5813
grub_err_t
5814
grub_zfs_defaultbootfsname (grub_device_t dev, char **bootfsname)
5815
{
5816
  grub_uint64_t mdnobj;
5817
  struct grub_zfs_data *data;
5818
  grub_err_t err;
5819
5820
  data = zfs_mount (dev);
5821
  if (! data)
5822
    return grub_errno;
5823
5824
  err = get_default_bootfsobj (&(data->mos), &mdnobj, data);
5825
  if (! err)
5826
    err = get_default_bootfsname(&(data->mos), mdnobj, data, &(*bootfsname));
5827
5828
  zfs_unmount (data);
5829
5830
  return err;
5831
}
5832
3877
static grub_err_t
5833
static grub_err_t
3878
fill_fs_info (struct grub_dirhook_info *info,
5834
fill_fs_info (struct grub_dirhook_info *info,
3879
	      dnode_end_t mdn, struct grub_zfs_data *data)
5835
	      dnode_end_t mdn, struct grub_zfs_data *data)
Lines 3984-4230 Link Here
3984
	{
5940
	{
3985
	  blkptr_t *bp = &dn.dn.dn_spill;
5941
	  blkptr_t *bp = &dn.dn.dn_spill;
3986
5942
3987
	  err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data);
5943
	  err = zio_read(bp, dn.endian, &sahdrp, NULL, ctx->data);
3988
	  if (err)
5944
	  if (err)
3989
	    {
5945
	    {
3990
	      grub_print_error ();
5946
	      grub_print_error();
3991
	      return 0;
5947
	      return 0;
3992
	    }
5948
	    }
3993
	}
5949
	}
3994
      else
5950
      else
3995
	{
5951
        {
3996
	  grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
5952
	  grub_error(GRUB_ERR_BAD_FS, "filesystem is corrupt");
3997
	  grub_print_error ();
5953
	  grub_print_error();
3998
	  return 0;
5954
	  return 0;
3999
	}
5955
	}
4000
5956
4001
      hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
5957
      hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
4002
      info.mtimeset = 1;
5958
      info.mtimeset = 1;
4003
      info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
5959
      info.mtime = grub_zfs_to_cpu64(grub_get_unaligned64((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
4004
      info.case_insensitive = ctx->data->subvol.case_insensitive;
5960
      info.case_insensitive = ctx->data->subvol.case_insensitive;
4005
    }
5961
    }
4006
  
5962
4007
  if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
5963
  if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
4008
    {	
5964
    {	
4009
      info.mtimeset = 1;
5965
      info.mtimeset = 1;
4010
      info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
5966
      info.mtime = grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
4011
				      dn.endian);
5967
				     dn.endian);
4012
    }
5968
    }
4013
  info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
5969
  info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
4014
  grub_dprintf ("zfs", "type=%d, name=%s\n", 
5970
  grub_dprintf ("zfs", "type=%d, name=%s\n", 
4015
		(int)dn.dn.dn_type, (char *)name);
5971
		(int)dn.dn.dn_type, (char *)name);
4016
  return ctx->hook (name, &info, ctx->hook_data);
5972
  return ctx->hook(name, &info, ctx->hook_data);
4017
}
5973
}
4018
5974
4019
/* Helper for grub_zfs_dir.  */
5975
/* Helper for grub_zfs_dir.  */
4020
static int
5976
static int
4021
iterate_zap_fs (const char *name, grub_uint64_t val,
5977
iterate_zap_fs(const char *name, grub_uint64_t val,
4022
		struct grub_zfs_dir_ctx *ctx)
5978
    struct grub_zfs_dir_ctx *ctx)
4023
{
5979
{
4024
  grub_err_t err;
5980
	grub_err_t err;
4025
  struct grub_dirhook_info info;
5981
	struct grub_dirhook_info info;
4026
5982
	dnode_end_t mdn;
4027
  dnode_end_t mdn;
5983
	err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
4028
  err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
5984
	if (err) {
4029
  if (err)
5985
		grub_errno = 0;
4030
    {
5986
		return 0;
4031
      grub_errno = 0;
5987
	}
4032
      return 0;
5988
	if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
4033
    }
5989
		return 0;
4034
  if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
5990
4035
    return 0;
5991
	err = fill_fs_info (&info, mdn, ctx->data);
5992
	if (err) {
5993
		grub_errno = 0;
5994
		return 0;
5995
	}
5996
	return ctx->hook (name, &info, ctx->hook_data);
4036
5997
4037
  err = fill_fs_info (&info, mdn, ctx->data);
4038
  if (err)
4039
    {
4040
      grub_errno = 0;
4041
      return 0;
4042
    }
4043
  return ctx->hook (name, &info, ctx->hook_data);
4044
}
5998
}
4045
5999
4046
/* Helper for grub_zfs_dir.  */
6000
/* Helper for grub_zfs_dir.  */
4047
static int
6001
static int
4048
iterate_zap_snap (const char *name, grub_uint64_t val,
6002
iterate_zap_snap(const char *name, grub_uint64_t val,
4049
		  struct grub_zfs_dir_ctx *ctx)
6003
    struct grub_zfs_dir_ctx *ctx)
4050
{
6004
{
4051
  grub_err_t err;
6005
	grub_err_t err;
4052
  struct grub_dirhook_info info;
6006
	struct grub_dirhook_info info;
4053
  char *name2;
6007
	char *name2;
4054
  int ret;
6008
	int ret;
4055
6009
	dnode_end_t mdn;
4056
  dnode_end_t mdn;
6010
4057
6011
	err = dnode_get(&(ctx->data->mos), val, 0, &mdn, ctx->data);
4058
  err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
6012
	if (err) {
4059
  if (err)
6013
		grub_errno = 0;
4060
    {
6014
		return 0;
4061
      grub_errno = 0;
6015
	}
4062
      return 0;
6016
4063
    }
6017
	if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
6018
		return 0;
6019
6020
	err = fill_fs_info(&info, mdn, ctx->data);
6021
	if (err) {
6022
		grub_errno = 0;
6023
		return 0;
6024
	}
6025
6026
	name2 = grub_malloc(grub_strlen (name) + 2);
6027
	name2[0] = '@';
6028
	grub_memcpy(name2 + 1, name, grub_strlen (name) + 1);
6029
	ret = ctx->hook(name2, &info, ctx->hook_data);
6030
	grub_free(name2);
6031
	return ret;
4064
6032
4065
  if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
4066
    return 0;
4067
4068
  err = fill_fs_info (&info, mdn, ctx->data);
4069
  if (err)
4070
    {
4071
      grub_errno = 0;
4072
      return 0;
4073
    }
4074
4075
  name2 = grub_malloc (grub_strlen (name) + 2);
4076
  name2[0] = '@';
4077
  grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
4078
  ret = ctx->hook (name2, &info, ctx->hook_data);
4079
  grub_free (name2);
4080
  return ret;
4081
}
6033
}
4082
6034
4083
static grub_err_t
6035
static grub_err_t
4084
grub_zfs_dir (grub_device_t device, const char *path,
6036
grub_zfs_dir (grub_device_t device, const char *path,
4085
	      grub_fs_dir_hook_t hook, void *hook_data)
6037
	      grub_fs_dir_hook_t hook, void *hook_data)
4086
{
6038
{
4087
  struct grub_zfs_dir_ctx ctx = {
6039
	struct grub_zfs_dir_ctx ctx = {
4088
    .hook = hook,
6040
		.hook = hook,
4089
    .hook_data = hook_data
6041
		.hook_data = hook_data
4090
  };
6042
	};
4091
  struct grub_zfs_data *data;
6043
	struct grub_zfs_data *data;
4092
  grub_err_t err;
6044
	grub_err_t err;
4093
  int isfs;
6045
	int isfs;
4094
4095
  data = zfs_mount (device);
4096
  if (! data)
4097
    return grub_errno;
4098
  err = dnode_get_fullpath (path, &(data->subvol), &(data->dnode), &isfs, data);
4099
  if (err)
4100
    {
4101
      zfs_unmount (data);
4102
      return err;
4103
    }
4104
  ctx.data = data;
4105
4106
  if (isfs)
4107
    {
4108
      grub_uint64_t childobj, headobj; 
4109
      grub_uint64_t snapobj;
4110
      dnode_end_t dn;
4111
      struct grub_dirhook_info info;
4112
4113
      err = fill_fs_info (&info, data->dnode, data);
4114
      if (err)
4115
	{
4116
	  zfs_unmount (data);
4117
	  return err;
4118
	}
4119
      if (hook ("@", &info, hook_data))
4120
	{
4121
	  zfs_unmount (data);
4122
	  return GRUB_ERR_NONE;
4123
	}
4124
6046
4125
      childobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj, data->dnode.endian);
6047
	data = zfs_mount(device);
4126
      headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj, data->dnode.endian);
6048
	if (!data)
4127
      err = dnode_get (&(data->mos), childobj,
6049
		return grub_errno;
4128
		       DMU_OT_DSL_DIR_CHILD_MAP, &dn, data);
6050
	err = dnode_get_fullpath(path, &(data->subvol), &(data->dnode),
4129
      if (err)
6051
	    &isfs, data);
4130
	{
6052
	if (err) {
4131
	  zfs_unmount (data);
6053
		grub_dprintf("zfs", "dnode_get_fullpath failed\n");
4132
	  return err;
6054
		zfs_unmount(data);
6055
		return err;
4133
	}
6056
	}
6057
	ctx.data = data;
4134
6058
4135
      zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx);
6059
	if (isfs) {
6060
		grub_uint64_t childobj, headobj;
6061
		grub_uint64_t snapobj;
6062
		dnode_end_t dn;
6063
		struct grub_dirhook_info info;
6064
6065
		err = fill_fs_info(&info, data->dnode, data);
6066
		if (err) {
6067
			zfs_unmount(data);
6068
			return err;
6069
		}
6070
		if (hook ("@", &info, hook_data)) {
6071
			zfs_unmount(data);
6072
			return GRUB_ERR_NONE;
6073
		}
4136
      
6074
      
4137
      err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data);
6075
		childobj = grub_zfs_to_cpu64(
4138
      if (err)
6076
		    ((dsl_dir_phys_t *)
4139
	{
6077
		    DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj,
4140
	  zfs_unmount (data);
6078
		    data->dnode.endian);
4141
	  return err;
6079
4142
	}
6080
		headobj = grub_zfs_to_cpu64(
4143
6081
		    ((dsl_dir_phys_t *)
4144
      snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&dn.dn))->ds_snapnames_zapobj, dn.endian);
6082
		    DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj,
4145
6083
		    data->dnode.endian);
4146
      err = dnode_get (&(data->mos), snapobj,
6084
		err = dnode_get (&(data->mos), childobj,
4147
		       DMU_OT_DSL_DS_SNAP_MAP, &dn, data);
6085
		    DMU_OT_DSL_DIR_CHILD_MAP, &dn, data);
4148
      if (err)
6086
		if (err) {
4149
	{
6087
			zfs_unmount(data);
4150
	  zfs_unmount (data);
6088
			return err;
4151
	  return err;
6089
		}
4152
	}
4153
4154
      zap_iterate_u64 (&dn, iterate_zap_snap, data, &ctx);
4155
    }
4156
  else
4157
    {
4158
      if (data->dnode.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS)
4159
	{
4160
	  zfs_unmount (data);
4161
	  return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
4162
	}
4163
      zap_iterate_u64 (&(data->dnode), iterate_zap, data, &ctx);
4164
    }
4165
  zfs_unmount (data);
4166
  return grub_errno;
4167
}
4168
6090
4169
static int
6091
		zap_iterate_u64(&dn, iterate_zap_fs, data, &ctx);
4170
check_feature (const char *name, grub_uint64_t val,
4171
	       struct grub_zfs_dir_ctx *ctx __attribute__((unused)))
4172
{
4173
  int i;
4174
  if (val == 0)
4175
    return 0;
4176
  if (name[0] == 0)
4177
    return 0;
4178
  for (i = 0; spa_feature_names[i] != NULL; i++) 
4179
    if (grub_strcmp (name, spa_feature_names[i]) == 0) 
4180
      return 0;
4181
  return 1;
4182
}
4183
6092
4184
/*
6093
		err = dnode_get(&(data->mos), headobj,
4185
 * Checks whether the MOS features that are active are supported by this
6094
		    DMU_OT_DSL_DATASET, &dn, data);
4186
 * (GRUB's) implementation of ZFS.
6095
		if (err) {
4187
 *
6096
			zfs_unmount(data);
4188
 * Return:
6097
			return err;
4189
 *	0: Success.
6098
		}
4190
 *	errnum: Failure.
4191
 */
4192
	    	   
4193
static int
4194
check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data )
4195
{
4196
  grub_uint64_t objnum;
4197
  grub_uint8_t errnum = 0;
4198
  dnode_end_t dn,mosmdn;
4199
  mzap_phys_t* mzp;
4200
  grub_zfs_endian_t endianzap;
4201
  int size;
4202
  grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t));
4203
  mosmdn.endian=endian;
4204
  errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT,
4205
		     DMU_OT_OBJECT_DIRECTORY, &dn,data);
4206
  if (errnum != 0)
4207
    return errnum;
4208
6099
4209
  /*
6100
		snapobj = grub_zfs_to_cpu64(
4210
   * Find the object number for 'features_for_read' and retrieve its
6101
		    ((dsl_dataset_phys_t *)
4211
   * corresponding dnode. Note that we don't check features_for_write
6102
		    DN_BONUS (&dn.dn))->ds_snapnames_zapobj, dn.endian);
4212
   * because GRUB is not opening the pool for write.
6103
4213
   */
6104
		err = dnode_get(&(data->mos), snapobj,
4214
  errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0);
6105
		    DMU_OT_DSL_DS_SNAP_MAP, &dn, data);
4215
  if (errnum != 0)
6106
		if (err) {
4216
    return errnum;
6107
			zfs_unmount(data);
4217
  
6108
			return err;
4218
  errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data);
6109
		}
4219
  if (errnum != 0)
4220
    return errnum;
4221
4222
  errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data);
4223
  if (errnum != 0)
4224
    return errnum;
4225
6110
4226
  size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT;
6111
		zap_iterate_u64(&dn, iterate_zap_snap, data, &ctx);
4227
  return mzap_iterate (mzp,endianzap, size, check_feature,NULL);
6112
	} else {
6113
		if (data->dnode.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS) {
6114
			zfs_unmount (data);
6115
			return grub_error(GRUB_ERR_BAD_FILE_TYPE,
6116
			    N_("not a directory"));
6117
		}
6118
		zap_iterate_u64(&(data->dnode), iterate_zap, data, &ctx);
6119
	}
6120
	zfs_unmount(data);
6121
	return grub_errno;
4228
}
6122
}
4229
6123
4230
6124
Lines 4260-4265 Link Here
4260
}
6154
}
4261
#endif
6155
#endif
4262
6156
6157
/* GRUB2 zfs FS module interface structure */
4263
static struct grub_fs grub_zfs_fs = {
6158
static struct grub_fs grub_zfs_fs = {
4264
  .name = "zfs",
6159
  .name = "zfs",
4265
  .dir = grub_zfs_dir,
6160
  .dir = grub_zfs_dir,
Lines 4272-4278 Link Here
4272
#ifdef GRUB_UTIL
6167
#ifdef GRUB_UTIL
4273
  .embed = grub_zfs_embed,
6168
  .embed = grub_zfs_embed,
4274
  .reserved_first_sector = 1,
6169
  .reserved_first_sector = 1,
4275
  .blocklist_install = 0,
6170
  .blocklist_install = 1,
4276
#endif
6171
#endif
4277
  .next = 0
6172
  .next = 0
4278
};
6173
};
Lines 4288-4292 Link Here
4288
6183
4289
GRUB_MOD_FINI (zfs)
6184
GRUB_MOD_FINI (zfs)
4290
{
6185
{
6186
  zfs_free_caches ();
4291
  grub_fs_unregister (&grub_zfs_fs);
6187
  grub_fs_unregister (&grub_zfs_fs);
4292
}
6188
}
(-)grub-2.02~beta2_/grub-core/fs/zfs/zfs_lz4.c (-45 / +76 lines)
Lines 33-44 Link Here
33
 */
33
 */
34
34
35
#include <grub/err.h>
35
#include <grub/err.h>
36
#include <grub/file.h>
36
#include <grub/mm.h>
37
#include <grub/mm.h>
37
#include <grub/misc.h>
38
#include <grub/misc.h>
39
#include <grub/disk.h>
40
#include <grub/dl.h>
38
#include <grub/types.h>
41
#include <grub/types.h>
39
42
40
static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
43
static grub_err_t LZ4_uncompress_unknownOutputSize(const grub_uint8_t *source,
41
					    int isize, int maxOutputSize);
44
	 char *dest, grub_uint32_t isize, grub_size_t maxOutputSize);
45
grub_err_t
46
lz4_decompress (void *s_start, void *d_start, grub_size_t s_len,
47
		grub_size_t d_len);
48
49
grub_err_t
50
lz4_decompress (void *s_start, void *d_start, grub_size_t s_len,
51
		grub_size_t d_len)
52
{
53
	const grub_uint8_t *src = s_start;
54
	grub_uint32_t bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) |
55
	    src[3];
56
57
	/* invalid compressed buffer size encoded at start */
58
	if (bufsiz + 4 > s_len)
59
		return grub_error (GRUB_ERR_BAD_FS, "lz4 decompression failed");
60
61
	/*
62
	 * Returns 0 on success (decompression function returned non-negative)
63
	 * and non-zero on failure (decompression function returned negative).
64
	 */
65
	return LZ4_uncompress_unknownOutputSize(src + 4, d_start, bufsiz,
66
	    d_len);
67
}
42
68
43
/*
69
/*
44
 * CPU Feature Detection
70
 * CPU Feature Detection
Lines 52-59 Link Here
52
#endif
78
#endif
53
79
54
/*
80
/*
81
 * Little Endian or Big Endian?
82
 * Note: overwrite the below #define if you know your architecture endianess.
83
 */
84
#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || \
85
	defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || \
86
	defined(__PPC) || defined(PPC) || defined(__powerpc__) || \
87
	defined(__powerpc) || defined(powerpc) || \
88
	((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))))
89
#define	LZ4_BIG_ENDIAN	1
90
#else
91
	/*
92
	 * Little Endian assumed. PDP Endian and other very rare endian format
93
	 * are unsupported.
94
	 */
95
#endif
96
97
/*
55
 * Compiler Options
98
 * Compiler Options
56
 */
99
 */
100
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L	/* C99 */
101
/* "restrict" is a known keyword */
102
#else
103
/* Disable restrict */
104
#if !defined restrict
105
#define	restrict
106
#endif
107
#endif
57
108
58
109
59
#define	GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
110
#define	GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
Lines 73-79 Link Here
73
#define	U32	grub_uint32_t
124
#define	U32	grub_uint32_t
74
#define	S32	grub_int32_t
125
#define	S32	grub_int32_t
75
#define	U64	grub_uint64_t
126
#define	U64	grub_uint64_t
76
typedef grub_size_t size_t;
77
127
78
typedef struct _U16_S {
128
typedef struct _U16_S {
79
	U16 v;
129
	U16 v;
Lines 125-173 Link Here
125
#define	INITBASE(base)		const int base = 0
175
#define	INITBASE(base)		const int base = 0
126
#endif
176
#endif
127
177
128
#define	LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - grub_le_to_cpu16 (A16 (p)); }
178
#define	LZ4_READ_LITTLEENDIAN_16(d, s, p) \
129
#define	LZ4_WRITE_LITTLEENDIAN_16(p, v)  { A16(p) = grub_cpu_to_le16 (v); p += 2; }
179
	{ d = (s) - grub_le_to_cpu16(A16(p)); }
180
#define	LZ4_WRITE_LITTLEENDIAN_16(p, v)  \
181
	{ A16(p) = grub_cpu_to_le16(v); p += 2; }
130
182
131
/* Macros */
183
/* Macros */
132
#define	LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e);
184
#define	LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e);
133
185
134
/* Decompression functions */
186
/* Decompression functions */
135
grub_err_t
136
lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len);
137
138
grub_err_t
139
lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len)
140
{
141
	const BYTE *src = s_start;
142
	U32 bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) |
143
	    src[3];
144
187
145
	/* invalid compressed buffer size encoded at start */
188
static grub_err_t
146
	if (bufsiz + 4 > s_len)
189
LZ4_uncompress_unknownOutputSize(const grub_uint8_t *source,
147
		return grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed.");
190
    char *dest, grub_uint32_t isize, grub_size_t maxOutputSize)
148
149
	/*
150
	 * Returns 0 on success (decompression function returned non-negative)
151
	 * and appropriate error on failure (decompression function returned negative).
152
	 */
153
	return (LZ4_uncompress_unknownOutputSize((char*)s_start + 4, d_start, bufsiz,
154
	    d_len) < 0)?grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."):0;
155
}
156
157
static int
158
LZ4_uncompress_unknownOutputSize(const char *source,
159
    char *dest, int isize, int maxOutputSize)
160
{
191
{
161
	/* Local Variables */
192
	/* Local Variables */
162
	const BYTE * ip = (const BYTE *) source;
193
	const BYTE *restrict ip = (const BYTE *) source;
163
	const BYTE *const iend = ip + isize;
194
	const BYTE *const iend = ip + isize;
164
	const BYTE * ref;
195
	const BYTE *restrict ref;
165
196
166
	BYTE * op = (BYTE *) dest;
197
	BYTE *restrict op = (BYTE *) dest;
167
	BYTE *const oend = op + maxOutputSize;
198
	BYTE *const oend = op + maxOutputSize;
168
	BYTE *cpy;
199
	BYTE *cpy;
169
200
170
	size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
201
	grub_size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
171
202
172
	/* Main Loop */
203
	/* Main Loop */
173
	while (ip < iend) {
204
	while (ip < iend) {
Lines 185-190 Link Here
185
		}
216
		}
186
		/* copy literals */
217
		/* copy literals */
187
		cpy = op + length;
218
		cpy = op + length;
219
		/* CORNER-CASE: cpy might overflow. */
220
		if (cpy < op)		/* cpy was overflowed, bail! */
221
			return grub_error (GRUB_ERR_BAD_FS,
222
			    "lz4 decompression failed");
188
		if ((cpy > oend - COPYLENGTH) ||
223
		if ((cpy > oend - COPYLENGTH) ||
189
		    (ip + length > iend - COPYLENGTH)) {
224
		    (ip + length > iend - COPYLENGTH)) {
190
			if (cpy > oend)
225
			if (cpy > oend)
Lines 192-210 Link Here
192
				 * Error: request to write beyond destination
227
				 * Error: request to write beyond destination
193
				 * buffer.
228
				 * buffer.
194
				 */
229
				 */
195
				goto _output_error;
230
				return grub_error (GRUB_ERR_BAD_FS, "lz4 decompression failed");
196
			if (ip + length > iend)
231
			if (ip + length > iend)
197
				/*
232
				/*
198
				 * Error : request to read beyond source
233
				 * Error : request to read beyond source
199
				 * buffer.
234
				 * buffer.
200
				 */
235
				 */
201
				goto _output_error;
236
				return grub_error (GRUB_ERR_BAD_FS, "lz4 decompression failed");
202
			grub_memcpy(op, ip, length);
237
			grub_memcpy(op, ip, length);
203
			op += length;
238
			op += length;
204
			ip += length;
239
			ip += length;
205
			if (ip < iend)
240
			if (ip < iend)
206
				/* Error : LZ4 format violation */
241
				/* Error : LZ4 format violation */
207
				goto _output_error;
242
				return grub_error (GRUB_ERR_BAD_FS, "lz4 decompression failed");
208
			/* Necessarily EOF, due to parsing restrictions. */
243
			/* Necessarily EOF, due to parsing restrictions. */
209
			break;
244
			break;
210
		}
245
		}
Lines 220-226 Link Here
220
			 * Error: offset creates reference outside of
255
			 * Error: offset creates reference outside of
221
			 * destination buffer.
256
			 * destination buffer.
222
			 */
257
			 */
223
			goto _output_error;
258
			return grub_error (GRUB_ERR_BAD_FS, "lz4 decompression failed");
224
259
225
		/* get matchlength */
260
		/* get matchlength */
226
		if ((length = (token & ML_MASK)) == ML_MASK) {
261
		if ((length = (token & ML_MASK)) == ML_MASK) {
Lines 235-242 Link Here
235
		/* copy repeated sequence */
270
		/* copy repeated sequence */
236
		if unlikely(op - ref < STEPSIZE) {
271
		if unlikely(op - ref < STEPSIZE) {
237
#if LZ4_ARCH64
272
#if LZ4_ARCH64
238
			size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
273
			grub_size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
239
			size_t dec2 = dec2table[op - ref];
274
			grub_size_t dec2 = dec2table[op - ref];
240
#else
275
#else
241
			const int dec2 = 0;
276
			const int dec2 = 0;
242
#endif
277
#endif
Lines 258-264 Link Here
258
				 * Error: request to write outside of
293
				 * Error: request to write outside of
259
				 * destination buffer.
294
				 * destination buffer.
260
				 */
295
				 */
261
				goto _output_error;
296
				return grub_error (GRUB_ERR_BAD_FS, "lz4 decompression failed");
262
			LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
297
			LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
263
			while (op < cpy)
298
			while (op < cpy)
264
				*op++ = *ref++;
299
				*op++ = *ref++;
Lines 276-284 Link Here
276
	}
311
	}
277
312
278
	/* end of decoding */
313
	/* end of decoding */
279
	return (int)(((char *)op) - dest);
314
	return GRUB_ERR_NONE;
280
281
	/* write overflow error detected */
282
	_output_error:
283
	return (int)(-(((char *)ip) - source));
284
}
315
}
(-)grub-2.02~beta2_/grub-core/fs/zfs/zfscrypt.c (-1 / +2 lines)
Lines 265-271 Link Here
265
			       mac_out, nonce,
265
			       mac_out, nonce,
266
			       15 - l, m);
266
			       15 - l, m);
267
    default:
267
    default:
268
      return GPG_ERR_CIPHER_ALGO;
268
      return grub_error(GPG_ERR_CIPHER_ALGO, "algorithm %"
269
			PRIuGRUB_UINT64_T " is not supported yet", algo);
269
    }
270
    }
270
}
271
}
271
272
(-)grub-2.02~beta2_/grub-core/fs/zfs/zfsinfo.c (-33 / +202 lines)
Lines 193-202 Link Here
193
  return GRUB_ERR_NONE;
193
  return GRUB_ERR_NONE;
194
}
194
}
195
195
196
static grub_err_t
196
#ifndef ZVBOOT
197
get_bootpath (char *nvlist, char **bootpath, char **devid)
197
static
198
#endif /* ZVBOOT */
199
grub_err_t
200
get_bootpath (char *nvlist, grub_uint64_t devguid, char **bootpath,
201
    char **devid)
198
{
202
{
199
  char *type = 0;
203
  char *type = 0;
204
  grub_uint64_t curguid;
205
  int found;
200
206
201
  type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
207
  type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
202
208
Lines 205-224 Link Here
205
211
206
  if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
212
  if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
207
    {
213
    {
214
      found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID,
215
					     &curguid);
216
217
      *bootpath = 0;
218
      *devid = 0;
219
220
      if (found && curguid != devguid)
221
	{
222
	  return GRUB_ERR_NONE;
223
	}
224
225
      if (grub_zfs_vdev_validate(nvlist))	/* device error */
226
	return GRUB_ERR_NONE;
227
208
      *bootpath = grub_zfs_nvlist_lookup_string (nvlist,
228
      *bootpath = grub_zfs_nvlist_lookup_string (nvlist,
209
						 ZPOOL_CONFIG_PHYS_PATH);
229
						 ZPOOL_CONFIG_PHYS_PATH);
210
      *devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
230
      *devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
211
      if (!*bootpath || !*devid)
231
212
	{
213
	  grub_free (*bootpath);
214
	  grub_free (*devid);
215
	  *bootpath = 0;
216
	  *devid = 0;
217
	}
218
      return GRUB_ERR_NONE;
232
      return GRUB_ERR_NONE;
219
    }
233
    }
220
234
221
  if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
235
  if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0 ||
236
      grub_strcmp (type, VDEV_TYPE_RAIDZ) == 0)
222
    {
237
    {
223
      int nelm, i;
238
      int nelm, i;
224
239
Lines 233-243 Link Here
233
						       ZPOOL_CONFIG_CHILDREN,
248
						       ZPOOL_CONFIG_CHILDREN,
234
						       i);
249
						       i);
235
250
236
	  get_bootpath (child, bootpath, devid);
251
	  if (! child)
252
	    {
253
	      grub_printf_ (N_("Unable to lookup child vdevs for pool: %s\n"),
254
				grub_errmsg);
255
	      return grub_errno;
256
	    }
257
258
	  get_bootpath (child, devguid, bootpath, devid);
237
259
238
	  grub_free (child);
260
	  grub_free (child);
239
261
240
	  if (*bootpath && *devid)
262
	  if (*bootpath || *devid)
241
	    return GRUB_ERR_NONE;
263
	    return GRUB_ERR_NONE;
242
	}
264
	}
243
    }
265
    }
Lines 274-280 Link Here
274
  int found;
296
  int found;
275
297
276
  if (argc < 1)
298
  if (argc < 1)
277
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
299
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("device name required"));
278
300
279
  if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
301
  if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
280
    {
302
    {
Lines 348-359 Link Here
348
  char *nv = 0;
370
  char *nv = 0;
349
  char *bootpath = 0, *devid = 0;
371
  char *bootpath = 0, *devid = 0;
350
  char *fsname;
372
  char *fsname;
351
  char *bootfs;
373
  char *bootfs = NULL;
352
  char *poolname;
374
  char *poolname = NULL;
353
  grub_uint64_t mdnobj;
375
  grub_uint64_t mdnobj, devguid;
376
  int found;
354
377
355
  if (argc < 1)
378
  if (argc < 1)
356
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
379
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filesystem name required"));
357
380
358
  devname = grub_file_get_device_name (args[0]);
381
  devname = grub_file_get_device_name (args[0]);
359
  if (grub_errno)
382
  if (grub_errno)
Lines 378-402 Link Here
378
  grub_device_close (dev);
401
  grub_device_close (dev);
379
402
380
  if (err)
403
  if (err)
381
    return err;
404
    {
405
      grub_free (nvlist);
406
      return err;
407
    }
408
409
  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID, &devguid);
410
411
  if (!found)
412
    {
413
      if (!grub_errno)
414
        grub_error(GRUB_ERR_BAD_FS, N_("No virtual device GUID found"));
415
      grub_free (nvlist);
416
      return grub_errno;
417
    }
382
418
383
  poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
419
  poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
384
  if (!poolname)
420
  if (!poolname)
385
    {
421
    {
386
      if (!grub_errno)
422
      if (!grub_errno)
387
	grub_error (GRUB_ERR_BAD_FS, "No poolname found");
423
	grub_error (GRUB_ERR_BAD_FS, "No poolname found");
424
      grub_free (nvlist);
388
      return grub_errno;
425
      return grub_errno;
389
    }
426
    }
390
427
391
  nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
428
  nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
392
429
393
  if (nv)
430
  if (nv && (get_bootpath (nv, devguid, &bootpath, &devid) == GRUB_ERR_NONE))
394
    get_bootpath (nv, &bootpath, &devid);
431
    {
395
432
       bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu%s%s%s%s%s%s",
396
  grub_free (nv);
397
  grub_free (nvlist);
398
399
  bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu%s%s%s%s%s%s",
400
			   poolname, (unsigned long long) mdnobj,
433
			   poolname, (unsigned long long) mdnobj,
401
			   bootpath ? ",bootpath=\"" : "",
434
			   bootpath ? ",bootpath=\"" : "",
402
			   bootpath ? : "",
435
			   bootpath ? : "",
Lines 404-409 Link Here
404
			   devid ? ",diskdevid=\"" : "",
437
			   devid ? ",diskdevid=\"" : "",
405
			   devid ? : "",
438
			   devid ? : "",
406
			   devid ? "\"" : "");
439
			   devid ? "\"" : "");
440
     }
441
  grub_free (nv);
442
  grub_free (nvlist);
443
  grub_free (poolname);
444
407
  if (!bootfs)
445
  if (!bootfs)
408
    return grub_errno;
446
    return grub_errno;
409
  if (argc >= 2)
447
  if (argc >= 2)
Lines 412-439 Link Here
412
    grub_printf ("%s\n", bootfs);
450
    grub_printf ("%s\n", bootfs);
413
451
414
  grub_free (bootfs);
452
  grub_free (bootfs);
415
  grub_free (poolname);
416
  grub_free (bootpath);
453
  grub_free (bootpath);
417
  grub_free (devid);
454
  grub_free (devid);
418
455
419
  return GRUB_ERR_NONE;
456
  return GRUB_ERR_NONE;
420
}
457
}
421
458
459
static grub_err_t
460
grub_cmd_zfs_defaultbootfs (grub_command_t cmd __attribute__ ((unused)),
461
	int argc, char **args)
462
{
463
  grub_device_t dev;
464
  char *devname = 0;
465
  grub_err_t err;
466
  char *nvlist = 0;
467
  char *nv = 0;
468
  char *bootpath = 0, *devid = 0;
469
  char *bootfs = 0;
470
  char *poolname;
471
  char *bootfsname = 0;
472
  grub_uint64_t mdnobj, devguid;
473
  int found;
474
475
  if (argc < 1)
476
    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable name required"));
477
478
  if (argc >= 2)
479
    {
480
      /* args[0] is the DEVICE name */
481
      if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
482
        {
483
          devname = grub_strdup (args[0] + 1);
484
          if (devname)
485
	    devname[grub_strlen (devname) - 1] = 0;
486
        }
487
      else
488
        devname = grub_strdup (args[0]);
489
    }
490
  else		/* args[0] is the variable, we'll use root device */
491
      devname = grub_strdup(grub_env_get("root"));
492
493
  if (grub_errno)
494
    {
495
      grub_free(devname);
496
      return grub_errno;
497
    }
498
499
  dev = grub_device_open (devname);
500
  grub_free (devname);
501
  if (!dev)
502
    return grub_errno;
503
504
  err = grub_zfs_fetch_nvlist (dev, &nvlist);
505
  if (!err)
506
    err = grub_zfs_defaultbootfsobj (dev, &mdnobj);
507
508
  if (err)
509
    {
510
      grub_device_close (dev);
511
      grub_free (nvlist);
512
      return err;
513
    }
514
515
  err = grub_zfs_defaultbootfsname (dev, &bootfsname);
516
517
  grub_device_close (dev);
518
519
  if (err)
520
    {
521
      grub_free (nvlist);
522
      return err;
523
    }
524
525
  if (argc >= 3)
526
    {
527
      found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID,
528
					    &devguid);
529
      if (!found)
530
	{
531
	  if (!grub_errno)
532
	    grub_error(GRUB_ERR_BAD_FS, N_("No virtual device GUID found"));
533
	  grub_free (nvlist);
534
	  grub_free (bootfsname);
535
	  return grub_errno;
536
	}
537
538
      poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
539
      if (!poolname)
540
	{
541
	  if (!grub_errno)
542
	    grub_error (GRUB_ERR_BAD_FS, N_("No poolname found"));
543
	  grub_free (nvlist);
544
	  grub_free (bootfsname);
545
	  return grub_errno;
546
	}
547
548
      nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
549
550
      if (nv && (get_bootpath (nv, devguid, &bootpath, &devid) == GRUB_ERR_NONE))
551
        {
552
          bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu%s%s%s%s%s%s",
553
				  poolname, (unsigned long long) mdnobj,
554
				  bootpath ? ",bootpath=\"" : "",
555
				  bootpath ? : "",
556
				  bootpath ? "\"" : "",
557
				  devid ? ",diskdevid=\"" : "",
558
				  devid ? : "",
559
				  devid ? "\"" : "");
560
	  grub_free (nv);
561
	  grub_free (poolname);
562
	  grub_free (bootpath);
563
	  grub_free (devid);
564
	  if (!bootfs)
565
	    {
566
	      grub_free (nvlist);
567
	      return grub_errno;
568
	    }
569
	  grub_dprintf ("zfs", "bootfs=%s\n", bootfs);
570
	  grub_env_set (args[2], bootfs);
571
	}
572
    }
573
574
  grub_dprintf ("zfs", "bootfsname=%s\n", bootfsname);
575
576
  if (argc >= 2)
577
    grub_env_set (args[1], bootfsname);
578
  else
579
    grub_env_set (args[0], bootfsname);
580
581
  grub_free (nvlist);
582
  grub_free (bootfs);
583
  grub_free (bootfsname);
584
585
  return GRUB_ERR_NONE;
586
}
422
587
423
static grub_command_t cmd_info, cmd_bootfs;
588
static grub_command_t cmd_info, cmd_bootfs, cmd_defaultbootfs;
424
589
425
GRUB_MOD_INIT (zfsinfo)
590
GRUB_MOD_INIT(zfsinfo)
426
{
591
{
427
  cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo,
592
  cmd_info = grub_register_command("zfsinfo", grub_cmd_zfsinfo,
428
				    N_("DEVICE"),
593
	N_("DEVICE"), N_("Print ZFS info about DEVICE."));
429
				    N_("Print ZFS info about DEVICE."));
430
  cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
594
  cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
431
				      N_("FILESYSTEM [VARIABLE]"),
595
	N_("FILESYSTEM [VARIABLE]"),
432
				      N_("Print ZFS-BOOTFSOBJ or store it into VARIABLE"));
596
	N_("Print ZFS-BOOTFSOBJ or store it into VARIABLE"));
597
  cmd_defaultbootfs = grub_register_command ("zfs-defaultbootfs",
598
	grub_cmd_zfs_defaultbootfs,
599
	N_("VARIABLE or zfs-defaultbootfs DEVICE VARIABLE-A or zfs-defaultbootfs DEVICE VARIABLE-A VARIABLE-B"),
600
	N_("Set default bootfs name of root device or given DEVICE to VARIABLE-A or set default bootfsname to VARIABLE-A and ZFS-BOOTFSOBJ to VARIABLE-B"));
433
}
601
}
434
602
435
GRUB_MOD_FINI (zfsinfo)
603
GRUB_MOD_FINI (zfsinfo)
436
{
604
{
437
  grub_unregister_command (cmd_info);
605
  grub_unregister_command (cmd_info);
438
  grub_unregister_command (cmd_bootfs);
606
  grub_unregister_command (cmd_bootfs);
607
  grub_unregister_command (cmd_defaultbootfs);
439
}
608
}
(-)grub-2.02~beta2_/grub-core/partmap/gpt.c (+9 lines)
Lines 24-29 Link Here
24
#include <grub/dl.h>
24
#include <grub/dl.h>
25
#include <grub/msdos_partition.h>
25
#include <grub/msdos_partition.h>
26
#include <grub/gpt_partition.h>
26
#include <grub/gpt_partition.h>
27
#include <grub/zfs/zio.h>
28
#include <grub/zfs/vdev_impl.h>
27
#include <grub/i18n.h>
29
#include <grub/i18n.h>
28
30
29
GRUB_MOD_LICENSE ("GPLv3+");
31
GRUB_MOD_LICENSE ("GPLv3+");
Lines 37-42 Link Here
37
39
38
#ifdef GRUB_UTIL
40
#ifdef GRUB_UTIL
39
static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
41
static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
42
static const grub_gpt_part_type_t grub_gpt_partition_type_zfs = GRUB_GPT_PARTITION_TYPE_ZFS;
40
#endif
43
#endif
41
44
42
/* 512 << 7 = 65536 byte sectors.  */
45
/* 512 << 7 = 65536 byte sectors.  */
Lines 162-167 Link Here
162
      return 1;
165
      return 1;
163
    }
166
    }
164
167
168
  if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_zfs, 16))
169
    {
170
      ctx->start = p->start + (VDEV_BOOT_OFFSET >> GRUB_DISK_SECTOR_BITS);
171
      ctx->len = (VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS);
172
      return 1;
173
    }
165
  return 0;
174
  return 0;
166
}
175
}
167
176
(-)grub-2.02~beta2_/include/grub/gpt_partition.h (+7 lines)
Lines 50-55 Link Here
50
	{ 0x85, 0xD2, 0xE1, 0xE9, 0x04, 0x34, 0xCF, 0xB3 }	\
50
	{ 0x85, 0xD2, 0xE1, 0xE9, 0x04, 0x34, 0xCF, 0xB3 }	\
51
  }
51
  }
52
52
53
#define GRUB_GPT_PARTITION_TYPE_ZFS \
54
  { grub_cpu_to_le32_compile_time (0x6A898CC3U),\
55
      grub_cpu_to_le16_compile_time (0x1DD2), \
56
      grub_cpu_to_le16_compile_time (0x11B2),	       \
57
	{ 0x99, 0xA6, 0x08, 0x00, 0x20, 0x73, 0x66, 0x31 }	\
58
  }
59
53
struct grub_gpt_header
60
struct grub_gpt_header
54
{
61
{
55
  grub_uint8_t magic[8];
62
  grub_uint8_t magic[8];
(-)grub-2.02~beta2_/include/grub/zfs/dmu.h (-43 / +54 lines)
Lines 22-60 Link Here
22
22
23
#ifndef	_SYS_DMU_H
23
#ifndef	_SYS_DMU_H
24
#define	_SYS_DMU_H
24
#define	_SYS_DMU_H
25
#define	B_FALSE	0
26
#define	B_TRUE	1
27
28
#define	DMU_OT_NEWTYPE 0x80
29
#define	DMU_OT_METADATA 0x40
30
#define	DMU_OT_BYTESWAP_MASK 0x3f
31
32
#define	DMU_OT(byteswap, metadata) \
33
	(DMU_OT_NEWTYPE | \
34
	((metadata) ? DMU_OT_METADATA : 0) | \
35
	((byteswap) & DMU_OT_BYTESWAP_MASK))
36
37
#define	DMU_OT_IS_VALID(ot) (((ot) & DMU_OT_NEWTYPE) ? \
38
	((ot) & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS : \
39
	(ot) < DMU_OT_NUMTYPES)
40
41
#define	DMU_OT_IS_METADATA(ot) (((ot) & DMU_OT_NEWTYPE) ? \
42
	((ot) & DMU_OT_METADATA) : \
43
	dmu_ot[(ot)].ot_metadata)
44
45
typedef enum dmu_object_byteswap {
46
	DMU_BSWAP_UINT8,
47
	DMU_BSWAP_UINT16,
48
	DMU_BSWAP_UINT32,
49
	DMU_BSWAP_UINT64,
50
	DMU_BSWAP_ZAP,
51
	DMU_BSWAP_DNODE,
52
	DMU_BSWAP_OBJSET,
53
	DMU_BSWAP_ZNODE,
54
	DMU_BSWAP_OLDACL,
55
	DMU_BSWAP_ACL,
56
	DMU_BSWAP_NUMFUNCS
57
} dmu_object_byteswap_t;
58
25
59
/*
26
/*
60
 * This file describes the interface that the DMU provides for its
27
 * This file describes the interface that the DMU provides for its
Lines 63-68 Link Here
63
 * The DMU also interacts with the SPA.  That interface is described in
30
 * The DMU also interacts with the SPA.  That interface is described in
64
 * dmu_spa.h.
31
 * dmu_spa.h.
65
 */
32
 */
33
34
#define B_FALSE 0
35
#define B_TRUE  1
36
37
#define DMU_OT_NEWTYPE 0x80
38
#define DMU_OT_METADATA 0x40
39
#define DMU_OT_BYTESWAP_MASK 0x3f
40
41
#define DMU_OT(byteswap, metadata) \
42
        (DMU_OT_NEWTYPE | \
43
        ((metadata) ? DMU_OT_METADATA : 0) | \
44
        ((byteswap) & DMU_OT_BYTESWAP_MASK))
45
46
#define DMU_OT_IS_VALID(ot) (((ot) & DMU_OT_NEWTYPE) ? \
47
        ((ot) & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS : \
48
        (ot) < DMU_OT_NUMTYPES)
49
50
#define DMU_OT_IS_METADATA(ot) (((ot) & DMU_OT_NEWTYPE) ? \
51
        ((ot) & DMU_OT_METADATA) : \
52
        dmu_ot[(ot)].ot_metadata)
53
54
typedef enum dmu_object_byteswap {
55
        DMU_BSWAP_UINT8,
56
        DMU_BSWAP_UINT16,
57
        DMU_BSWAP_UINT32,
58
        DMU_BSWAP_UINT64,
59
        DMU_BSWAP_ZAP,
60
        DMU_BSWAP_DNODE,
61
        DMU_BSWAP_OBJSET,
62
        DMU_BSWAP_ZNODE,
63
        DMU_BSWAP_OLDACL,
64
        DMU_BSWAP_ACL,
65
        DMU_BSWAP_NUMFUNCS
66
} dmu_object_byteswap_t;
67
66
typedef enum dmu_object_type {
68
typedef enum dmu_object_type {
67
	DMU_OT_NONE,
69
	DMU_OT_NONE,
68
	/* general: */
70
	/* general: */
Lines 122-138 Link Here
122
	DMU_OT_SA_ATTR_REGISTRATION,	/* ZAP */
124
	DMU_OT_SA_ATTR_REGISTRATION,	/* ZAP */
123
	DMU_OT_SA_ATTR_LAYOUTS,		/* ZAP */
125
	DMU_OT_SA_ATTR_LAYOUTS,		/* ZAP */
124
	DMU_OT_DSL_KEYCHAIN = 54,
126
	DMU_OT_DSL_KEYCHAIN = 54,
127
	DMU_OT_SHARE,			/* UINT64 */
128
	DMU_OT_DSL_SHARES,		/* ZAP */
129
	DMU_OT_BPMAP_ARRAY,
130
	DMU_OT_BPMAP_DEFER,
125
	DMU_OT_NUMTYPES,
131
	DMU_OT_NUMTYPES,
126
	DMU_OTN_UINT8_DATA = DMU_OT(DMU_BSWAP_UINT8, B_FALSE),
132
127
	DMU_OTN_UINT8_METADATA = DMU_OT(DMU_BSWAP_UINT8, B_TRUE),
133
        DMU_OTN_UINT8_DATA = DMU_OT(DMU_BSWAP_UINT8, B_FALSE),
128
	DMU_OTN_UINT16_DATA = DMU_OT(DMU_BSWAP_UINT16, B_FALSE),
134
        DMU_OTN_UINT8_METADATA = DMU_OT(DMU_BSWAP_UINT8, B_TRUE),
129
	DMU_OTN_UINT16_METADATA = DMU_OT(DMU_BSWAP_UINT16, B_TRUE),
135
        DMU_OTN_UINT16_DATA = DMU_OT(DMU_BSWAP_UINT16, B_FALSE),
130
	DMU_OTN_UINT32_DATA = DMU_OT(DMU_BSWAP_UINT32, B_FALSE),
136
        DMU_OTN_UINT16_METADATA = DMU_OT(DMU_BSWAP_UINT16, B_TRUE),
131
	DMU_OTN_UINT32_METADATA = DMU_OT(DMU_BSWAP_UINT32, B_TRUE),
137
        DMU_OTN_UINT32_DATA = DMU_OT(DMU_BSWAP_UINT32, B_FALSE),
132
	DMU_OTN_UINT64_DATA = DMU_OT(DMU_BSWAP_UINT64, B_FALSE),
138
        DMU_OTN_UINT32_METADATA = DMU_OT(DMU_BSWAP_UINT32, B_TRUE),
133
	DMU_OTN_UINT64_METADATA = DMU_OT(DMU_BSWAP_UINT64, B_TRUE),
139
        DMU_OTN_UINT64_DATA = DMU_OT(DMU_BSWAP_UINT64, B_FALSE),
134
	DMU_OTN_ZAP_DATA = DMU_OT(DMU_BSWAP_ZAP, B_FALSE),
140
        DMU_OTN_UINT64_METADATA = DMU_OT(DMU_BSWAP_UINT64, B_TRUE),
135
	DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE),
141
        DMU_OTN_ZAP_DATA = DMU_OT(DMU_BSWAP_ZAP, B_FALSE),
142
        DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE)
136
} dmu_object_type_t;
143
} dmu_object_type_t;
137
144
138
typedef enum dmu_objset_type {
145
typedef enum dmu_objset_type {
Lines 160-164 Link Here
160
#define	DMU_POOL_PROPS			"pool_props"
167
#define	DMU_POOL_PROPS			"pool_props"
161
#define	DMU_POOL_L2CACHE		"l2cache"
168
#define	DMU_POOL_L2CACHE		"l2cache"
162
#define	DMU_POOL_FEATURES_FOR_READ	"features_for_read"
169
#define	DMU_POOL_FEATURES_FOR_READ	"features_for_read"
170
#define	DMU_POOL_FEATURES_FOR_WRITE	"features_for_write"
171
#define	DMU_POOL_FEATURE_DESCRIPTIONS	"feature_descriptions"
172
#define	DMU_POOL_BPMAP_OBJ		"bpmap-vdev-%llu-%llu"
173
#define	DMU_POOL_BPMAP_DEFER		"bpmap_defer_obj"
163
174
164
#endif	/* _SYS_DMU_H */
175
#endif	/* _SYS_DMU_H */
(-)grub-2.02~beta2_/include/grub/zfs/dnode.h (+3 lines)
Lines 18-23 Link Here
18
/*
18
/*
19
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
19
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
20
 * Use is subject to license terms.
20
 * Use is subject to license terms.
21
 * Copyright (c) 2014 by Delphix. All rights reserved.
21
 */
22
 */
22
23
23
#ifndef	_SYS_DNODE_H
24
#ifndef	_SYS_DNODE_H
Lines 29-34 Link Here
29
 * Fixed constants.
30
 * Fixed constants.
30
 */
31
 */
31
#define	DNODE_SHIFT		9	/* 512 bytes */
32
#define	DNODE_SHIFT		9	/* 512 bytes */
33
#define	DN_MIN_INDBLKSHIFT	12	/* 1k */
34
#define	DN_MAX_INDBLKSHIFT	14	/* 16k */
32
#define	DNODE_BLOCK_SHIFT	14	/* 16k */
35
#define	DNODE_BLOCK_SHIFT	14	/* 16k */
33
#define	DNODE_CORE_SIZE		64	/* 64 bytes for dnode sans blkptrs */
36
#define	DNODE_CORE_SIZE		64	/* 64 bytes for dnode sans blkptrs */
34
37
(-)grub-2.02~beta2_/include/grub/zfs/spa.h (-12 / +58 lines)
Lines 1-7 Link Here
1
/*
1
/*
2
 *  GRUB  --  GRand Unified Bootloader
2
 *  GRUB  --  GRand Unified Bootloader
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009  Free Software Foundation, Inc.
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009  Free Software Foundation, Inc.
4
 *  Copyright 2010 Sun Microsystems, Inc.
4
 *  Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
5
 *
5
 *
6
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  GRUB is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
7
 *  it under the terms of the GNU General Public License as published by
Lines 67-72 Link Here
67
	BF64_SET(x, low, len, ((val) >> (shift)) - (bias))
67
	BF64_SET(x, low, len, ((val) >> (shift)) - (bias))
68
68
69
#define	SPA_MINBLOCKSHIFT	9
69
#define	SPA_MINBLOCKSHIFT	9
70
#define	SPA_MAXBLOCKSHIFT	24
71
#define	SPA_128KBLOCKSHIFT	17
70
#define	SPA_MINBLOCKSIZE	(1ULL << SPA_MINBLOCKSHIFT)
72
#define	SPA_MINBLOCKSIZE	(1ULL << SPA_MINBLOCKSHIFT)
71
73
72
/*
74
/*
Lines 126-132 Link Here
126
 *	+-------+-------+-------+-------+-------+-------+-------+-------+
128
 *	+-------+-------+-------+-------+-------+-------+-------+-------+
127
 * 5	|G|			 offset3				|
129
 * 5	|G|			 offset3				|
128
 *	+-------+-------+-------+-------+-------+-------+-------+-------+
130
 *	+-------+-------+-------+-------+-------+-------+-------+-------+
129
 * 6	|BDX|lvl| type	| cksum | comp	|     PSIZE	|     LSIZE	|
131
 * 6	|BDX|lvl| type	| cksum |E| comp|     PSIZE	|     LSIZE	|
130
 *	+-------+-------+-------+-------+-------+-------+-------+-------+
132
 *	+-------+-------+-------+-------+-------+-------+-------+-------+
131
 * 7	|			padding					|
133
 * 7	|			padding					|
132
 *	+-------+-------+-------+-------+-------+-------+-------+-------+
134
 *	+-------+-------+-------+-------+-------+-------+-------+-------+
Lines 160-166 Link Here
160
 * G		gang block indicator
162
 * G		gang block indicator
161
 * B		byteorder (endianness)
163
 * B		byteorder (endianness)
162
 * D		dedup
164
 * D		dedup
163
 * X		unused
165
 * X		encryption (on version 30, which is not supported in openzfs)
166
 * E		blkptr_t contains embedded data
164
 * lvl		level of indirection
167
 * lvl		level of indirection
165
 * type		DMU object type
168
 * type		DMU object type
166
 * phys birth	txg of block allocation; zero if same as logical birth txg
169
 * phys birth	txg of block allocation; zero if same as logical birth txg
Lines 195-212 Link Here
195
#define	DVA_GET_VDEV(dva)	BF64_GET((dva)->dva_word[0], 32, 32)
198
#define	DVA_GET_VDEV(dva)	BF64_GET((dva)->dva_word[0], 32, 32)
196
#define	DVA_SET_VDEV(dva, x)	BF64_SET((dva)->dva_word[0], 32, 32, x)
199
#define	DVA_SET_VDEV(dva, x)	BF64_SET((dva)->dva_word[0], 32, 32, x)
197
200
198
#define	DVA_GET_GANG(dva)	BF64_GET((dva)->dva_word[1], 63, 1)
201
#define	DVA_GET_OFFSET(dva, e)	\
202
	BF64_GET_SB((grub_zfs_to_cpu64 ((dva)->dva_word[1], (e))), 0, 63, \
203
			SPA_MINBLOCKSHIFT, 0)
204
#define	DVA_SET_OFFSET(dva, x)	\
205
	BF64_SET_SB((dva)->dva_word[1], 0, 63, SPA_MINBLOCKSHIFT, 0, x)
206
207
#define	DVA_GET_GANG(dva, e)	\
208
	BF64_GET((grub_zfs_to_cpu64 ((dva)->dva_word[1], (e))), 62, 1)
199
#define	DVA_SET_GANG(dva, x)	BF64_SET((dva)->dva_word[1], 63, 1, x)
209
#define	DVA_SET_GANG(dva, x)	BF64_SET((dva)->dva_word[1], 63, 1, x)
200
210
201
#define	BP_GET_LSIZE(bp)	\
211
#define	BP_GET_LSIZE(bp, e)	\
202
	BF64_GET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1)
212
	(BP_IS_HOLE(bp, e) ? 0 : \
213
	BF64_GET_SB((grub_zfs_to_cpu64((bp)->blk_prop, e)), 0, SPA_LSIZEBITS, \
214
			SPA_MINBLOCKSHIFT, 1))
203
#define	BP_SET_LSIZE(bp, x)	\
215
#define	BP_SET_LSIZE(bp, x)	\
204
	BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x)
216
	BF64_SET_SB((bp)->blk_prop, 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1, x)
217
218
#define	BP_GET_PSIZE(bp, e)	\
219
	BF64_GET_SB((grub_zfs_to_cpu64((bp)->blk_prop, e)), 16, SPA_PSIZEBITS, \
220
			SPA_MINBLOCKSHIFT, 1)
221
#define	BP_SET_PSIZE(bp, x)	\
222
	BF64_SET_SB((bp)->blk_prop, 16, SPA_PSIZEBITS, SPA_MINBLOCKSHIFT, 1, x)
223
224
#define	BP_GET_COMPRESS(bp, e)	\
225
	BF64_GET(grub_zfs_to_cpu64((bp)->blk_prop, e), 32, 7)
226
#define	BP_SET_COMPRESS(bp, x)		BF64_SET((bp)->blk_prop, 32, 7, x)
205
227
206
#define	BP_GET_COMPRESS(bp)		BF64_GET((bp)->blk_prop, 32, 8)
228
#define	BP_IS_EMBEDDED(bp, e)	\
207
#define	BP_SET_COMPRESS(bp, x)		BF64_SET((bp)->blk_prop, 32, 8, x)
229
	BF64_GET(grub_zfs_to_cpu64((bp)->blk_prop, e), 39, 1)
208
230
209
#define	BP_GET_CHECKSUM(bp)		BF64_GET((bp)->blk_prop, 40, 8)
231
#define	BP_GET_CHECKSUM(bp, e)	\
232
	BF64_GET(grub_zfs_to_cpu64((bp)->blk_prop, e), 40, 8)
210
#define	BP_SET_CHECKSUM(bp, x)		BF64_SET((bp)->blk_prop, 40, 8, x)
233
#define	BP_SET_CHECKSUM(bp, x)		BF64_SET((bp)->blk_prop, 40, 8, x)
211
234
212
#define	BP_GET_TYPE(bp)			BF64_GET((bp)->blk_prop, 48, 8)
235
#define	BP_GET_TYPE(bp)			BF64_GET((bp)->blk_prop, 48, 8)
Lines 278-285 Link Here
278
}
301
}
279
302
280
#define	BP_IDENTITY(bp)		(&(bp)->blk_dva[0])
303
#define	BP_IDENTITY(bp)		(&(bp)->blk_dva[0])
281
#define	BP_IS_GANG(bp)		DVA_GET_GANG(BP_IDENTITY(bp))
304
#define	BP_IS_GANG(bp, e)		\
282
#define	BP_IS_HOLE(bp)		((bp)->blk_birth == 0)
305
	((BP_IS_EMBEDDED((bp), (e))) ? B_FALSE : \
306
	 (DVA_GET_GANG((BP_IDENTITY(bp)),(e))))
307
#define	DVA_IS_EMPTY(dva)	\
308
	((dva)->dva_word[0] == 0ULL && \
309
	(dva)->dva_word[1] == 0ULL)
310
311
#define	BP_IS_HOLE(bp, e)		\
312
	(!BP_IS_EMBEDDED(bp, e) && DVA_IS_EMPTY(BP_IDENTITY(bp)))
283
313
284
/* BP_IS_RAIDZ(bp) assumes no block compression */
314
/* BP_IS_RAIDZ(bp) assumes no block compression */
285
#define	BP_IS_RAIDZ(bp)		(DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \
315
#define	BP_IS_RAIDZ(bp)		(DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \
Lines 302-307 Link Here
302
	ZIO_SET_CHECKSUM(&(bp)->blk_cksum, 0, 0, 0, 0);	\
332
	ZIO_SET_CHECKSUM(&(bp)->blk_cksum, 0, 0, 0, 0);	\
303
}
333
}
304
334
335
#define	BPE_GET_ETYPE(bp, e)	BP_GET_CHECKSUM(bp, e)
336
#define	BPE_GET_LSIZE(bp, e)	\
337
	BF64_GET_SB((grub_zfs_to_cpu64 ((bp)->blk_prop, e)), 0, 25, 0, 1)
338
#define	BPE_GET_PSIZE(bp, e)	\
339
	BF64_GET_SB((grub_zfs_to_cpu64 ((bp)->blk_prop, e)), 25, 7, 0, 1)
340
341
typedef enum bp_embedded_type {
342
	BP_EMBEDDED_TYPE_DATA,
343
	NUM_BP_EMBEDDED_TYPES
344
} bp_embedded_type_t;
345
346
#define	BPE_NUM_WORDS	14
347
#define	BPE_PAYLOAD_SIZE (BPE_NUM_WORDS * sizeof (grub_uint64_t))
348
#define	BPE_IS_PAYLOADWORD(bp, wp) \
349
	((wp) != &(bp)->blk_prop && (wp) != &(bp)->blk_birth)
350
305
#define	BP_SPRINTF_LEN	320
351
#define	BP_SPRINTF_LEN	320
306
352
307
#endif	/* ! GRUB_ZFS_SPA_HEADER */
353
#endif	/* ! GRUB_ZFS_SPA_HEADER */
(-)grub-2.02~beta2_/include/grub/zfs/uberblock_impl.h (-14 / +14 lines)
Lines 1-6 Link Here
1
/*
1
/*
2
 *  GRUB  --  GRand Unified Bootloader
2
 *  GRUB  --  GRand Unified Bootloader
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
4
 *  Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
4
 *
5
 *
5
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  it under the terms of the GNU General Public License as published by
Lines 15-24 Link Here
15
 *  You should have received a copy of the GNU General Public License
16
 *  You should have received a copy of the GNU General Public License
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
 */
18
/*
19
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
20
 * Use is subject to license terms.
21
 */
22
19
23
#ifndef _SYS_UBERBLOCK_IMPL_H
20
#ifndef _SYS_UBERBLOCK_IMPL_H
24
#define	_SYS_UBERBLOCK_IMPL_H
21
#define	_SYS_UBERBLOCK_IMPL_H
Lines 43-60 Link Here
43
	grub_uint64_t	ub_guid_sum;	/* sum of all vdev guids	*/
40
	grub_uint64_t	ub_guid_sum;	/* sum of all vdev guids	*/
44
	grub_uint64_t	ub_timestamp;	/* UTC time of last sync	*/
41
	grub_uint64_t	ub_timestamp;	/* UTC time of last sync	*/
45
	blkptr_t	ub_rootbp;	/* MOS objset_phys_t		*/
42
	blkptr_t	ub_rootbp;	/* MOS objset_phys_t		*/
43
44
	/* highest SPA_VERSION supported by software that wrote this txg */
45
	grub_uint64_t	ub_software_version;
46
} uberblock_t;
46
} uberblock_t;
47
47
48
#define	ZFS_MAX(x,y)		(((x) > (y)) ? (x) : (y))
49
#define	ZFS_MIN(x,y)		(((x) < (y)) ? (x) : (y))
50
#define	MAX_UBERBLOCK_SHIFT	(13)
48
#define	UBERBLOCK_SIZE		(1ULL << UBERBLOCK_SHIFT)
51
#define	UBERBLOCK_SIZE		(1ULL << UBERBLOCK_SHIFT)
49
#define	VDEV_UBERBLOCK_SHIFT	UBERBLOCK_SHIFT
52
#define	VDEV_UBERBLOCK_SHIFT(a)	\
50
53
	(ZFS_MIN((ZFS_MAX(UBERBLOCK_SHIFT, (a))), MAX_UBERBLOCK_SHIFT))
51
/* XXX Uberblock_phys_t is no longer in the kernel zfs */
54
#define	VDEV_UBERBLOCK_COUNT(a)	\
52
typedef struct uberblock_phys {
55
	(VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT(a))
53
	uberblock_t	ubp_uberblock;
56
#define	VDEV_UBERBLOCK_OFFSET(a, n)	\
54
	char		ubp_pad[UBERBLOCK_SIZE - sizeof (uberblock_t) -
57
	offsetof(vdev_label_t, vl_uberblock[(n) << VDEV_UBERBLOCK_SHIFT(a)])
55
				sizeof (zio_eck_t)];
58
#define	VDEV_UBERBLOCK_SIZE(a)	(1ULL << VDEV_UBERBLOCK_SHIFT(a))
56
	zio_eck_t	ubp_zec;
57
} uberblock_phys_t;
58
59
59
60
#endif	/* _SYS_UBERBLOCK_IMPL_H */
60
#endif	/* _SYS_UBERBLOCK_IMPL_H */
(-)grub-2.02~beta2_/include/grub/zfs/vdev_impl.h (+2 lines)
Lines 23-28 Link Here
23
#ifndef _SYS_VDEV_IMPL_H
23
#ifndef _SYS_VDEV_IMPL_H
24
#define	_SYS_VDEV_IMPL_H
24
#define	_SYS_VDEV_IMPL_H
25
25
26
#define	VDEV_RAIDZ_MAXPARITY	3
27
26
#define	VDEV_SKIP_SIZE		(8 << 10)
28
#define	VDEV_SKIP_SIZE		(8 << 10)
27
#define	VDEV_BOOT_HEADER_SIZE	(8 << 10)
29
#define	VDEV_BOOT_HEADER_SIZE	(8 << 10)
28
#define	VDEV_PHYS_SIZE		(112 << 10)
30
#define	VDEV_PHYS_SIZE		(112 << 10)
(-)grub-2.02~beta2_/include/grub/zfs/zap_impl.h (-4 / +3 lines)
Lines 1-6 Link Here
1
/*
1
/*
2
 *  GRUB  --  GRand Unified Bootloader
2
 *  GRUB  --  GRand Unified Bootloader
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
4
 *  Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
4
 *
5
 *
5
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  it under the terms of the GNU General Public License as published by
Lines 15-24 Link Here
15
 *  You should have received a copy of the GNU General Public License
16
 *  You should have received a copy of the GNU General Public License
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
 */
18
/*
19
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
20
 * Use is subject to license terms.
21
 */
22
19
23
#ifndef	_SYS_ZAP_IMPL_H
20
#ifndef	_SYS_ZAP_IMPL_H
24
#define	_SYS_ZAP_IMPL_H
21
#define	_SYS_ZAP_IMPL_H
Lines 28-33 Link Here
28
#define	ZAP_HASHBITS		28
25
#define	ZAP_HASHBITS		28
29
#define	MZAP_ENT_LEN		64
26
#define	MZAP_ENT_LEN		64
30
#define	MZAP_NAME_LEN		(MZAP_ENT_LEN - 8 - 4 - 2)
27
#define	MZAP_NAME_LEN		(MZAP_ENT_LEN - 8 - 4 - 2)
28
#define	MZAP_MAX_BLKSHIFT	SPA_128KBLOCKSHIFT
29
#define	MZAP_MAX_BLKSZ		(1 << MZAP_MAX_BLKSHIFT)
31
30
32
typedef struct mzap_ent_phys {
31
typedef struct mzap_ent_phys {
33
	grub_uint64_t mze_value;
32
	grub_uint64_t mze_value;
(-)grub-2.02~beta2_/include/grub/zfs/zfs.h (-7 / +9 lines)
Lines 1-6 Link Here
1
/*
1
/*
2
 *  GRUB  --  GRand Unified Bootloader
2
 *  GRUB  --  GRand Unified Bootloader
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009  Free Software Foundation, Inc.
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009  Free Software Foundation, Inc.
4
 *  Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
4
 *
5
 *
5
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  it under the terms of the GNU General Public License as published by
Lines 15-23 Link Here
15
 *  You should have received a copy of the GNU General Public License
16
 *  You should have received a copy of the GNU General Public License
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
 */
18
 /*
19
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
20
  */
21
19
22
#ifndef	GRUB_ZFS_HEADER
20
#ifndef	GRUB_ZFS_HEADER
23
#define	GRUB_ZFS_HEADER 1
21
#define	GRUB_ZFS_HEADER 1
Lines 38-47 Link Here
38
 */
36
 */
39
#define	SPA_VERSION_INITIAL		1ULL
37
#define	SPA_VERSION_INITIAL		1ULL
40
#define	SPA_VERSION_BEFORE_FEATURES	33ULL
38
#define	SPA_VERSION_BEFORE_FEATURES	33ULL
39
#define	SPA_VERSION_ORACLE		35ULL
40
#define	SPA_VERSION			5000ULL
41
#define	SPA_VERSION_FEATURES		5000ULL
41
#define	SPA_VERSION_FEATURES		5000ULL
42
#define	SPA_VERSION_IS_SUPPORTED(v) \
42
#define	SPA_VERSION_IS_SUPPORTED(v) \
43
	(((v) >= SPA_VERSION_INITIAL && (v) <= SPA_VERSION_BEFORE_FEATURES) || \
43
	(((v) >= SPA_VERSION_INITIAL && (v) <= SPA_VERSION_ORACLE) || \
44
	((v) == SPA_VERSION_FEATURES))
44
	((v) >= SPA_VERSION_FEATURES && (v) == SPA_VERSION))
45
/*
45
/*
46
 * The following are configuration names used in the nvlist describing a pool's
46
 * The following are configuration names used in the nvlist describing a pool's
47
 * configuration.
47
 * configuration.
Lines 124-139 Link Here
124
grub_err_t grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist);
124
grub_err_t grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist);
125
grub_err_t grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename,
125
grub_err_t grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename,
126
			       grub_uint64_t *mdnobj);
126
			       grub_uint64_t *mdnobj);
127
127
grub_err_t grub_zfs_defaultbootfsobj (grub_device_t dev, grub_uint64_t *mdnobj);
128
grub_err_t grub_zfs_defaultbootfsname (grub_device_t dev, char **bootfsname);
128
char *grub_zfs_nvlist_lookup_string (const char *nvlist, const char *name);
129
char *grub_zfs_nvlist_lookup_string (const char *nvlist, const char *name);
129
char *grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name);
130
char *grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name);
130
int grub_zfs_nvlist_lookup_uint64 (const char *nvlist, const char *name,
131
int grub_zfs_nvlist_lookup_uint64 (const char *nvlist, const char *name,
131
				   grub_uint64_t *out);
132
				   grub_uint64_t *out);
132
char *grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist,
133
char *grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist,
133
					   const char *name,
134
					   const char *name,
134
					   grub_size_t array_index);
135
					   grub_size_t index);
135
int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (const char *nvlist,
136
int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (const char *nvlist,
136
						  const char *name);
137
						  const char *name);
138
int grub_zfs_vdev_validate (const char *nv);
137
grub_err_t
139
grub_err_t
138
grub_zfs_add_key (grub_uint8_t *key_in,
140
grub_zfs_add_key (grub_uint8_t *key_in,
139
		  grub_size_t keylen,
141
		  grub_size_t keylen,
(-)grub-2.02~beta2_/include/grub/zfs/zfs_znode.h (-5 / +2 lines)
Lines 1-6 Link Here
1
/*
1
/*
2
 *  GRUB  --  GRand Unified Bootloader
2
 *  GRUB  --  GRand Unified Bootloader
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
4
 *  Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
4
 *
5
 *
5
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  GRUB is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  it under the terms of the GNU General Public License as published by
Lines 15-24 Link Here
15
 *  You should have received a copy of the GNU General Public License
16
 *  You should have received a copy of the GNU General Public License
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
 */
18
/*
19
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
20
 * Use is subject to license terms.
21
 */
22
19
23
#ifndef	_SYS_FS_ZFS_ZNODE_H
20
#ifndef	_SYS_FS_ZFS_ZNODE_H
24
#define	_SYS_FS_ZFS_ZNODE_H
21
#define	_SYS_FS_ZFS_ZNODE_H
Lines 30-36 Link Here
30
#define	ZPL_VERSION_STR		"VERSION"
27
#define	ZPL_VERSION_STR		"VERSION"
31
#define	ZFS_SA_ATTRS		"SA_ATTRS"
28
#define	ZFS_SA_ATTRS		"SA_ATTRS"
32
29
33
#define	ZPL_VERSION		5ULL
30
#define	ZPL_VERSION		6ULL
34
31
35
#define	ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
32
#define	ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
36
33

Return to bug 549274