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)