Linux 3.6 compat, sops->write_super() removed
[zfs.git] / module / zfs / vdev.c
index 1630d2f..205a1d1 100644 (file)
@@ -21,6 +21,8 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -107,7 +109,7 @@ vdev_get_min_asize(vdev_t *vd)
        vdev_t *pvd = vd->vdev_parent;
 
        /*
-        * The our parent is NULL (inactive spare or cache) or is the root,
+        * If our parent is NULL (inactive spare or cache) or is the root,
         * just return our own asize.
         */
        if (pvd == NULL)
@@ -193,7 +195,7 @@ vdev_add_child(vdev_t *pvd, vdev_t *cvd)
        pvd->vdev_children = MAX(pvd->vdev_children, id + 1);
        newsize = pvd->vdev_children * sizeof (vdev_t *);
 
-       newchild = kmem_zalloc(newsize, KM_SLEEP);
+       newchild = kmem_zalloc(newsize, KM_PUSHPAGE);
        if (pvd->vdev_child != NULL) {
                bcopy(pvd->vdev_child, newchild, oldsize);
                kmem_free(pvd->vdev_child, oldsize);
@@ -263,7 +265,7 @@ vdev_compact_children(vdev_t *pvd)
                if (pvd->vdev_child[c])
                        newc++;
 
-       newchild = kmem_alloc(newc * sizeof (vdev_t *), KM_SLEEP);
+       newchild = kmem_alloc(newc * sizeof (vdev_t *), KM_PUSHPAGE);
 
        for (c = newc = 0; c < oldc; c++) {
                if ((cvd = pvd->vdev_child[c]) != NULL) {
@@ -286,11 +288,12 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
        vdev_t *vd;
        int t;
 
-       vd = kmem_zalloc(sizeof (vdev_t), KM_SLEEP);
+       vd = kmem_zalloc(sizeof (vdev_t), KM_PUSHPAGE);
 
        if (spa->spa_root_vdev == NULL) {
                ASSERT(ops == &vdev_root_ops);
                spa->spa_root_vdev = vd;
+               spa->spa_load_guid = spa_generate_guid(NULL);
        }
 
        if (guid == 0 && ops != &vdev_hole_ops) {
@@ -744,6 +747,7 @@ vdev_add_parent(vdev_t *cvd, vdev_ops_t *ops)
 
        mvd->vdev_asize = cvd->vdev_asize;
        mvd->vdev_min_asize = cvd->vdev_min_asize;
+       mvd->vdev_max_asize = cvd->vdev_max_asize;
        mvd->vdev_ashift = cvd->vdev_ashift;
        mvd->vdev_state = cvd->vdev_state;
        mvd->vdev_crtxg = cvd->vdev_crtxg;
@@ -835,7 +839,7 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg)
 
        ASSERT(oldc <= newc);
 
-       mspp = kmem_zalloc(newc * sizeof (*mspp), KM_SLEEP | KM_NODEBUG);
+       mspp = kmem_zalloc(newc * sizeof (*mspp), KM_PUSHPAGE | KM_NODEBUG);
 
        if (oldc != 0) {
                bcopy(vd->vdev_ms, mspp, oldc * sizeof (*mspp));
@@ -990,7 +994,7 @@ vdev_probe(vdev_t *vd, zio_t *zio)
        mutex_enter(&vd->vdev_probe_lock);
 
        if ((pio = vd->vdev_probe_zio) == NULL) {
-               vps = kmem_zalloc(sizeof (*vps), KM_SLEEP);
+               vps = kmem_zalloc(sizeof (*vps), KM_PUSHPAGE);
 
                vps->vps_flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_PROBE |
                    ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_AGGREGATE |
@@ -1129,7 +1133,8 @@ vdev_open(vdev_t *vd)
        spa_t *spa = vd->vdev_spa;
        int error;
        uint64_t osize = 0;
-       uint64_t asize, psize;
+       uint64_t max_osize = 0;
+       uint64_t asize, max_asize, psize;
        uint64_t ashift = 0;
        int c;
 
@@ -1161,7 +1166,7 @@ vdev_open(vdev_t *vd)
                return (ENXIO);
        }
 
-       error = vd->vdev_ops->vdev_op_open(vd, &osize, &ashift);
+       error = vd->vdev_ops->vdev_op_open(vd, &osize, &max_osize, &ashift);
 
        /*
         * Reset the vdev_reopening flag so that we actually close
@@ -1219,6 +1224,7 @@ vdev_open(vdev_t *vd)
        }
 
        osize = P2ALIGN(osize, (uint64_t)sizeof (vdev_label_t));
+       max_osize = P2ALIGN(max_osize, (uint64_t)sizeof (vdev_label_t));
 
        if (vd->vdev_children == 0) {
                if (osize < SPA_MINDEVSIZE) {
@@ -1228,6 +1234,8 @@ vdev_open(vdev_t *vd)
                }
                psize = osize;
                asize = osize - (VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE);
+               max_asize = max_osize - (VDEV_LABEL_START_SIZE +
+                   VDEV_LABEL_END_SIZE);
        } else {
                if (vd->vdev_parent != NULL && osize < SPA_MINDEVSIZE -
                    (VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE)) {
@@ -1237,6 +1245,7 @@ vdev_open(vdev_t *vd)
                }
                psize = 0;
                asize = osize;
+               max_asize = max_osize;
        }
 
        vd->vdev_psize = psize;
@@ -1256,6 +1265,7 @@ vdev_open(vdev_t *vd)
                 * For testing purposes, a higher ashift can be requested.
                 */
                vd->vdev_asize = asize;
+               vd->vdev_max_asize = max_asize;
                vd->vdev_ashift = MAX(ashift, vd->vdev_ashift);
        } else {
                /*
@@ -1266,6 +1276,7 @@ vdev_open(vdev_t *vd)
                            VDEV_AUX_BAD_LABEL);
                        return (EINVAL);
                }
+               vd->vdev_max_asize = max_asize;
        }
 
        /*
@@ -1307,13 +1318,18 @@ vdev_open(vdev_t *vd)
  * contents.  This needs to be done before vdev_load() so that we don't
  * inadvertently do repair I/Os to the wrong device.
  *
+ * If 'strict' is false ignore the spa guid check. This is necessary because
+ * if the machine crashed during a re-guid the new guid might have been written
+ * to all of the vdev labels, but not the cached config. The strict check
+ * will be performed when the pool is opened again using the mos config.
+ *
  * This function will only return failure if one of the vdevs indicates that it
  * has since been destroyed or exported.  This is only possible if
  * /etc/zfs/zpool.cache was readonly at the time.  Otherwise, the vdev state
  * will be updated but the function will return 0.
  */
 int
-vdev_validate(vdev_t *vd)
+vdev_validate(vdev_t *vd, boolean_t strict)
 {
        spa_t *spa = vd->vdev_spa;
        nvlist_t *label;
@@ -1322,7 +1338,7 @@ vdev_validate(vdev_t *vd)
        int c;
 
        for (c = 0; c < vd->vdev_children; c++)
-               if (vdev_validate(vd->vdev_child[c]) != 0)
+               if (vdev_validate(vd->vdev_child[c], strict) != 0)
                        return (EBADF);
 
        /*
@@ -1352,8 +1368,9 @@ vdev_validate(vdev_t *vd)
                        return (0);
                }
 
-               if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID,
-                   &guid) != 0 || guid != spa_guid(spa)) {
+               if (strict && (nvlist_lookup_uint64(label,
+                   ZPOOL_CONFIG_POOL_GUID, &guid) != 0 ||
+                   guid != spa_guid(spa))) {
                        vdev_set_state(vd, B_FALSE, VDEV_STATE_CANT_OPEN,
                            VDEV_AUX_CORRUPT_DATA);
                        nvlist_free(label);
@@ -1516,7 +1533,7 @@ vdev_reopen(vdev_t *vd)
                    !l2arc_vdev_present(vd))
                        l2arc_add_vdev(spa, vd);
        } else {
-               (void) vdev_validate(vd);
+               (void) vdev_validate(vd, B_TRUE);
        }
 
        /*
@@ -2490,6 +2507,7 @@ vdev_get_stats(vdev_t *vd, vdev_stat_t *vs)
        vs->vs_rsize = vdev_get_min_asize(vd);
        if (vd->vdev_ops->vdev_op_leaf)
                vs->vs_rsize += VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE;
+       vs->vs_esize = vd->vdev_max_asize - vd->vdev_asize;
        mutex_exit(&vd->vdev_stat_lock);
 
        /*