Fix RAIDZ(2) for >= 5 devices.
* grub-core/fs/zfs/zfs.c (read_device): Fix length formula. Remove asize argument. All users updated.
This commit is contained in:
parent
ce8ca56ed9
commit
aca5aefc7c
2 changed files with 31 additions and 18 deletions
|
@ -1,3 +1,10 @@
|
|||
2011-11-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Fix RAIDZ(2) for >= 5 devices.
|
||||
|
||||
* grub-core/fs/zfs/zfs.c (read_device): Fix length formula. Remove
|
||||
asize argument. All users updated.
|
||||
|
||||
2011-11-01 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Fix RAIDZ(2).
|
||||
|
|
|
@ -852,7 +852,7 @@ scan_devices (struct grub_zfs_data *data)
|
|||
|
||||
static grub_err_t
|
||||
read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
|
||||
grub_uint32_t asize, grub_size_t len, void *buf)
|
||||
grub_size_t len, void *buf)
|
||||
{
|
||||
switch (desc->type)
|
||||
{
|
||||
|
@ -876,7 +876,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
|
|||
"non-positive number of mirror children");
|
||||
for (i = 0; i < desc->n_children; i++)
|
||||
{
|
||||
err = read_device (offset, &desc->children[i], asize,
|
||||
err = read_device (offset, &desc->children[i],
|
||||
len, buf);
|
||||
if (!err)
|
||||
break;
|
||||
|
@ -893,28 +893,32 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
|
|||
grub_uint64_t redundancy_strip2 = 0;
|
||||
grub_uint32_t s;
|
||||
|
||||
/* (4,1) -> 2, (3,1) -> 1 */
|
||||
if (desc->nparity == 1)
|
||||
s = asize + desc->n_children - 2;
|
||||
else
|
||||
s = asize + desc->n_children - 3;
|
||||
if (desc->nparity < 1 || desc->nparity > 2)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"raidz%d is not supported", desc->nparity);
|
||||
|
||||
s = (((len + (1 << desc->ashift) - 1) >> desc->ashift)
|
||||
+ (desc->n_children - desc->nparity) - 1);
|
||||
|
||||
high = grub_divmod64 ((offset >> desc->ashift),
|
||||
desc->n_children, &m);
|
||||
|
||||
if (desc->nparity == 1)
|
||||
|
||||
switch (desc->nparity)
|
||||
{
|
||||
case 1:
|
||||
redundancy_strip = m;
|
||||
redundancy_strip += ((offset >> (desc->ashift + 11)) & 1);
|
||||
if (redundancy_strip == desc->n_children)
|
||||
redundancy_strip = 0;
|
||||
redundancy_strip2 = redundancy_strip;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case 2:
|
||||
redundancy_strip = m;
|
||||
redundancy_strip2 = m + 1;
|
||||
if (redundancy_strip2 == desc->n_children)
|
||||
redundancy_strip2 = 0;
|
||||
break;
|
||||
}
|
||||
grub_dprintf ("zfs", "rs = %x, %llx\n",
|
||||
(int) redundancy_strip,
|
||||
|
@ -924,8 +928,8 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
|
|||
grub_size_t csize;
|
||||
grub_uint32_t bsize;
|
||||
grub_err_t err;
|
||||
bsize = s / desc->n_children;
|
||||
|
||||
bsize = s / (desc->n_children - desc->nparity);
|
||||
|
||||
while (1)
|
||||
{
|
||||
high = grub_divmod64 ((offset >> desc->ashift) + c,
|
||||
|
@ -934,21 +938,24 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
|
|||
break;
|
||||
c++;
|
||||
}
|
||||
|
||||
csize = bsize << desc->ashift;
|
||||
if (csize > len)
|
||||
csize = len;
|
||||
|
||||
grub_dprintf ("zfs", "RAIDZ mapping 0x%" PRIxGRUB_UINT64_T
|
||||
"+%u (%d, %d) -> (0x%" PRIxGRUB_UINT64_T ", 0x%"
|
||||
"+%u (%" PRIxGRUB_SIZE ", %" PRIxGRUB_UINT32_T
|
||||
") -> (0x%" PRIxGRUB_UINT64_T ", 0x%"
|
||||
PRIxGRUB_UINT64_T ")\n",
|
||||
offset >> desc->ashift, c, asize, bsize, high,
|
||||
offset >> desc->ashift, c, len, bsize, high,
|
||||
devn);
|
||||
err = read_device ((high << desc->ashift)
|
||||
| (offset & ((1 << desc->ashift) - 1)),
|
||||
&desc->children[devn],
|
||||
bsize, csize, buf);
|
||||
csize, buf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
c++;
|
||||
s--;
|
||||
buf = (char *) buf + csize;
|
||||
|
@ -976,8 +983,7 @@ read_dva (const dva_t *dva,
|
|||
for (i = 0; i < data->n_devices_attached; i++)
|
||||
if (data->devices_attached[i].id == DVA_GET_VDEV (dva))
|
||||
{
|
||||
err = read_device (offset, &data->devices_attached[i],
|
||||
dva->dva_word[0] & 0xffffff, len, buf);
|
||||
err = read_device (offset, &data->devices_attached[i], len, buf);
|
||||
if (!err)
|
||||
return GRUB_ERR_NONE;
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue