- merge all the hook insertion and deletion code so that we don't create
a fourth copy. - add exithook to be executed when a process exits.
This commit is contained in:
parent
dc7d18ff88
commit
f7d98e2451
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_subr.c,v 1.79 2002/03/04 02:25:23 simonb Exp $ */
|
||||
/* $NetBSD: kern_subr.c,v 1.80 2002/03/17 22:19:20 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -90,7 +90,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.79 2002/03/04 02:25:23 simonb Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.80 2002/03/17 22:19:20 christos Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_md.h"
|
||||
|
@ -117,6 +117,21 @@ static struct device *finddevice __P((const char *));
|
|||
static struct device *getdisk __P((char *, int, int, dev_t *, int));
|
||||
static struct device *parsedisk __P((char *, int, int, dev_t *));
|
||||
|
||||
/*
|
||||
* A generic linear hook.
|
||||
*/
|
||||
struct hook_desc {
|
||||
LIST_ENTRY(hook_desc) hk_list;
|
||||
void (*hk_fn) __P((void *));
|
||||
void *hk_arg;
|
||||
};
|
||||
typedef LIST_HEAD(, hook_desc) hook_list_t;
|
||||
|
||||
static void *hook_establish __P((hook_list_t *, void (*)(void *), void *));
|
||||
static void hook_disestablish __P((hook_list_t *, void *));
|
||||
static void hook_destroy __P((hook_list_t *));
|
||||
static void hook_proc_run __P((hook_list_t *, struct proc *));
|
||||
|
||||
int
|
||||
uiomove(buf, n, uio)
|
||||
void *buf;
|
||||
|
@ -287,54 +302,95 @@ hashdone(hashtbl, mtype)
|
|||
free(hashtbl, mtype);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
hook_establish(list, fn, arg)
|
||||
hook_list_t *list;
|
||||
void (*fn) __P((void *));
|
||||
void *arg;
|
||||
{
|
||||
struct hook_desc *hd;
|
||||
|
||||
hd = malloc(sizeof(*hd), M_DEVBUF, M_NOWAIT);
|
||||
if (hd == NULL)
|
||||
return (NULL);
|
||||
|
||||
hd->hk_fn = fn;
|
||||
hd->hk_arg = arg;
|
||||
LIST_INSERT_HEAD(list, hd, hk_list);
|
||||
|
||||
return (hd);
|
||||
}
|
||||
|
||||
static void
|
||||
hook_disestablish(list, vhook)
|
||||
hook_list_t *list;
|
||||
void *vhook;
|
||||
{
|
||||
#ifdef DIAGNOSTIC
|
||||
struct hook_desc *hd;
|
||||
|
||||
for (hd = list->lh_first; hd != NULL; hd = hd->hk_list.le_next)
|
||||
if (hd == vhook)
|
||||
break;
|
||||
if (hd == NULL)
|
||||
panic("hook_disestablish: hook not established");
|
||||
#endif
|
||||
LIST_REMOVE((struct hook_desc *)vhook, hk_list);
|
||||
free(vhook, M_DEVBUF);
|
||||
}
|
||||
|
||||
static void
|
||||
hook_destroy(list)
|
||||
hook_list_t *list;
|
||||
{
|
||||
struct hook_desc *hd;
|
||||
|
||||
while ((hd = list->lh_first) != NULL) {
|
||||
LIST_REMOVE(hd, hk_list);
|
||||
free(hd, M_DEVBUF);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hook_proc_run(list, p)
|
||||
hook_list_t *list;
|
||||
struct proc *p;
|
||||
{
|
||||
struct hook_desc *hd;
|
||||
|
||||
for (hd = LIST_FIRST(list); hd != NULL; hd = LIST_NEXT(hd, hk_list)) {
|
||||
((void (*) __P((struct proc *, void *)))*hd->hk_fn)(p,
|
||||
hd->hk_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "Shutdown hook" types, functions, and variables.
|
||||
*
|
||||
* Should be invoked immediately before the
|
||||
* system is halted or rebooted, i.e. after file systems unmounted,
|
||||
* after crash dump done, etc.
|
||||
*
|
||||
* Each shutdown hook is removed from the list before it's run, so that
|
||||
* it won't be run again.
|
||||
*/
|
||||
|
||||
struct shutdownhook_desc {
|
||||
LIST_ENTRY(shutdownhook_desc) sfd_list;
|
||||
void (*sfd_fn) __P((void *));
|
||||
void *sfd_arg;
|
||||
};
|
||||
|
||||
LIST_HEAD(, shutdownhook_desc) shutdownhook_list;
|
||||
hook_list_t shutdownhook_list;
|
||||
|
||||
void *
|
||||
shutdownhook_establish(fn, arg)
|
||||
void (*fn) __P((void *));
|
||||
void *arg;
|
||||
{
|
||||
struct shutdownhook_desc *ndp;
|
||||
|
||||
ndp = (struct shutdownhook_desc *)
|
||||
malloc(sizeof(*ndp), M_DEVBUF, M_NOWAIT);
|
||||
if (ndp == NULL)
|
||||
return (NULL);
|
||||
|
||||
ndp->sfd_fn = fn;
|
||||
ndp->sfd_arg = arg;
|
||||
LIST_INSERT_HEAD(&shutdownhook_list, ndp, sfd_list);
|
||||
|
||||
return (ndp);
|
||||
return hook_establish(&shutdownhook_list, fn, arg);
|
||||
}
|
||||
|
||||
void
|
||||
shutdownhook_disestablish(vhook)
|
||||
void *vhook;
|
||||
{
|
||||
#ifdef DIAGNOSTIC
|
||||
struct shutdownhook_desc *dp;
|
||||
|
||||
for (dp = shutdownhook_list.lh_first; dp != NULL;
|
||||
dp = dp->sfd_list.le_next)
|
||||
if (dp == vhook)
|
||||
break;
|
||||
if (dp == NULL)
|
||||
panic("shutdownhook_disestablish: hook not established");
|
||||
#endif
|
||||
|
||||
LIST_REMOVE((struct shutdownhook_desc *)vhook, sfd_list);
|
||||
free(vhook, M_DEVBUF);
|
||||
return hook_disestablish(&shutdownhook_list, vhook);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -348,11 +404,11 @@ shutdownhook_disestablish(vhook)
|
|||
void
|
||||
doshutdownhooks()
|
||||
{
|
||||
struct shutdownhook_desc *dp;
|
||||
struct hook_desc *dp;
|
||||
|
||||
while ((dp = shutdownhook_list.lh_first) != NULL) {
|
||||
LIST_REMOVE(dp, sfd_list);
|
||||
(*dp->sfd_fn)(dp->sfd_arg);
|
||||
LIST_REMOVE(dp, hk_list);
|
||||
(*dp->hk_fn)(dp->hk_arg);
|
||||
#if 0
|
||||
/*
|
||||
* Don't bother freeing the hook structure,, since we may
|
||||
|
@ -366,6 +422,102 @@ doshutdownhooks()
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "Mountroot hook" types, functions, and variables.
|
||||
*/
|
||||
|
||||
hook_list_t mountroothook_list;
|
||||
|
||||
void *
|
||||
mountroothook_establish(fn, dev)
|
||||
void (*fn) __P((struct device *));
|
||||
struct device *dev;
|
||||
{
|
||||
return hook_establish(&mountroothook_list, (void (*)__P((void *)))fn,
|
||||
dev);
|
||||
}
|
||||
|
||||
void
|
||||
mountroothook_disestablish(vhook)
|
||||
void *vhook;
|
||||
{
|
||||
return hook_disestablish(&mountroothook_list, vhook);
|
||||
}
|
||||
|
||||
void
|
||||
mountroothook_destroy()
|
||||
{
|
||||
hook_destroy(&mountroothook_list);
|
||||
}
|
||||
|
||||
void
|
||||
domountroothook()
|
||||
{
|
||||
struct hook_desc *hd;
|
||||
|
||||
for (hd = mountroothook_list.lh_first; hd != NULL;
|
||||
hd = hd->hk_list.le_next) {
|
||||
if (hd->hk_arg == (void *)root_device) {
|
||||
(*hd->hk_fn)(hd->hk_arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hook_list_t exechook_list;
|
||||
|
||||
void *
|
||||
exechook_establish(fn, arg)
|
||||
void (*fn) __P((struct proc *, void *));
|
||||
void *arg;
|
||||
{
|
||||
return hook_establish(&exechook_list, (void (*) __P((void *)))fn, arg);
|
||||
}
|
||||
|
||||
void
|
||||
exechook_disestablish(vhook)
|
||||
void *vhook;
|
||||
{
|
||||
hook_disestablish(&exechook_list, vhook);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run exec hooks.
|
||||
*/
|
||||
void
|
||||
doexechooks(p)
|
||||
struct proc *p;
|
||||
{
|
||||
hook_proc_run(&exechook_list, p);
|
||||
}
|
||||
|
||||
hook_list_t exithook_list;
|
||||
|
||||
void *
|
||||
exithook_establish(fn, arg)
|
||||
void (*fn) __P((struct proc *, void *));
|
||||
void *arg;
|
||||
{
|
||||
return hook_establish(&exithook_list, (void (*) __P((void *)))fn, arg);
|
||||
}
|
||||
|
||||
void
|
||||
exithook_disestablish(vhook)
|
||||
void *vhook;
|
||||
{
|
||||
hook_disestablish(&exithook_list, vhook);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run exit hooks.
|
||||
*/
|
||||
void
|
||||
doexithooks(p)
|
||||
struct proc *p;
|
||||
{
|
||||
hook_proc_run(&exithook_list, p);
|
||||
}
|
||||
|
||||
/*
|
||||
* "Power hook" types, functions, and variables.
|
||||
* The list of power hooks is kept ordered with the last registered hook
|
||||
|
@ -373,7 +525,6 @@ doshutdownhooks()
|
|||
* When running the hooks on power down the hooks are called in reverse
|
||||
* registration order, when powering up in registration order.
|
||||
*/
|
||||
|
||||
struct powerhook_desc {
|
||||
CIRCLEQ_ENTRY(powerhook_desc) sfd_list;
|
||||
void (*sfd_fn) __P((int, void *));
|
||||
|
@ -441,147 +592,6 @@ dopowerhooks(why)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "Mountroot hook" types, functions, and variables.
|
||||
*/
|
||||
|
||||
struct mountroothook_desc {
|
||||
LIST_ENTRY(mountroothook_desc) mrd_list;
|
||||
struct device *mrd_device;
|
||||
void (*mrd_func) __P((struct device *));
|
||||
};
|
||||
|
||||
LIST_HEAD(, mountroothook_desc) mountroothook_list;
|
||||
|
||||
void *
|
||||
mountroothook_establish(func, dev)
|
||||
void (*func) __P((struct device *));
|
||||
struct device *dev;
|
||||
{
|
||||
struct mountroothook_desc *mrd;
|
||||
|
||||
mrd = (struct mountroothook_desc *)
|
||||
malloc(sizeof(*mrd), M_DEVBUF, M_NOWAIT);
|
||||
if (mrd == NULL)
|
||||
return (NULL);
|
||||
|
||||
mrd->mrd_device = dev;
|
||||
mrd->mrd_func = func;
|
||||
LIST_INSERT_HEAD(&mountroothook_list, mrd, mrd_list);
|
||||
|
||||
return (mrd);
|
||||
}
|
||||
|
||||
void
|
||||
mountroothook_disestablish(vhook)
|
||||
void *vhook;
|
||||
{
|
||||
#ifdef DIAGNOSTIC
|
||||
struct mountroothook_desc *mrd;
|
||||
|
||||
for (mrd = mountroothook_list.lh_first; mrd != NULL;
|
||||
mrd = mrd->mrd_list.le_next)
|
||||
if (mrd == vhook)
|
||||
break;
|
||||
if (mrd == NULL)
|
||||
panic("mountroothook_disestablish: hook not established");
|
||||
#endif
|
||||
|
||||
LIST_REMOVE((struct mountroothook_desc *)vhook, mrd_list);
|
||||
free(vhook, M_DEVBUF);
|
||||
}
|
||||
|
||||
void
|
||||
mountroothook_destroy()
|
||||
{
|
||||
struct mountroothook_desc *mrd;
|
||||
|
||||
while ((mrd = mountroothook_list.lh_first) != NULL) {
|
||||
LIST_REMOVE(mrd, mrd_list);
|
||||
free(mrd, M_DEVBUF);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
domountroothook()
|
||||
{
|
||||
struct mountroothook_desc *mrd;
|
||||
|
||||
for (mrd = mountroothook_list.lh_first; mrd != NULL;
|
||||
mrd = mrd->mrd_list.le_next) {
|
||||
if (mrd->mrd_device == root_device) {
|
||||
(*mrd->mrd_func)(root_device);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Exec hook code.
|
||||
*/
|
||||
|
||||
struct exechook_desc {
|
||||
LIST_ENTRY(exechook_desc) ehk_list;
|
||||
void (*ehk_fn) __P((struct proc *, void *));
|
||||
void *ehk_arg;
|
||||
};
|
||||
|
||||
LIST_HEAD(, exechook_desc) exechook_list;
|
||||
|
||||
void *
|
||||
exechook_establish(fn, arg)
|
||||
void (*fn) __P((struct proc *, void *));
|
||||
void *arg;
|
||||
{
|
||||
struct exechook_desc *edp;
|
||||
|
||||
edp = (struct exechook_desc *)
|
||||
malloc(sizeof(*edp), M_DEVBUF, M_NOWAIT);
|
||||
if (edp == NULL)
|
||||
return (NULL);
|
||||
|
||||
edp->ehk_fn = fn;
|
||||
edp->ehk_arg = arg;
|
||||
LIST_INSERT_HEAD(&exechook_list, edp, ehk_list);
|
||||
|
||||
return (edp);
|
||||
}
|
||||
|
||||
void
|
||||
exechook_disestablish(vhook)
|
||||
void *vhook;
|
||||
{
|
||||
#ifdef DIAGNOSTIC
|
||||
struct exechook_desc *edp;
|
||||
|
||||
for (edp = exechook_list.lh_first; edp != NULL;
|
||||
edp = edp->ehk_list.le_next)
|
||||
if (edp == vhook)
|
||||
break;
|
||||
if (edp == NULL)
|
||||
panic("exechook_disestablish: hook not established");
|
||||
#endif
|
||||
|
||||
LIST_REMOVE((struct exechook_desc *)vhook, ehk_list);
|
||||
free(vhook, M_DEVBUF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run exec hooks.
|
||||
*/
|
||||
void
|
||||
doexechooks(p)
|
||||
struct proc *p;
|
||||
{
|
||||
struct exechook_desc *edp;
|
||||
|
||||
for (edp = LIST_FIRST(&exechook_list);
|
||||
edp != NULL;
|
||||
edp = LIST_NEXT(edp, ehk_list)) {
|
||||
(*edp->ehk_fn)(p, edp->ehk_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the root device and, if instructed to, the root file system.
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: systm.h,v 1.141 2002/03/04 02:24:37 simonb Exp $ */
|
||||
/* $NetBSD: systm.h,v 1.142 2002/03/17 22:19:22 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1988, 1991, 1993
|
||||
|
@ -305,6 +305,13 @@ void *exechook_establish __P((void (*)(struct proc *, void *), void *));
|
|||
void exechook_disestablish __P((void *));
|
||||
void doexechooks __P((struct proc *));
|
||||
|
||||
/*
|
||||
* Exit hooks. Subsystems may want to do cleanup when a process exits.
|
||||
*/
|
||||
void *exithook_establish __P((void (*)(struct proc *, void *), void *));
|
||||
void exithook_disestablish __P((void *));
|
||||
void doexithooks __P((struct proc *));
|
||||
|
||||
int uiomove __P((void *, int, struct uio *));
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
|
Loading…
Reference in New Issue