diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-09-07 11:45:34 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-09-07 11:45:34 +0000 |
commit | 3bcafc09fab076aba91ad89b8f2d7e2283aeb6f1 (patch) | |
tree | 4f6dfe0466d94a7a0432796c1bc02383709a2279 | |
parent | b5921b68e3c3270372dc07d568b4024543b4f957 (diff) | |
parent | 554675eee75dd2d7398d960aa5c81083ceb8505a (diff) | |
download | illumos-joyent-3bcafc09fab076aba91ad89b8f2d7e2283aeb6f1.tar.gz |
[illumos-gate merge]
commit 554675eee75dd2d7398d960aa5c81083ceb8505a
8473 scrub does not detect errors on active spares
commit f9a980108feff422ad1ee1bc0bb6f1613fa680d3
8608 debug.h: CTASSERT will trigger variable unused errors
-rw-r--r-- | usr/src/uts/common/fs/zfs/vdev_mirror.c | 53 | ||||
-rw-r--r-- | usr/src/uts/common/sys/debug.h | 2 |
2 files changed, 48 insertions, 7 deletions
diff --git a/usr/src/uts/common/fs/zfs/vdev_mirror.c b/usr/src/uts/common/fs/zfs/vdev_mirror.c index a57bd6c73b..d4cf540ee5 100644 --- a/usr/src/uts/common/fs/zfs/vdev_mirror.c +++ b/usr/src/uts/common/fs/zfs/vdev_mirror.c @@ -29,6 +29,9 @@ #include <sys/zfs_context.h> #include <sys/spa.h> +#include <sys/spa_impl.h> +#include <sys/dsl_pool.h> +#include <sys/dsl_scan.h> #include <sys/vdev_impl.h> #include <sys/zio.h> #include <sys/abd.h> @@ -49,7 +52,7 @@ typedef struct mirror_child { typedef struct mirror_map { int mm_children; - int mm_replacing; + int mm_resilvering; int mm_preferred; int mm_root; mirror_child_t mm_child[1]; @@ -86,7 +89,7 @@ vdev_mirror_map_alloc(zio_t *zio) mm = kmem_zalloc(offsetof(mirror_map_t, mm_child[c]), KM_SLEEP); mm->mm_children = c; - mm->mm_replacing = B_FALSE; + mm->mm_resilvering = B_FALSE; mm->mm_preferred = spa_get_random(c); mm->mm_root = B_TRUE; @@ -109,13 +112,51 @@ vdev_mirror_map_alloc(zio_t *zio) mc->mc_offset = DVA_GET_OFFSET(&dva[c]); } } else { + int replacing; + c = vd->vdev_children; mm = kmem_zalloc(offsetof(mirror_map_t, mm_child[c]), KM_SLEEP); mm->mm_children = c; - mm->mm_replacing = (vd->vdev_ops == &vdev_replacing_ops || + /* + * If we are resilvering, then we should handle scrub reads + * differently; we shouldn't issue them to the resilvering + * device because it might not have those blocks. + * + * We are resilvering iff: + * 1) We are a replacing vdev (ie our name is "replacing-1" or + * "spare-1" or something like that), and + * 2) The pool is currently being resilvered. + * + * We cannot simply check vd->vdev_resilver_txg, because it's + * not set in this path. + * + * Nor can we just check our vdev_ops; there are cases (such as + * when a user types "zpool replace pool odev spare_dev" and + * spare_dev is in the spare list, or when a spare device is + * automatically used to replace a DEGRADED device) when + * resilvering is complete but both the original vdev and the + * spare vdev remain in the pool. That behavior is intentional. + * It helps implement the policy that a spare should be + * automatically removed from the pool after the user replaces + * the device that originally failed. + */ + replacing = (vd->vdev_ops == &vdev_replacing_ops || vd->vdev_ops == &vdev_spare_ops); - mm->mm_preferred = mm->mm_replacing ? 0 : + /* + * If a spa load is in progress, then spa_dsl_pool may be + * uninitialized. But we shouldn't be resilvering during a spa + * load anyway. + */ + if (replacing && + (spa_load_state(vd->vdev_spa) == SPA_LOAD_NONE) && + dsl_scan_resilvering(vd->vdev_spa->spa_dsl_pool)) { + mm->mm_resilvering = B_TRUE; + } else { + mm->mm_resilvering = B_FALSE; + } + + mm->mm_preferred = mm->mm_resilvering ? 0 : (zio->io_offset >> vdev_mirror_shift) % c; mm->mm_root = B_FALSE; @@ -271,7 +312,7 @@ vdev_mirror_io_start(zio_t *zio) mm = vdev_mirror_map_alloc(zio); if (zio->io_type == ZIO_TYPE_READ) { - if ((zio->io_flags & ZIO_FLAG_SCRUB) && !mm->mm_replacing) { + if ((zio->io_flags & ZIO_FLAG_SCRUB) && !mm->mm_resilvering) { /* * For scrubbing reads we need to allocate a read * buffer for each child and issue reads to all @@ -408,7 +449,7 @@ vdev_mirror_io_done(zio_t *zio) if (good_copies && spa_writeable(zio->io_spa) && (unexpected_errors || (zio->io_flags & ZIO_FLAG_RESILVER) || - ((zio->io_flags & ZIO_FLAG_SCRUB) && mm->mm_replacing))) { + ((zio->io_flags & ZIO_FLAG_SCRUB) && mm->mm_resilvering))) { /* * Use the good data we have in hand to repair damaged children. */ diff --git a/usr/src/uts/common/sys/debug.h b/usr/src/uts/common/sys/debug.h index 05e62aa1a1..645716cd9c 100644 --- a/usr/src/uts/common/sys/debug.h +++ b/usr/src/uts/common/sys/debug.h @@ -134,7 +134,7 @@ _NOTE(CONSTCOND) } while (0) #define CTASSERT(x) _CTASSERT(x, __LINE__) #define _CTASSERT(x, y) __CTASSERT(x, y) #define __CTASSERT(x, y) \ - typedef char __compile_time_assertion__ ## y [(x) ? 1 : -1] + typedef char __compile_time_assertion__ ## y [(x) ? 1 : -1] __unused #ifdef _KERNEL |