Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Jan 2016 17:08:27 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r295045 - in head: . sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201601291708.u0TH8R5p072419@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Fri Jan 29 17:08:26 2016
New Revision: 295045
URL: https://svnweb.freebsd.org/changeset/base/295045

Log:
  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

Modified:
  head/UPDATING
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c

Modified: head/UPDATING
==============================================================================
--- head/UPDATING	Fri Jan 29 17:05:30 2016	(r295044)
+++ head/UPDATING	Fri Jan 29 17:08:26 2016	(r295045)
@@ -31,6 +31,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11
 	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.

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c	Fri Jan 29 17:05:30 2016	(r295044)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c	Fri Jan 29 17:08:26 2016	(r295045)
@@ -134,6 +134,9 @@ SYSCTL_NODE(_vfs_zfs, OID_AUTO, vol, CTL
 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 fla
 		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 fla
 		 */
 		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 fla
 	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 @@ out:
 #ifdef illumos
 	mutex_exit(&zfsdev_state_lock);
 #else
-	mutex_exit(&zfsdev_state_lock);
+	if (locked)
+		mutex_exit(&zfsdev_state_lock);
 #endif
 	return (err);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601291708.u0TH8R5p072419>