diff options
author | Ryan Moeller <[email protected]> | 2020-05-04 18:10:41 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2020-05-04 15:10:41 -0700 |
commit | 6f3e1a48287f3d93a78668cb24cf4a2fb12991cd (patch) | |
tree | bd15c8e8e379c3a0258ddb56373295b764e1f7fb | |
parent | 639dfeb83124105615041c45b4574703803ae781 (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.c | 13 |
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; |