43#include <sys/kernel.h>
46#include <sys/malloc.h>
47#include <sys/module.h>
48#include <sys/module_khelp.h>
51#include <sys/refcount.h>
60 STAILQ_ENTRY(
hhook) hhk_next;
63static MALLOC_DEFINE(M_HHOOK,
"hhook",
"Helper hooks are linked off hhook_head lists");
68#define V_hhook_vhead_list VNET(hhook_vhead_list)
81#define HHHLIST_LOCK() mtx_lock(&hhook_head_list_lock)
82#define HHHLIST_UNLOCK() mtx_unlock(&hhook_head_list_lock)
83#define HHHLIST_LOCK_ASSERT() mtx_assert(&hhook_head_list_lock, MA_OWNED)
85#define HHH_LOCK_INIT(hhh) rm_init(&(hhh)->hhh_lock, "hhook_head rm lock")
86#define HHH_LOCK_DESTROY(hhh) rm_destroy(&(hhh)->hhh_lock)
87#define HHH_WLOCK(hhh) rm_wlock(&(hhh)->hhh_lock)
88#define HHH_WUNLOCK(hhh) rm_wunlock(&(hhh)->hhh_lock)
89#define HHH_RLOCK(hhh, rmpt) rm_rlock(&(hhh)->hhh_lock, (rmpt))
90#define HHH_RUNLOCK(hhh, rmpt) rm_runlock(&(hhh)->hhh_lock, (rmpt))
100 struct rm_priotracker rmpt;
102 KASSERT(hhh->hhh_refcount > 0, (
"hhook_head %p refcount is 0", hhh));
105 STAILQ_FOREACH(hhk, &hhh->hhh_hooks, hhk_next) {
107 hhk->
hhk_helper->h_flags & HELPER_NEEDS_OSD) {
124 ctx_data, hdata, hosd);
135 struct hhook *hhk, *tmp;
144 M_ZERO | ((
flags & HHOOK_WAITOK) ? M_WAITOK : M_NOWAIT));
154 STAILQ_FOREACH(tmp, &hhh->hhh_hooks, hhk_next) {
155 if (tmp->
hhk_func == hki->hook_func &&
164 STAILQ_INSERT_TAIL(&hhh->hhh_hooks, hhk, hhk_next);
192 struct hhook_head **heads_to_hook, *hhh;
193 int error, i, n_heads_to_hook;
203 heads_to_hook =
malloc(n_heads_to_hook *
sizeof(
struct hhook_head *),
204 M_HHOOK,
flags & HHOOK_WAITOK ? M_WAITOK : M_NOWAIT);
205 if (heads_to_hook == NULL)
210 if (hhh->hhh_type == hki->hook_type &&
211 hhh->hhh_id == hki->hook_id) {
212 if (i < n_heads_to_hook) {
213 heads_to_hook[i] = hhh;
214 refcount_acquire(&heads_to_hook[i]->hhh_refcount);
223 for (i--; i >= 0; i--)
224 refcount_release(&heads_to_hook[i]->hhh_refcount);
225 free(heads_to_hook, M_HHOOK);
233 for (i--; i >= 0; i--) {
236 refcount_release(&heads_to_hook[i]->hhh_refcount);
239 free(heads_to_hook, M_HHOOK);
256 STAILQ_FOREACH(tmp, &hhh->hhh_hooks, hhk_next) {
257 if (tmp->
hhk_func == hki->hook_func &&
259 STAILQ_REMOVE(&hhh->hhh_hooks, tmp,
hhook, hhk_next);
277 struct hhook_head *hhh;
281 if (hhh->hhh_type == hki->hook_type &&
282 hhh->hhh_id == hki->hook_id)
297 struct hhook_head *tmphhh;
301 if (tmphhh != NULL) {
307 tmphhh =
malloc(
sizeof(
struct hhook_head), M_HHOOK,
308 M_ZERO | ((
flags & HHOOK_WAITOK) ? M_WAITOK : M_NOWAIT));
313 tmphhh->hhh_type = hhook_type;
314 tmphhh->hhh_id = hhook_id;
315 tmphhh->hhh_nhooks = 0;
316 STAILQ_INIT(&tmphhh->hhh_hooks);
318 refcount_init(&tmphhh->hhh_refcount, 1);
321 if (
flags & HHOOK_HEADISINVNET) {
322 tmphhh->hhh_flags |= HHH_ISINVNET;
324 KASSERT(curvnet != NULL, (
"curvnet is NULL"));
325 tmphhh->hhh_vid = (uintptr_t)curvnet;
338 refcount_release(&tmphhh->hhh_refcount);
346 struct hhook *tmp, *tmp2;
349 KASSERT(
n_hhookheads > 0, (
"n_hhookheads should be > 0"));
351 LIST_REMOVE(hhh, hhh_next);
354 LIST_REMOVE(hhh, hhh_vnext);
357 STAILQ_FOREACH_SAFE(tmp, &hhh->hhh_hooks, hhk_next, tmp2)
378 else if (hhh->hhh_refcount > 1)
393 struct hhook_head *hhh;
412 struct hhook_head *hhh;
416 if (hhh->hhh_type == hhook_type && hhh->hhh_id == hhook_id) {
419 HHOOK_HEADISINVNET) {
420 KASSERT(curvnet != NULL, (
"curvnet is NULL"));
421 if (hhh->hhh_vid != (uintptr_t)curvnet)
425 refcount_acquire(&hhh->hhh_refcount);
438 refcount_release(&hhh->hhh_refcount);
455 if (hhh->hhh_flags & HHH_ISINVNET)
456 ret = HHOOK_HEADISINVNET;
465 struct hhook_head *hhh;
495 struct hhook_head *hhh, *tmphhh;
504 printf(
"%s: hhook_head type=%d, id=%d cleanup required\n",
505 __func__, hhh->hhh_type, hhh->hhh_id);
int hhook_add_hook_lookup(struct hookinfo *hki, uint32_t flags)
#define HHHLIST_LOCK_ASSERT()
static struct mtx hhook_head_list_lock
static MALLOC_DEFINE(M_HHOOK, "hhook", "Helper hooks are linked off hhook_head lists")
int hhook_head_deregister_lookup(int32_t hhook_type, int32_t hhook_id)
VNET_SYSUNINIT(hhook_vnet_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST, hhook_vnet_uninit, NULL)
int hhook_remove_hook_lookup(struct hookinfo *hki)
static void hhook_vnet_init(const void *unused __unused)
static void hhook_vnet_uninit(const void *unused __unused)
void hhook_run_hooks(struct hhook_head *hhh, void *ctx_data, struct osd *hosd)
struct hhookheadhead hhook_head_list
#define HHH_RUNLOCK(hhh, rmpt)
int hhook_head_deregister(struct hhook_head *hhh)
int hhook_remove_hook(struct hhook_head *hhh, struct hookinfo *hki)
#define HHH_LOCK_DESTROY(hhh)
LIST_HEAD(hhookheadhead, hhook_head)
VNET_DEFINE(struct hhookheadhead, hhook_vhead_list)
void hhook_head_release(struct hhook_head *hhh)
#define V_hhook_vhead_list
static uint32_t n_hhookheads
struct hhook_head * hhook_head_get(int32_t hhook_type, int32_t hhook_id)
int hhook_head_register(int32_t hhook_type, int32_t hhook_id, struct hhook_head **hhh, uint32_t flags)
void khelp_new_hhook_registered(struct hhook_head *hhh, uint32_t flags)
static void hhook_head_destroy(struct hhook_head *hhh)
#define HHH_LOCK_INIT(hhh)
#define HHH_RLOCK(hhh, rmpt)
uint32_t hhook_head_is_virtualised_lookup(int32_t hook_type, int32_t hook_id)
MTX_SYSINIT(hhookheadlistlock, &hhook_head_list_lock, "hhook_head list lock", MTX_DEF)
uint32_t hhook_head_is_virtualised(struct hhook_head *hhh)
VNET_SYSINIT(hhook_vnet_init, SI_SUB_INIT_IF, SI_ORDER_FIRST, hhook_vnet_init, NULL)
int hhook_add_hook(struct hhook_head *hhh, struct hookinfo *hki, uint32_t flags)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
void * osd_get(u_int type, struct osd *osd, u_int slot)
struct helper * hhk_helper
int printf(const char *fmt,...)