summaryrefslogtreecommitdiffstats
path: root/sys/geom/geom_event.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-09-27 20:38:36 +0000
committerphk <phk@FreeBSD.org>2002-09-27 20:38:36 +0000
commit83aec680cb55261466c7d21ac999144f9985d59e (patch)
tree7b1c2e6a84e3db3c03aa2837e686fbd1569016ee /sys/geom/geom_event.c
parenta09a7e0aa751dc58e8f65d2417ed2cbb9cb3e686 (diff)
downloadFreeBSD-src-83aec680cb55261466c7d21ac999144f9985d59e.zip
FreeBSD-src-83aec680cb55261466c7d21ac999144f9985d59e.tar.gz
Implement g_call_me() as a way for geom methods to schedule operations
to be performed in the event-thread. To do this, we need to lock the eventlist with g_eventlock (nee g_doorlock), since g_call_me() being called from the UP/DOWN paths will not be able to aquire g_topology_lock. This also means that for now these events are not referenced on any particular consumer/provider/geom. For UP/DOWN path use, this will not become a problem since the access() function will make sure we drain any bio's before we dismantle. Sponsored by: DARPA & NAI Labs.
Diffstat (limited to 'sys/geom/geom_event.c')
-rw-r--r--sys/geom/geom_event.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/sys/geom/geom_event.c b/sys/geom/geom_event.c
index c6c7c9a..4188405 100644
--- a/sys/geom/geom_event.c
+++ b/sys/geom/geom_event.c
@@ -151,8 +151,13 @@ g_do_event(struct g_event *ep)
ep, ep->event, ep->class, ep->geom, ep->provider, ep->consumer);
g_topology_assert();
switch (ep->event) {
+ case EV_CALL_ME:
+ ep->func(ep->arg);
+ break;
case EV_NEW_CLASS:
mp2 = ep->class;
+ if (g_shutdown)
+ break;
if (mp2->taste == NULL)
break;
if (g_shutdown)
@@ -226,12 +231,15 @@ one_event(void)
break;
g_orphan_register(pp);
}
+ mtx_lock(&g_eventlock);
ep = TAILQ_FIRST(&g_events);
if (ep == NULL) {
+ mtx_unlock(&g_eventlock);
g_topology_unlock();
return (0);
}
TAILQ_REMOVE(&g_events, ep, events);
+ mtx_unlock(&g_eventlock);
if (ep->class != NULL)
ep->class->event = NULL;
if (ep->geom != NULL)
@@ -288,9 +296,31 @@ g_post_event(enum g_events ev, struct g_class *mp, struct g_geom *gp, struct g_p
KASSERT(cp->event == NULL, ("Double event on consumer"));
cp->event = ep;
}
+ mtx_lock(&g_eventlock);
g_pending_events++;
TAILQ_INSERT_TAIL(&g_events, ep, events);
+ mtx_unlock(&g_eventlock);
+ wakeup(&g_wait_event);
+}
+
+int
+g_call_me(g_call_me_t *func, void *arg)
+{
+ struct g_event *ep;
+
+ g_trace(G_T_TOPOLOGY, "g_call_me(%p, %p", func, arg);
+ ep = g_malloc(sizeof *ep, M_NOWAIT | M_ZERO);
+ if (ep == NULL)
+ return (ENOMEM);
+ ep->event = EV_CALL_ME;
+ ep->func = func;
+ ep->arg = arg;
+ mtx_lock(&g_eventlock);
+ g_pending_events++;
+ TAILQ_INSERT_TAIL(&g_events, ep, events);
+ mtx_unlock(&g_eventlock);
wakeup(&g_wait_event);
+ return (0);
}
#ifdef _KERNEL
OpenPOWER on IntegriCloud