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>