Add a sysctl to allow ZFS pools backed by zvols

Change 294329 removed the ability to build ZFS pools that are backed by
zvols, because having that ability (even if it's not used) leads to
deadlocks. By popular demand, I'm adding an off-by-default sysctl to
reenable that ability.

Reviewed by:	lidl, delphij
MFC after:	Never
Sponsored by:	Spectra Logic Corp
Differential Revision:	https://reviews.freebsd.org/D4998
This commit is contained in:
Alan Somers 2016-01-29 17:08:26 +00:00
parent 1fc390d1a1
commit d4b9233a96
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=295045
2 changed files with 36 additions and 7 deletions

View File

@ -31,6 +31,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
20160129:
Building ZFS pools on top of zvols is prohibited by default. That
feature has never worked safely; it's always been prone to deadlocks.
Using a zvol as the backing store for a VM guest's virtual disk will
still work, even if the guest is using ZFS. Legacy behavior can be
restored by setting vfs.zfs.vol.recursive=1.
20160119:
The NONE and HPN patches has been removed from OpenSSH. They are
still available in the security/openssh-portable port.

View File

@ -134,6 +134,9 @@ SYSCTL_NODE(_vfs_zfs, OID_AUTO, vol, CTLFLAG_RW, 0, "ZFS VOLUME");
static int volmode = ZFS_VOLMODE_GEOM;
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, mode, CTLFLAG_RWTUN, &volmode, 0,
"Expose as GEOM providers (1), device files (2) or neither");
static boolean_t zpool_on_zvol = B_FALSE;
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, recursive, CTLFLAG_RWTUN, &zpool_on_zvol, 0,
"Allow zpools to use zvols as vdevs (DANGEROUS)");
#endif
typedef struct zvol_extent {
@ -1114,7 +1117,9 @@ zvol_open(struct g_provider *pp, int flag, int count)
return (err);
}
#else /* !illumos */
if (tsd_get(zfs_geom_probe_vdev_key) != NULL) {
boolean_t locked = B_FALSE;
if (!zpool_on_zvol && tsd_get(zfs_geom_probe_vdev_key) != NULL) {
/*
* if zfs_geom_probe_vdev_key is set, that means that zfs is
* attempting to probe geom providers while looking for a
@ -1125,19 +1130,34 @@ zvol_open(struct g_provider *pp, int flag, int count)
*/
return (EOPNOTSUPP);
}
mutex_enter(&zfsdev_state_lock);
/*
* Protect against recursively entering spa_namespace_lock
* when spa_open() is used for a pool on a (local) ZVOL(s).
* This is needed since we replaced upstream zfsdev_state_lock
* with spa_namespace_lock in the ZVOL code.
* We are using the same trick as spa_open().
* Note that calls in zvol_first_open which need to resolve
* pool name to a spa object will enter spa_open()
* recursively, but that function already has all the
* necessary protection.
*/
if (!MUTEX_HELD(&zfsdev_state_lock)) {
mutex_enter(&zfsdev_state_lock);
locked = B_TRUE;
}
zv = pp->private;
if (zv == NULL) {
mutex_exit(&zfsdev_state_lock);
if (locked)
mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(ENXIO));
}
if (zv->zv_total_opens == 0) {
err = zvol_first_open(zv);
if (err) {
mutex_exit(&zfsdev_state_lock);
if (locked)
mutex_exit(&zfsdev_state_lock);
return (err);
}
pp->mediasize = zv->zv_volsize;
@ -1171,7 +1191,8 @@ zvol_open(struct g_provider *pp, int flag, int count)
mutex_exit(&zfsdev_state_lock);
#else
zv->zv_total_opens += count;
mutex_exit(&zfsdev_state_lock);
if (locked)
mutex_exit(&zfsdev_state_lock);
#endif
return (err);
@ -1181,7 +1202,8 @@ zvol_open(struct g_provider *pp, int flag, int count)
#ifdef illumos
mutex_exit(&zfsdev_state_lock);
#else
mutex_exit(&zfsdev_state_lock);
if (locked)
mutex_exit(&zfsdev_state_lock);
#endif
return (err);
}