summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/kern/kern_khelp.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-06 16:20:21 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-11 10:08:08 +0100
commit66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch)
tree48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/kern/kern_khelp.c
parentDefine __GLOBL1() and __GLOBL() (diff)
downloadrtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/kern/kern_khelp.c')
-rw-r--r--freebsd/sys/kern/kern_khelp.c211
1 files changed, 56 insertions, 155 deletions
diff --git a/freebsd/sys/kern/kern_khelp.c b/freebsd/sys/kern/kern_khelp.c
index 9e4127da..e1192ae8 100644
--- a/freebsd/sys/kern/kern_khelp.c
+++ b/freebsd/sys/kern/kern_khelp.c
@@ -1,7 +1,7 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
- * Copyright (c) 2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010,2013 Lawrence Stewart <lstewart@freebsd.org>
* Copyright (c) 2010 The FreeBSD Foundation
* All rights reserved.
*
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/param.h>
#include <sys/kernel.h>
#include <sys/hhook.h>
-#include <sys/jail.h>
#include <sys/khelp.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/malloc.h>
@@ -54,8 +53,6 @@ __FBSDID("$FreeBSD$");
#include <sys/rwlock.h>
#include <sys/systm.h>
-#include <net/vnet.h>
-
static struct rwlock khelp_list_lock;
RW_SYSINIT(khelplistlock, &khelp_list_lock, "helper list lock");
@@ -63,6 +60,7 @@ static TAILQ_HEAD(helper_head, helper) helpers = TAILQ_HEAD_INITIALIZER(helpers)
/* Private function prototypes. */
static inline void khelp_remove_osd(struct helper *h, struct osd *hosd);
+void khelp_new_hhook_registered(struct hhook_head *hhh, uint32_t flags);
#define KHELP_LIST_WLOCK() rw_wlock(&khelp_list_lock)
#define KHELP_LIST_WUNLOCK() rw_wunlock(&khelp_list_lock)
@@ -76,33 +74,32 @@ khelp_register_helper(struct helper *h)
struct helper *tmph;
int error, i, inserted;
- error = 0;
- inserted = 0;
+ error = inserted = 0;
refcount_init(&h->h_refcount, 0);
h->h_id = osd_register(OSD_KHELP, NULL, NULL);
/* It's only safe to add the hooks after osd_register(). */
- if (h->h_nhooks > 0) {
- for (i = 0; i < h->h_nhooks && !error; i++) {
- /* We don't require the module to assign hook_helper. */
- h->h_hooks[i].hook_helper = h;
- error = khelp_add_hhook(&h->h_hooks[i], HHOOK_NOWAIT);
- }
-
- if (error) {
- for (i--; i >= 0; i--)
- khelp_remove_hhook(&h->h_hooks[i]);
-
- osd_deregister(OSD_KHELP, h->h_id);
- }
+ for (i = 0; i < h->h_nhooks && !error; i++) {
+ /* We don't require the module to assign hook_helper. */
+ h->h_hooks[i].hook_helper = h;
+ error = hhook_add_hook_lookup(&h->h_hooks[i], HHOOK_WAITOK);
+ if (error)
+ printf("%s: \"%s\" khelp module unable to "
+ "hook type %d id %d due to error %d\n", __func__,
+ h->h_name, h->h_hooks[i].hook_type,
+ h->h_hooks[i].hook_id, error);
}
- if (!error) {
+ if (error) {
+ for (i--; i >= 0; i--)
+ hhook_remove_hook_lookup(&h->h_hooks[i]);
+ osd_deregister(OSD_KHELP, h->h_id);
+ } else {
KHELP_LIST_WLOCK();
/*
* Keep list of helpers sorted in descending h_id order. Due to
* the way osd_set() works, a sorted list ensures
- * init_helper_osd() will operate with improved efficiency.
+ * khelp_init_osd() will operate with improved efficiency.
*/
TAILQ_FOREACH(tmph, &helpers, h_next) {
if (tmph->h_id < h->h_id) {
@@ -126,8 +123,6 @@ khelp_deregister_helper(struct helper *h)
struct helper *tmph;
int error, i;
- error = 0;
-
KHELP_LIST_WLOCK();
if (h->h_refcount > 0)
error = EBUSY;
@@ -144,10 +139,8 @@ khelp_deregister_helper(struct helper *h)
KHELP_LIST_WUNLOCK();
if (!error) {
- if (h->h_nhooks > 0) {
- for (i = 0; i < h->h_nhooks; i++)
- khelp_remove_hhook(&h->h_hooks[i]);
- }
+ for (i = 0; i < h->h_nhooks; i++)
+ hhook_remove_hook_lookup(&h->h_hooks[i]);
osd_deregister(OSD_KHELP, h->h_id);
}
@@ -265,28 +258,13 @@ khelp_get_id(char *hname)
int
khelp_add_hhook(struct hookinfo *hki, uint32_t flags)
{
- VNET_ITERATOR_DECL(vnet_iter);
int error;
- error = 0;
-
/*
- * XXXLAS: If a helper is dynamically adding a helper hook function at
- * runtime using this function, we should update the helper's h_hooks
- * struct member to include the additional hookinfo struct.
+ * XXXLAS: Should probably include the functionality to update the
+ * helper's h_hooks struct member.
*/
-
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- error = hhook_add_hook_lookup(hki, flags);
- CURVNET_RESTORE();
-#ifdef VIMAGE
- if (error)
- break;
-#endif
- }
- VNET_LIST_RUNLOCK_NOSLEEP();
+ error = hhook_add_hook_lookup(hki, flags);
return (error);
}
@@ -294,32 +272,47 @@ khelp_add_hhook(struct hookinfo *hki, uint32_t flags)
int
khelp_remove_hhook(struct hookinfo *hki)
{
- VNET_ITERATOR_DECL(vnet_iter);
int error;
- error = 0;
-
/*
- * XXXLAS: If a helper is dynamically removing a helper hook function at
- * runtime using this function, we should update the helper's h_hooks
- * struct member to remove the defunct hookinfo struct.
+ * XXXLAS: Should probably include the functionality to update the
+ * helper's h_hooks struct member.
*/
-
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- error = hhook_remove_hook_lookup(hki);
- CURVNET_RESTORE();
-#ifdef VIMAGE
- if (error)
- break;
-#endif
- }
- VNET_LIST_RUNLOCK_NOSLEEP();
+ error = hhook_remove_hook_lookup(hki);
return (error);
}
+/*
+ * Private KPI between hhook and khelp that allows khelp modules to insert hook
+ * functions into hhook points which register after the modules were loaded.
+ */
+void
+khelp_new_hhook_registered(struct hhook_head *hhh, uint32_t flags)
+{
+ struct helper *h;
+ int error, i;
+
+ KHELP_LIST_RLOCK();
+ TAILQ_FOREACH(h, &helpers, h_next) {
+ for (i = 0; i < h->h_nhooks; i++) {
+ if (hhh->hhh_type != h->h_hooks[i].hook_type ||
+ hhh->hhh_id != h->h_hooks[i].hook_id)
+ continue;
+ error = hhook_add_hook(hhh, &h->h_hooks[i], flags);
+ if (error) {
+ printf("%s: \"%s\" khelp module unable to "
+ "hook type %d id %d due to error %d\n",
+ __func__, h->h_name,
+ h->h_hooks[i].hook_type,
+ h->h_hooks[i].hook_id, error);
+ error = 0;
+ }
+ }
+ }
+ KHELP_LIST_RUNLOCK();
+}
+
#ifndef __rtems__
int
khelp_modevent(module_t mod, int event_type, void *data)
@@ -381,95 +374,3 @@ khelp_modevent(module_t mod, int event_type, void *data)
return (error);
}
#endif /* __rtems__ */
-
-/*
- * This function is called in two separate situations:
- *
- * - When the kernel is booting, it is called directly by the SYSINIT framework
- * to allow Khelp modules which were compiled into the kernel or loaded by the
- * boot loader to insert their non-virtualised hook functions into the kernel.
- *
- * - When the kernel is booting or a vnet is created, this function is also
- * called indirectly through khelp_vnet_init() by the vnet initialisation code.
- * In this situation, Khelp modules are able to insert their virtualised hook
- * functions into the virtualised hook points in the vnet which is being
- * initialised. In the case where the kernel is not compiled with "options
- * VIMAGE", this step is still run once at boot, but the hook functions get
- * transparently inserted into the standard unvirtualised network stack.
- */
-static void
-khelp_init(const void *vnet)
-{
- struct helper *h;
- int error, i, vinit;
- int32_t htype, hid;
-
- error = 0;
- vinit = vnet != NULL;
-
- KHELP_LIST_RLOCK();
- TAILQ_FOREACH(h, &helpers, h_next) {
- for (i = 0; i < h->h_nhooks && !error; i++) {
- htype = h->h_hooks[i].hook_type;
- hid = h->h_hooks[i].hook_id;
-
- /*
- * If we're doing a virtualised init (vinit != 0) and
- * the hook point is virtualised, or we're doing a plain
- * sysinit at boot and the hook point is not
- * virtualised, insert the hook.
- */
- if ((hhook_head_is_virtualised_lookup(htype, hid) ==
- HHOOK_HEADISINVNET && vinit) ||
- (!hhook_head_is_virtualised_lookup(htype, hid) &&
- !vinit)) {
- error = hhook_add_hook_lookup(&h->h_hooks[i],
- HHOOK_NOWAIT);
- }
- }
-
- if (error) {
- /* Remove any helper's hooks we successfully added. */
- for (i--; i >= 0; i--)
- hhook_remove_hook_lookup(&h->h_hooks[i]);
-
- printf("%s: Failed to add hooks for helper \"%s\" (%p)",
- __func__, h->h_name, h);
- if (vinit)
- printf(" to vnet %p.\n", vnet);
- else
- printf(".\n");
-
- error = 0;
- }
- }
- KHELP_LIST_RUNLOCK();
-}
-
-/*
- * Vnet created and being initialised.
- */
-static void
-khelp_vnet_init(const void *unused __unused)
-{
-
- khelp_init(TD_TO_VNET(curthread));
-}
-
-
-/*
- * As the kernel boots, allow Khelp modules which were compiled into the kernel
- * or loaded by the boot loader to insert their non-virtualised hook functions
- * into the kernel.
- */
-SYSINIT(khelp_init, SI_SUB_PROTO_END, SI_ORDER_FIRST, khelp_init, NULL);
-
-/*
- * When a vnet is created and being initialised, we need to insert the helper
- * hook functions for all currently registered Khelp modules into the vnet's
- * helper hook points. The hhook KPI provides a mechanism for subsystems which
- * export helper hook points to clean up on vnet shutdown, so we don't need a
- * VNET_SYSUNINIT for Khelp.
- */
-VNET_SYSINIT(khelp_vnet_init, SI_SUB_PROTO_END, SI_ORDER_FIRST,
- khelp_vnet_init, NULL);