37 #include <sys/cdefs.h>
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/hhook.h>
43 #include <sys/khelp.h>
44 #include <sys/malloc.h>
45 #include <sys/module.h>
46 #include <sys/module_khelp.h>
48 #include <sys/queue.h>
49 #include <sys/refcount.h>
50 #include <sys/systm.h>
58 STAILQ_ENTRY(
hhook) hhk_next;
61 static
MALLOC_DEFINE(M_HHOOK, "
hhook", "Helper hooks are linked off hhook_head lists");
65 VNET_DEFINE(struct hhookheadhead, hhook_vhead_list);
66 #define V_hhook_vhead_list VNET(hhook_vhead_list)
79 #define HHHLIST_LOCK() mtx_lock(&hhook_head_list_lock)
80 #define HHHLIST_UNLOCK() mtx_unlock(&hhook_head_list_lock)
81 #define HHHLIST_LOCK_ASSERT() mtx_assert(&hhook_head_list_lock, MA_OWNED)
83 #define HHH_LOCK_INIT(hhh) rm_init(&(hhh)->hhh_lock, "hhook_head rm lock")
84 #define HHH_LOCK_DESTROY(hhh) rm_destroy(&(hhh)->hhh_lock)
85 #define HHH_WLOCK(hhh) rm_wlock(&(hhh)->hhh_lock)
86 #define HHH_WUNLOCK(hhh) rm_wunlock(&(hhh)->hhh_lock)
87 #define HHH_RLOCK(hhh, rmpt) rm_rlock(&(hhh)->hhh_lock, (rmpt))
88 #define HHH_RUNLOCK(hhh, rmpt) rm_runlock(&(hhh)->hhh_lock, (rmpt))
98 struct rm_priotracker rmpt;
100 KASSERT(hhh->hhh_refcount > 0, (
"hhook_head %p refcount is 0", hhh));
103 STAILQ_FOREACH(hhk, &hhh->hhh_hooks, hhk_next) {
104 if (hhk->
hhk_helper->h_flags & HELPER_NEEDS_OSD) {
121 ctx_data, hdata, hosd);
132 struct hhook *hhk, *tmp;
140 hhk =
malloc(
sizeof(
struct hhook), M_HHOOK,
141 M_ZERO | ((flags & HHOOK_WAITOK) ? M_WAITOK : M_NOWAIT));
151 STAILQ_FOREACH(tmp, &hhh->hhh_hooks, hhk_next) {
152 if (tmp->
hhk_func == hki->hook_func &&
161 STAILQ_INSERT_TAIL(&hhh->hhh_hooks, hhk, hhk_next);
189 struct hhook_head **heads_to_hook, *hhh;
190 int error, i, n_heads_to_hook;
200 heads_to_hook =
malloc(n_heads_to_hook *
sizeof(
struct hhook_head *),
201 M_HHOOK, flags & HHOOK_WAITOK ? M_WAITOK : M_NOWAIT);
202 if (heads_to_hook == NULL)
206 LIST_FOREACH(hhh, &hhook_head_list, hhh_next) {
207 if (hhh->hhh_type == hki->hook_type &&
208 hhh->hhh_id == hki->hook_id) {
209 if (i < n_heads_to_hook) {
210 heads_to_hook[i] = hhh;
211 refcount_acquire(&heads_to_hook[i]->hhh_refcount);
220 for (i--; i >= 0; i--)
221 refcount_release(&heads_to_hook[i]->hhh_refcount);
222 free(heads_to_hook, M_HHOOK);
230 for (i--; i >= 0; i--) {
233 refcount_release(&heads_to_hook[i]->hhh_refcount);
236 free(heads_to_hook, M_HHOOK);
253 STAILQ_FOREACH(tmp, &hhh->hhh_hooks, hhk_next) {
254 if (tmp->
hhk_func == hki->hook_func &&
256 STAILQ_REMOVE(&hhh->hhh_hooks, tmp, hhook, hhk_next);
274 struct hhook_head *hhh;
277 LIST_FOREACH(hhh, &hhook_head_list, hhh_next) {
278 if (hhh->hhh_type == hki->hook_type &&
279 hhh->hhh_id == hki->hook_id)
294 struct hhook_head *tmphhh;
298 if (tmphhh != NULL) {
304 tmphhh =
malloc(
sizeof(
struct hhook_head), M_HHOOK,
305 M_ZERO | ((flags & HHOOK_WAITOK) ? M_WAITOK : M_NOWAIT));
310 tmphhh->hhh_type = hhook_type;
311 tmphhh->hhh_id = hhook_id;
312 tmphhh->hhh_nhooks = 0;
313 STAILQ_INIT(&tmphhh->hhh_hooks);
315 refcount_init(&tmphhh->hhh_refcount, 1);
318 if (flags & HHOOK_HEADISINVNET) {
319 tmphhh->hhh_flags |= HHH_ISINVNET;
321 KASSERT(curvnet != NULL, (
"curvnet is NULL"));
322 tmphhh->hhh_vid = (uintptr_t)curvnet;
326 LIST_INSERT_HEAD(&hhook_head_list, tmphhh, hhh_next);
335 refcount_release(&tmphhh->hhh_refcount);
343 struct hhook *tmp, *tmp2;
346 KASSERT(n_hhookheads > 0, (
"n_hhookheads should be > 0"));
348 LIST_REMOVE(hhh, hhh_next);
351 LIST_REMOVE(hhh, hhh_vnext);
354 STAILQ_FOREACH_SAFE(tmp, &hhh->hhh_hooks, hhk_next, tmp2)
375 else if (hhh->hhh_refcount > 1)
390 struct hhook_head *hhh;
409 struct hhook_head *hhh;
412 LIST_FOREACH(hhh, &hhook_head_list, hhh_next) {
413 if (hhh->hhh_type == hhook_type && hhh->hhh_id == hhook_id) {
416 HHOOK_HEADISINVNET) {
417 KASSERT(curvnet != NULL, (
"curvnet is NULL"));
418 if (hhh->hhh_vid != (uintptr_t)curvnet)
422 refcount_acquire(&hhh->hhh_refcount);
435 refcount_release(&hhh->hhh_refcount);
452 if (hhh->hhh_flags & HHH_ISINVNET)
453 ret = HHOOK_HEADISINVNET;
462 struct hhook_head *hhh;
492 struct hhook_head *hhh, *tmphhh;
501 printf(
"%s: hhook_head type=%d, id=%d cleanup required\n",
502 __func__, hhh->hhh_type, hhh->hhh_id);
struct hhookheadhead hhook_head_list
int hhook_head_deregister(struct hhook_head *hhh)
int hhook_remove_hook(struct hhook_head *hhh, struct hookinfo *hki)
int hhook_add_hook_lookup(struct hookinfo *hki, uint32_t flags)
VNET_SYSUNINIT(hhook_vnet_uninit, SI_SUB_MBUF, SI_ORDER_ANY, hhook_vnet_uninit, NULL)
void * malloc(unsigned long size, struct malloc_type *mtp, int flags)
uint32_t hhook_head_is_virtualised(struct hhook_head *hhh)
struct hhook_head * hhook_head_get(int32_t hhook_type, int32_t hhook_id)
LIST_HEAD(hhookheadhead, hhook_head)
void hhook_head_release(struct hhook_head *hhh)
int hhook_add_hook(struct hhook_head *hhh, struct hookinfo *hki, uint32_t flags)
static void hhook_vnet_uninit(const void *unused __unused)
#define HHHLIST_LOCK_ASSERT()
void khelp_new_hhook_registered(struct hhook_head *hhh, uint32_t flags)
void * osd_get(u_int type, struct osd *osd, u_int slot)
#define V_hhook_vhead_list
static uint32_t n_hhookheads
uint32_t hhook_head_is_virtualised_lookup(int32_t hook_type, int32_t hook_id)
VNET_DEFINE(struct hhookheadhead, hhook_vhead_list)
#define HHH_RUNLOCK(hhh, rmpt)
#define HHH_RLOCK(hhh, rmpt)
int hhook_head_register(int32_t hhook_type, int32_t hhook_id, struct hhook_head **hhh, uint32_t flags)
int hhook_remove_hook_lookup(struct hookinfo *hki)
MTX_SYSINIT(hhookheadlistlock,&hhook_head_list_lock,"hhook_head list lock", MTX_DEF)
#define HHH_LOCK_DESTROY(hhh)
struct helper * hhk_helper
int hhook_head_deregister_lookup(int32_t hhook_type, int32_t hhook_id)
void hhook_run_hooks(struct hhook_head *hhh, void *ctx_data, struct osd *hosd)
void free(void *addr, struct malloc_type *mtp)
static struct mtx hhook_head_list_lock
int printf(const char *fmt,...)
static void hhook_vnet_init(const void *unused __unused)
static MALLOC_DEFINE(M_HHOOK,"hhook","Helper hooks are linked off hhook_head lists")
#define HHH_LOCK_INIT(hhh)
VNET_SYSINIT(hhook_vnet_init, SI_SUB_MBUF, SI_ORDER_FIRST, hhook_vnet_init, NULL)
static void hhook_head_destroy(struct hhook_head *hhh)