Home | History | Annotate | Download | only in zfs
      1    789    ahrens /*
      2    789    ahrens  * CDDL HEADER START
      3    789    ahrens  *
      4    789    ahrens  * The contents of this file are subject to the terms of the
      5   1544  eschrock  * Common Development and Distribution License (the "License").
      6   1544  eschrock  * You may not use this file except in compliance with the License.
      7    789    ahrens  *
      8    789    ahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9    789    ahrens  * or http://www.opensolaris.org/os/licensing.
     10    789    ahrens  * See the License for the specific language governing permissions
     11    789    ahrens  * and limitations under the License.
     12    789    ahrens  *
     13    789    ahrens  * When distributing Covered Code, include this CDDL HEADER in each
     14    789    ahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15    789    ahrens  * If applicable, add the following below this CDDL HEADER, with the
     16    789    ahrens  * fields enclosed by brackets "[]" replaced with your own identifying
     17    789    ahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
     18    789    ahrens  *
     19    789    ahrens  * CDDL HEADER END
     20    789    ahrens  */
     21    789    ahrens /*
     22   8632      Bill  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23    789    ahrens  * Use is subject to license terms.
     24    789    ahrens  */
     25    789    ahrens 
     26    789    ahrens #include <sys/zfs_context.h>
     27    789    ahrens #include <sys/spa.h>
     28    789    ahrens #include <sys/vdev_impl.h>
     29    789    ahrens #include <sys/zio.h>
     30    789    ahrens #include <sys/fs/zfs.h>
     31    789    ahrens 
     32    789    ahrens /*
     33    789    ahrens  * Virtual device vector for mirroring.
     34    789    ahrens  */
     35    789    ahrens 
     36   1775     billm typedef struct mirror_child {
     37   1775     billm 	vdev_t		*mc_vd;
     38   1775     billm 	uint64_t	mc_offset;
     39   1775     billm 	int		mc_error;
     40   7754      Jeff 	uint8_t		mc_tried;
     41   7754      Jeff 	uint8_t		mc_skipped;
     42   7754      Jeff 	uint8_t		mc_speculative;
     43   1775     billm } mirror_child_t;
     44   1775     billm 
     45    789    ahrens typedef struct mirror_map {
     46   1775     billm 	int		mm_children;
     47   1775     billm 	int		mm_replacing;
     48   1775     billm 	int		mm_preferred;
     49   1775     billm 	int		mm_root;
     50   1775     billm 	mirror_child_t	mm_child[1];
     51    789    ahrens } mirror_map_t;
     52    789    ahrens 
     53   2391    maybee int vdev_mirror_shift = 21;
     54   7754      Jeff 
     55   7754      Jeff static void
     56   7754      Jeff vdev_mirror_map_free(zio_t *zio)
     57   7754      Jeff {
     58   7754      Jeff 	mirror_map_t *mm = zio->io_vsd;
     59   7754      Jeff 
     60   7754      Jeff 	kmem_free(mm, offsetof(mirror_map_t, mm_child[mm->mm_children]));
     61   7754      Jeff }
     62   2391    maybee 
     63  10614  Jonathan static const zio_vsd_ops_t vdev_mirror_vsd_ops = {
     64  10614  Jonathan 	vdev_mirror_map_free,
     65  10614  Jonathan 	zio_vsd_default_cksum_report
     66  10614  Jonathan };
     67  10614  Jonathan 
     68    789    ahrens static mirror_map_t *
     69    789    ahrens vdev_mirror_map_alloc(zio_t *zio)
     70    789    ahrens {
     71   1775     billm 	mirror_map_t *mm = NULL;
     72   1775     billm 	mirror_child_t *mc;
     73   1775     billm 	vdev_t *vd = zio->io_vd;
     74   1775     billm 	int c, d;
     75   1775     billm 
     76   1775     billm 	if (vd == NULL) {
     77   1775     billm 		dva_t *dva = zio->io_bp->blk_dva;
     78   1775     billm 		spa_t *spa = zio->io_spa;
     79   1775     billm 
     80   1775     billm 		c = BP_GET_NDVAS(zio->io_bp);
     81   1775     billm 
     82   1775     billm 		mm = kmem_zalloc(offsetof(mirror_map_t, mm_child[c]), KM_SLEEP);
     83   1775     billm 		mm->mm_children = c;
     84   1775     billm 		mm->mm_replacing = B_FALSE;
     85   1775     billm 		mm->mm_preferred = spa_get_random(c);
     86   1775     billm 		mm->mm_root = B_TRUE;
     87   1775     billm 
     88   1775     billm 		/*
     89   1775     billm 		 * Check the other, lower-index DVAs to see if they're on
     90   1775     billm 		 * the same vdev as the child we picked.  If they are, use
     91   1775     billm 		 * them since they are likely to have been allocated from
     92   1775     billm 		 * the primary metaslab in use at the time, and hence are
     93   1775     billm 		 * more likely to have locality with single-copy data.
     94   1775     billm 		 */
     95   1775     billm 		for (c = mm->mm_preferred, d = c - 1; d >= 0; d--) {
     96   1775     billm 			if (DVA_GET_VDEV(&dva[d]) == DVA_GET_VDEV(&dva[c]))
     97   1775     billm 				mm->mm_preferred = d;
     98   1775     billm 		}
     99   1775     billm 
    100   1775     billm 		for (c = 0; c < mm->mm_children; c++) {
    101   1775     billm 			mc = &mm->mm_child[c];
    102   2082  eschrock 
    103   1775     billm 			mc->mc_vd = vdev_lookup_top(spa, DVA_GET_VDEV(&dva[c]));
    104   1775     billm 			mc->mc_offset = DVA_GET_OFFSET(&dva[c]);
    105   1775     billm 		}
    106   1775     billm 	} else {
    107   1775     billm 		c = vd->vdev_children;
    108   1775     billm 
    109   1775     billm 		mm = kmem_zalloc(offsetof(mirror_map_t, mm_child[c]), KM_SLEEP);
    110   1775     billm 		mm->mm_children = c;
    111   2082  eschrock 		mm->mm_replacing = (vd->vdev_ops == &vdev_replacing_ops ||
    112   2082  eschrock 		    vd->vdev_ops == &vdev_spare_ops);
    113   2391    maybee 		mm->mm_preferred = mm->mm_replacing ? 0 :
    114   2391    maybee 		    (zio->io_offset >> vdev_mirror_shift) % c;
    115   1775     billm 		mm->mm_root = B_FALSE;
    116   1775     billm 
    117   1775     billm 		for (c = 0; c < mm->mm_children; c++) {
    118   1775     billm 			mc = &mm->mm_child[c];
    119   1775     billm 			mc->mc_vd = vd->vdev_child[c];
    120   1775     billm 			mc->mc_offset = zio->io_offset;
    121   1775     billm 		}
    122   1775     billm 	}
    123   1775     billm 
    124   1775     billm 	zio->io_vsd = mm;
    125  10614  Jonathan 	zio->io_vsd_ops = &vdev_mirror_vsd_ops;
    126   1775     billm 	return (mm);
    127    789    ahrens }
    128    789    ahrens 
    129    789    ahrens static int
    130    789    ahrens vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift)
    131    789    ahrens {
    132    789    ahrens 	int numerrors = 0;
    133   9846      Eric 	int lasterror = 0;
    134    789    ahrens 
    135    789    ahrens 	if (vd->vdev_children == 0) {
    136    789    ahrens 		vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
    137    789    ahrens 		return (EINVAL);
    138    789    ahrens 	}
    139    789    ahrens 
    140   9846      Eric 	vdev_open_children(vd);
    141    789    ahrens 
    142   9846      Eric 	for (int c = 0; c < vd->vdev_children; c++) {
    143   9846      Eric 		vdev_t *cvd = vd->vdev_child[c];
    144   9846      Eric 
    145   9846      Eric 		if (cvd->vdev_open_error) {
    146   9846      Eric 			lasterror = cvd->vdev_open_error;
    147    789    ahrens 			numerrors++;
    148    789    ahrens 			continue;
    149    789    ahrens 		}
    150    789    ahrens 
    151    789    ahrens 		*asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1;
    152   1732   bonwick 		*ashift = MAX(*ashift, cvd->vdev_ashift);
    153    789    ahrens 	}
    154    789    ahrens 
    155    789    ahrens 	if (numerrors == vd->vdev_children) {
    156    789    ahrens 		vd->vdev_stat.vs_aux = VDEV_AUX_NO_REPLICAS;
    157    789    ahrens 		return (lasterror);
    158    789    ahrens 	}
    159    789    ahrens 
    160    789    ahrens 	return (0);
    161    789    ahrens }
    162    789    ahrens 
    163    789    ahrens static void
    164    789    ahrens vdev_mirror_close(vdev_t *vd)
    165    789    ahrens {
    166   9846      Eric 	for (int c = 0; c < vd->vdev_children; c++)
    167    789    ahrens 		vdev_close(vd->vdev_child[c]);
    168    789    ahrens }
    169    789    ahrens 
    170    789    ahrens static void
    171    789    ahrens vdev_mirror_child_done(zio_t *zio)
    172    789    ahrens {
    173   1775     billm 	mirror_child_t *mc = zio->io_private;
    174    789    ahrens 
    175   1775     billm 	mc->mc_error = zio->io_error;
    176   1775     billm 	mc->mc_tried = 1;
    177   1775     billm 	mc->mc_skipped = 0;
    178    789    ahrens }
    179    789    ahrens 
    180    789    ahrens static void
    181    789    ahrens vdev_mirror_scrub_done(zio_t *zio)
    182    789    ahrens {
    183   1775     billm 	mirror_child_t *mc = zio->io_private;
    184    789    ahrens 
    185    789    ahrens 	if (zio->io_error == 0) {
    186   8632      Bill 		zio_t *pio;
    187   8632      Bill 
    188   8632      Bill 		mutex_enter(&zio->io_lock);
    189   8632      Bill 		while ((pio = zio_walk_parents(zio)) != NULL) {
    190   8632      Bill 			mutex_enter(&pio->io_lock);
    191   8632      Bill 			ASSERT3U(zio->io_size, >=, pio->io_size);
    192   8632      Bill 			bcopy(zio->io_data, pio->io_data, pio->io_size);
    193   8632      Bill 			mutex_exit(&pio->io_lock);
    194   8632      Bill 		}
    195   8632      Bill 		mutex_exit(&zio->io_lock);
    196    789    ahrens 	}
    197    789    ahrens 
    198    789    ahrens 	zio_buf_free(zio->io_data, zio->io_size);
    199    789    ahrens 
    200   1775     billm 	mc->mc_error = zio->io_error;
    201   1775     billm 	mc->mc_tried = 1;
    202   1775     billm 	mc->mc_skipped = 0;
    203   1732   bonwick }
    204   1732   bonwick 
    205    789    ahrens /*
    206    789    ahrens  * Try to find a child whose DTL doesn't contain the block we want to read.
    207    789    ahrens  * If we can't, try the read on any vdev we haven't already tried.
    208    789    ahrens  */
    209    789    ahrens static int
    210    789    ahrens vdev_mirror_child_select(zio_t *zio)
    211    789    ahrens {
    212    789    ahrens 	mirror_map_t *mm = zio->io_vsd;
    213   1775     billm 	mirror_child_t *mc;
    214    789    ahrens 	uint64_t txg = zio->io_txg;
    215    789    ahrens 	int i, c;
    216    789    ahrens 
    217  10922      Jeff 	ASSERT(zio->io_bp == NULL || BP_PHYSICAL_BIRTH(zio->io_bp) == txg);
    218    789    ahrens 
    219    789    ahrens 	/*
    220    789    ahrens 	 * Try to find a child whose DTL doesn't contain the block to read.
    221    789    ahrens 	 * If a child is known to be completely inaccessible (indicated by
    222   5329   gw25295 	 * vdev_readable() returning B_FALSE), don't even try.
    223    789    ahrens 	 */
    224   1775     billm 	for (i = 0, c = mm->mm_preferred; i < mm->mm_children; i++, c++) {
    225   1775     billm 		if (c >= mm->mm_children)
    226    789    ahrens 			c = 0;
    227   1775     billm 		mc = &mm->mm_child[c];
    228   1775     billm 		if (mc->mc_tried || mc->mc_skipped)
    229    789    ahrens 			continue;
    230   7754      Jeff 		if (!vdev_readable(mc->mc_vd)) {
    231   1775     billm 			mc->mc_error = ENXIO;
    232   1775     billm 			mc->mc_tried = 1;	/* don't even try */
    233   1775     billm 			mc->mc_skipped = 1;
    234    789    ahrens 			continue;
    235    789    ahrens 		}
    236   8241      Jeff 		if (!vdev_dtl_contains(mc->mc_vd, DTL_MISSING, txg, 1))
    237    789    ahrens 			return (c);
    238   1775     billm 		mc->mc_error = ESTALE;
    239   1775     billm 		mc->mc_skipped = 1;
    240   7754      Jeff 		mc->mc_speculative = 1;
    241    789    ahrens 	}
    242    789    ahrens 
    243    789    ahrens 	/*
    244    789    ahrens 	 * Every device is either missing or has this txg in its DTL.
    245   1775     billm 	 * Look for any child we haven't already tried before giving up.
    246    789    ahrens 	 */
    247   1775     billm 	for (c = 0; c < mm->mm_children; c++)
    248   1775     billm 		if (!mm->mm_child[c].mc_tried)
    249   1775     billm 			return (c);
    250    789    ahrens 
    251    789    ahrens 	/*
    252    789    ahrens 	 * Every child failed.  There's no place left to look.
    253    789    ahrens 	 */
    254    789    ahrens 	return (-1);
    255    789    ahrens }
    256    789    ahrens 
    257   5530   bonwick static int
    258    789    ahrens vdev_mirror_io_start(zio_t *zio)
    259    789    ahrens {
    260    789    ahrens 	mirror_map_t *mm;
    261   1775     billm 	mirror_child_t *mc;
    262    789    ahrens 	int c, children;
    263    789    ahrens 
    264    789    ahrens 	mm = vdev_mirror_map_alloc(zio);
    265    789    ahrens 
    266    789    ahrens 	if (zio->io_type == ZIO_TYPE_READ) {
    267   1775     billm 		if ((zio->io_flags & ZIO_FLAG_SCRUB) && !mm->mm_replacing) {
    268    789    ahrens 			/*
    269    789    ahrens 			 * For scrubbing reads we need to allocate a read
    270    789    ahrens 			 * buffer for each child and issue reads to all
    271    789    ahrens 			 * children.  If any child succeeds, it will copy its
    272    789    ahrens 			 * data into zio->io_data in vdev_mirror_scrub_done.
    273    789    ahrens 			 */
    274   1775     billm 			for (c = 0; c < mm->mm_children; c++) {
    275   1775     billm 				mc = &mm->mm_child[c];
    276    789    ahrens 				zio_nowait(zio_vdev_child_io(zio, zio->io_bp,
    277   1775     billm 				    mc->mc_vd, mc->mc_offset,
    278    789    ahrens 				    zio_buf_alloc(zio->io_size), zio->io_size,
    279   7754      Jeff 				    zio->io_type, zio->io_priority, 0,
    280   1775     billm 				    vdev_mirror_scrub_done, mc));
    281    789    ahrens 			}
    282   7754      Jeff 			return (ZIO_PIPELINE_CONTINUE);
    283    789    ahrens 		}
    284    789    ahrens 		/*
    285    789    ahrens 		 * For normal reads just pick one child.
    286    789    ahrens 		 */
    287    789    ahrens 		c = vdev_mirror_child_select(zio);
    288    789    ahrens 		children = (c >= 0);
    289    789    ahrens 	} else {
    290    789    ahrens 		ASSERT(zio->io_type == ZIO_TYPE_WRITE);
    291    789    ahrens 
    292    789    ahrens 		/*
    293   8241      Jeff 		 * Writes go to all children.
    294    789    ahrens 		 */
    295   8241      Jeff 		c = 0;
    296   8241      Jeff 		children = mm->mm_children;
    297    789    ahrens 	}
    298    789    ahrens 
    299    789    ahrens 	while (children--) {
    300   1775     billm 		mc = &mm->mm_child[c];
    301    789    ahrens 		zio_nowait(zio_vdev_child_io(zio, zio->io_bp,
    302   7754      Jeff 		    mc->mc_vd, mc->mc_offset, zio->io_data, zio->io_size,
    303   7754      Jeff 		    zio->io_type, zio->io_priority, 0,
    304   7754      Jeff 		    vdev_mirror_child_done, mc));
    305    789    ahrens 		c++;
    306    789    ahrens 	}
    307    789    ahrens 
    308   7754      Jeff 	return (ZIO_PIPELINE_CONTINUE);
    309    789    ahrens }
    310    789    ahrens 
    311   5530   bonwick static int
    312   7754      Jeff vdev_mirror_worst_error(mirror_map_t *mm)
    313   7754      Jeff {
    314   7754      Jeff 	int error[2] = { 0, 0 };
    315   7754      Jeff 
    316   7754      Jeff 	for (int c = 0; c < mm->mm_children; c++) {
    317   7754      Jeff 		mirror_child_t *mc = &mm->mm_child[c];
    318   7754      Jeff 		int s = mc->mc_speculative;
    319   7754      Jeff 		error[s] = zio_worst_error(error[s], mc->mc_error);
    320   7754      Jeff 	}
    321   7754      Jeff 
    322   7754      Jeff 	return (error[0] ? error[0] : error[1]);
    323   7754      Jeff }
    324   7754      Jeff 
    325   7754      Jeff static void
    326    789    ahrens vdev_mirror_io_done(zio_t *zio)
    327    789    ahrens {
    328    789    ahrens 	mirror_map_t *mm = zio->io_vsd;
    329   1775     billm 	mirror_child_t *mc;
    330    789    ahrens 	int c;
    331    789    ahrens 	int good_copies = 0;
    332    789    ahrens 	int unexpected_errors = 0;
    333    789    ahrens 
    334   1775     billm 	for (c = 0; c < mm->mm_children; c++) {
    335   1775     billm 		mc = &mm->mm_child[c];
    336   1775     billm 
    337   1775     billm 		if (mc->mc_error) {
    338   1775     billm 			if (!mc->mc_skipped)
    339    789    ahrens 				unexpected_errors++;
    340   7754      Jeff 		} else if (mc->mc_tried) {
    341   7754      Jeff 			good_copies++;
    342    789    ahrens 		}
    343    789    ahrens 	}
    344    789    ahrens 
    345    789    ahrens 	if (zio->io_type == ZIO_TYPE_WRITE) {
    346    789    ahrens 		/*
    347    789    ahrens 		 * XXX -- for now, treat partial writes as success.
    348   7754      Jeff 		 *
    349   7754      Jeff 		 * Now that we support write reallocation, it would be better
    350   7754      Jeff 		 * to treat partial failure as real failure unless there are
    351   7754      Jeff 		 * no non-degraded top-level vdevs left, and not update DTLs
    352   7754      Jeff 		 * if we intend to reallocate.
    353    789    ahrens 		 */
    354    789    ahrens 		/* XXPOLICY */
    355   7754      Jeff 		if (good_copies != mm->mm_children) {
    356   7754      Jeff 			/*
    357   7754      Jeff 			 * Always require at least one good copy.
    358   7754      Jeff 			 *
    359   7754      Jeff 			 * For ditto blocks (io_vd == NULL), require
    360   7754      Jeff 			 * all copies to be good.
    361   7754      Jeff 			 *
    362   7754      Jeff 			 * XXX -- for replacing vdevs, there's no great answer.
    363   7754      Jeff 			 * If the old device is really dead, we may not even
    364   7754      Jeff 			 * be able to access it -- so we only want to
    365   7754      Jeff 			 * require good writes to the new device.  But if
    366   7754      Jeff 			 * the new device turns out to be flaky, we want
    367   7754      Jeff 			 * to be able to detach it -- which requires all
    368   7754      Jeff 			 * writes to the old device to have succeeded.
    369   7754      Jeff 			 */
    370   7754      Jeff 			if (good_copies == 0 || zio->io_vd == NULL)
    371   7754      Jeff 				zio->io_error = vdev_mirror_worst_error(mm);
    372   7754      Jeff 		}
    373   7754      Jeff 		return;
    374    789    ahrens 	}
    375    789    ahrens 
    376    789    ahrens 	ASSERT(zio->io_type == ZIO_TYPE_READ);
    377    789    ahrens 
    378    789    ahrens 	/*
    379    789    ahrens 	 * If we don't have a good copy yet, keep trying other children.
    380    789    ahrens 	 */
    381    789    ahrens 	/* XXPOLICY */
    382    789    ahrens 	if (good_copies == 0 && (c = vdev_mirror_child_select(zio)) != -1) {
    383   1775     billm 		ASSERT(c >= 0 && c < mm->mm_children);
    384   1775     billm 		mc = &mm->mm_child[c];
    385    789    ahrens 		zio_vdev_io_redone(zio);
    386   1775     billm 		zio_nowait(zio_vdev_child_io(zio, zio->io_bp,
    387   1775     billm 		    mc->mc_vd, mc->mc_offset, zio->io_data, zio->io_size,
    388   7754      Jeff 		    ZIO_TYPE_READ, zio->io_priority, 0,
    389   1775     billm 		    vdev_mirror_child_done, mc));
    390   7754      Jeff 		return;
    391    789    ahrens 	}
    392    789    ahrens 
    393    789    ahrens 	/* XXPOLICY */
    394   7754      Jeff 	if (good_copies == 0) {
    395   7754      Jeff 		zio->io_error = vdev_mirror_worst_error(mm);
    396    789    ahrens 		ASSERT(zio->io_error != 0);
    397   7754      Jeff 	}
    398    789    ahrens 
    399   8241      Jeff 	if (good_copies && spa_writeable(zio->io_spa) &&
    400   1807   bonwick 	    (unexpected_errors ||
    401   1807   bonwick 	    (zio->io_flags & ZIO_FLAG_RESILVER) ||
    402   1807   bonwick 	    ((zio->io_flags & ZIO_FLAG_SCRUB) && mm->mm_replacing))) {
    403    789    ahrens 		/*
    404    789    ahrens 		 * Use the good data we have in hand to repair damaged children.
    405    789    ahrens 		 */
    406   1775     billm 		for (c = 0; c < mm->mm_children; c++) {
    407    789    ahrens 			/*
    408    789    ahrens 			 * Don't rewrite known good children.
    409    789    ahrens 			 * Not only is it unnecessary, it could
    410    789    ahrens 			 * actually be harmful: if the system lost
    411    789    ahrens 			 * power while rewriting the only good copy,
    412    789    ahrens 			 * there would be no good copies left!
    413    789    ahrens 			 */
    414   1775     billm 			mc = &mm->mm_child[c];
    415    789    ahrens 
    416   1775     billm 			if (mc->mc_error == 0) {
    417   1775     billm 				if (mc->mc_tried)
    418    789    ahrens 					continue;
    419   1807   bonwick 				if (!(zio->io_flags & ZIO_FLAG_SCRUB) &&
    420   8241      Jeff 				    !vdev_dtl_contains(mc->mc_vd, DTL_PARTIAL,
    421    789    ahrens 				    zio->io_txg, 1))
    422    789    ahrens 					continue;
    423   1775     billm 				mc->mc_error = ESTALE;
    424    789    ahrens 			}
    425    789    ahrens 
    426   7754      Jeff 			zio_nowait(zio_vdev_child_io(zio, zio->io_bp,
    427   7754      Jeff 			    mc->mc_vd, mc->mc_offset,
    428   7754      Jeff 			    zio->io_data, zio->io_size,
    429    789    ahrens 			    ZIO_TYPE_WRITE, zio->io_priority,
    430   8241      Jeff 			    ZIO_FLAG_IO_REPAIR | (unexpected_errors ?
    431   8241      Jeff 			    ZIO_FLAG_SELF_HEAL : 0), NULL, NULL));
    432    789    ahrens 		}
    433    789    ahrens 	}
    434    789    ahrens }
    435    789    ahrens 
    436    789    ahrens static void
    437    789    ahrens vdev_mirror_state_change(vdev_t *vd, int faulted, int degraded)
    438    789    ahrens {
    439    789    ahrens 	if (faulted == vd->vdev_children)
    440   1544  eschrock 		vdev_set_state(vd, B_FALSE, VDEV_STATE_CANT_OPEN,
    441   1544  eschrock 		    VDEV_AUX_NO_REPLICAS);
    442    789    ahrens 	else if (degraded + faulted != 0)
    443   1544  eschrock 		vdev_set_state(vd, B_FALSE, VDEV_STATE_DEGRADED, VDEV_AUX_NONE);
    444    789    ahrens 	else
    445   1544  eschrock 		vdev_set_state(vd, B_FALSE, VDEV_STATE_HEALTHY, VDEV_AUX_NONE);
    446    789    ahrens }
    447    789    ahrens 
    448    789    ahrens vdev_ops_t vdev_mirror_ops = {
    449    789    ahrens 	vdev_mirror_open,
    450    789    ahrens 	vdev_mirror_close,
    451    789    ahrens 	vdev_default_asize,
    452    789    ahrens 	vdev_mirror_io_start,
    453    789    ahrens 	vdev_mirror_io_done,
    454    789    ahrens 	vdev_mirror_state_change,
    455    789    ahrens 	VDEV_TYPE_MIRROR,	/* name of this vdev type */
    456    789    ahrens 	B_FALSE			/* not a leaf vdev */
    457    789    ahrens };
    458    789    ahrens 
    459    789    ahrens vdev_ops_t vdev_replacing_ops = {
    460    789    ahrens 	vdev_mirror_open,
    461    789    ahrens 	vdev_mirror_close,
    462    789    ahrens 	vdev_default_asize,
    463    789    ahrens 	vdev_mirror_io_start,
    464    789    ahrens 	vdev_mirror_io_done,
    465    789    ahrens 	vdev_mirror_state_change,
    466    789    ahrens 	VDEV_TYPE_REPLACING,	/* name of this vdev type */
    467    789    ahrens 	B_FALSE			/* not a leaf vdev */
    468    789    ahrens };
    469   2082  eschrock 
    470   2082  eschrock vdev_ops_t vdev_spare_ops = {
    471   2082  eschrock 	vdev_mirror_open,
    472   2082  eschrock 	vdev_mirror_close,
    473   2082  eschrock 	vdev_default_asize,
    474   2082  eschrock 	vdev_mirror_io_start,
    475   2082  eschrock 	vdev_mirror_io_done,
    476   2082  eschrock 	vdev_mirror_state_change,
    477   2082  eschrock 	VDEV_TYPE_SPARE,	/* name of this vdev type */
    478   2082  eschrock 	B_FALSE			/* not a leaf vdev */
    479   2082  eschrock };
    480