]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/vdev_label.c
cstyle: Resolve C style issues
[mirror_zfs.git] / module / zfs / vdev_label.c
index 352b630fa2ecf6566ebe432741405196908f3505..d5af110a5f4dc50f2b662131203a628105c28690 100644 (file)
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 /*
@@ -218,28 +218,23 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
 
        VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_PUSHPAGE) == 0);
 
-       VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
-           vd->vdev_ops->vdev_op_type) == 0);
+       fnvlist_add_string(nv, ZPOOL_CONFIG_TYPE, vd->vdev_ops->vdev_op_type);
        if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)))
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_ID, vd->vdev_id)
-                   == 0);
-       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_GUID, vd->vdev_guid) == 0);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_ID, vd->vdev_id);
+       fnvlist_add_uint64(nv, ZPOOL_CONFIG_GUID, vd->vdev_guid);
 
        if (vd->vdev_path != NULL)
-               VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_PATH,
-                   vd->vdev_path) == 0);
+               fnvlist_add_string(nv, ZPOOL_CONFIG_PATH, vd->vdev_path);
 
        if (vd->vdev_devid != NULL)
-               VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_DEVID,
-                   vd->vdev_devid) == 0);
+               fnvlist_add_string(nv, ZPOOL_CONFIG_DEVID, vd->vdev_devid);
 
        if (vd->vdev_physpath != NULL)
-               VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_PHYS_PATH,
-                   vd->vdev_physpath) == 0);
+               fnvlist_add_string(nv, ZPOOL_CONFIG_PHYS_PATH,
+                   vd->vdev_physpath);
 
        if (vd->vdev_fru != NULL)
-               VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_FRU,
-                   vd->vdev_fru) == 0);
+               fnvlist_add_string(nv, ZPOOL_CONFIG_FRU, vd->vdev_fru);
 
        if (vd->vdev_nparity != 0) {
                ASSERT(strcmp(vd->vdev_ops->vdev_op_type,
@@ -260,59 +255,54 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
                 * that only support a single parity device -- older software
                 * will just ignore it.
                 */
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_NPARITY,
-                   vd->vdev_nparity) == 0);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_NPARITY, vd->vdev_nparity);
        }
 
        if (vd->vdev_wholedisk != -1ULL)
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
-                   vd->vdev_wholedisk) == 0);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
+                   vd->vdev_wholedisk);
 
        if (vd->vdev_not_present)
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1) == 0);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1);
 
        if (vd->vdev_isspare)
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 1) == 0);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 1);
 
        if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)) &&
            vd == vd->vdev_top) {
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY,
-                   vd->vdev_ms_array) == 0);
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_SHIFT,
-                   vd->vdev_ms_shift) == 0);
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_ASHIFT,
-                   vd->vdev_ashift) == 0);
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_ASIZE,
-                   vd->vdev_asize) == 0);
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_IS_LOG,
-                   vd->vdev_islog) == 0);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY,
+                   vd->vdev_ms_array);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_SHIFT,
+                   vd->vdev_ms_shift);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_ASHIFT, vd->vdev_ashift);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_ASIZE,
+                   vd->vdev_asize);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_LOG, vd->vdev_islog);
                if (vd->vdev_removing)
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVING,
-                           vd->vdev_removing) == 0);
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVING,
+                           vd->vdev_removing);
        }
 
        if (vd->vdev_dtl_smo.smo_object != 0)
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_DTL,
-                   vd->vdev_dtl_smo.smo_object) == 0);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_DTL,
+                   vd->vdev_dtl_smo.smo_object);
 
        if (vd->vdev_crtxg)
