summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2013-02-26 11:25:55 -0800
committerBrian Behlendorf <[email protected]>2013-02-28 12:02:59 -0800
commit0d8103d9561bd2314da320dd5d43f9d5e044b64d (patch)
treeeac8f08332646b8112e86c88e6979b5f4a28ff2b
parentc5b247f3354d5c9e24577af997c84d90625620a6 (diff)
Leaf vdevs should not be reopened
When vdev_disk.c was implemented for Linux we failed to handle the reopen case. According to the vdev_reopen() comment leaf vdevs should not be closed or opened when v->vdev_reopening is set. Under Linux we would always close and open the device. This issue was only noticed when a 'zpool scrub' command was run while the leaf vdev device names in /dev/disk/by-vdev were missing. The scrub command calls vdev_reopen() which caused the vdevs to be closed but they couldn't be reopened due to the missing links. The result was that all the vdevs were marked unavailable and the pool was halted due to failmode=wait. This patch adds the missing functionality in a similiar fashion to to the Illumos code. Signed-off-by: Brian Behlendorf <[email protected]>
-rw-r--r--module/zfs/vdev_disk.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/module/zfs/vdev_disk.c b/module/zfs/vdev_disk.c
index e902a70e1..4e38c7860 100644
--- a/module/zfs/vdev_disk.c
+++ b/module/zfs/vdev_disk.c
@@ -249,6 +249,16 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
return EINVAL;
}
+ /*
+ * Reopen the device if it's not currently open. Otherwise,
+ * just update the physical size of the device.
+ */
+ if (v->vdev_tsd != NULL) {
+ ASSERT(v->vdev_reopening);
+ vd = v->vdev_tsd;
+ goto skip_open;
+ }
+
vd = kmem_zalloc(sizeof(vdev_disk_t), KM_PUSHPAGE);
if (vd == NULL)
return ENOMEM;
@@ -279,7 +289,10 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
v->vdev_tsd = vd;
vd->vd_bdev = bdev;
- block_size = vdev_bdev_block_size(bdev);
+
+skip_open:
+ /* Determine the physical block size */
+ block_size = vdev_bdev_block_size(vd->vd_bdev);
/* We think the wholedisk property should always be set when this
* function is called. ASSERT here so if any legitimate cases exist
@@ -299,7 +312,7 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
v->vdev_nowritecache = B_FALSE;
/* Physical volume size in bytes */
- *psize = bdev_capacity(bdev);
+ *psize = bdev_capacity(vd->vd_bdev);
/* TODO: report possible expansion size */
*max_psize = *psize;
@@ -318,7 +331,7 @@ vdev_disk_close(vdev_t *v)
{
vdev_disk_t *vd = v->vdev_tsd;
- if (vd == NULL)
+ if (v->vdev_reopening || vd == NULL)
return;
if (vd->vd_bdev != NULL)