From a31e67878a1bf006016a43cafa1fdffa37e432e6 Mon Sep 17 00:00:00 2001 From: George Wilson Date: Thu, 30 Oct 2008 18:04:43 -0700 Subject: 6764914 vdev_reopen() can lead to failed allocations --- usr/src/uts/common/fs/zfs/metaslab.c | 2 +- usr/src/uts/common/fs/zfs/sys/vdev.h | 1 + usr/src/uts/common/fs/zfs/vdev.c | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'usr/src/uts/common') diff --git a/usr/src/uts/common/fs/zfs/metaslab.c b/usr/src/uts/common/fs/zfs/metaslab.c index 1e4f35db95..87727fac2d 100644 --- a/usr/src/uts/common/fs/zfs/metaslab.c +++ b/usr/src/uts/common/fs/zfs/metaslab.c @@ -781,7 +781,7 @@ top: /* * Don't allocate from faulted devices. */ - if (!vdev_writeable(vd)) + if (!vdev_allocatable(vd)) goto next; /* * Avoid writing single-copy data to a failing vdev diff --git a/usr/src/uts/common/fs/zfs/sys/vdev.h b/usr/src/uts/common/fs/zfs/sys/vdev.h index 013389501e..c070d6f3d6 100644 --- a/usr/src/uts/common/fs/zfs/sys/vdev.h +++ b/usr/src/uts/common/fs/zfs/sys/vdev.h @@ -85,6 +85,7 @@ extern void vdev_clear(spa_t *spa, vdev_t *vd); extern boolean_t vdev_is_dead(vdev_t *vd); extern boolean_t vdev_readable(vdev_t *vd); extern boolean_t vdev_writeable(vdev_t *vd); +extern boolean_t vdev_allocatable(vdev_t *vd); extern boolean_t vdev_accessible(vdev_t *vd, zio_t *zio); extern void vdev_cache_init(vdev_t *vd); diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c index 240f955ea2..38b238e3ed 100644 --- a/usr/src/uts/common/fs/zfs/vdev.c +++ b/usr/src/uts/common/fs/zfs/vdev.c @@ -1870,6 +1870,19 @@ vdev_writeable(vdev_t *vd) return (!vdev_is_dead(vd) && !vd->vdev_cant_write); } +boolean_t +vdev_allocatable(vdev_t *vd) +{ + /* + * We currently allow allocations from vdevs which maybe in the + * process of reopening (i.e. VDEV_STATE_CLOSED). If the device + * fails to reopen then we'll catch it later when we're holding + * the proper locks. + */ + return (!(vdev_is_dead(vd) && vd->vdev_state != VDEV_STATE_CLOSED) && + !vd->vdev_cant_write); +} + boolean_t vdev_accessible(vdev_t *vd, zio_t *zio) { -- cgit v1.2.3