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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to