mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-17 18:11:00 +03:00
zvol_os: Fix handling of zvol private data
zvol private data is supposed to be nulled by zvol_clear_private before zvol_free is called as an indicator that the zvol is going away. Implement zvol_clear_private for volmode=dev. Assert that zvol_clear_private has been called before zvol_free. Check that zvol_clear_private has not been called when updating volsize. If it has, fail with ENXIO. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Matt Macy <mmacy@FreeBSD.org> Signed-off-by: Ryan Moeller <ryan@iXsystems.com> Closes #11117
This commit is contained in:
parent
0c270bb6c4
commit
aaeffd09bf
@ -424,7 +424,6 @@ zvol_geom_destroy(zvol_state_t *zv)
|
||||
VERIFY(zsg->zsg_state == ZVOL_GEOM_RUNNING);
|
||||
mutex_exit(&zv->zv_state_lock);
|
||||
zsg->zsg_provider = NULL;
|
||||
pp->private = NULL;
|
||||
g_wither_geom(pp->geom, ENXIO);
|
||||
}
|
||||
|
||||
@ -1216,6 +1215,9 @@ zvol_free(zvol_state_t *zv)
|
||||
|
||||
if (zv->zv_zso->zso_volmode == ZFS_VOLMODE_GEOM) {
|
||||
struct zvol_state_geom *zsg = &zv->zv_zso->zso_geom;
|
||||
struct g_provider *pp __maybe_unused = zsg->zsg_provider;
|
||||
|
||||
ASSERT3P(pp->private, ==, NULL);
|
||||
|
||||
g_topology_lock();
|
||||
zvol_geom_destroy(zv);
|
||||
@ -1225,8 +1227,9 @@ zvol_free(zvol_state_t *zv)
|
||||
struct zvol_state_dev *zsd = &zv->zv_zso->zso_dev;
|
||||
struct cdev *dev = zsd->zsd_cdev;
|
||||
|
||||
if (dev != NULL)
|
||||
destroy_dev(dev);
|
||||
ASSERT3P(dev->si_drv2, ==, NULL);
|
||||
|
||||
destroy_dev(dev);
|
||||
}
|
||||
|
||||
mutex_destroy(&zv->zv_state_lock);
|
||||
@ -1384,7 +1387,7 @@ zvol_clear_private(zvol_state_t *zv)
|
||||
struct zvol_state_geom *zsg = &zv->zv_zso->zso_geom;
|
||||
struct g_provider *pp = zsg->zsg_provider;
|
||||
|
||||
if (pp == NULL) /* XXX when? */
|
||||
if (pp->private == NULL) /* already cleared */
|
||||
return;
|
||||
|
||||
mtx_lock(&zsg->zsg_queue_mtx);
|
||||
@ -1392,11 +1395,15 @@ zvol_clear_private(zvol_state_t *zv)
|
||||
pp->private = NULL;
|
||||
wakeup_one(&zsg->zsg_queue);
|
||||
while (zsg->zsg_state != ZVOL_GEOM_RUNNING)
|
||||
msleep(&zsg->zsg_state,
|
||||
&zsg->zsg_queue_mtx,
|
||||
msleep(&zsg->zsg_state, &zsg->zsg_queue_mtx,
|
||||
0, "zvol:w", 0);
|
||||
mtx_unlock(&zsg->zsg_queue_mtx);
|
||||
ASSERT(!RW_LOCK_HELD(&zv->zv_suspend_lock));
|
||||
} else if (zv->zv_zso->zso_volmode == ZFS_VOLMODE_DEV) {
|
||||
struct zvol_state_dev *zsd = &zv->zv_zso->zso_dev;
|
||||
struct cdev *dev = zsd->zsd_cdev;
|
||||
|
||||
dev->si_drv2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1408,11 +1415,13 @@ zvol_update_volsize(zvol_state_t *zv, uint64_t volsize)
|
||||
struct zvol_state_geom *zsg = &zv->zv_zso->zso_geom;
|
||||
struct g_provider *pp = zsg->zsg_provider;
|
||||
|
||||
if (pp == NULL) /* XXX when? */
|
||||
return (0);
|
||||
|
||||
g_topology_lock();
|
||||
|
||||
if (pp->private == NULL) {
|
||||
g_topology_unlock();
|
||||
return (SET_ERROR(ENXIO));
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not invoke resize event when initial size was zero.
|
||||
* ZVOL initializes the size on first open, this is not
|
||||
|
Loading…
Reference in New Issue
Block a user