diff options
author | mav <mav@FreeBSD.org> | 2016-10-28 18:18:53 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2016-10-28 18:18:53 +0000 |
commit | c8c4c6244daef57c7b854dfe5de8a10d8675634b (patch) | |
tree | a8e6cb6833101513ffe3bbb9ecea29fca0736409 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c | |
parent | c60f65ebc02c81225657a336afc72d7d08f4fe36 (diff) | |
download | FreeBSD-src-c8c4c6244daef57c7b854dfe5de8a10d8675634b.zip FreeBSD-src-c8c4c6244daef57c7b854dfe5de8a10d8675634b.tar.gz |
MFC r294329 (by asomers): Disallow zvol-backed ZFS pools
Using zvols as backing devices for ZFS pools is fraught with panics and
deadlocks. For example, attempting to online a missing device in the
presence of a zvol can cause a panic when vdev_geom tastes the zvol. Better
to completely disable vdev_geom from ever opening a zvol. The solution
relies on setting a thread-local variable during vdev_geom_open, and
returning EOPNOTSUPP during zvol_open if that thread-local variable is set.
Remove the check for MUTEX_HELD(&zfsdev_state_lock) in zvol_open. Its intent
was to prevent a recursive mutex acquisition panic. However, the new check
for the thread-local variable also fixes that problem.
Also, fix a panic in vdev_geom_taste_orphan. For an unknown reason, this
function was set to panic. But it can occur that a device disappears during
tasting, and it causes no problems to ignore this departure.
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c index ac994f5..deb2bfd 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c @@ -63,6 +63,13 @@ TUNABLE_INT("vfs.zfs.vdev.bio_delete_disable", &vdev_geom_bio_delete_disable); SYSCTL_INT(_vfs_zfs_vdev, OID_AUTO, bio_delete_disable, CTLFLAG_RW, &vdev_geom_bio_delete_disable, 0, "Disable BIO_DELETE"); +/* + * Thread local storage used to indicate when a thread is probing geoms + * for their guids. If NULL, this thread is not tasting geoms. If non NULL, + * it is looking for a replacement for the vdev_t* that is its value. + */ +uint_t zfs_geom_probe_vdev_key; + static void vdev_geom_set_rotation_rate(vdev_t *vd, struct g_consumer *cp) { @@ -329,9 +336,8 @@ vdev_geom_io(struct g_consumer *cp, int cmd, void *data, off_t offset, off_t siz static void vdev_geom_taste_orphan(struct g_consumer *cp) { - - KASSERT(1 == 0, ("%s called while tasting %s.", __func__, - cp->provider->name)); + ZFS_LOG(0, "WARNING: Orphan %s while tasting its VDev GUID.", + cp->provider->name); } static int @@ -578,7 +584,6 @@ vdev_geom_attach_by_guids(vdev_t *vd) g_topology_assert(); zgp = g_new_geomf(&zfs_vdev_class, "zfs::vdev::taste"); - /* This orphan function should be never called. */ zgp->orphan = vdev_geom_taste_orphan; zcp = g_new_consumer(zgp); @@ -714,6 +719,9 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, size_t bufsize; int error; + /* Set the TLS to indicate downstack that we should not access zvols*/ + VERIFY(tsd_set(zfs_geom_probe_vdev_key, vd) == 0); + /* * We must have a pathname, and it must be absolute. */ @@ -764,6 +772,9 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, } } + /* Clear the TLS now that tasting is done */ + VERIFY(tsd_set(zfs_geom_probe_vdev_key, NULL) == 0); + if (cp == NULL) { ZFS_LOG(1, "Provider %s not found.", vd->vdev_path); error = ENOENT; |