Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Feb 2012 17:35:44 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r231696 - in stable/8/sys: kern netgraph
Message-ID:  <201202141735.q1EHZiju010205@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Tue Feb 14 17:35:44 2012
New Revision: 231696
URL: http://svn.freebsd.org/changeset/base/231696

Log:
  Merge netgraph related fixes and enhancements from head/. Revisions
  merged: r223754,224031,226829,229003,230213,230480, 230486-230487,231585.
  
  r223754 to ng_base:
    - Use refcount(9) API to manage node and hook refcounting.
  
  r224031 to ng_socket:
    In ng_attach_cntl() first allocate things that may fail, and then
    do the rest of initialization. This simplifies code and fixes
    a double free in failure scenario.
  
  r226829 to ng_base:
    - If KDB & NETGRAPH_DEBUG are on, print traces on discovered failed
      invariants.
    - Reduce tautology in NETGRAPH_DEBUG output.
  
  r229003 to ng_base:
    style(9), whitespace and spelling nits.
  
  r230213 to ng_socket:
    Remove some disabled NOTYET code. Probability of enabling it is low,
    if anyone wants, he/she can take it from svn.
  
  r230480 to ng_base:
    Convert locks that protect name hash, ID hash and typelist from
    mutex(9) to rwlock(9) based locks.
  
    While here remove dropping lock when processing NGM_LISTNODES,
    and NGM_LISTTYPES generic commands. We don't need to drop it
    since memory allocation is done with M_NOWAIT.
  
  r230486 to hashinit(9):
    Convert panic()s to KASSERT()s. This is an optimisation for
    hashdestroy() since in absence of INVARIANTS a compiler
    will drop the entire for() cycle.
  
  r230487,r231585 to ng_socket:
    Provide a findhook method for ng_socket(4). The node stores a
    hash with names of its hooks. It starts with size of 16, and
    grows when number of hooks reaches twice the current size. A
    failure to grow (memory is allocated with M_NOWAIT) isn't
    fatal, however.
  
  Tested by:	Eugene Grosbein, Mike Tancsa

Modified:
  stable/8/sys/kern/kern_subr.c
  stable/8/sys/netgraph/netgraph.h
  stable/8/sys/netgraph/ng_base.c
  stable/8/sys/netgraph/ng_socket.c
  stable/8/sys/netgraph/ng_socketvar.h
Directory Properties:
  stable/8/sys/   (props changed)

Modified: stable/8/sys/kern/kern_subr.c
==============================================================================
--- stable/8/sys/kern/kern_subr.c	Tue Feb 14 17:18:45 2012	(r231695)
+++ stable/8/sys/kern/kern_subr.c	Tue Feb 14 17:35:44 2012	(r231696)
@@ -373,9 +373,7 @@ hashinit_flags(int elements, struct mall
 	LIST_HEAD(generic, generic) *hashtbl;
 	int i;
 
-	if (elements <= 0)
-		panic("hashinit: bad elements");
-
+	KASSERT(elements > 0, ("%s: bad elements", __func__));
 	/* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */
 	KASSERT((flags & HASH_WAITOK) ^ (flags & HASH_NOWAIT),
 	    ("Bad flags (0x%x) passed to hashinit_flags", flags));
@@ -416,8 +414,7 @@ hashdestroy(void *vhashtbl, struct mallo
 
 	hashtbl = vhashtbl;
 	for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++)
-		if (!LIST_EMPTY(hp))
-			panic("hashdestroy: hash not empty");
+		KASSERT(LIST_EMPTY(hp), ("%s: hash not empty", __func__));
 	free(hashtbl, type);
 }
 