-               VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_CREATE_TXG,
-                   vd->vdev_crtxg) == 0);
+               fnvlist_add_uint64(nv, ZPOOL_CONFIG_CREATE_TXG, vd->vdev_crtxg);
 
        if (getstats) {
                vdev_stat_t vs;
                pool_scan_stat_t ps;
 
                vdev_get_stats(vd, &vs);
-               VERIFY(nvlist_add_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
-                   (uint64_t *)&vs, sizeof (vs) / sizeof (uint64_t)) == 0);
+               fnvlist_add_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
+                   (uint64_t *)&vs, sizeof (vs) / sizeof (uint64_t));
 
                /* provide either current or previous scan information */
                if (spa_scan_get_stats(spa, &ps) == 0) {
-                       VERIFY(nvlist_add_uint64_array(nv,
+                       fnvlist_add_uint64_array(nv,
                            ZPOOL_CONFIG_SCAN_STATS, (uint64_t *)&ps,
-                           sizeof (pool_scan_stat_t) / sizeof (uint64_t))
-                           == 0);
+                           sizeof (pool_scan_stat_t) / sizeof (uint64_t));
                }
        }
 
@@ -342,8 +332,8 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
                }
 
                if (idx) {
-                       VERIFY(nvlist_add_nvlist_array(nv,
-                           ZPOOL_CONFIG_CHILDREN, child, idx) == 0);
+                       fnvlist_add_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
+                           child, idx);
                }
 
                for (c = 0; c < idx; c++)
@@ -355,26 +345,20 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
                const char *aux = NULL;
 
                if (vd->vdev_offline && !vd->vdev_tmpoffline)
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_OFFLINE,
-                           B_TRUE) == 0);
-               if (vd->vdev_resilvering)
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_RESILVERING,
-                           B_TRUE) == 0);
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_OFFLINE, B_TRUE);
+               if (vd->vdev_resilver_txg != 0)
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_RESILVER_TXG,
+                           vd->vdev_resilver_txg);
                if (vd->vdev_faulted)
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_FAULTED,
-                           B_TRUE) == 0);
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_FAULTED, B_TRUE);
                if (vd->vdev_degraded)
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_DEGRADED,
-                           B_TRUE) == 0);
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_DEGRADED, B_TRUE);
                if (vd->vdev_removed)
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVED,
-                           B_TRUE) == 0);
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_REMOVED, B_TRUE);
                if (vd->vdev_unspare)
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_UNSPARE,
-                           B_TRUE) == 0);
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_UNSPARE, B_TRUE);
                if (vd->vdev_ishole)
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_IS_HOLE,
-                           B_TRUE) == 0);
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_HOLE, B_TRUE);
 
                switch (vd->vdev_stat.vs_aux) {
                case VDEV_AUX_ERR_EXCEEDED:
@@ -387,12 +371,11 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
                }
 
                if (aux != NULL)
-                       VERIFY(nvlist_add_string(nv, ZPOOL_CONFIG_AUX_STATE,
-                           aux) == 0);
+                       fnvlist_add_string(nv, ZPOOL_CONFIG_AUX_STATE, aux);
 
                if (vd->vdev_splitting && vd->vdev_orig_guid != 0LL) {
-                       VERIFY(nvlist_add_uint64(nv, ZPOOL_CONFIG_ORIG_GUID,
-                           vd->vdev_orig_guid) == 0);
+                       fnvlist_add_uint64(nv, ZPOOL_CONFIG_ORIG_GUID,
+                           vd->vdev_orig_guid);
                }
        }
 
@@ -433,17 +416,22 @@ vdev_top_config_generate(spa_t *spa, nvlist_t *config)
 }
 
 /*
- * Returns the configuration from the label of the given vdev. If 'label' is
- * VDEV_BEST_LABEL, each label of the vdev will be read until a valid
- * configuration is found; otherwise, only the specified label will be read.
+ * Returns the configuration from the label of the given vdev. For vdevs
+ * which don't have a txg value stored on their label (i.e. spares/cache)
+ * or have not been completely initialized (txg = 0) just return
+ * the configuration from the first valid label we find. Otherwise,
+ * find the most up-to-date label that does not exceed the specified
+ * 'txg' value.
  */
 nvlist_t *
