Skip to content

Commit

Permalink
Leaf vdevs should not be reopened
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
behlendorf committed Feb 28, 2013
1 parent c5b247f commit 0d8103d
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions module/zfs/vdev_disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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)
Expand Down

0 comments on commit 0d8103d

Please sign in to comment.