summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2013-07-27 15:02:19 +0000
committermav <mav@FreeBSD.org>2013-07-27 15:02:19 +0000
commit2b433ed7774220e85663873a45c2aa18d9f66fe0 (patch)
tree1d1b60a5dcf784d009b813886135a6ccc6d06223 /sys/geom
parent9422356f0bce3d487909287f59096d27929e27db (diff)
downloadFreeBSD-src-2b433ed7774220e85663873a45c2aa18d9f66fe0.zip
FreeBSD-src-2b433ed7774220e85663873a45c2aa18d9f66fe0.tar.gz
Introduce 3 seconds timeout on `graid stop` command (mostly with -f flag).
Since completion waiting goes in g_event thread, it may cause GEOM deadlock if consumer on top (for example, ZFS) uses g_event thread for closing.
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/raid/g_raid.c17
-rw-r--r--sys/geom/raid/g_raid_ctl.c2
2 files changed, 8 insertions, 11 deletions
diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c
index 0d7ac49..fd6d69c 100644
--- a/sys/geom/raid/g_raid.c
+++ b/sys/geom/raid/g_raid.c
@@ -2171,7 +2171,7 @@ g_raid_destroy_disk(struct g_raid_disk *disk)
int
g_raid_destroy(struct g_raid_softc *sc, int how)
{
- int opens;
+ int error, opens;
g_topology_assert_not();
if (sc == NULL)
@@ -2188,11 +2188,13 @@ g_raid_destroy(struct g_raid_softc *sc, int how)
G_RAID_DEBUG1(1, sc,
"%d volumes are still open.",
opens);
+ sx_xunlock(&sc->sc_lock);
return (EBUSY);
case G_RAID_DESTROY_DELAYED:
G_RAID_DEBUG1(1, sc,
"Array will be destroyed on last close.");
sc->sc_stopping = G_RAID_DESTROY_DELAYED;
+ sx_xunlock(&sc->sc_lock);
return (EBUSY);
case G_RAID_DESTROY_HARD:
G_RAID_DEBUG1(1, sc,
@@ -2206,9 +2208,9 @@ g_raid_destroy(struct g_raid_softc *sc, int how)
/* Wake up worker to let it selfdestruct. */
g_raid_event_send(sc, G_RAID_NODE_E_WAKE, 0);
/* Sleep until node destroyed. */
- sx_sleep(&sc->sc_stopping, &sc->sc_lock,
- PRIBIO | PDROP, "r:destroy", 0);
- return (0);
+ error = sx_sleep(&sc->sc_stopping, &sc->sc_lock,
+ PRIBIO | PDROP, "r:destroy", hz * 3);
+ return (error == EWOULDBLOCK ? EBUSY : 0);
}
static void
@@ -2303,8 +2305,6 @@ g_raid_destroy_geom(struct gctl_req *req __unused,
sx_xlock(&sc->sc_lock);
g_cancel_event(sc);
error = g_raid_destroy(gp->softc, G_RAID_DESTROY_SOFT);
- if (error != 0)
- sx_xunlock(&sc->sc_lock);
g_topology_lock();
return (error);
}
@@ -2469,7 +2469,6 @@ g_raid_shutdown_post_sync(void *arg, int howto)
struct g_geom *gp, *gp2;
struct g_raid_softc *sc;
struct g_raid_volume *vol;
- int error;
mp = arg;
DROP_GIANT();
@@ -2483,9 +2482,7 @@ g_raid_shutdown_post_sync(void *arg, int howto)
TAILQ_FOREACH(vol, &sc->sc_volumes, v_next)
g_raid_clean(vol, -1);
g_cancel_event(sc);
- error = g_raid_destroy(sc, G_RAID_DESTROY_DELAYED);
- if (error != 0)
- sx_xunlock(&sc->sc_lock);
+ g_raid_destroy(sc, G_RAID_DESTROY_DELAYED);
g_topology_lock();
}
g_topology_unlock();
diff --git a/sys/geom/raid/g_raid_ctl.c b/sys/geom/raid/g_raid_ctl.c
index 428f315..dc1536a 100644
--- a/sys/geom/raid/g_raid_ctl.c
+++ b/sys/geom/raid/g_raid_ctl.c
@@ -181,7 +181,7 @@ g_raid_ctl_stop(struct gctl_req *req, struct g_class *mp)
sx_xlock(&sc->sc_lock);
error = g_raid_destroy(sc, how);
if (error != 0)
- sx_xunlock(&sc->sc_lock);
+ gctl_error(req, "Array is busy.");
g_topology_lock();
}
OpenPOWER on IntegriCloud