-vdev_label_read_config(vdev_t *vd, int label)
+vdev_label_read_config(vdev_t *vd, uint64_t txg)
 {
        spa_t *spa = vd->vdev_spa;
        nvlist_t *config = NULL;
        vdev_phys_t *vp;
        zio_t *zio;
+       uint64_t best_txg = 0;
+       int error = 0;
        int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL |
            ZIO_FLAG_SPECULATIVE;
        int l;
@@ -457,8 +445,7 @@ vdev_label_read_config(vdev_t *vd, int label)
 
 retry:
        for (l = 0; l < VDEV_LABELS; l++) {
-               if (label >= 0 && label < VDEV_LABELS && label != l)
-                       continue;
+               nvlist_t *label = NULL;
 
                zio = zio_root(spa, NULL, NULL, flags);
 
@@ -468,12 +455,31 @@ retry:
 
                if (zio_wait(zio) == 0 &&
                    nvlist_unpack(vp->vp_nvlist, sizeof (vp->vp_nvlist),
-                   &config, 0) == 0)
-                       break;
+                   &label, 0) == 0) {
+                       uint64_t label_txg = 0;
+
+                       /*
+                        * Auxiliary vdevs won't have txg values in their
+                        * labels and newly added vdevs may not have been
+                        * completely initialized so just return the
+                        * configuration from the first valid label we
+                        * encounter.
+                        */
+                       error = nvlist_lookup_uint64(label,
+                           ZPOOL_CONFIG_POOL_TXG, &label_txg);
+                       if ((error || label_txg == 0) && !config) {
+                               config = label;
+                               break;
+                       } else if (label_txg <= txg && label_txg > best_txg) {
+                               best_txg = label_txg;
+                               nvlist_free(config);
+                               config = fnvlist_dup(label);
+                       }
+               }
 
-               if (config != NULL) {
-                       nvlist_free(config);
-                       config = NULL;
+               if (label != NULL) {
+                       nvlist_free(label);
+                       label = NULL;
                }
        }
 
@@ -508,7 +514,7 @@ vdev_inuse(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason,
        /*
         * Read the label, if any, and perform some basic sanity checks.
         */
-       if ((label = vdev_label_read_config(vd, VDEV_BEST_LABEL)) == NULL)
+       if ((label = vdev_label_read_config(vd, -1ULL)) == NULL)
                return (B_FALSE);
 
        (void) nvlist_lookup_uint64(label, ZPOOL_CONFIG_CREATE_TXG,
@@ -638,21 +644,21 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
        /* Track the creation time for this vdev */
        vd->vdev_crtxg = crtxg;
 
-       if (!vd->vdev_ops->vdev_op_leaf)
+       if (!vd->vdev_ops->vdev_op_leaf || !spa_writeable(spa))
                return (0);
 
        /*
         * Dead vdevs cannot be initialized.
         */
        if (vdev_is_dead(vd))
-               return (EIO);
+               return (SET_ERROR(EIO));
 
        /*
         * Determine if the vdev is in use.
         */
        if (reason != VDEV_LABEL_REMOVE && reason != VDEV_LABEL_SPLIT &&
            vdev_inuse(vd, crtxg, reason, &spare_guid, &l2cache_guid))
-               return (EBUSY);
+               return (SET_ERROR(EBUSY));
 
        /*
         * If this is a request to add or replace a spare or l2cache device
@@ -872,7 +878,6 @@ vdev_uberblock_compare(uberblock_t *ub1, uberblock_t *ub2)
 struct ubl_cbdata {
        uberblock_t     *ubl_ubbest;    /* Best uberblock */
        vdev_t          *ubl_vd;        /* vdev associated with the above */
-       int             ubl_label;      /* Label associated with the above */
 };
 
 static void
@@ -891,15 +896,13 @@ vdev_uberblock_load_done(zio_t *zio)
                if (ub->ub_txg <= spa->spa_load_max_txg &&
                    vdev_uberblock_compare(ub, cbp->ubl_ubbest) > 0) {
                        /*
-                        * Keep track of the vdev and label in which this
-                        * uberblock was found. We will use this information
-                        * later to obtain the config nvlist associated with
+                        * Keep track of the vdev in which this uberblock
+                        * was found. We will use this information later
+                        * to obtain the config nvlist associated with
                         * this uberblock.
                         */
                        *cbp->ubl_ubbest = *ub;
                        cbp->ubl_vd = vd;
-                       cbp->ubl_label = vdev_label_number(vd->vdev_psize,
-                           zio->io_offset);
                }
                mutex_exit(&rio->io_lock);
        }
