FreeBSD: Fix spurious failure in zvol_geom_open
In zvol_geom_open on first open we need to guarantee that the namespace lock is held to avoid spurious failures in zvol_first_open. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Ryan Moeller <freqlabs@FreeBSD.org> Signed-off-by: Matt Macy <mmacy@FreeBSD.org> Closes #10841
This commit is contained in:
parent
8639ca86da
commit
f4c8e9c69b
|
@ -210,6 +210,7 @@ zvol_geom_open(struct g_provider *pp, int flag, int count)
|
||||||
zvol_state_t *zv;
|
zvol_state_t *zv;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
boolean_t drop_suspend = B_TRUE;
|
boolean_t drop_suspend = B_TRUE;
|
||||||
|
boolean_t drop_namespace = B_FALSE;
|
||||||
|
|
||||||
if (!zpool_on_zvol && tsd_get(zfs_geom_probe_vdev_key) != NULL) {
|
if (!zpool_on_zvol && tsd_get(zfs_geom_probe_vdev_key) != NULL) {
|
||||||
/*
|
/*
|
||||||
|
@ -223,13 +224,28 @@ zvol_geom_open(struct g_provider *pp, int flag, int count)
|
||||||
return (SET_ERROR(EOPNOTSUPP));
|
return (SET_ERROR(EOPNOTSUPP));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
rw_enter(&zvol_state_lock, ZVOL_RW_READER);
|
rw_enter(&zvol_state_lock, ZVOL_RW_READER);
|
||||||
zv = pp->private;
|
zv = pp->private;
|
||||||
if (zv == NULL) {
|
if (zv == NULL) {
|
||||||
|
if (drop_namespace)
|
||||||
|
mutex_exit(&spa_namespace_lock);
|
||||||
rw_exit(&zvol_state_lock);
|
rw_exit(&zvol_state_lock);
|
||||||
return (SET_ERROR(ENXIO));
|
return (SET_ERROR(ENXIO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (zv->zv_open_count == 0 && !mutex_owned(&spa_namespace_lock)) {
|
||||||
|
/*
|
||||||
|
* We need to guarantee that the namespace lock is held
|
||||||
|
* to avoid spurious failures in zvol_first_open
|
||||||
|
*/
|
||||||
|
drop_namespace = B_TRUE;
|
||||||
|
if (!mutex_tryenter(&spa_namespace_lock)) {
|
||||||
|
rw_exit(&zvol_state_lock);
|
||||||
|
mutex_enter(&spa_namespace_lock);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
mutex_enter(&zv->zv_state_lock);
|
mutex_enter(&zv->zv_state_lock);
|
||||||
|
|
||||||
ASSERT(zv->zv_zso->zso_volmode == ZFS_VOLMODE_GEOM);
|
ASSERT(zv->zv_zso->zso_volmode == ZFS_VOLMODE_GEOM);
|
||||||
|
@ -291,6 +307,8 @@ zvol_geom_open(struct g_provider *pp, int flag, int count)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
zv->zv_open_count += count;
|
zv->zv_open_count += count;
|
||||||
|
if (drop_namespace)
|
||||||
|
mutex_exit(&spa_namespace_lock);
|
||||||
mutex_exit(&zv->zv_state_lock);
|
mutex_exit(&zv->zv_state_lock);
|
||||||
if (drop_suspend)
|
if (drop_suspend)
|
||||||
rw_exit(&zv->zv_suspend_lock);
|
rw_exit(&zv->zv_suspend_lock);
|
||||||
|
@ -300,6 +318,8 @@ out_open_count:
|
||||||
if (zv->zv_open_count == 0)
|
if (zv->zv_open_count == 0)
|
||||||
zvol_last_close(zv);
|
zvol_last_close(zv);
|
||||||
out_mutex:
|
out_mutex:
|
||||||
|
if (drop_namespace)
|
||||||
|
mutex_exit(&spa_namespace_lock);
|
||||||
mutex_exit(&zv->zv_state_lock);
|
mutex_exit(&zv->zv_state_lock);
|
||||||
if (drop_suspend)
|
if (drop_suspend)
|
||||||
rw_exit(&zv->zv_suspend_lock);
|
rw_exit(&zv->zv_suspend_lock);
|
||||||
|
|
Loading…
Reference in New Issue