summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Moeller <[email protected]>2020-05-04 18:10:41 -0400
committerGitHub <[email protected]>2020-05-04 15:10:41 -0700
commit6f3e1a48287f3d93a78668cb24cf4a2fb12991cd (patch)
treebd15c8e8e379c3a0258ddb56373295b764e1f7fb
parent639dfeb83124105615041c45b4574703803ae781 (diff)
Avoid the GEOM topology lock recursion when autoexpanding a pool
The steps to reproduce the problem: mdconfig -a -t swap -s 3g -u 0 gpart create -s GPT md0 gpart add -t freebsd-zfs -s 1g md0 zpool create -o autoexpand=on foo md0p1 gpart resize -i 1 -s 2g md0 Authored by: pjd <[email protected]> FreeBSD-commit: freebsd/freebsd@bccd2db598ede073d6d06781a5fd3b119c08aa81 Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Ported-by: Ryan Moeller <[email protected]> Signed-off-by: Ryan Moeller <[email protected]> Closes #10270
-rw-r--r--module/os/freebsd/zfs/vdev_geom.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/module/os/freebsd/zfs/vdev_geom.c b/module/os/freebsd/zfs/vdev_geom.c
index d87bbbc18..0df343190 100644
--- a/module/os/freebsd/zfs/vdev_geom.c
+++ b/module/os/freebsd/zfs/vdev_geom.c
@@ -38,6 +38,10 @@
#include <geom/geom_disk.h>
#include <geom/geom_int.h>
+#ifndef g_topology_locked
+#define g_topology_locked() sx_xlocked(&topology_lock)
+#endif
+
/*
* Virtual device vector for GEOM.
*/
@@ -800,7 +804,7 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
{
struct g_provider *pp;
struct g_consumer *cp;
- int error, has_trim;
+ int error, has_trim, locked;
uint16_t rate;
/*
@@ -827,7 +831,9 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
}
DROP_GIANT();
- g_topology_lock();
+ locked = g_topology_locked();
+ if (!locked)
+ g_topology_lock();
error = 0;
if (vd->vdev_spa->spa_is_splitting ||
@@ -922,7 +928,8 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
vdev_geom_set_physpath(vd, cp, /* do_null_update */B_FALSE);
}
- g_topology_unlock();
+ if (!locked)
+ g_topology_unlock();
PICKUP_GIANT();
if (cp == NULL) {
vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;