@@ -436,8 +433,7 @@ phashinit(int elements, struct malloc_ty
 	LIST_HEAD(generic, generic) *hashtbl;
 	int i;
 
-	if (elements <= 0)
-		panic("phashinit: bad elements");
+	KASSERT(elements > 0, ("%s: bad elements", __func__));
 	for (i = 1, hashsize = primes[1]; hashsize <= elements;) {
 		i++;
 		if (i == NPRIMES)

Modified: stable/8/sys/netgraph/netgraph.h
==============================================================================
--- stable/8/sys/netgraph/netgraph.h	Tue Feb 14 17:18:45 2012	(r231695)
+++ stable/8/sys/netgraph/netgraph.h	Tue Feb 14 17:35:44 2012	(r231696)
@@ -53,9 +53,11 @@
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
+#include <sys/refcount.h>
 
 #ifdef HAVE_KERNEL_OPTION_HEADERS
 #include "opt_netgraph.h"
+#include "opt_kdb.h"
 #endif
 
 /* debugging options */
@@ -137,7 +139,7 @@ struct ng_hook {
  * If you can't do it with these you probably shouldn;t be doing it.
  */
 void ng_unref_hook(hook_p hook); /* don't move this */
-#define	_NG_HOOK_REF(hook)	atomic_add_int(&(hook)->hk_refs, 1)
+#define	_NG_HOOK_REF(hook)	refcount_acquire(&(hook)->hk_refs)
 #define _NG_HOOK_NAME(hook)	((hook)->hk_name)
 #define _NG_HOOK_UNREF(hook)	ng_unref_hook(hook)
 #define	_NG_HOOK_SET_PRIVATE(hook, val)	do {(hook)->hk_private = val;} while (0)
@@ -189,7 +191,7 @@ static __inline void
 _chkhook(hook_p hook, char *file, int line)
 {
 	if (hook->hk_magic != HK_MAGIC) {
-		printf("Accessing freed hook ");
+		printf("Accessing freed ");
 		dumphook(hook, file, line);
 	}
 	hook->lastline = line;
@@ -400,7 +402,7 @@ int	ng_unref_node(node_p node); /* don't
 #define _NG_NODE_NAME(node)	((node)->nd_name + 0)
 #define _NG_NODE_HAS_NAME(node)	((node)->nd_name[0] + 0)
 #define _NG_NODE_ID(node)	((node)->nd_ID + 0)
-#define	_NG_NODE_REF(node)	atomic_add_int(&(node)->nd_refs, 1)
+#define	_NG_NODE_REF(node)	refcount_acquire(&(node)->nd_refs)
 #define	_NG_NODE_UNREF(node)	ng_unref_node(node)
 #define	_NG_NODE_SET_PRIVATE(node, val)	do {(node)->nd_private = val;} while (0)
 #define	_NG_NODE_PRIVATE(node)	((node)->nd_private)
@@ -457,7 +459,7 @@ static __inline void
 _chknode(node_p node, char *file, int line)
 {
 	if (node->nd_magic != ND_MAGIC) {
-		printf("Accessing freed node ");
+		printf("Accessing freed ");
 		dumpnode(node, file, line);
 	}
 	node->lastline = line;

Modified: stable/8/sys/netgraph/ng_base.c
==============================================================================
--- stable/8/sys/netgraph/ng_base.c	Tue Feb 14 17:18:45 2012	(r231695)
+++ stable/8/sys/netgraph/ng_base.c	Tue Feb 14 17:35:44 2012	(r231696)
@@ -1,7 +1,3 @@
-/*
- * ng_base.c
- */
-
 /*-
  * Copyright (c) 1996-1999 Whistle Communications, Inc.
  * All rights reserved.
@@ -54,6 +50,7 @@
 #include <sys/kernel.h>
 #include <sys/ktr.h>
 #include <sys/limits.h>
+#include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/queue.h>
@@ -61,6 +58,7 @@
 #include <sys/syslog.h>
 #include <sys/refcount.h>
 #include <sys/proc.h>
+#include <sys/rwlock.h>
 #include <sys/unistd.h>
 #include <sys/kthread.h>
 #include <sys/smp.h>
@@ -167,19 +165,28 @@ static struct mtx	ng_worklist_mtx;   /* 
 
 /* List of installed types */
 static LIST_HEAD(, ng_type) ng_typelist;
-static struct mtx	ng_typelist_mtx;
+static struct rwlock	ng_typelist_lock;
+#define	TYPELIST_RLOCK()	rw_rlock(&ng_typelist_lock)
+#define	TYPELIST_RUNLOCK()	rw_runlock(&ng_typelist_lock)
+#define	TYPELIST_WLOCK()	rw_wlock(&ng_typelist_lock)
+#define	TYPELIST_WUNLOCK()	rw_wunlock(&ng_typelist_lock)
 
 /* Hash related definitions */
 /* XXX Don't need to initialise them because it's a LIST */
 static VNET_DEFINE(LIST_HEAD(, ng_node), ng_ID_hash[NG_ID_HASH_SIZE]);
 #define	V_ng_ID_hash			VNET(ng_ID_hash)
 
-static struct mtx	ng_idhash_mtx;
+static struct rwlock	ng_idhash_lock;
+#define	IDHASH_RLOCK()		rw_rlock(&ng_idhash_lock)
+#define	IDHASH_RUNLOCK()	rw_runlock(&ng_idhash_lock)
+#define	IDHASH_WLOCK()		rw_wlock(&ng_idhash_lock)
+#define	IDHASH_WUNLOCK()	rw_wunlock(&ng_idhash_lock)
+
 /* Method to find a node.. used twice so do it here */
 #define NG_IDHASH_FN(ID) ((ID) % (NG_ID_HASH_SIZE))
 #define NG_IDHASH_FIND(ID, node)					\
 	do { 								\
-		mtx_assert(&ng_idhash_mtx, MA_OWNED);			\
+		rw_assert(&ng_idhash_lock, RA_LOCKED);			\
 		LIST_FOREACH(node, &V_ng_ID_hash[NG_IDHASH_FN(ID)],	\
 						nd_idnodes) {		\
 			if (NG_NODE_IS_VALID(node)			\
@@ -192,7 +199,6 @@ static struct mtx	ng_idhash_mtx;
 static VNET_DEFINE(LIST_HEAD(, ng_node), ng_name_hash[NG_NAME_HASH_SIZE]);
 #define	V_ng_name_hash			VNET(ng_name_hash)
 
-static struct mtx	ng_namehash_mtx;
 #define NG_NAMEHASH(NAME, HASH)				\
 	do {						\
 		u_char	h = 0;				\
@@ -202,6 +208,11 @@ static struct mtx	ng_namehash_mtx;
 		(HASH) = h % (NG_NAME_HASH_SIZE);	\
 	} while (0)
 
+static struct rwlock	ng_namehash_lock;
+#define	NAMEHASH_RLOCK()	rw_rlock(&ng_namehash_lock)
+#define	NAMEHASH_RUNLOCK()	rw_runlock(&ng_namehash_lock)
+#define	NAMEHASH_WLOCK()	rw_wlock(&ng_namehash_lock)
+#define	NAMEHASH_WUNLOCK()	rw_wunlock(&ng_namehash_lock)
 
 /* Internal functions */
 static int	ng_add_hook(node_p node, const char *name, hook_p * hookp);
@@ -330,18 +341,18 @@ ng_alloc_node(void)
 
 #define NG_FREE_HOOK(hook)						\
 	do {								\
-		mtx_lock(&ng_nodelist_mtx);			\
+		mtx_lock(&ng_nodelist_mtx);				\
 		LIST_INSERT_HEAD(&ng_freehooks, hook, hk_hooks);	\
 		hook->hk_magic = 0;					\
-		mtx_unlock(&ng_nodelist_mtx);			\
+		mtx_unlock(&ng_nodelist_mtx);				\
 	} while (0)
 
 #define NG_FREE_NODE(node)						\
 	do {								\
-		mtx_lock(&ng_nodelist_mtx);			\
+		mtx_lock(&ng_nodelist_mtx);				\
 		LIST_INSERT_HEAD(&ng_freenodes, node, nd_nodes);	\
 		node->nd_magic = 0;					\
-		mtx_unlock(&ng_nodelist_mtx);			\
+		mtx_unlock(&ng_nodelist_mtx);				\
 	} while (0)
 
 #else /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
@@ -651,12 +662,12 @@ ng_make_node_common(struct ng_type *type
 	LIST_INIT(&node->nd_hooks);
 
 	/* Link us into the name hash. */
-	mtx_lock(&ng_namehash_mtx);
+	NAMEHASH_WLOCK();
 	LIST_INSERT_HEAD(&V_ng_name_hash[0], node, nd_nodes);
-	mtx_unlock(&ng_namehash_mtx);
+	NAMEHASH_WUNLOCK();
 
 	/* get an ID and put us in the hash chain */
-	mtx_lock(&ng_idhash_mtx);
+	IDHASH_WLOCK();
 	for (;;) { /* wrap protection, even if silly */
 		node_p node2 = NULL;
 		node->nd_ID = V_nextID++; /* 137/sec for 1 year before wrap */
@@ -667,9 +678,9 @@ ng_make_node_common(struct ng_type *type
 			break;
 		}
 	}
-	LIST_INSERT_HEAD(&V_ng_ID_hash[NG_IDHASH_FN(node->nd_ID)],
-							node, nd_idnodes);
-	mtx_unlock(&ng_idhash_mtx);
+	LIST_INSERT_HEAD(&V_ng_ID_hash[NG_IDHASH_FN(node->nd_ID)], node,
+	    nd_idnodes);
+	IDHASH_WUNLOCK();
 
 	/* Done */
 	*nodepp = node;
@@ -771,33 +782,39 @@ ng_rmnode(node_p node, hook_p dummy1, vo
 /*
  * Remove a reference to the node, possibly the last.
  * deadnode always acts as it it were the last.
+ *
+ * XXX: in head this function is void, since it isn't
+ * safe to trust its value. But for API compatibility
+ * here it is left int, and in case of non-last reference
+ * count it returns a large positive value.
  */
 int
 ng_unref_node(node_p node)
 {
-	int v;
 
-	if (node == &ng_deadnode) {
+	if (node == &ng_deadnode)
 		return (0);
-	}
-
-	v = atomic_fetchadd_int(&node->nd_refs, -1);
 
-	if (v == 1) { /* we were the last */
+	if (refcount_release(&node->nd_refs)) { /* we were the last */
 
-		mtx_lock(&ng_namehash_mtx);
 		node->nd_type->refs--; /* XXX maybe should get types lock? */
+		NAMEHASH_WLOCK();
 		LIST_REMOVE(node, nd_nodes);
-		mtx_unlock(&ng_namehash_mtx);
+		NAMEHASH_WUNLOCK();
 
-		mtx_lock(&ng_idhash_mtx);
+		IDHASH_WLOCK();
 		LIST_REMOVE(node, nd_idnodes);
-		mtx_unlock(&ng_idhash_mtx);
+		IDHASH_WUNLOCK();
 
 		mtx_destroy(&node->nd_input_queue.q_mtx);
 		NG_FREE_NODE(node);
+
+		/* XXX */
+		return (0);
 	}
-	return (v - 1);
+
+	/* XXX */
+	return (42);
 }
 
 /************************************************************************
@@ -807,11 +824,11 @@ static node_p
 ng_ID2noderef(ng_ID_t ID)
 {
 	node_p node;
-	mtx_lock(&ng_idhash_mtx);
+	IDHASH_RLOCK();
 	NG_IDHASH_FIND(ID, node);
 	if(node)
 		NG_NODE_REF(node);
-	mtx_unlock(&ng_idhash_mtx);
+	IDHASH_RUNLOCK();
 	return(node);
 }
 
@@ -826,7 +843,7 @@ ng_node2ID(node_p node)
 ************************************************************************/
 
 /*
- * Assign a node a name. Once assigned, the name cannot be changed.
+ * Assign a node a name.
  */
 int
 ng_name_node(node_p node, const char *name)
@@ -860,10 +877,10 @@ ng_name_node(node_p node, const char *na
 
 	/* Update name hash. */
 	NG_NAMEHASH(name, hash);
-	mtx_lock(&ng_namehash_mtx);
+	NAMEHASH_WLOCK();
 	LIST_REMOVE(node, nd_nodes);
 	LIST_INSERT_HEAD(&V_ng_name_hash[hash], node, nd_nodes);
-	mtx_unlock(&ng_namehash_mtx);
+	NAMEHASH_WUNLOCK();
 
 	return (0);
 }
@@ -898,16 +915,15 @@ ng_name2noderef(node_p here, const char 
 
 	/* Find node by name */
 	NG_NAMEHASH(name, hash);
-	mtx_lock(&ng_namehash_mtx);
-	LIST_FOREACH(node, &V_ng_name_hash[hash], nd_nodes) {
+	NAMEHASH_RLOCK();
+	LIST_FOREACH(node, &V_ng_name_hash[hash], nd_nodes)
 		if (NG_NODE_IS_VALID(node) &&
 		    (strcmp(NG_NODE_NAME(node), name) == 0)) {
+			NG_NODE_REF(node);
 			break;
 		}
-	}
-	if (node)
-		NG_NODE_REF(node);
-	mtx_unlock(&ng_namehash_mtx);
+	NAMEHASH_RUNLOCK();
+
 	return (node);
 }
 
@@ -923,27 +939,21 @@ ng_decodeidname(const char *name)
 	u_long val;
 
 	/* Check for proper length, brackets, no leading junk */
-	if ((len < 3)
-	|| (name[0] != '[')
-	|| (name[len - 1] != ']')
-	|| (!isxdigit(name[1]))) {
+	if ((len < 3) || (name[0] != '[') || (name[len - 1] != ']') ||
+	    (!isxdigit(name[1])))
 		return ((ng_ID_t)0);
-	}
 
 	/* Decode number */
 	val = strtoul(name + 1, &eptr, 16);
-	if ((eptr - name != len - 1)
-	|| (val == ULONG_MAX)
-	|| (val == 0)) {
+	if ((eptr - name != len - 1) || (val == ULONG_MAX) || (val == 0))
 		return ((ng_ID_t)0);
-	}
-	return (ng_ID_t)val;
+
+	return ((ng_ID_t)val);
 }
 
 /*
  * Remove a name from a node. This should only be called
  * when shutting down and removing the node.
- * IF we allow name changing this may be more resurrected.
  */
 void
 ng_unname(node_p node)
@@ -963,15 +973,11 @@ ng_unname(node_p node)
 void
 ng_unref_hook(hook_p hook)
 {
-	int v;
 
-	if (hook == &ng_deadhook) {
+	if (hook == &ng_deadhook)
 		return;
-	}
-
-	v = atomic_fetchadd_int(&hook->hk_refs, -1);
 
-	if (v == 1) { /* we were the last */
+	if (refcount_release(&hook->hk_refs)) { /* we were the last */
 		if (_NG_HOOK_NODE(hook)) /* it'll probably be ng_deadnode */
 			_NG_NODE_UNREF((_NG_HOOK_NODE(hook)));
 		NG_FREE_HOOK(hook);
@@ -1051,8 +1057,8 @@ ng_findhook(node_p node, const char *nam
 	if (node->nd_type->findhook != NULL)
 		return (*node->nd_type->findhook)(node, name);
 	LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
-		if (NG_HOOK_IS_VALID(hook)
-		&& (strcmp(NG_HOOK_NAME(hook), name) == 0))
+		if (NG_HOOK_IS_VALID(hook) &&
+		    (strcmp(NG_HOOK_NAME(hook), name) == 0))
 			return (hook);
 	}
 	return (NULL);
@@ -1188,12 +1194,12 @@ ng_newtype(struct ng_type *tp)
 	const size_t namelen = strlen(tp->name);
 
 	/* Check version and type name fields */
-	if ((tp->version != NG_ABI_VERSION)
-	|| (namelen == 0)
-	|| (namelen >= NG_TYPESIZ)) {
+	if ((tp->version != NG_ABI_VERSION) || (namelen == 0) ||
+	    (namelen >= NG_TYPESIZ)) {
 		TRAP_ERROR();
 		if (tp->version != NG_ABI_VERSION) {
-			printf("Netgraph: Node type rejected. ABI mismatch. Suggest recompile\n");
+			printf("Netgraph: Node type rejected. ABI mismatch. "
+			    "Suggest recompile\n");
 		}
 		return (EINVAL);
 	}
@@ -1206,10 +1212,10 @@ ng_newtype(struct ng_type *tp)
 
 
 	/* Link in new type */
-	mtx_lock(&ng_typelist_mtx);
+	TYPELIST_WLOCK();
 	LIST_INSERT_HEAD(&ng_typelist, tp, types);
 	tp->refs = 1;	/* first ref is linked list */
-	mtx_unlock(&ng_typelist_mtx);
+	TYPELIST_WUNLOCK();
 	return (0);
 }
 
@@ -1227,9 +1233,9 @@ ng_rmtype(struct ng_type *tp)
 	}
 
 	/* Unlink type */
-	mtx_lock(&ng_typelist_mtx);
+	TYPELIST_WLOCK();
 	LIST_REMOVE(tp, types);
-	mtx_unlock(&ng_typelist_mtx);
+	TYPELIST_WUNLOCK();
 	return (0);
 }
 
@@ -1241,12 +1247,12 @@ ng_findtype(const char *typename)
 {
 	struct ng_type *type;
 
-	mtx_lock(&ng_typelist_mtx);
+	TYPELIST_RLOCK();
 	LIST_FOREACH(type, &ng_typelist, types) {
 		if (strcmp(type->name, typename) == 0)
 			break;
 	}
-	mtx_unlock(&ng_typelist_mtx);
+	TYPELIST_RUNLOCK();
 	return (type);
 }
 
@@ -1641,8 +1647,8 @@ ng_path_parse(char *addr, char **nodep, 
  * return the destination node.
  */
 int
-ng_path2noderef(node_p here, const char *address,
-				node_p *destp, hook_p *lasthook)
+ng_path2noderef(node_p here, const char *address, node_p *destp,
+    hook_p *lasthook)
 {
 	char    fullpath[NG_PATHSIZ];
 	char   *nodename, *path;
@@ -1721,10 +1727,9 @@ ng_path2noderef(node_p here, const char 
 
 		mtx_lock(&ng_topo_mtx);
 		/* Can't get there from here... */
-		if (hook == NULL
-		    || NG_HOOK_PEER(hook) == NULL
-		    || NG_HOOK_NOT_VALID(hook)
-		    || NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))) {
+		if (hook == NULL || NG_HOOK_PEER(hook) == NULL ||
+		    NG_HOOK_NOT_VALID(hook) ||
+		    NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))) {
 			TRAP_ERROR();
 			NG_NODE_UNREF(node);
 			mtx_unlock(&ng_topo_mtx);
@@ -1888,9 +1893,9 @@ ng_dequeue(node_p node, int *rw)
 			long t = ngq->q_flags;
 			if (t & WRITER_ACTIVE) {
 				/* There is writer, reader can't proceed. */
-				CTR4(KTR_NET, "%20s: node [%x] (%p) queued reader "
-				    "can't proceed; queue flags 0x%lx", __func__,
-				    node->nd_ID, node, t);
+				CTR4(KTR_NET, "%20s: node [%x] (%p) queued "
+				    "reader can't proceed; queue flags 0x%lx",
+				    __func__, node->nd_ID, node, t);
 				return (NULL);
 			}
 			if (atomic_cmpset_acq_int(&ngq->q_flags, t,
@@ -1906,9 +1911,9 @@ ng_dequeue(node_p node, int *rw)
 		*rw = NGQRW_W;
 	} else {
 		/* There is somebody other, writer can't proceed. */
-		CTR4(KTR_NET, "%20s: node [%x] (%p) queued writer "
-		    "can't proceed; queue flags 0x%lx", __func__,
-		    node->nd_ID, node, ngq->q_flags);
+		CTR4(KTR_NET, "%20s: node [%x] (%p) queued writer can't "
+		    "proceed; queue flags 0x%lx", __func__, node->nd_ID, node,
+		    ngq->q_flags);
 		return (NULL);
 	}
 
@@ -1920,10 +1925,9 @@ ng_dequeue(node_p node, int *rw)
 	STAILQ_REMOVE_HEAD(&ngq->queue, el_next);
 	if (STAILQ_EMPTY(&ngq->queue))
 		atomic_clear_int(&ngq->q_flags, OP_PENDING);
-	CTR6(KTR_NET, "%20s: node [%x] (%p) returning item %p as %s; "
-	    "queue flags 0x%lx", __func__,
-	    node->nd_ID, node, item, *rw ? "WRITER" : "READER" ,
-	    ngq->q_flags);
+	CTR6(KTR_NET, "%20s: node [%x] (%p) returning item %p as %s; queue "
+	    "flags 0x%lx", __func__, node->nd_ID, node, item, *rw ? "WRITER" :
+	    "READER", ngq->q_flags);
 	return (item);
 }
 
@@ -1947,7 +1951,7 @@ ng_queue_rw(node_p node, item_p  item, i
 
 	CTR5(KTR_NET, "%20s: node [%x] (%p) queued item %p as %s", __func__,
 	    node->nd_ID, node, item, rw ? "WRITER" : "READER" );
-	    
+
 	/*
 	 * We can take the worklist lock with the node locked
 	 * BUT NOT THE REVERSE!
@@ -1965,12 +1969,12 @@ ng_acquire_read(node_p node, item_p item
 	    ("%s: working on deadnode", __func__));
 
 	/* Reader needs node without writer and pending items. */
-	while (1) {
+	for (;;) {
 		long t = node->nd_input_queue.q_flags;
 		if (t & NGQ_RMASK)
 			break; /* Node is not ready for reader. */
-		if (atomic_cmpset_acq_int(&node->nd_input_queue.q_flags,
-		    t, t + READER_INCREMENT)) {
+		if (atomic_cmpset_acq_int(&node->nd_input_queue.q_flags, t,
+		    t + READER_INCREMENT)) {
 	    		/* Successfully grabbed node */
 			CTR4(KTR_NET, "%20s: node [%x] (%p) acquired item %p",
 			    __func__, node->nd_ID, node, item);
@@ -1993,8 +1997,8 @@ ng_acquire_write(node_p node, item_p ite
 	    ("%s: working on deadnode", __func__));
 
 	/* Writer needs completely idle node. */
-	if (atomic_cmpset_acq_int(&node->nd_input_queue.q_flags,
-	    0, WRITER_ACTIVE)) {
+	if (atomic_cmpset_acq_int(&node->nd_input_queue.q_flags, 0,
+	    WRITER_ACTIVE)) {
 	    	/* Successfully grabbed node */
 		CTR4(KTR_NET, "%20s: node [%x] (%p) acquired item %p",
 		    __func__, node->nd_ID, node, item);
@@ -2038,11 +2042,10 @@ ng_upgrade_write(node_p node, item_p ite
 		ng_apply_item(node, item, 0);
 
 		/*
-		 * Having acted on the item, atomically 
-		 * down grade back to READER and finish up
+		 * Having acted on the item, atomically
+		 * downgrade back to READER and finish up.
 	 	 */
-		atomic_add_int(&ngq->q_flags,
-		    READER_INCREMENT - WRITER_ACTIVE);
+		atomic_add_int(&ngq->q_flags, READER_INCREMENT - WRITER_ACTIVE);
 
 		/* Our caller will call ng_leave_read() */
 		return;
@@ -2210,11 +2213,10 @@ ng_snd_item(item_p item, int flags)
 		size_t	st, su, sl;
 		GET_STACK_USAGE(st, su);
 		sl = st - su;
-		if ((sl * 4 < st) ||
-		    ((sl * 2 < st) && ((node->nd_flags & NGF_HI_STACK) ||
-		      (hook && (hook->hk_flags & HK_HI_STACK))))) {
+		if ((sl * 4 < st) || ((sl * 2 < st) &&
+		    ((node->nd_flags & NGF_HI_STACK) || (hook &&
+		    (hook->hk_flags & HK_HI_STACK)))))
 			queue = 1;
-		}
 #endif
 	}
 
@@ -2316,10 +2318,10 @@ ng_apply_item(node_p node, item_p item, 
 		}
 		/*
 		 * If no receive method, just silently drop it.
-		 * Give preference to the hook over-ride method
+		 * Give preference to the hook over-ride method.
 		 */
-		if ((!(rcvdata = hook->hk_rcvdata))
-		&& (!(rcvdata = NG_HOOK_NODE(hook)->nd_type->rcvdata))) {
+		if ((!(rcvdata = hook->hk_rcvdata)) &&
+		    (!(rcvdata = NG_HOOK_NODE(hook)->nd_type->rcvdata))) {
 			error = 0;
 			NG_FREE_ITEM(item);
 			break;
@@ -2539,8 +2541,8 @@ ng_generic_msg(node_p here, item_p item,
 		hook_p hook;
 
 		/* Get response struct */
-		NG_MKRESPONSE(resp, msg, sizeof(*hl)
-		    + (nhooks * sizeof(struct linkinfo)), M_NOWAIT);
+		NG_MKRESPONSE(resp, msg, sizeof(*hl) +
+		    (nhooks * sizeof(struct linkinfo)), M_NOWAIT);
 		if (resp == NULL) {
 			error = ENOMEM;
 			break;
@@ -2588,7 +2590,7 @@ ng_generic_msg(node_p here, item_p item,
 		node_p node;
 		int num = 0, i;
 
-		mtx_lock(&ng_namehash_mtx);
+		NAMEHASH_RLOCK();
 		/* Count number of nodes */
 		for (i = 0; i < NG_NAME_HASH_SIZE; i++) {
 			LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) {
@@ -2598,12 +2600,12 @@ ng_generic_msg(node_p here, item_p item,
 				}
 			}
 		}
-		mtx_unlock(&ng_namehash_mtx);
 
 		/* Get response struct */
-		NG_MKRESPONSE(resp, msg, sizeof(*nl)
-		    + (num * sizeof(struct nodeinfo)), M_NOWAIT);
+		NG_MKRESPONSE(resp, msg, sizeof(*nl) +
+		    (num * sizeof(struct nodeinfo)), M_NOWAIT);
 		if (resp == NULL) {
+			NAMEHASH_RUNLOCK();
 			error = ENOMEM;
 			break;
 		}
@@ -2611,7 +2613,6 @@ ng_generic_msg(node_p here, item_p item,
 
 		/* Cycle through the linked list of nodes */
 		nl->numnames = 0;
-		mtx_lock(&ng_namehash_mtx);
 		for (i = 0; i < NG_NAME_HASH_SIZE; i++) {
 			LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) {
 				struct nodeinfo *const np =
@@ -2621,20 +2622,17 @@ ng_generic_msg(node_p here, item_p item,
 					continue;
 				if (!unnamed && (! NG_NODE_HAS_NAME(node)))
 					continue;
-				if (nl->numnames >= num) {
-					log(LOG_ERR, "%s: number of nodes changed\n",
-					    __func__);
-					break;
-				}
 				if (NG_NODE_HAS_NAME(node))
 					strcpy(np->name, NG_NODE_NAME(node));
 				strcpy(np->type, node->nd_type->name);
 				np->id = ng_node2ID(node);
 				np->hooks = node->nd_numhooks;
+				KASSERT(nl->numnames < num, ("%s: no space",
+				    __func__));
 				nl->numnames++;
 			}
 		}
-		mtx_unlock(&ng_namehash_mtx);
+		NAMEHASH_RUNLOCK();
 		break;
 	    }
 
@@ -2644,17 +2642,16 @@ ng_generic_msg(node_p here, item_p item,
 		struct ng_type *type;
 		int num = 0;
 
-		mtx_lock(&ng_typelist_mtx);
+		TYPELIST_RLOCK();
 		/* Count number of types */
-		LIST_FOREACH(type, &ng_typelist, types) {
+		LIST_FOREACH(type, &ng_typelist, types)
 			num++;
-		}
-		mtx_unlock(&ng_typelist_mtx);
 
 		/* Get response struct */
-		NG_MKRESPONSE(resp, msg, sizeof(*tl)
-		    + (num * sizeof(struct typeinfo)), M_NOWAIT);
+		NG_MKRESPONSE(resp, msg, sizeof(*tl) +
+		    (num * sizeof(struct typeinfo)), M_NOWAIT);
 		if (resp == NULL) {
+			TYPELIST_RUNLOCK();
 			error = ENOMEM;
 			break;
 		}
@@ -2662,20 +2659,15 @@ ng_generic_msg(node_p here, item_p item,
 
 		/* Cycle through the linked list of types */
 		tl->numtypes = 0;
-		mtx_lock(&ng_typelist_mtx);
 		LIST_FOREACH(type, &ng_typelist, types) {
 			struct typeinfo *const tp = &tl->typeinfo[tl->numtypes];
 
-			if (tl->numtypes >= num) {
-				log(LOG_ERR, "%s: number of %s changed\n",
-				    __func__, "types");
-				break;
-			}
 			strcpy(tp->type_name, type->name);
 			tp->numnodes = type->refs - 1; /* don't count list */
+			KASSERT(tl->numtypes < num, ("%s: no space", __func__));
 			tl->numtypes++;
 		}
-		mtx_unlock(&ng_typelist_mtx);
+		TYPELIST_RUNLOCK();
 		break;
 	    }
 
@@ -2708,16 +2700,16 @@ ng_generic_msg(node_p here, item_p item,
 		bcopy(binary, ascii, sizeof(*binary));
 
 		/* Find command by matching typecookie and command number */
-		for (c = here->nd_type->cmdlist;
-		    c != NULL && c->name != NULL; c++) {
-			if (binary->header.typecookie == c->cookie
-			    && binary->header.cmd == c->cmd)
+		for (c = here->nd_type->cmdlist; c != NULL && c->name != NULL;
+		    c++) {
+			if (binary->header.typecookie == c->cookie &&
+			    binary->header.cmd == c->cmd)
 				break;
 		}
 		if (c == NULL || c->name == NULL) {
 			for (c = ng_generic_cmds; c->name != NULL; c++) {
-				if (binary->header.typecookie == c->cookie
-				    && binary->header.cmd == c->cmd)
+				if (binary->header.typecookie == c->cookie &&
+				    binary->header.cmd == c->cmd)
 					break;
 			}
 			if (c->name == NULL) {
@@ -2811,8 +2803,8 @@ ng_generic_msg(node_p here, item_p item,
 		if (argstype == NULL) {
 			bufSize = 0;
 		} else {
-			if ((error = ng_parse(argstype, ascii->data,
-			    &off, (u_char *)binary->data, &bufSize)) != 0) {
+			if ((error = ng_parse(argstype, ascii->data, &off,
+			    (u_char *)binary->data, &bufSize)) != 0) {
 				NG_FREE_MSG(resp);
 				break;
 			}
@@ -2843,7 +2835,7 @@ ng_generic_msg(node_p here, item_p item,
 	}
 	/*
 	 * Sometimes a generic message may be statically allocated
-	 * to avoid problems with allocating when in tight memeory situations.
+	 * to avoid problems with allocating when in tight memory situations.
 	 * Don't free it if it is so.
 	 * I break them appart here, because erros may cause a free if the item
 	 * in which case we'd be doing it twice.
@@ -2877,7 +2869,7 @@ SYSCTL_INT(_net_graph, OID_AUTO, maxdata
 
 #ifdef	NETGRAPH_DEBUG
 static TAILQ_HEAD(, ng_item) ng_itemlist = TAILQ_HEAD_INITIALIZER(ng_itemlist);
-static int			allocated;	/* number of items malloc'd */
+static int allocated;	/* number of items malloc'd */
 #endif
 
 /*
@@ -2895,7 +2887,7 @@ ng_alloc_item(int type, int flags)
 	KASSERT(((type & ~NGQF_TYPE) == 0),
 	    ("%s: incorrect item type: %d", __func__, type));
 
-	item = uma_zalloc((type == NGQF_DATA)?ng_qdzone:ng_qzone,
+	item = uma_zalloc((type == NGQF_DATA) ? ng_qdzone : ng_qzone,
 	    ((flags & NG_WAITOK) ? M_WAITOK : M_NOWAIT) | M_ZERO);
 
 	if (item) {
@@ -2951,8 +2943,8 @@ ng_free_item(item_p item)
 	allocated--;
 	mtx_unlock(&ngq_mtx);
 #endif
-	uma_zfree(((item->el_flags & NGQF_TYPE) == NGQF_DATA)?
-	    ng_qdzone:ng_qzone, item);
+	uma_zfree(((item->el_flags & NGQF_TYPE) == NGQF_DATA) ?
+	    ng_qdzone : ng_qzone, item);
 }
 
 /*
@@ -2997,51 +2989,40 @@ int
 ng_mod_event(module_t mod, int event, void *data)
 {
 	struct ng_type *const type = data;
-	int s, error = 0;
+	int error = 0;
 
 	switch (event) {
 	case MOD_LOAD:
 
 		/* Register new netgraph node type */
-		s = splnet();
-		if ((error = ng_newtype(type)) != 0) {
-			splx(s);
+		if ((error = ng_newtype(type)) != 0)
 			break;
-		}
 
 		/* Call type specific code */
 		if (type->mod_event != NULL)
 			if ((error = (*type->mod_event)(mod, event, data))) {
-				mtx_lock(&ng_typelist_mtx);
+				TYPELIST_WLOCK();
 				type->refs--;	/* undo it */
 				LIST_REMOVE(type, types);
-				mtx_unlock(&ng_typelist_mtx);
+				TYPELIST_WUNLOCK();
 			}
-		splx(s);
 		break;
 
 	case MOD_UNLOAD:
-		s = splnet();
 		if (type->refs > 1) {		/* make sure no nodes exist! */
 			error = EBUSY;
 		} else {
-			if (type->refs == 0) {
-				/* failed load, nothing to undo */
-				splx(s);
+			if (type->refs == 0) /* failed load, nothing to undo */
 				break;
-			}
 			if (type->mod_event != NULL) {	/* check with type */
 				error = (*type->mod_event)(mod, event, data);
-				if (error != 0) {	/* type refuses.. */
-					splx(s);
+				if (error != 0)	/* type refuses.. */
 					break;
-				}
 			}
-			mtx_lock(&ng_typelist_mtx);
+			TYPELIST_WLOCK();
 			LIST_REMOVE(type, types);
-			mtx_unlock(&ng_typelist_mtx);
+			TYPELIST_WUNLOCK();
 		}
-		splx(s);
 		break;
 
 	default:
@@ -3054,7 +3035,7 @@ ng_mod_event(module_t mod, int event, vo
 	return (error);
 }
 
-#ifdef VIMAGE 
+#ifdef VIMAGE
 static void
 vnet_netgraph_uninit(const void *unused __unused)
 {
@@ -3063,7 +3044,7 @@ vnet_netgraph_uninit(const void *unused 
 
 	do {
 		/* Find a node to kill */
-		mtx_lock(&ng_namehash_mtx);
+		NAMEHASH_RLOCK();
 		for (i = 0; i < NG_NAME_HASH_SIZE; i++) {
 			LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) {
 				if (node != &ng_deadnode) {
@@ -3074,14 +3055,14 @@ vnet_netgraph_uninit(const void *unused 
 			if (node != NULL)
 				break;
 		}
-		mtx_unlock(&ng_namehash_mtx);
+		NAMEHASH_RUNLOCK();
 
 		/* Attempt to kill it only if it is a regular node */
 		if (node != NULL) {
 			if (node == last_killed) {
 				/* This should never happen */
-				printf("ng node %s needs"
-				    "NGF_REALLY_DIE\n", node->nd_name);
+				printf("ng node %s needs NGF_REALLY_DIE\n",
+				    node->nd_name);
 				if (node->nd_flags & NGF_REALLY_DIE)
 					panic("ng node %s won't die",
 					    node->nd_name);
@@ -3112,12 +3093,9 @@ ngb_mod_event(module_t mod, int event, v
 	case MOD_LOAD:
 		/* Initialize everything. */
 		NG_WORKLIST_LOCK_INIT();
-		mtx_init(&ng_typelist_mtx, "netgraph types mutex", NULL,
-		    MTX_DEF);
-		mtx_init(&ng_idhash_mtx, "netgraph idhash mutex", NULL,
-		    MTX_DEF);
-		mtx_init(&ng_namehash_mtx, "netgraph namehash mutex", NULL,
-		    MTX_DEF);
+		rw_init(&ng_typelist_lock, "netgraph types");
+		rw_init(&ng_idhash_lock, "netgraph idhash");
+		rw_init(&ng_namehash_lock, "netgraph namehash");
 		mtx_init(&ng_topo_mtx, "netgraph topology mutex", NULL,
 		    MTX_DEF);
 #ifdef	NETGRAPH_DEBUG
@@ -3129,8 +3107,9 @@ ngb_mod_event(module_t mod, int event, v
 		ng_qzone = uma_zcreate("NetGraph items", sizeof(struct ng_item),
 		    NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
 		uma_zone_set_max(ng_qzone, maxalloc);
-		ng_qdzone = uma_zcreate("NetGraph data items", sizeof(struct ng_item),
-		    NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
+		ng_qdzone = uma_zcreate("NetGraph data items",
+		    sizeof(struct ng_item), NULL, NULL, NULL, NULL,
+		    UMA_ALIGN_CACHE, 0);
 		uma_zone_set_max(ng_qdzone, maxdata);
 		/* Autoconfigure number of threads. */
 		if (numthreads <= 0)
@@ -3176,6 +3155,9 @@ dumphook (hook_p hook, char *file, int l
 		hook->lastfile, hook->lastline);
 	if (line) {
 		printf(" problem discovered at file %s, line %d\n", file, line);
+#ifdef KDB
+		kdb_backtrace();
+#endif
 	}
 }
 
@@ -3190,6 +3172,9 @@ dumpnode(node_p node, char *file, int li
 		node->lastfile, node->lastline);
 	if (line) {
 		printf(" problem discovered at file %s, line %d\n", file, line);
+#ifdef KDB
+		kdb_backtrace();
+#endif
 	}
 }
 
@@ -3365,7 +3350,7 @@ ng_worklist_add(node_p node)
 		 * then put us on.
 		 */
 		node->nd_input_queue.q_flags2 |= NGQ2_WORKQ;
-		NG_NODE_REF(node); /* XXX fafe in mutex? */
+		NG_NODE_REF(node); /* XXX safe in mutex? */
 		NG_WORKLIST_LOCK();
 		STAILQ_INSERT_TAIL(&ng_worklist, node, nd_input_queue.q_work);
 		NG_WORKLIST_UNLOCK();
@@ -3493,8 +3478,7 @@ ng_address_hook(node_p here, item_p item
 	 * that the peer node is present, though maybe invalid.
 	 */
 	mtx_lock(&ng_topo_mtx);
-	if ((hook == NULL) ||
-	    NG_HOOK_NOT_VALID(hook) ||
+	if ((hook == NULL) || NG_HOOK_NOT_VALID(hook) ||
 	    NG_HOOK_NOT_VALID(peer = NG_HOOK_PEER(hook)) ||
 	    NG_NODE_NOT_VALID(peernode = NG_PEER_NODE(hook))) {
 		NG_FREE_ITEM(item);
@@ -3786,4 +3770,3 @@ ng_macro_test(item_p item)
 	NG_FWD_MSG_HOOK(error, node, item, hook, retaddr);
 }
 #endif /* TESTING */
-

Modified: stable/8/sys/netgraph/ng_socket.c
==============================================================================
--- stable/8/sys/netgraph/ng_socket.c	Tue Feb 14 17:18:45 2012	(r231695)
+++ stable/8/sys/netgraph/ng_socket.c	Tue Feb 14 17:35:44 2012	(r231696)
@@ -51,6 +51,7 @@
 
 #include <sys/param.h>
 #include <sys/domain.h>
+#include <sys/hash.h>
 #include <sys/kernel.h>
 #include <sys/linker.h>
 #include <sys/lock.h>
@@ -64,9 +65,6 @@
 #include <sys/socketvar.h>
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
-#ifdef NOTYET
-#include <sys/vnode.h>
-#endif
 
 #include <net/vnet.h>
 
@@ -115,6 +113,7 @@ static ng_rcvmsg_t	ngs_rcvmsg;
 static ng_shutdown_t	ngs_shutdown;
 static ng_newhook_t	ngs_newhook;
 static ng_connect_t	ngs_connect;
+static ng_findhook_t	ngs_findhook;
 static ng_rcvdata_t	ngs_rcvdata;
 static ng_disconnect_t	ngs_disconnect;
 
@@ -124,9 +123,6 @@ static int	ng_attach_cntl(struct socket 
 static int	ng_attach_common(struct socket *so, int type);
 static void	ng_detach_common(struct ngpcb *pcbp, int type);
 static void	ng_socket_free_priv(struct ngsock *priv);
-#ifdef NOTYET
-static int	ng_internalize(struct mbuf *m, struct thread *p);
-#endif
 static int	ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
 static int	ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
 
@@ -143,6 +139,7 @@ static struct ng_type typestruct = {
 	.shutdown =	ngs_shutdown,
 	.newhook =	ngs_newhook,
 	.connect =	ngs_connect,
+	.findhook =	ngs_findhook,
 	.rcvdata =	ngs_rcvdata,
 	.disconnect =	ngs_disconnect,
 };
@@ -209,19 +206,10 @@ ngc_send(struct socket *so, int flags, s
 	int len, error = 0;
 	struct ng_apply_info apply;
 
-#ifdef	NOTYET
-	if (control && (error = ng_internalize(control, td))) {
-		if (pcbp->sockdata == NULL) {
-			error = ENOTCONN;
-			goto release;
-		}
-	}
-#else	/* NOTYET */
 	if (control) {
 		error = EINVAL;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202141735.q1EHZiju010205>