]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Fix RAIDZ(2) for >= 5 devices.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 2 Nov 2011 19:48:04 +0000 (20:48 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 2 Nov 2011 19:48:04 +0000 (20:48 +0100)
* grub-core/fs/zfs/zfs.c (read_device): Fix length formula. Remove
asize argument. All users updated.

ChangeLog
grub-core/fs/zfs/zfs.c

index e112868f01484a14fc56aa15ce8ca44ba1d71a64..08bad81c6914f5820595c495549ac8219f0e3879 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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).
index c7fd130188e31c4cd3df100ee8d95b6050e185cf..1c9b240ab85d88248dfa9bc5dd20eb2f09e0f388 100644 (file)
@@ -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;