summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph/ng_base.c')
-rw-r--r--sys/netgraph/ng_base.c732
1 files changed, 475 insertions, 257 deletions
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 0cbd63d..975f8fb 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -65,11 +65,23 @@
MODULE_VERSION(netgraph, 1);
-/* List of all nodes */
+/* List of all active nodes */
static LIST_HEAD(, ng_node) ng_nodelist;
static struct mtx ng_nodelist_mtx;
-/* NETISR queue */
+#ifdef NETGRAPH_DEBUG
+
+static SLIST_HEAD(, ng_node) ng_allnodes;
+static LIST_HEAD(, ng_node) ng_freenodes; /* in debug, we never free() them */
+static SLIST_HEAD(, ng_hook) ng_allhooks;
+static LIST_HEAD(, ng_hook) ng_freehooks; /* in debug, we never free() them */
+
+static void ng_dumpitems(void);
+static void ng_dumpnodes(void);
+static void ng_dumphooks(void);
+
+#endif /* NETGRAPH_DEBUG */
+
/* List nodes with unallocated work */
static TAILQ_HEAD(, ng_node) ng_worklist = TAILQ_HEAD_INITIALIZER(ng_worklist);
static struct mtx ng_worklist_mtx;
@@ -102,7 +114,7 @@ static void ng_flush_input_queue(struct ng_queue * ngq);
static void ng_setisr(node_p node);
static node_p ng_ID2noderef(ng_ID_t ID);
-/* imported */
+/* imported , these used to be externally visible, some may go back */
int ng_bypass(hook_p hook1, hook_p hook2);
void ng_cutlinks(node_p node);
int ng_con_nodes(node_p node, const char *name, node_p node2,
@@ -116,6 +128,7 @@ int ng_make_node(const char *type, node_p *nodepp);
int ng_mkpeer(node_p node, const char *name, const char *name2, char *type);
int ng_path_parse(char *addr, char **node, char **path, char **hook);
void ng_rmnode(node_p node);
+void ng_unname(node_p node);
/* Our own netgraph malloc type */
@@ -127,9 +140,105 @@ MALLOC_DEFINE(M_NETGRAPH_META, "netgraph_meta", "netgraph name storage");
MALLOC_DEFINE(M_NETGRAPH_MSG, "netgraph_msg", "netgraph name storage");
/* Should not be visible outside this file */
+
+#define _NG_ALLOC_HOOK(hook) \
+ MALLOC(hook, hook_p, sizeof(*hook), M_NETGRAPH_HOOK, M_NOWAIT | M_ZERO)
+#define _NG_ALLOC_NODE(node) \
+ MALLOC(node, node_p, sizeof(*node), M_NETGRAPH_NODE, M_NOWAIT | M_ZERO)
+
+#ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
+/*
+ * In debug mode:
+ * In an attempt to help track reference count screwups
+ * we do not free objects back to the malloc system, but keep them
+ * in a local cache where we can examine them and keep information safely
+ * after they have been freed.
+ * We use this scheme for nodes and hooks, and to some extent for items.
+ */
+static __inline hook_p
+ng_alloc_hook(void)
+{
+ hook_p hook;
+ SLIST_ENTRY(ng_hook) temp;
+ mtx_enter(&ng_nodelist_mtx, MTX_DEF);
+ hook = LIST_FIRST(&ng_freehooks);
+ if (hook) {
+ LIST_REMOVE(hook, hk_hooks);
+ bcopy(&hook->hk_all, &temp, sizeof(temp));
+ bzero(hook, sizeof(struct ng_hook));
+ bcopy(&temp, &hook->hk_all, sizeof(temp));
+ mtx_exit(&ng_nodelist_mtx, MTX_DEF);
+ hook->hk_magic = HK_MAGIC;
+ } else {
+ mtx_exit(&ng_nodelist_mtx, MTX_DEF);
+ _NG_ALLOC_HOOK(hook);
+ if (hook) {
+ hook->hk_magic = HK_MAGIC;
+ mtx_enter(&ng_nodelist_mtx, MTX_DEF);
+ SLIST_INSERT_HEAD(&ng_allhooks, hook, hk_all);
+ mtx_exit(&ng_nodelist_mtx, MTX_DEF);
+ }
+ }
+ return (hook);
+}
+
+static __inline node_p
+ng_alloc_node(void)
+{
+ node_p node;
+ SLIST_ENTRY(ng_node) temp;
+ mtx_enter(&ng_nodelist_mtx, MTX_DEF);
+ node = LIST_FIRST(&ng_freenodes);
+ if (node) {
+ LIST_REMOVE(node, nd_nodes);
+ bcopy(&node->nd_all, &temp, sizeof(temp));
+ bzero(node, sizeof(struct ng_node));
+ bcopy(&temp, &node->nd_all, sizeof(temp));
+ mtx_exit(&ng_nodelist_mtx, MTX_DEF);
+ node->nd_magic = ND_MAGIC;
+ } else {
+ mtx_exit(&ng_nodelist_mtx, MTX_DEF);
+ _NG_ALLOC_NODE(node);
+ if (node) {
+ node->nd_magic = ND_MAGIC;
+ mtx_enter(&ng_nodelist_mtx, MTX_DEF);
+ SLIST_INSERT_HEAD(&ng_allnodes, node, nd_all);
+ mtx_exit(&ng_nodelist_mtx, MTX_DEF);
+ }
+ }
+ return (node);
+}
+
+#define NG_ALLOC_HOOK(hook) do { (hook) = ng_alloc_hook(); } while (0)
+#define NG_ALLOC_NODE(node) do { (node) = ng_alloc_node(); } while (0)
+
+
+#define NG_FREE_HOOK(hook) \
+ do { \
+ mtx_enter(&ng_nodelist_mtx, MTX_DEF); \
+ LIST_INSERT_HEAD(&ng_freehooks, hook, hk_hooks); \
+ hook->hk_magic = 0; \
+ mtx_exit(&ng_nodelist_mtx, MTX_DEF); \
+ } while (0)
+
+#define NG_FREE_NODE(node) \
+ do { \
+ mtx_enter(&ng_nodelist_mtx, MTX_DEF); \
+ LIST_INSERT_HEAD(&ng_freenodes, node, nd_nodes); \
+ node->nd_magic = 0; \
+ mtx_exit(&ng_nodelist_mtx, MTX_DEF); \
+ } while (0)
+
+#else /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
+
+#define NG_ALLOC_HOOK(hook) _NG_ALLOC_HOOK(hook)
+#define NG_ALLOC_NODE(node) _NG_ALLOC_NODE(node)
+
#define NG_FREE_HOOK(hook) do { FREE((hook), M_NETGRAPH_HOOK); } while (0)
#define NG_FREE_NODE(node) do { FREE((node), M_NETGRAPH_NODE); } while (0)
-#define NG_FREE_NAME(name) do { FREE((name), M_NETGRAPH_NAME); } while (0)
+
+#endif /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
+
/* Warning: Generally use NG_FREE_ITEM() instead */
#define NG_FREE_ITEM_REAL(item) do { FREE((item), M_NETGRAPH_ITEM); } while (0)
@@ -384,7 +493,7 @@ ng_make_node(const char *typename, node_p *nodepp)
if (type->constructor != NULL) {
if ((error = ng_make_node_common(type, nodepp)) == 0) {
if ((error = ((*type->constructor)(*nodepp)) != 0)) {
- ng_unref(*nodepp);
+ NG_NODE_UNREF(*nodepp);
}
}
} else {
@@ -395,6 +504,7 @@ ng_make_node(const char *typename, node_p *nodepp)
* call ng_make_node_common() directly to get the
* netgraph part initialised.
*/
+ TRAP_ERROR
error = EINVAL;
}
return (error);
@@ -417,44 +527,48 @@ ng_make_node_common(struct ng_type *type, node_p *nodepp)
}
/* Make a node and try attach it to the type */
- MALLOC(node, node_p, sizeof(*node), M_NETGRAPH_NODE, M_NOWAIT | M_ZERO);
+ NG_ALLOC_NODE(node);
if (node == NULL) {
TRAP_ERROR;
return (ENOMEM);
}
- node->type = type;
- node->refs++; /* note reference */
+ node->nd_type = type;
+ NG_NODE_REF(node); /* note reference */
type->refs++;
- mtx_init(&node->input_queue.q_mtx, "netgraph node mutex", 0);
- node->input_queue.queue = NULL;
- node->input_queue.last = &node->input_queue.queue;
- node->input_queue.q_flags = 0;
- node->input_queue.q_node = node;
+ mtx_init(&node->nd_input_queue.q_mtx, "netgraph node mutex", 0);
+ node->nd_input_queue.queue = NULL;
+ node->nd_input_queue.last = &node->nd_input_queue.queue;
+ node->nd_input_queue.q_flags = 0;
+ node->nd_input_queue.q_node = node;
/* Initialize hook list for new node */
- LIST_INIT(&node->hooks);
+ LIST_INIT(&node->nd_hooks);
/* Link us into the node linked list */
mtx_enter(&ng_nodelist_mtx, MTX_DEF);
- LIST_INSERT_HEAD(&ng_nodelist, node, nodes);
+ LIST_INSERT_HEAD(&ng_nodelist, node, nd_nodes);
mtx_exit(&ng_nodelist_mtx, MTX_DEF);
/* get an ID and put us in the hash chain */
mtx_enter(&ng_idhash_mtx, MTX_DEF);
- do { /* wrap protection, even if silly */
+ for (;;) { /* wrap protection, even if silly */
node_p node2 = NULL;
- node->ID = nextID++; /* 137 per second for 1 year before wrap */
- if ((node->ID == 0) || (node2 = ng_ID2noderef(node->ID))) {
+ node->nd_ID = nextID++; /* 137/second for 1 year before wrap */
+ /* Is there a problem with the new number? */
+ if ((node->nd_ID == 0)
+ || (node2 = ng_ID2noderef(node->nd_ID))) {
if (node2) {
- ng_unref(node2);
+ NG_NODE_UNREF(node2);
node2 = NULL;
}
- continue; /* try again */
+ } else {
+ break;
}
- } while (0);
- LIST_INSERT_HEAD(&ng_ID_hash[node->ID % ID_HASH_SIZE], node, idnodes);
+ }
+ LIST_INSERT_HEAD(&ng_ID_hash[node->nd_ID % ID_HASH_SIZE],
+ node, nd_idnodes);
mtx_exit(&ng_idhash_mtx, MTX_DEF);
/* Done */
@@ -477,41 +591,69 @@ void
ng_rmnode(node_p node)
{
/* Check if it's already shutting down */
- if ((node->flags & NG_CLOSING) != 0)
+ if ((node->nd_flags & NG_CLOSING) != 0)
return;
/* Add an extra reference so it doesn't go away during this */
- node->refs++;
+ NG_NODE_REF(node);
- /* Mark it invalid so any newcomers know not to try use it */
- node->flags |= NG_INVALID|NG_CLOSING;
+ /*
+ * Mark it invalid so any newcomers know not to try use it
+ * Also add our own mark so we can't recurse
+ * note that NG_INVALID does not do this as it's also set during
+ * creation
+ */
+ node->nd_flags |= NG_INVALID|NG_CLOSING;
- ng_unname(node);
ng_cutlinks(node);
+
/*
* Drain the input queue forceably.
+ * it has no hooks so what's it going to do, bleed on someone?
+ * Theoretically we came here from a queue entry that was added
+ * Just before the queue was closed, so it should be empty anyway.
*/
- ng_flush_input_queue(&node->input_queue);
+ ng_flush_input_queue(&node->nd_input_queue);
/*
* Take us off the work queue if we are there.
+ * We definatly have no work to be done.
*/
ng_worklist_remove(node);
-
/* Ask the type if it has anything to do in this case */
- if (node->type && node->type->shutdown) {
- (*node->type->shutdown)(node);
+ if (node->nd_type && node->nd_type->shutdown) {
+ (*node->nd_type->shutdown)(node);
} else { /* do the default thing */
- ng_unref(node); /* XXX hmmmmm check this */
+ NG_NODE_UNREF(node);
+ }
+ if (NG_NODE_IS_VALID(node)) {
+ /*
+ * Well, blow me down if the node code hasn't declared
+ * that it doesn't want to die.
+ * Presumably it is a persistant node.
+ * XXX we need a way to tell the node
+ * "No, really.. the hardware's going away.. REALLY die"
+ * We need a way
+ */
+ return;
}
- /* Remove extra reference, possibly the last */
- ng_unref(node);
+ ng_unname(node); /* basically a NOP these days */
+
+ /*
+ * Remove extra reference, possibly the last
+ * Possible other holders of references may include
+ * timeout callouts, but theoretically the node's supposed to
+ * have cancelled them. Possibly hardware dependencies may
+ * force a driver to 'linger' with a reference.
+ */
+ NG_NODE_UNREF(node);
}
/*
* Called by the destructor to remove any STANDARD external references
+ * May one day have it's own message to call it..
*/
void
ng_cutlinks(node_p node)
@@ -519,17 +661,17 @@ ng_cutlinks(node_p node)
hook_p hook;
/* Make sure that this is set to stop infinite loops */
- node->flags |= NG_INVALID;
+ node->nd_flags |= NG_INVALID;
/*
* Drain the input queue forceably.
* We also do this in ng_rmnode
* to make sure we get all code paths.
*/
- ng_flush_input_queue(&node->input_queue);
+ ng_flush_input_queue(&node->nd_input_queue);
/* Notify all remaining connected nodes to disconnect */
- while ((hook = LIST_FIRST(&node->hooks)) != NULL)
+ while ((hook = LIST_FIRST(&node->nd_hooks)) != NULL)
ng_destroy_hook(hook);
}
@@ -537,26 +679,26 @@ ng_cutlinks(node_p node)
* Remove a reference to the node, possibly the last
*/
void
-ng_unref(node_p node)
+ng_unref_node(node_p node)
{
- int s;
+ int v;
+ do {
+ v = node->nd_refs;
+ } while (! atomic_cmpset_int(&node->nd_refs, v, v - 1));
- s = splhigh();
-/* XXX not atomic.. fix */
- if (--node->refs <= 0) {
+ if (v == 1) { /* we were the last */
mtx_enter(&ng_nodelist_mtx, MTX_DEF);
- node->type->refs--; /* XXX maybe should get types lock? */
- LIST_REMOVE(node, nodes);
+ node->nd_type->refs--; /* XXX maybe should get types lock? */
+ LIST_REMOVE(node, nd_nodes);
mtx_exit(&ng_nodelist_mtx, MTX_DEF);
mtx_enter(&ng_idhash_mtx, MTX_DEF);
- LIST_REMOVE(node, idnodes);
+ LIST_REMOVE(node, nd_idnodes);
mtx_exit(&ng_idhash_mtx, MTX_DEF);
NG_FREE_NODE(node);
}
- splx(s);
}
/************************************************************************
@@ -565,22 +707,22 @@ ng_unref(node_p node)
static node_p
ng_ID2noderef(ng_ID_t ID)
{
- node_p np;
+ node_p node;
mtx_enter(&ng_idhash_mtx, MTX_DEF);
- LIST_FOREACH(np, &ng_ID_hash[ID % ID_HASH_SIZE], idnodes) {
- if (np->ID == ID)
+ LIST_FOREACH(node, &ng_ID_hash[ID % ID_HASH_SIZE], nd_idnodes) {
+ if (node->nd_ID == ID)
break;
}
- if(np)
- np->refs++;
+ if(node)
+ NG_NODE_REF(node);
mtx_exit(&ng_idhash_mtx, MTX_DEF);
- return(np);
+ return(node);
}
ng_ID_t
ng_node2ID(node_p node)
{
- return (node?node->ID:0);
+ return (node?node->nd_ID:0);
}
/************************************************************************
@@ -612,13 +754,13 @@ ng_name_node(node_p node, const char *name)
/* Check the name isn't already being used */
if ((node2 = ng_name2noderef(node, name)) != NULL) {
- ng_unref(node2);
+ NG_NODE_UNREF(node2);
TRAP_ERROR;
return (EADDRINUSE);
}
/* copy it */
- strcpy(node->name, name);
+ strncpy(NG_NODE_NAME(node), name, NG_NODELEN);
return (0);
}
@@ -630,7 +772,7 @@ ng_name_node(node_p node, const char *name)
*
* Returns the node if found, else NULL.
* Eventually should add something faster than a sequential search.
- * Note it holds a reference on the node so you an be sure it's still there.
+ * Note it aquires a reference on the node so you can be sure it's still there.
*/
node_p
ng_name2noderef(node_p here, const char *name)
@@ -640,7 +782,7 @@ ng_name2noderef(node_p here, const char *name)
/* "." means "this node" */
if (strcmp(name, ".") == 0) {
- here->refs++;
+ NG_NODE_REF(here);
return(here);
}
@@ -651,12 +793,13 @@ ng_name2noderef(node_p here, const char *name)
/* Find node by name */
mtx_enter(&ng_nodelist_mtx, MTX_DEF);
- LIST_FOREACH(node, &ng_nodelist, nodes) {
- if (node->name[0] != '\0' && strcmp(node->name, name) == 0)
+ LIST_FOREACH(node, &ng_nodelist, nd_nodes) {
+ if (NG_NODE_HAS_NAME(node)
+ && (strcmp(NG_NODE_NAME(node), name) == 0))
break;
}
if (node)
- node->refs++;
+ NG_NODE_REF(node);
mtx_exit(&ng_nodelist_mtx, MTX_DEF);
return (node);
}
@@ -691,7 +834,7 @@ ng_decodeidname(const char *name)
void
ng_unname(node_p node)
{
- bzero(node->name, NG_NODELEN);
+ bzero(NG_NODE_NAME(node), NG_NODELEN);
}
/************************************************************************
@@ -703,21 +846,21 @@ ng_unname(node_p node)
/*
* Remove a hook reference
*/
-static void
+void
ng_unref_hook(hook_p hook)
{
- int s;
+ int v;
+ do {
+ v = hook->hk_refs;
+ } while (! atomic_cmpset_int(&hook->hk_refs, v, v - 1));
- s = splhigh();
-/* XXX not atomic.. fix */
- if (--hook->refs == 0) {
- if (hook->node) {
- ng_unref(hook->node);
- hook->node = NULL;
+ if (v == 1) { /* we were the last */
+ if (NG_HOOK_NODE(hook)) {
+ NG_NODE_UNREF((NG_HOOK_NODE(hook)));
+ hook->hk_node = NULL;
}
NG_FREE_HOOK(hook);
}
- splx(s);
}
/*
@@ -740,20 +883,20 @@ ng_add_hook(node_p node, const char *name, hook_p *hookp)
}
/* Allocate the hook and link it up */
- MALLOC(hook, hook_p, sizeof(*hook), M_NETGRAPH_HOOK, M_NOWAIT | M_ZERO);
+ NG_ALLOC_HOOK(hook);
if (hook == NULL) {
TRAP_ERROR;
return (ENOMEM);
}
- hook->refs = 1;
- hook->flags = HK_INVALID;
- hook->node = node;
- node->refs++; /* each hook counts as a reference */
+ hook->hk_refs = 1;
+ hook->hk_flags = HK_INVALID;
+ hook->hk_node = node;
+ NG_NODE_REF(node); /* each hook counts as a reference */
/* Check if the node type code has something to say about it */
- if (node->type->newhook != NULL)
- if ((error = (*node->type->newhook)(node, hook, name)) != 0) {
- ng_unref_hook(hook); /* this frees the hook */
+ if (node->nd_type->newhook != NULL)
+ if ((error = (*node->nd_type->newhook)(node, hook, name)) != 0) {
+ NG_HOOK_UNREF(hook); /* this frees the hook */
return (error);
}
@@ -762,11 +905,11 @@ ng_add_hook(node_p node, const char *name, hook_p *hookp)
* We'll ask again later when we actually connect the hooks.
* The reference we have is for this linkage.
*/
- LIST_INSERT_HEAD(&node->hooks, hook, hooks);
- node->numhooks++;
+ LIST_INSERT_HEAD(&node->nd_hooks, hook, hk_hooks);
+ node->nd_numhooks++;
/* Set hook name */
- strcpy(hook->name, name);
+ strncpy(NG_HOOK_NAME(hook), name, NG_HOOKLEN);
if (hookp)
*hookp = hook;
return (error);
@@ -780,24 +923,24 @@ ng_connect(hook_p hook1, hook_p hook2)
{
int error;
- hook1->peer = hook2;
- hook2->peer = hook1;
+ hook1->hk_peer = hook2;
+ hook2->hk_peer = hook1;
/* Give each node the opportunity to veto the impending connection */
- if (hook1->node->type->connect) {
- if ((error = (*hook1->node->type->connect) (hook1))) {
+ if (hook1->hk_node->nd_type->connect) {
+ if ((error = (*hook1->hk_node->nd_type->connect) (hook1))) {
ng_destroy_hook(hook1); /* also zaps hook2 */
return (error);
}
}
- if (hook2->node->type->connect) {
- if ((error = (*hook2->node->type->connect) (hook2))) {
+ if (hook2->hk_node->nd_type->connect) {
+ if ((error = (*hook2->hk_node->nd_type->connect) (hook2))) {
ng_destroy_hook(hook2); /* also zaps hook1 */
return (error);
}
}
- hook1->flags &= ~HK_INVALID;
- hook2->flags &= ~HK_INVALID;
+ hook1->hk_flags &= ~HK_INVALID;
+ hook2->hk_flags &= ~HK_INVALID;
return (0);
}
@@ -812,10 +955,10 @@ ng_findhook(node_p node, const char *name)
{
hook_p hook;
- if (node->type->findhook != NULL)
- return (*node->type->findhook)(node, name);
- LIST_FOREACH(hook, &node->hooks, hooks) {
- if (strcmp(hook->name, name) == 0)
+ if (node->nd_type->findhook != NULL)
+ return (*node->nd_type->findhook)(node, name);
+ LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
+ if (strcmp(NG_HOOK_NAME(hook), name) == 0)
return (hook);
}
return (NULL);
@@ -831,13 +974,13 @@ ng_findhook(node_p node, const char *name)
void
ng_destroy_hook(hook_p hook)
{
- hook_p peer = hook->peer;
+ hook_p peer = NG_HOOK_PEER(hook);
- hook->flags |= HK_INVALID; /* as soon as possible */
+ hook->hk_flags |= HK_INVALID; /* as soon as possible */
if (peer) {
- peer->flags |= HK_INVALID; /* as soon as possible */
- hook->peer = NULL;
- peer->peer = NULL;
+ peer->hk_flags |= HK_INVALID; /* as soon as possible */
+ hook->hk_peer = NULL;
+ peer->hk_peer = NULL;
ng_disconnect_hook(peer);
}
ng_disconnect_hook(hook);
@@ -853,22 +996,22 @@ ng_destroy_hook(hook_p hook)
static void
ng_disconnect_hook(hook_p hook)
{
- node_p node = hook->node;
+ node_p node = NG_HOOK_NODE(hook);
/*
* Remove the hook from the node's list to avoid possible recursion
* in case the disconnection results in node shutdown.
*/
- LIST_REMOVE(hook, hooks);
- node->numhooks--;
- if (node->type->disconnect) {
+ LIST_REMOVE(hook, hk_hooks);
+ node->nd_numhooks--;
+ if (node->nd_type->disconnect) {
/*
* The type handler may elect to destroy the peer so don't
* trust its existance after this point.
*/
- (*node->type->disconnect) (hook);
+ (*node->nd_type->disconnect) (hook);
}
- ng_unref_hook(hook);
+ NG_HOOK_UNREF(hook);
}
/*
@@ -878,14 +1021,16 @@ ng_disconnect_hook(hook_p hook)
int
ng_bypass(hook_p hook1, hook_p hook2)
{
- if (hook1->node != hook2->node)
+ if (hook1->hk_node != hook2->hk_node) {
+ TRAP_ERROR
return (EINVAL);
- hook1->peer->peer = hook2->peer;
- hook2->peer->peer = hook1->peer;
+ }
+ hook1->hk_peer->hk_peer = hook2->hk_peer;
+ hook2->hk_peer->hk_peer = hook1->hk_peer;
/* XXX If we ever cache methods on hooks update them as well */
- hook1->peer = NULL;
- hook2->peer = NULL;
+ hook1->hk_peer = NULL;
+ hook2->hk_peer = NULL;
ng_destroy_hook(hook1);
ng_destroy_hook(hook2);
return (0);
@@ -1037,11 +1182,11 @@ ng_rmnode_self(node_p here)
* to hold a reference actually to stop it from all
* going up in smoke.
*/
-/* ng_flush_input_queue(&here->input_queue); will mask problem */
+/* ng_flush_input_queue(&here->nd_input_queue); will mask problem */
item = ng_package_msg_self(here, NULL, msg);
if (item == NULL) { /* it would have freed the msg except static */
/* try again after flushing our queue */
- ng_flush_input_queue(&here->input_queue);
+ ng_flush_input_queue(&here->nd_input_queue);
item = ng_package_msg_self(here, NULL, msg);
if (item == NULL) {
printf("failed to free node 0x%x\n", ng_node2ID(here));
@@ -1146,8 +1291,10 @@ ng_path2noderef(node_p here, const char *address,
hook_p hook = NULL;
/* Initialize */
- if (destp == NULL)
+ if (destp == NULL) {
+ TRAP_ERROR
return EINVAL;
+ }
*destp = NULL;
/* Make a writable copy of address for ng_path_parse() */
@@ -1173,7 +1320,7 @@ ng_path2noderef(node_p here, const char *address,
if (nodename) {
node = ng_name2noderef(here, nodename);
if (node == NULL) {
- TRAP_ERROR;
+ TRAP_ERROR
return (ENOENT);
}
} else {
@@ -1182,7 +1329,7 @@ ng_path2noderef(node_p here, const char *address,
return (EINVAL);
}
node = here;
- node->refs++;
+ NG_NODE_REF(node);
}
/*
@@ -1222,11 +1369,20 @@ ng_path2noderef(node_p here, const char *address,
/* Can't get there from here... */
if (hook == NULL
- || hook->peer == NULL
- || (hook->flags & HK_INVALID) != 0
- || (hook->peer->flags & HK_INVALID) != 0) {
+ || NG_HOOK_PEER(hook) == NULL
+ || NG_HOOK_NOT_VALID(hook)
+ || NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))) {
TRAP_ERROR;
- ng_unref(node);
+ NG_NODE_UNREF(node);
+#if 0
+ printf("hooknotvalid %s %s %d %d %d %d ",
+ path,
+ segment,
+ hook == NULL,
+ NG_HOOK_PEER(hook) == NULL,
+ NG_HOOK_NOT_VALID(hook),
+ NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook)));
+#endif
return (ENOENT);
}
@@ -1238,11 +1394,11 @@ ng_path2noderef(node_p here, const char *address,
* instead of the direct hook in this crawl?
*/
oldnode = node;
- if ((node = hook->peer->node))
- node->refs++; /* XXX RACE */
- ng_unref(oldnode); /* XXX another race */
- if (node->flags & NG_INVALID) {
- ng_unref(node); /* XXX more races */
+ if ((node = NG_PEER_NODE(hook)))
+ NG_NODE_REF(node); /* XXX RACE */
+ NG_NODE_UNREF(oldnode); /* XXX another race */
+ if (NG_NODE_NOT_VALID(node)) {
+ NG_NODE_UNREF(node); /* XXX more races */
node = NULL;
}
}
@@ -1256,7 +1412,7 @@ ng_path2noderef(node_p here, const char *address,
/* Done */
*destp = node;
if (lasthook != NULL)
- *lasthook = (hook ? hook->peer : NULL);
+ *lasthook = (hook ? NG_HOOK_PEER(hook) : NULL);
return (0);
}
@@ -1684,17 +1840,19 @@ ng_snd_item(item_p item, int queue)
int rw;
int error = 0, ierror;
item_p oitem;
- struct ng_queue * ngq = &dest->input_queue;
+ struct ng_queue * ngq = &dest->nd_input_queue;
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__);
#endif
if (item == NULL) {
+ TRAP_ERROR;
return (EINVAL); /* failed to get queue element */
}
if (dest == NULL) {
NG_FREE_ITEM(item);
+ TRAP_ERROR;
return (EINVAL); /* No address */
}
if ((item->el_flags & NGQF_D_M) == NGQF_DATA) {
@@ -1705,21 +1863,21 @@ ng_snd_item(item_p item, int queue)
* the node is derivable from the hook.
* References are held on both by the item.
*/
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__);
#endif
CHECK_DATA_MBUF(NGI_M(item));
if (hook == NULL) {
NG_FREE_ITEM(item);
+ TRAP_ERROR;
return(EINVAL);
}
- if (((hook->flags & HK_INVALID) != 0)
- || ((hook->node->flags & NG_INVALID) != 0)) {
- TRAP_ERROR;
+ if ((NG_HOOK_NOT_VALID(hook))
+ || (NG_NODE_NOT_VALID(NG_HOOK_NODE(hook)))) {
NG_FREE_ITEM(item);
return (ENOTCONN);
}
- if ((hook->flags & HK_QUEUE)) {
+ if ((hook->hk_flags & HK_QUEUE)) {
queue = 1;
}
/* By default data is a reader in the locking scheme */
@@ -1733,7 +1891,7 @@ ng_snd_item(item_p item, int queue)
* References are held by the item on the node and
* the hook if it is present.
*/
- if (hook && (hook->flags & HK_QUEUE)) {
+ if (hook && (hook->hk_flags & HK_QUEUE)) {
queue = 1;
}
/* Data messages count as writers unles explicitly exempted */
@@ -1751,14 +1909,14 @@ ng_snd_item(item_p item, int queue)
* These are over-rides.
*/
if ((ngq->q_flags & SINGLE_THREAD_ONLY)
- || (dest->flags & NG_FORCE_WRITER)
- || (hook && (hook->flags & HK_FORCE_WRITER))) {
+ || (dest->nd_flags & NG_FORCE_WRITER)
+ || (hook && (hook->hk_flags & HK_FORCE_WRITER))) {
rw = NGQRW_W;
item->el_flags &= ~NGQF_TYPE;
}
if (queue) {
/* Put it on the queue for that node*/
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__);
#endif
mtx_enter(&(ngq->q_mtx), MTX_SPIN);
@@ -1802,7 +1960,7 @@ ng_snd_item(item_p item, int queue)
return (0);
}
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__);
#endif
ierror = ng_apply_item(dest, item); /* drops r/w lock when done */
@@ -1824,7 +1982,7 @@ ng_snd_item(item_p item, int queue)
for (;;) {
/* quick hack to save all that mutex stuff */
if ((ngq->q_flags & (WRITE_PENDING | READ_PENDING)) == 0) {
- if (dest->flags & NG_WORKQ)
+ if (dest->nd_flags & NG_WORKQ)
ng_worklist_remove(dest);
return (0);
}
@@ -1841,11 +1999,11 @@ ng_snd_item(item_p item, int queue)
* then we certainly don't need to be
* on the worklist.
*/
- if (dest->flags & NG_WORKQ)
+ if (dest->nd_flags & NG_WORKQ)
ng_worklist_remove(dest);
return (0);
}
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__);
#endif
@@ -1880,12 +2038,12 @@ ng_apply_item(node_p node, item_p item)
ng_rcvdata_t *rcvdata;
hook = item->el_hook;
- item->el_hook = NULL; /* so NG_FREE_ITEM doesn't ng_unref_hook() */
+ item->el_hook = NULL; /* so NG_FREE_ITEM doesn't NG_HOOK_UNREF() */
/* We already have the node.. assume responsibility */
/* And the reference */
/* node = item->el_dest; */
item->el_dest = NULL; /* same as for the hook above */
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__);
#endif
@@ -1896,9 +2054,9 @@ ng_apply_item(node_p node, item_p item)
*/
if ((hook == NULL)
- || ((hook->flags & HK_INVALID) != 0)
- || ((hook->node->flags & NG_INVALID) != 0)
- || ((rcvdata = hook->node->type->rcvdata) == NULL)) {
+ || NG_HOOK_NOT_VALID(hook)
+ || NG_NODE_NOT_VALID(NG_HOOK_NODE(hook))
+ || ((rcvdata = NG_HOOK_NODE(hook)->nd_type->rcvdata) == NULL)) {
error = EIO;
NG_FREE_ITEM(item);
} else {
@@ -1909,13 +2067,13 @@ ng_apply_item(node_p node, item_p item)
if (hook) {
item->el_hook = NULL;
- if ((hook->flags & HK_INVALID) != 0) {
+ if (NG_HOOK_NOT_VALID(hook)) {
/*
* If the hook has been zapped then we can't use it.
* Immediatly drop its reference.
* The message may not need it.
*/
- ng_unref_hook(hook);
+ NG_HOOK_UNREF(hook);
hook = NULL;
}
}
@@ -1923,7 +2081,8 @@ ng_apply_item(node_p node, item_p item)
* Similarly, if the node is a zombie there is
* nothing we can do with it, drop everything.
*/
- if (node->flags & NG_INVALID) {
+ if (NG_NODE_NOT_VALID(node)) {
+ TRAP_ERROR;
error = EINVAL;
NG_FREE_ITEM(item);
} else {
@@ -1945,8 +2104,8 @@ ng_apply_item(node_p node, item_p item)
&& ((msg->header.flags & NGF_RESP) == 0)) {
error = ng_generic_msg(node, item, hook);
} else {
- if ((node)->type->rcvmsg != NULL) {
- error = (*(node)->type->rcvmsg)((node),
+ if ((node)->nd_type->rcvmsg != NULL) {
+ error = (*(node)->nd_type->rcvmsg)((node),
(item), (hook));
} else {
TRAP_ERROR;
@@ -1964,15 +2123,15 @@ ng_apply_item(node_p node, item_p item)
* finished doing everything, drop those references.
*/
if (hook) {
- ng_unref_hook(hook);
+ NG_HOOK_UNREF(hook);
}
if (was_reader) {
- ng_leave_read(&node->input_queue);
+ ng_leave_read(&node->nd_input_queue);
} else {
- ng_leave_write(&node->input_queue);
+ ng_leave_write(&node->nd_input_queue);
}
- ng_unref(node);
+ NG_NODE_UNREF(node);
return (error);
}
@@ -1988,6 +2147,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
NGI_GET_MSG(item, msg);
if (msg->header.typecookie != NGM_GENERIC_COOKIE) {
+ TRAP_ERROR
error = EINVAL;
goto out;
}
@@ -2000,6 +2160,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data;
if (msg->header.arglen != sizeof(*mkp)) {
+ TRAP_ERROR
error = EINVAL;
break;
}
@@ -2016,6 +2177,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
node_p node2;
if (msg->header.arglen != sizeof(*con)) {
+ TRAP_ERROR
error = EINVAL;
break;
}
@@ -2027,7 +2189,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
if (error)
break;
error = ng_con_nodes(here, con->ourhook, node2, con->peerhook);
- ng_unref(node2);
+ NG_NODE_UNREF(node2);
break;
}
case NGM_NAME:
@@ -2035,6 +2197,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
struct ngm_name *const nam = (struct ngm_name *) msg->data;
if (msg->header.arglen != sizeof(*nam)) {
+ TRAP_ERROR
error = EINVAL;
break;
}
@@ -2048,6 +2211,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
hook_p hook;
if (msg->header.arglen != sizeof(*rmh)) {
+ TRAP_ERROR
error = EINVAL;
break;
}
@@ -2068,16 +2232,16 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
/* Fill in node info */
ni = (struct nodeinfo *) resp->data;
- if (here->name != NULL)
- strncpy(ni->name, here->name, NG_NODELEN);
- strncpy(ni->type, here->type->name, NG_TYPELEN);
+ if (NG_NODE_HAS_NAME(here))
+ strncpy(ni->name, NG_NODE_NAME(here), NG_NODELEN);
+ strncpy(ni->type, here->nd_type->name, NG_TYPELEN);
ni->id = ng_node2ID(here);
- ni->hooks = here->numhooks;
+ ni->hooks = here->nd_numhooks;
break;
}
case NGM_LISTHOOKS:
{
- const int nhooks = here->numhooks;
+ const int nhooks = here->nd_numhooks;
struct hooklist *hl;
struct nodeinfo *ni;
hook_p hook;
@@ -2093,14 +2257,14 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
ni = &hl->nodeinfo;
/* Fill in node info */
- if (here->name)
- strncpy(ni->name, here->name, NG_NODELEN);
- strncpy(ni->type, here->type->name, NG_TYPELEN);
+ if (NG_NODE_HAS_NAME(here))
+ strncpy(ni->name, NG_NODE_NAME(here), NG_NODELEN);
+ strncpy(ni->type, here->nd_type->name, NG_TYPELEN);
ni->id = ng_node2ID(here);
/* Cycle through the linked list of hooks */
ni->hooks = 0;
- LIST_FOREACH(hook, &here->hooks, hooks) {
+ LIST_FOREACH(hook, &here->nd_hooks, hk_hooks) {
struct linkinfo *const link = &hl->link[ni->hooks];
if (ni->hooks >= nhooks) {
@@ -2108,17 +2272,18 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
__FUNCTION__, "hooks");
break;
}
- if ((hook->flags & HK_INVALID) != 0)
+ if (NG_HOOK_NOT_VALID(hook))
continue;
- strncpy(link->ourhook, hook->name, NG_HOOKLEN);
- strncpy(link->peerhook, hook->peer->name, NG_HOOKLEN);
- if (hook->peer->node->name[0] != '\0')
+ strncpy(link->ourhook, NG_HOOK_NAME(hook), NG_HOOKLEN);
+ strncpy(link->peerhook,
+ NG_PEER_HOOK_NAME(hook), NG_HOOKLEN);
+ if (NG_PEER_NODE_NAME(hook)[0] != '\0')
strncpy(link->nodeinfo.name,
- hook->peer->node->name, NG_NODELEN);
+ NG_PEER_NODE_NAME(hook), NG_NODELEN);
strncpy(link->nodeinfo.type,
- hook->peer->node->type->name, NG_TYPELEN);
- link->nodeinfo.id = ng_node2ID(hook->peer->node);
- link->nodeinfo.hooks = hook->peer->node->numhooks;
+ NG_PEER_NODE(hook)->nd_type->name, NG_TYPELEN);
+ link->nodeinfo.id = ng_node2ID(NG_PEER_NODE(hook));
+ link->nodeinfo.hooks = NG_PEER_NODE(hook)->nd_numhooks;
ni->hooks++;
}
break;
@@ -2134,8 +2299,8 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
mtx_enter(&ng_nodelist_mtx, MTX_DEF);
/* Count number of nodes */
- LIST_FOREACH(node, &ng_nodelist, nodes) {
- if (unnamed || node->name[0] != '\0')
+ LIST_FOREACH(node, &ng_nodelist, nd_nodes) {
+ if (unnamed || NG_NODE_HAS_NAME(node))
num++;
}
mtx_exit(&ng_nodelist_mtx, MTX_DEF);
@@ -2152,7 +2317,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
/* Cycle through the linked list of nodes */
nl->numnames = 0;
mtx_enter(&ng_nodelist_mtx, MTX_DEF);
- LIST_FOREACH(node, &ng_nodelist, nodes) {
+ LIST_FOREACH(node, &ng_nodelist, nd_nodes) {
struct nodeinfo *const np = &nl->nodeinfo[nl->numnames];
if (nl->numnames >= num) {
@@ -2160,15 +2325,15 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
__FUNCTION__, "nodes");
break;
}
- if ((node->flags & NG_INVALID) != 0)
+ if (NG_NODE_NOT_VALID(node))
continue;
- if (!unnamed && node->name[0] == '\0')
+ if (!unnamed && (! NG_NODE_HAS_NAME(node)))
continue;
- if (node->name[0] != '\0')
- strncpy(np->name, node->name, NG_NODELEN);
- strncpy(np->type, node->type->name, NG_TYPELEN);
+ if (NG_NODE_HAS_NAME(node))
+ strncpy(np->name, NG_NODE_NAME(node), NG_NODELEN);
+ strncpy(np->type, node->nd_type->name, NG_TYPELEN);
np->id = ng_node2ID(node);
- np->hooks = node->numhooks;
+ np->hooks = node->nd_numhooks;
nl->numnames++;
}
mtx_exit(&ng_nodelist_mtx, MTX_DEF);
@@ -2227,6 +2392,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
if (msg->header.arglen < sizeof(struct ng_mesg)
|| msg->header.arglen - sizeof(struct ng_mesg)
< binary->header.arglen) {
+ TRAP_ERROR
error = EINVAL;
break;
}
@@ -2243,7 +2409,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
bcopy(binary, ascii, sizeof(*binary));
/* Find command by matching typecookie and command number */
- for (c = here->type->cmdlist;
+ for (c = here->nd_type->cmdlist;
c != NULL && c->name != NULL; c++) {
if (binary->header.typecookie == c->cookie
&& binary->header.cmd == c->cmd)
@@ -2301,6 +2467,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
|| ascii->header.arglen < 1
|| msg->header.arglen
< sizeof(*ascii) + ascii->header.arglen) {
+ TRAP_ERROR
error = EINVAL;
break;
}
@@ -2318,7 +2485,7 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
bcopy(ascii, binary, sizeof(*ascii));
/* Find command by matching ASCII command string */
- for (c = here->type->cmdlist;
+ for (c = here->nd_type->cmdlist;
c != NULL && c->name != NULL; c++) {
if (strcmp(ascii->header.cmdstr, c->name) == 0)
break;
@@ -2366,9 +2533,9 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook)
* This means we must assume that the item/msg is already freed
* when control passes back to us.
*/
- if (here->type->rcvmsg != NULL) {
+ if (here->nd_type->rcvmsg != NULL) {
NGI_MSG(item) = msg; /* put it back as we found it */
- return((*here->type->rcvmsg)(here, item, lasthook));
+ return((*here->nd_type->rcvmsg)(here, item, lasthook));
}
/* Fall through if rcvmsg not supported */
default:
@@ -2521,7 +2688,7 @@ static int maxalloc = 128; /* limit the damage of a leak */
static const int ngqfreemax = 64;/* cache at most this many */
static const int ngqfreelow = 4; /* try malloc if free < this */
static volatile int ngqfreesize; /* number of cached entries */
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
static TAILQ_HEAD(, ng_item) ng_itemlist = TAILQ_HEAD_INITIALIZER(ng_itemlist);
#endif
/*
@@ -2558,10 +2725,10 @@ ng_getqblk(void)
sizeof(*item), M_NETGRAPH_ITEM,
(M_NOWAIT | M_ZERO));
if (item) {
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
TAILQ_INSERT_TAIL(&ng_itemlist,
item, all);
-#endif /* ITEM_DEBUG */
+#endif /* NETGRAPH_DEBUG */
atomic_add_int(&allocated, 1);
break;
}
@@ -2626,11 +2793,11 @@ ng_free_item(item_p item)
}
/* If we still have a node or hook referenced... */
if (item->el_dest) {
- ng_unref(item->el_dest);
+ NG_NODE_UNREF(item->el_dest);
item->el_dest = NULL;
}
if (item->el_hook) {
- ng_unref_hook(item->el_hook);
+ NG_HOOK_UNREF(item->el_hook);
item->el_hook = NULL;
}
item->el_flags |= NGQF_FREE;
@@ -2649,15 +2816,41 @@ ng_free_item(item_p item)
atomic_add_int(&ngqfreesize, 1);
} else {
/* This is the only place that should use this Macro */
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
TAILQ_REMOVE(&ng_itemlist, item, all);
-#endif /* ITEM_DEBUG */
+#endif /* NETGRAPH_DEBUG */
NG_FREE_ITEM_REAL(item);
atomic_subtract_int(&allocated, 1);
}
}
-#ifdef ITEM_DEBUG
+#ifdef NETGRAPH_DEBUG
+void
+dumphook (hook_p hook, char *file, int line)
+{
+ printf("hook: name %s, %d refs, Last touched:\n",
+ _NG_HOOK_NAME(hook), hook->hk_refs);
+ printf(" Last active @ %s, line %d\n",
+ hook->lastfile, hook->lastline);
+ if (line) {
+ printf(" problem discovered at file %s, line %d\n", file, line);
+ }
+}
+
+void
+dumpnode(node_p node, char *file, int line)
+{
+ printf("node: ID [%x]: type '%s', %d hooks, flags 0x%x, %d refs, %s:\n",
+ ng_node2ID(node), node->nd_type->name,
+ node->nd_numhooks, node->nd_flags,
+ node->nd_refs, node->nd_name);
+ printf(" Last active @ %s, line %d\n",
+ node->lastfile, node->lastline);
+ if (line) {
+ printf(" problem discovered at file %s, line %d\n", file, line);
+ }
+}
+
void
dumpitem(item_p item, char *file, int line)
{
@@ -2673,48 +2866,70 @@ dumpitem(item_p item, char *file, int line)
printf(" - [data]\n");
}
}
- printf(" problem discovered at file %s, line %d\n", file, line);
- if (item->el_dest)
- printf("node %X ([%x])\n",
- item->el_dest, ng_node2ID(item->el_dest));
+ if (line) {
+ printf(" problem discovered at file %s, line %d\n", file, line);
+ if (item->el_dest) {
+ printf("node %p ([%x])\n",
+ item->el_dest, ng_node2ID(item->el_dest));
+ }
+ }
+}
+
+static void
+ng_dumpitems(void)
+{
+ item_p item;
+ int i = 1;
+ TAILQ_FOREACH(item, &ng_itemlist, all) {
+ printf("[%d] ", i++);
+ dumpitem(item, NULL, 0);
+ }
+}
+
+static void
+ng_dumpnodes(void)
+{
+ node_p node;
+ int i = 1;
+ SLIST_FOREACH(node, &ng_allnodes, nd_all) {
+ printf("[%d] ", i++);
+ dumpnode(node, NULL, 0);
+ }
+}
+
+static void
+ng_dumphooks(void)
+{
+ hook_p hook;
+ int i = 1;
+ SLIST_FOREACH(hook, &ng_allhooks, hk_all) {
+ printf("[%d] ", i++);
+ dumphook(hook, NULL, 0);
+ }
}
static int
sysctl_debug_ng_dump_items(SYSCTL_HANDLER_ARGS)
{
+ static int count;
int error;
int val;
- item_p item;
int i;
val = allocated;
i = 1;
error = sysctl_handle_int(oidp, &val, sizeof(int), req);
- TAILQ_FOREACH(item, &ng_itemlist, all) {
- if (item->el_flags & NGQF_FREE) {
- printf("[%d] free item, freed at %s, line %d\n",
- i++, item->lastfile, item->lastline);
- } else {
- printf("[%d] ACTIVE item, last used at %s, line %d",
- i++, item->lastfile, item->lastline);
- if ((item->el_flags & NGQF_D_M) == NGQF_MESG) {
- printf(" - retaddr[%d]:\n", _NGI_RETADDR(item));
- } else {
- printf(" - [data]\n");
- }
- }
- if (item->el_dest) {
- printf("node %X ([%x])",
- item->el_dest, ng_node2ID(item->el_dest));
- printf("<%X>\n",item->el_dest->input_queue.q_flags);
- }
+ if(count++ & 1) { /* for some reason sysctl calls it twice */
+ ng_dumpitems();
+ ng_dumpnodes();
+ ng_dumphooks();
}
return error;
}
SYSCTL_PROC(_debug, OID_AUTO, ng_dump_items, CTLTYPE_INT | CTLFLAG_RD,
0, 0, sysctl_debug_ng_dump_items, "I", "Number of allocated items");
-#endif /* ITEM_DEBUG */
+#endif /* NETGRAPH_DEBUG */
/***********************************************************************
@@ -2739,7 +2954,7 @@ ngintr(void)
mtx_exit(&ng_worklist_mtx, MTX_SPIN);
break;
}
- TAILQ_REMOVE(&ng_worklist, node, work);
+ TAILQ_REMOVE(&ng_worklist, node, nd_work);
mtx_exit(&ng_worklist_mtx, MTX_SPIN);
/*
* We have the node. We also take over the reference
@@ -2751,8 +2966,8 @@ ngintr(void)
* Let the reference go at the last minute.
*/
for (;;) {
- mtx_enter(&node->input_queue.q_mtx, MTX_SPIN);
- item = ng_dequeue(&node->input_queue);
+ mtx_enter(&node->nd_input_queue.q_mtx, MTX_SPIN);
+ item = ng_dequeue(&node->nd_input_queue);
if (item == NULL) {
/*
* Say we are on the queue as long as
@@ -2760,13 +2975,13 @@ ngintr(void)
* it probably wouldn't come here while we
* are processing anyhow.
*/
- node->flags &= ~NG_WORKQ;
- mtx_exit(&node->input_queue.q_mtx, MTX_SPIN);
- ng_unref(node);
+ node->nd_flags &= ~NG_WORKQ;
+ mtx_exit(&node->nd_input_queue.q_mtx, MTX_SPIN);
+ NG_NODE_UNREF(node);
break; /* go look for another node */
} else {
- mtx_exit(&node->input_queue.q_mtx, MTX_SPIN);
-#ifdef ITEM_DEBUG
+ mtx_exit(&node->nd_input_queue.q_mtx, MTX_SPIN);
+#ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__);
#endif
ng_apply_item(node, item);
@@ -2779,11 +2994,11 @@ static void
ng_worklist_remove(node_p node)
{
mtx_enter(&ng_worklist_mtx, MTX_SPIN);
- if (node->flags & NG_WORKQ) {
- TAILQ_REMOVE(&ng_worklist, node, work);
- ng_unref(node);
+ if (node->nd_flags & NG_WORKQ) {
+ TAILQ_REMOVE(&ng_worklist, node, nd_work);
+ NG_NODE_UNREF(node);
}
- node->flags &= ~NG_WORKQ;
+ node->nd_flags &= ~NG_WORKQ;
mtx_exit(&ng_worklist_mtx, MTX_SPIN);
}
@@ -2791,14 +3006,14 @@ static void
ng_setisr(node_p node)
{
mtx_enter(&ng_worklist_mtx, MTX_SPIN);
- if ((node->flags & NG_WORKQ) == 0) {
+ if ((node->nd_flags & NG_WORKQ) == 0) {
/*
* If we are not already on the work queue,
* then put us on.
*/
- node->flags |= NG_WORKQ;
- TAILQ_INSERT_TAIL(&ng_worklist, node, work);
- node->refs++;
+ node->nd_flags |= NG_WORKQ;
+ TAILQ_INSERT_TAIL(&ng_worklist, node, nd_work);
+ NG_NODE_REF(node);
}
mtx_exit(&ng_worklist_mtx, MTX_SPIN);
schednetisr(NETISR_NETGRAPH);
@@ -2809,24 +3024,24 @@ ng_setisr(node_p node)
* Externally useable functions to set up a queue item ready for sending
***********************************************************************/
-#ifdef ITEM_DEBUG
-#define DEBUG_CHECKS \
+#ifdef NETGRAPH_DEBUG
+#define ITEM_DEBUG_CHECKS \
do { \
if (item->el_dest ) { \
printf("item already has node"); \
Debugger("has node"); \
- ng_unref(item->el_dest); \
+ NG_NODE_UNREF(item->el_dest); \
item->el_dest = NULL; \
} \
if (item->el_hook ) { \
printf("item already has hook"); \
Debugger("has hook"); \
- ng_unref_hook(item->el_hook); \
+ NG_HOOK_UNREF(item->el_hook); \
item->el_hook = NULL; \
} \
} while (0)
#else
-#define DEBUG_CHECKS
+#define ITEM_DEBUG_CHECKS
#endif
/*
@@ -2852,7 +3067,7 @@ ng_package_data(struct mbuf *m, meta_p meta)
NG_FREE_META(meta);
return (NULL);
}
- DEBUG_CHECKS;
+ ITEM_DEBUG_CHECKS;
item->el_flags = NGQF_DATA;
item->el_next = NULL;
NGI_M(item) = m;
@@ -2878,7 +3093,7 @@ ng_package_msg(struct ng_mesg *msg)
}
return (NULL);
}
- DEBUG_CHECKS;
+ ITEM_DEBUG_CHECKS;
item->el_flags = NGQF_MESG;
item->el_next = NULL;
/*
@@ -2913,27 +3128,30 @@ ng_package_msg(struct ng_mesg *msg)
int
ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr)
{
- DEBUG_CHECKS;
+ ITEM_DEBUG_CHECKS;
/*
* Quick sanity check..
+ * Since a hook holds a reference on it's node, once we know
+ * that the peer is still connected (even if invalid,) we know
+ * that the peer node is present, though maybe invalid.
*/
if ((hook == NULL)
- || ((hook->flags & HK_INVALID) != 0)
- || (hook->peer == NULL)
- || ((hook->peer->flags & HK_INVALID) != 0)
- || ((hook->peer->node->flags & NG_INVALID) != 0)) {
+ || NG_HOOK_NOT_VALID(hook)
+ || (NG_HOOK_PEER(hook) == NULL)
+ || NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))
+ || NG_NODE_NOT_VALID(NG_PEER_NODE(hook))) {
NG_FREE_ITEM(item);
+ TRAP_ERROR
return (EINVAL);
}
/*
* Transfer our interest to the other (peer) end.
- * note sleazy use of 'hook'.
*/
- item->el_hook = hook->peer;
- item->el_hook->refs++; /* don't let it go away while on the queue */
- item->el_dest = hook->peer->node; /* sleaze */
- item->el_dest->refs++; /* XXX dangerous, not atomic */
+ item->el_hook = NG_HOOK_PEER(hook);
+ NG_HOOK_REF(item->el_hook); /* Don't let it go while on the queue */
+ item->el_dest = NG_PEER_NODE(hook);
+ NG_NODE_REF(item->el_dest); /* Nor this */
SET_RETADDR;
return (0);
}
@@ -2945,7 +3163,7 @@ ng_address_path(node_p here, item_p item, char *address, ng_ID_t retaddr)
hook_p hook = NULL;
int error;
- DEBUG_CHECKS;
+ ITEM_DEBUG_CHECKS;
/*
* Note that ng_path2noderef increments the reference count
* on the node for us if it finds one. So we don't have to.
@@ -2953,11 +3171,11 @@ ng_address_path(node_p here, item_p item, char *address, ng_ID_t retaddr)
error = ng_path2noderef(here, address, &dest, &hook);
if (error) {
NG_FREE_ITEM(item);
- return (EINVAL);
+ return (error);
}
item->el_dest = dest;
if (( item->el_hook = hook))
- hook->refs++; /* don't let it go away while on the queue */
+ NG_HOOK_REF(hook); /* don't let it go while on the queue */
SET_RETADDR;
return (0);
}
@@ -2967,13 +3185,14 @@ ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr)
{
node_p dest;
- DEBUG_CHECKS;
+ ITEM_DEBUG_CHECKS;
/*
* Find the target node.
*/
dest = ng_ID2noderef(ID); /* GETS REFERENCE! */
if (dest == NULL) {
NG_FREE_ITEM(item);
+ TRAP_ERROR
return(EINVAL);
}
/* Fill out the contents */
@@ -2981,7 +3200,6 @@ ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr)
item->el_next = NULL;
item->el_dest = dest;
item->el_hook = NULL;
- /* NGI_RETADDR(item) = ng_node2ID(here); not sure why its here XXX */
SET_RETADDR;
return (0);
}
@@ -3012,10 +3230,10 @@ ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg)
item->el_flags = NGQF_MESG;
item->el_next = NULL;
item->el_dest = here;
- here->refs++; /* XXX not atomic, + May have other races */
+ NG_NODE_REF(here);
item->el_hook = hook;
if (hook)
- hook->refs++;
+ NG_HOOK_REF(hook);
NGI_MSG(item) = msg;
NGI_RETADDR(item) = ng_node2ID(here);
return (item);
@@ -3061,7 +3279,7 @@ ng_macro_test(item_p item)
NG_SEND_DATA(error, hook, m, meta);
NG_SEND_DATA_ONLY(error, hook, m);
NG_FWD_NEW_DATA(error, item, hook, m);
- NG_FWD_DATA(error, item, hook);
+ NG_FWD_ITEM_HOOK(error, item, hook);
NG_SEND_MSG_HOOK(error, node, msg, hook, retaddr);
NG_SEND_MSG_ID(error, node, msg, retaddr, retaddr);
NG_SEND_MSG_PATH(error, node, msg, ".:", retaddr);
OpenPOWER on IntegriCloud