3521: Support raidz3

This commit is contained in:
Robert Millan 2011-11-09 19:08:08 +00:00
parent 251323a490
commit f86cfb5021

View File

@ -9,6 +9,7 @@ Revisions:
3518: Rewrite RAIDZ part based on reverse engineering 3518: Rewrite RAIDZ part based on reverse engineering
3519: Fix RAIDZ(2) for >= 5 devices 3519: Fix RAIDZ(2) for >= 5 devices
3520: Add ability to sustain a single drive failure on both raidz and raidz2 3520: Add ability to sustain a single drive failure on both raidz and raidz2
3521: Support raidz3
--- a/grub-core/fs/zfs/zfs.c --- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c
@ -143,7 +144,7 @@ Revisions:
{ {
grub_dprintf ("zfs", "dva=%llx, %llx\n", grub_dprintf ("zfs", "dva=%llx, %llx\n",
(unsigned long long) dva->dva_word[0], (unsigned long long) dva->dva_word[0],
@@ -401,6 +445,589 @@ @@ -401,6 +445,590 @@
endian) << SPA_MINBLOCKSHIFT; endian) << SPA_MINBLOCKSHIFT;
} }
@ -606,7 +607,7 @@ Revisions:
+ void *recovery_buf = NULL; + void *recovery_buf = NULL;
+ grub_size_t recovery_len = 0; + grub_size_t recovery_len = 0;
+ +
+ if (desc->nparity < 1 || desc->nparity > 2) + if (desc->nparity < 1 || desc->nparity > 3)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "raidz%d is not supported", desc->nparity); + "raidz%d is not supported", desc->nparity);
+ +
@ -616,9 +617,10 @@ Revisions:
+ +
+ high = grub_divmod64_full ((offset >> desc->ashift), + high = grub_divmod64_full ((offset >> desc->ashift),
+ desc->n_children, &m); + desc->n_children, &m);
+
+ if (desc->nparity == 2) + if (desc->nparity == 2)
+ c = 2; + c = 2;
+ if (desc->nparity == 3)
+ c = 3;
+ while (len > 0) + while (len > 0)
+ { + {
+ grub_size_t csize; + grub_size_t csize;
@ -733,7 +735,7 @@ Revisions:
/* /*
* Read a block of data based on the gang block address dva, * Read a block of data based on the gang block address dva,
@@ -412,7 +1039,6 @@ @@ -412,7 +1040,6 @@
struct grub_zfs_data *data) struct grub_zfs_data *data)
{ {
zio_gbh_phys_t *zio_gb; zio_gbh_phys_t *zio_gb;
@ -741,7 +743,7 @@ Revisions:
unsigned i; unsigned i;
grub_err_t err; grub_err_t err;
zio_cksum_t zc; zio_cksum_t zc;
@@ -424,13 +1050,8 @@ @@ -424,13 +1051,8 @@
return grub_errno; return grub_errno;
grub_dprintf ("zfs", endian == LITTLE_ENDIAN ? "little-endian gang\n" grub_dprintf ("zfs", endian == LITTLE_ENDIAN ? "little-endian gang\n"
:"big-endian gang\n"); :"big-endian gang\n");
@ -756,7 +758,7 @@ Revisions:
if (err) if (err)
{ {
grub_free (zio_gb); grub_free (zio_gb);
@@ -483,20 +1104,13 @@ @@ -483,20 +1105,13 @@
/* pick a good dva from the block pointer */ /* pick a good dva from the block pointer */
for (i = 0; i < SPA_DVAS_PER_BP; i++) for (i = 0; i < SPA_DVAS_PER_BP; i++)
{ {
@ -778,7 +780,7 @@ Revisions:
if (!err) if (!err)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@@ -527,7 +1141,7 @@ @@ -527,7 +1142,7 @@
*buf = NULL; *buf = NULL;
checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
@ -787,7 +789,7 @@ Revisions:
lsize = (BP_IS_HOLE(bp) ? 0 : lsize = (BP_IS_HOLE(bp) ? 0 :
(((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
<< SPA_MINBLOCKSHIFT)); << SPA_MINBLOCKSHIFT));
@@ -602,7 +1216,8 @@ @@ -602,7 +1217,8 @@
dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf,
grub_zfs_endian_t *endian_out, struct grub_zfs_data *data) grub_zfs_endian_t *endian_out, struct grub_zfs_data *data)
{ {
@ -797,7 +799,7 @@ Revisions:
blkptr_t *bp_array = dn->dn.dn_blkptr; blkptr_t *bp_array = dn->dn.dn_blkptr;
int epbs = dn->dn.dn_indblkshift - SPA_BLKPTRSHIFT; int epbs = dn->dn.dn_indblkshift - SPA_BLKPTRSHIFT;
blkptr_t *bp; blkptr_t *bp;
@@ -816,7 +1431,7 @@ @@ -816,7 +1432,7 @@
return grub_error (GRUB_ERR_BAD_FS, "invalid leaf magic"); return grub_error (GRUB_ERR_BAD_FS, "invalid leaf magic");
for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h)], endian); for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h)], endian);
@ -806,7 +808,7 @@ Revisions:
{ {
if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
@@ -840,7 +1455,8 @@ @@ -840,7 +1456,8 @@
{ {
struct zap_leaf_array *la; struct zap_leaf_array *la;
@ -816,7 +818,7 @@ Revisions:
return grub_error (GRUB_ERR_BAD_FS, "invalid leaf chunk entry"); return grub_error (GRUB_ERR_BAD_FS, "invalid leaf chunk entry");
/* get the uint64_t property value */ /* get the uint64_t property value */
@@ -858,9 +1474,9 @@ @@ -858,9 +1475,9 @@
/* Verify if this is a fat zap header block */ /* Verify if this is a fat zap header block */
static grub_err_t static grub_err_t
@ -828,7 +830,7 @@ Revisions:
return grub_error (GRUB_ERR_BAD_FS, "bad ZAP magic"); return grub_error (GRUB_ERR_BAD_FS, "bad ZAP magic");
if (zap->zap_flags != 0) if (zap->zap_flags != 0)
@@ -888,7 +1504,7 @@ @@ -888,7 +1505,7 @@
grub_err_t err; grub_err_t err;
grub_zfs_endian_t leafendian; grub_zfs_endian_t leafendian;
@ -837,7 +839,7 @@ Revisions:
if (err) if (err)
return err; return err;
@@ -899,7 +1515,7 @@ @@ -899,7 +1516,7 @@
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"external pointer tables not supported"); "external pointer tables not supported");
idx = ZAP_HASH_IDX (hash, zap->zap_ptrtbl.zt_shift); idx = ZAP_HASH_IDX (hash, zap->zap_ptrtbl.zt_shift);
@ -846,7 +848,7 @@ Revisions:
/* Get the leaf block */ /* Get the leaf block */
if ((1U << blksft) < sizeof (zap_leaf_phys_t)) if ((1U << blksft) < sizeof (zap_leaf_phys_t))
@@ -922,14 +1538,14 @@ @@ -922,14 +1539,14 @@
{ {
zap_leaf_phys_t *l; zap_leaf_phys_t *l;
void *l_in; void *l_in;
@ -863,7 +865,7 @@ Revisions:
return 0; return 0;
/* get block id from index */ /* get block id from index */
@@ -945,9 +1561,17 @@ @@ -945,9 +1562,17 @@
grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small"); grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small");
return 0; return 0;
} }
@ -883,7 +885,7 @@ Revisions:
err = dmu_read (zap_dnode, blkid, &l_in, &endian, data); err = dmu_read (zap_dnode, blkid, &l_in, &endian, data);
l = l_in; l = l_in;
@@ -983,8 +1607,11 @@ @@ -983,8 +1608,11 @@
buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian) buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
+ 1); + 1);
@ -897,7 +899,7 @@ Revisions:
{ {
grub_free (buf); grub_free (buf);
continue; continue;
@@ -996,7 +1623,9 @@ @@ -996,7 +1624,9 @@
continue; continue;
/* get the uint64_t property value */ /* get the uint64_t property value */
@ -908,7 +910,7 @@ Revisions:
val = grub_be_to_cpu64 (la->la_array64); val = grub_be_to_cpu64 (la->la_array64);
if (hook (buf, val)) if (hook (buf, val))
return 1; return 1;
@@ -1074,7 +1703,7 @@ @@ -1074,7 +1704,7 @@
return 0; return 0;
block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian); block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
@ -917,7 +919,7 @@ Revisions:
if (block_type == ZBT_MICRO) if (block_type == ZBT_MICRO)
{ {
@@ -1291,22 +1920,54 @@ @@ -1291,22 +1921,54 @@
break; break;
*path = ch; *path = ch;
@ -981,7 +983,7 @@ Revisions:
grub_memcpy (path + grub_strlen (path), oldpath, grub_memcpy (path + grub_strlen (path), oldpath,
grub_strlen (oldpath) + 1); grub_strlen (oldpath) + 1);
@@ -1324,7 +1985,62 @@ @@ -1324,7 +1986,62 @@
grub_free (dn_new); grub_free (dn_new);
} }
} }
@ -1045,7 +1047,7 @@ Revisions:
} }
if (!err) if (!err)
@@ -1625,11 +2341,12 @@ @@ -1625,11 +2342,12 @@
*/ */
static int static int
@ -1060,7 +1062,7 @@ Revisions:
/* Verify if the 1st and 2nd byte in the nvlist are valid. */ /* Verify if the 1st and 2nd byte in the nvlist are valid. */
/* NOTE: independently of what endianness header announces all /* NOTE: independently of what endianness header announces all
@@ -1671,7 +2388,7 @@ @@ -1671,7 +2389,7 @@
if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype) if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype)
{ {
@ -1069,7 +1071,7 @@ Revisions:
*size_out = encode_size; *size_out = encode_size;
if (nelm_out) if (nelm_out)
*nelm_out = nelm; *nelm_out = nelm;
@@ -1684,7 +2401,8 @@ @@ -1684,7 +2402,8 @@
} }
int int
@ -1079,7 +1081,7 @@ Revisions:
{ {
char *nvpair; char *nvpair;
grub_size_t size; grub_size_t size;
@@ -1704,7 +2422,7 @@ @@ -1704,7 +2423,7 @@
} }
char * char *
@ -1088,7 +1090,7 @@ Revisions:
{ {
char *nvpair; char *nvpair;
char *ret; char *ret;
@@ -1732,7 +2450,7 @@ @@ -1732,7 +2451,7 @@
} }
char * char *
@ -1097,7 +1099,7 @@ Revisions:
{ {
char *nvpair; char *nvpair;
char *ret; char *ret;
@@ -1753,199 +2471,114 @@ @@ -1753,199 +2472,114 @@
} }
int int
@ -1380,7 +1382,7 @@ Revisions:
grub_free (data->dnode_buf); grub_free (data->dnode_buf);
grub_free (data->dnode_mdn); grub_free (data->dnode_mdn);
grub_free (data->file_buf); grub_free (data->file_buf);
@@ -1961,13 +2594,11 @@ @@ -1961,13 +2595,11 @@
zfs_mount (grub_device_t dev) zfs_mount (grub_device_t dev)
{ {
struct grub_zfs_data *data = 0; struct grub_zfs_data *data = 0;
@ -1398,7 +1400,7 @@ Revisions:
if (! dev->disk) if (! dev->disk)
{ {
@@ -1975,119 +2606,56 @@ @@ -1975,119 +2607,56 @@
return 0; return 0;
} }
@ -1547,7 +1549,7 @@ Revisions:
} }
grub_err_t grub_err_t
@@ -2099,7 +2667,7 @@ @@ -2099,7 +2668,7 @@
zfs = zfs_mount (dev); zfs = zfs_mount (dev);
if (!zfs) if (!zfs)
return grub_errno; return grub_errno;
@ -1556,7 +1558,7 @@ Revisions:
zfs_unmount (zfs); zfs_unmount (zfs);
return err; return err;
} }
@@ -2115,7 +2683,7 @@ @@ -2115,7 +2684,7 @@
if (! data) if (! data)
return grub_errno; return grub_errno;
@ -1565,7 +1567,7 @@ Revisions:
if (err) if (err)
{ {
zfs_unmount (data); zfs_unmount (data);
@@ -2131,11 +2699,7 @@ @@ -2131,11 +2700,7 @@
static grub_err_t static grub_err_t
zfs_uuid (grub_device_t device, char **uuid) zfs_uuid (grub_device_t device, char **uuid)
{ {
@ -1577,7 +1579,7 @@ Revisions:
*uuid = 0; *uuid = 0;
@@ -2143,24 +2707,36 @@ @@ -2143,24 +2708,36 @@
if (! data) if (! data)
return grub_errno; return grub_errno;
@ -1626,7 +1628,7 @@ Revisions:
/* /*
* zfs_open() locates a file in the rootpool by following the * zfs_open() locates a file in the rootpool by following the
* MOS and places the dnode of the file in the memory address DNODE. * MOS and places the dnode of the file in the memory address DNODE.
@@ -2227,12 +2803,14 @@ @@ -2227,12 +2804,14 @@
} }
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
@ -1643,7 +1645,7 @@ Revisions:
file->data = data; file->data = data;
file->offset = 0; file->offset = 0;
@@ -2248,7 +2826,7 @@ @@ -2248,7 +2827,7 @@
grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) grub_zfs_read (grub_file_t file, char *buf, grub_size_t len)
{ {
struct grub_zfs_data *data = (struct grub_zfs_data *) file->data; struct grub_zfs_data *data = (struct grub_zfs_data *) file->data;
@ -1652,7 +1654,7 @@ Revisions:
grub_size_t length; grub_size_t length;
grub_size_t read; grub_size_t read;
grub_err_t err; grub_err_t err;
@@ -2302,7 +2880,7 @@ @@ -2302,7 +2881,7 @@
data->file_start = blkid * blksz; data->file_start = blkid * blksz;
data->file_end = data->file_start + blksz; data->file_end = data->file_start + blksz;
@ -1661,7 +1663,7 @@ Revisions:
grub_memmove (buf, data->file_buf + file->offset + read grub_memmove (buf, data->file_buf + file->offset + read
- data->file_start, movesize); - data->file_start, movesize);
@@ -2391,8 +2969,39 @@ @@ -2391,8 +2970,39 @@
return; return;
} }
@ -1703,7 +1705,7 @@ Revisions:
return; return;
} }
@@ -2416,10 +3025,47 @@ @@ -2416,10 +3026,47 @@
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
dnode_get (&(data->mdn), val, 0, &dn, data); dnode_get (&(data->mdn), val, 0, &dn, data);
@ -1755,7 +1757,7 @@ Revisions:
(int)dn.dn.dn_type, (char *)name); (int)dn.dn.dn_type, (char *)name);
return hook (name, &info); return hook (name, &info);
} }
@@ -2532,12 +3178,13 @@ @@ -2532,12 +3179,13 @@
.close = grub_zfs_close, .close = grub_zfs_close,
.label = zfs_label, .label = zfs_label,
.uuid = zfs_uuid, .uuid = zfs_uuid,