1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-19 10:53:58 +00:00

This should not be permitted, but some GEOM classes held the topology lock

while doing g_(read|write)_data() (e.g. BSD). This can cause a deadlock
in MIRROR class. Not sure if this is safe to drop the topology lock in BSD
class, so change the code in MIRROR class to avoid this deadlock.
This commit is contained in:
Pawel Jakub Dawidek 2004-12-21 18:42:51 +00:00
parent 54bab03f04
commit f663832b75
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=139140

View File

@ -214,12 +214,20 @@ g_mirror_event_get(struct g_mirror_softc *sc)
mtx_lock(&sc->sc_events_mtx);
ep = TAILQ_FIRST(&sc->sc_events);
if (ep != NULL)
TAILQ_REMOVE(&sc->sc_events, ep, e_next);
mtx_unlock(&sc->sc_events_mtx);
return (ep);
}
static void
g_mirror_event_remove(struct g_mirror_softc *sc, struct g_mirror_event *ep)
{
mtx_lock(&sc->sc_events_mtx);
TAILQ_REMOVE(&sc->sc_events, ep, e_next);
mtx_unlock(&sc->sc_events_mtx);
}
static void
g_mirror_event_cancel(struct g_mirror_disk *disk)
{
@ -500,6 +508,7 @@ g_mirror_destroy_device(struct g_mirror_softc *sc)
g_mirror_destroy_disk(disk);
}
while ((ep = g_mirror_event_get(sc)) != NULL) {
g_mirror_event_remove(sc, ep);
if ((ep->e_flags & G_MIRROR_EVENT_DONTWAIT) != 0)
g_mirror_event_free(ep);
else {
@ -1461,8 +1470,8 @@ g_mirror_worker(void *arg)
* This is important to handle events before any I/O requests.
*/
ep = g_mirror_event_get(sc);
if (ep != NULL) {
g_topology_lock();
if (ep != NULL && g_topology_try_lock()) {
g_mirror_event_remove(sc, ep);
if ((ep->e_flags & G_MIRROR_EVENT_DEVICE) != 0) {
/* Update only device status. */
G_MIRROR_DEBUG(3,
@ -1507,6 +1516,14 @@ g_mirror_worker(void *arg)
mtx_lock(&sc->sc_queue_mtx);
bp = bioq_first(&sc->sc_queue);
if (bp == NULL) {
if (ep != NULL) {
/*
* No I/O requests and topology lock was
* already held? Try again.
*/
mtx_unlock(&sc->sc_queue_mtx);
continue;
}
if ((sc->sc_flags &
G_MIRROR_DEVICE_FLAG_DESTROY) != 0) {
mtx_unlock(&sc->sc_queue_mtx);
@ -1586,10 +1603,17 @@ g_mirror_worker(void *arg)
G_MIRROR_DEBUG(5, "%s: I'm here 6.", __func__);
continue;
}
if (ep != NULL) {
/*
* We have some pending events, don't sleep now.
*/
G_MIRROR_DEBUG(5, "%s: I'm here 7.", __func__);
continue;
}
mtx_lock(&sc->sc_queue_mtx);
if (bioq_first(&sc->sc_queue) != NULL) {
mtx_unlock(&sc->sc_queue_mtx);
G_MIRROR_DEBUG(5, "%s: I'm here 7.", __func__);
G_MIRROR_DEBUG(5, "%s: I'm here 8.", __func__);
continue;
}
timeout = hz / sps;
@ -1600,7 +1624,7 @@ g_mirror_worker(void *arg)
} else {
g_mirror_register_request(bp);
}
G_MIRROR_DEBUG(5, "%s: I'm here 8.", __func__);
G_MIRROR_DEBUG(5, "%s: I'm here 9.", __func__);
}
}