@@ -933,12 +936,11 @@ vdev_uberblock_load_impl(zio_t *zio, vdev_t *vd, int flags,
  * Reads the 'best' uberblock from disk along with its associated
  * configuration. First, we read the uberblock array of each label of each
  * vdev, keeping track of the uberblock with the highest txg in each array.
- * Then, we read the configuration from the same label as the best uberblock.
+ * Then, we read the configuration from the same vdev as the best uberblock.
  */
 void
 vdev_uberblock_load(vdev_t *rvd, uberblock_t *ub, nvlist_t **config)
 {
-       int i;
        zio_t *zio;
        spa_t *spa = rvd->vdev_spa;
        struct ubl_cbdata cb;
@@ -958,13 +960,15 @@ vdev_uberblock_load(vdev_t *rvd, uberblock_t *ub, nvlist_t **config)
        zio = zio_root(spa, NULL, &cb, flags);
        vdev_uberblock_load_impl(zio, rvd, flags, &cb);
        (void) zio_wait(zio);
-       if (cb.ubl_vd != NULL) {
-               for (i = cb.ubl_label % 2; i < VDEV_LABELS; i += 2) {
-                       *config = vdev_label_read_config(cb.ubl_vd, i);
-                       if (*config != NULL)
-                               break;
-               }
-       }
+
+       /*
+        * It's possible that the best uberblock was discovered on a label
+        * that has a configuration which was written in a future txg.
+        * Search all labels on this vdev to find the configuration that
+        * matches the txg for our uberblock.
+        */
+       if (cb.ubl_vd != NULL)
+               *config = vdev_label_read_config(cb.ubl_vd, ub->ub_txg);
        spa_config_exit(spa, SCL_ALL, FTAG);
 }
 
@@ -1014,6 +1018,7 @@ vdev_uberblock_sync(zio_t *zio, uberblock_t *ub, vdev_t *vd, int flags)
        zio_buf_free(ubbuf, VDEV_UBERBLOCK_SIZE(vd));
 }
 
+/* Sync the uberblocks to all vdevs in svd[] */
 int
 vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
 {
@@ -1065,7 +1070,7 @@ vdev_label_sync_top_done(zio_t *zio)
        uint64_t *good_writes = zio->io_private;
 
        if (*good_writes == 0)
-               zio->io_error = EIO;
+               zio->io_error = SET_ERROR(EIO);
 
        kmem_free(good_writes, sizeof (uint64_t));
 }
@@ -1111,7 +1116,7 @@ vdev_label_sync(zio_t *zio, vdev_t *vd, int l, uint64_t txg, int flags)
        buf = vp->vp_nvlist;
        buflen = sizeof (vp->vp_nvlist);
 
-       if (nvlist_pack(label, &buf, &buflen, NV_ENCODE_XDR, KM_PUSHPAGE) == 0) {
+       if (!nvlist_pack(label, &buf, &buflen, NV_ENCODE_XDR, KM_PUSHPAGE)) {
                for (; l < VDEV_LABELS; l += 2) {
                        vdev_label_write(zio, vd, l, vp,
                            offsetof(vdev_label_t, vl_vdev_phys),