Author: tsoome
Date: Thu Jul  9 13:19:00 2020
New Revision: 363042
URL: https://svnweb.freebsd.org/changeset/base/363042

Log:
  loader: setting vdev size based on label asize is not working
  
  Because we need to read asize from vdev_tree. We also need to consider
  different vdev type difference.
  
  Reviewed by:  allanjude
  Sponsored by: Netflix, Klara Inc.
  Differential Revision:        https://reviews.freebsd.org/D25586

Modified:
  head/stand/libsa/zfs/zfsimpl.c

Modified: head/stand/libsa/zfs/zfsimpl.c
==============================================================================
--- head/stand/libsa/zfs/zfsimpl.c      Thu Jul  9 11:06:29 2020        
(r363041)
+++ head/stand/libsa/zfs/zfsimpl.c      Thu Jul  9 13:19:00 2020        
(r363042)
@@ -1586,6 +1586,57 @@ vdev_label_read(vdev_t *vd, int l, void *buf, uint64_t
        return (vdev_read_phys(vd, &bp, buf, off, size));
 }
 
+static uint64_t
+vdev_get_label_asize(nvlist_t *nvl)
+{
+       nvlist_t *vdevs;
+       uint64_t asize;
+       const char *type;
+       int len;
+
+       asize = 0;
+       /* Get vdev tree */
+       if (nvlist_find(nvl, ZPOOL_CONFIG_VDEV_TREE, DATA_TYPE_NVLIST,
+           NULL, &vdevs, NULL) != 0)
+               return (asize);
+
+       /*
+        * Get vdev type. We will calculate asize for raidz, mirror and disk.
+        * For raidz, the asize is raw size of all children.
+        */
+       if (nvlist_find(vdevs, ZPOOL_CONFIG_TYPE, DATA_TYPE_STRING,
+           NULL, &type, &len) != 0)
+               goto done;
+
+       if (memcmp(type, VDEV_TYPE_MIRROR, len) != 0 &&
+           memcmp(type, VDEV_TYPE_DISK, len) != 0 &&
+           memcmp(type, VDEV_TYPE_RAIDZ, len) != 0)
+               goto done;
+
+       if (nvlist_find(vdevs, ZPOOL_CONFIG_ASIZE, DATA_TYPE_UINT64,
+           NULL, &asize, NULL) != 0)
+               goto done;
+
+       if (memcmp(type, VDEV_TYPE_RAIDZ, len) == 0) {
+               nvlist_t *kids;
+               int nkids;
+
+               if (nvlist_find(vdevs, ZPOOL_CONFIG_CHILDREN,
+                   DATA_TYPE_NVLIST_ARRAY, &nkids, &kids, NULL) != 0) {
+                       asize = 0;
+                       goto done;
+               }
+
+               asize /= nkids;
+               nvlist_destroy(kids);
+       }
+
+       asize += VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE;
+done:
+       nvlist_destroy(vdevs);
+       return (asize);
+}
+
 static nvlist_t *
 vdev_label_read_config(vdev_t *vd, uint64_t txg)
 {
@@ -1631,10 +1682,9 @@ vdev_label_read_config(vdev_t *vd, uint64_t txg)
                         * Use asize from pool config. We need this
                         * because we can get bad value from BIOS.
                         */
-                       if (nvlist_find(nvl, ZPOOL_CONFIG_ASIZE,
-                           DATA_TYPE_UINT64, NULL, &asize, NULL) == 0) {
-                               vd->v_psize = asize +
-                                   VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE;
+                       asize = vdev_get_label_asize(nvl);
+                       if (asize != 0) {
+                               vd->v_psize = asize;
                        }
                }
                nvlist_destroy(tmp);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to