Skip to content

Instantly share code, notes, and snippets.

@vstakhov
Last active December 21, 2015 00:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vstakhov/6223170 to your computer and use it in GitHub Desktop.
Save vstakhov/6223170 to your computer and use it in GitHub Desktop.
ng_ipacct locking improvement
--- ng_ipacct/ng_ipacct.c.orig 2006-12-05 23:46:04.000000000 +0300
+++ ng_ipacct/ng_ipacct.c 2013-08-13 16:21:16.000000000 +0400
@@ -140,9 +140,6 @@
struct ipacct_hook {
hook_p hook;
node_p node;
-#if __FreeBSD_version >= 503000
- struct mtx h_mtx; /* protects hook data */
-#endif
struct ip_acct_hash *active; /* active database */
struct ip_acct_hash *checked; /* checkpointed database */
struct ng_ipacct_hinfo hi; /* hook info */
@@ -242,9 +239,6 @@
if (!strncmp(name + strlen(name) - 3, "_in", 3))
hip->hi.hi_flags |= HI_INCOMING_HOOK;
-#if __FreeBSD_version >= 503000
- mtx_init(&hip->h_mtx, "ng_ipacct hash", NULL, MTX_DEF);
-#endif
NG_HOOK_SET_PRIVATE(hook, hip);
hip->hi.hi_debug = 0;
#ifdef VERBOSE
@@ -531,13 +525,7 @@
if (!error) {
Dbg_print(DBG_DLT, ("IP packet, m_pkthdr.len = %d, m_len = %d\n",
m->m_pkthdr.len, m->m_len));
-#if __FreeBSD_version >= 503000
- mtx_lock(&hip->h_mtx);
-#endif
error = ip_account_add(hip, &m);
-#if __FreeBSD_version >= 503000
- mtx_unlock(&hip->h_mtx);
-#endif
}
#if __FreeBSD_version >= 503000
@@ -581,9 +569,6 @@
ip_account_stop(hip);
NG_HOOK_SET_PRIVATE(hook, NULL);
-#if __FreeBSD_version >= 503000
- mtx_destroy(&hip->h_mtx);
-#endif
FREE(hip, M_NETGRAPH);
#ifdef VERBOSE
printf("NG_ipacct: disconnect hook %s\n", NG_HOOK_NAME(hook));
@@ -902,7 +899,11 @@
int i;
for (i = 0, ina = r->r_dst, port = r->r_dport; i < 2; i++) {
+#if __FreeBSD_version >= 700110
+ pcb = in_pcblookup_local(pcbinfo, ina, port, 1, NOCRED);
+#else
pcb = in_pcblookup_local(pcbinfo, ina, port, 1);
+#endif
if ((pcb != NULL) &&
(pcb->inp_laddr.s_addr == ina.s_addr)) {
break;
--- ng_ipacct/ng_ipacct_hash.h.orig 2004-11-27 23:35:19.000000000 +0300
+++ ng_ipacct/ng_ipacct_hash.h 2013-08-13 20:50:07.000000000 +0400
@@ -26,7 +26,10 @@
* $Id: ng_ipacct_hash.h,v 1.6 2004/11/27 20:35:19 romanp Exp $
*/
-#define NBUCKETS (256) /* must be power of 2 */
+#define NBUCKETS (256) /* must be power of 2 */
+
+#include <sys/lock.h>
+#include <sys/rmlock.h>
#define NG_IPACCT_HASH3(faddr, fport, lport)\
((faddr) ^ ((faddr) >> 16) ^ ntohs((lport) ^ (fport)))
@@ -34,6 +37,7 @@
((faddr ^ (faddr >> 23) ^ (faddr >> 17)))
struct ip_acct_hash {
+ struct rmlock bl;
SLIST_HEAD( ,ip_acct_chunk) head;
};
@@ -42,12 +46,20 @@
static __inline int
ip_hash_init(struct ip_acct_hash **h)
{
+ int i;
+ struct ip_acct_hash *ph;
+
MALLOC(*h, struct ip_acct_hash *,
NBUCKETS * sizeof(struct ip_acct_hash),
M_NETGRAPH, M_NOWAIT | M_ZERO);
if (*h == NULL)
return (ENOMEM);
+ ph = *h;
+ for (i = 0; i < NBUCKETS; i ++) {
+ rm_init(&ph[i].bl, "ng_ipacct hash lock");
+ }
+
return (0);
}
@@ -59,15 +71,18 @@
struct ip_acct_chunk *pe, *lastpe;
struct ip_acct_record *pr;
int i;
+ struct rm_priotracker track;
#ifdef HASH_DEBUG
int nchunk = 0;
#endif
pe = lastpe = NULL;
+ rm_rlock(&h[slot].bl, &track);
SLIST_FOREACH(pe, &(h[slot].head), next) {
lastpe = pe;
for (i = 0; i < pe->nrecs; i++) {
if(bcmp(s, &pe->recs[i].s, sizeof(struct ip_acct_stream)) == 0) {
+ rm_runlock(&h[slot].bl, &track);
return (&pe->recs[i]);
}
}
@@ -75,12 +90,29 @@
nchunk ++;
#endif
}
+ rm_runlock(&h[slot].bl, &track);
#ifdef HASH_DEBUG
if (nchunk)
nchunk --;
#endif
/* stream is not in hash. Add it if we allowed to do so. */
if (ok_to_insert) {
+
+ rm_wlock(&h[slot].bl);
+ if (lastpe != NULL && SLIST_NEXT(lastpe, next) != NULL) {
+ /* It has been changed, need to scan again */
+ pe = lastpe;
+ while (pe != NULL) {
+ lastpe = pe;
+ for (i = 0; i < pe->nrecs; i++) {
+ if(bcmp(s, &pe->recs[i].s, sizeof(struct ip_acct_stream)) == 0) {
+ rm_wunlock(&h[slot].bl);
+ return (&pe->recs[i]);
+ }
+ }
+ pe = SLIST_NEXT(pe, next);
+ }
+ }
/*
* This is first chunk in slot or no
* more space left in current chunk ?
@@ -92,8 +124,10 @@
sizeof(*pe));
#endif
/* allocate new accounting chunk */
- if ((pe = HASH_ALLOC()) == NULL)
+ if ((pe = HASH_ALLOC()) == NULL) {
+ rm_wunlock(&h[slot].bl);
return (NULL);
+ }
if (lastpe == NULL)
SLIST_INSERT_HEAD(&(h[slot].head), pe, next);
else
@@ -109,6 +143,7 @@
pr->when = time_second;
bcopy(s, &pr->s, sizeof(pr->s));
(*nrecs) ++;
+ rm_wunlock(&h[slot].bl);
return (pr);
} else {
return (NULL);
@@ -120,6 +155,7 @@
{
int i;
struct ip_acct_chunk *ipe, *nxt;
+ struct ip_acct_hash *ph = *h;
/* sanity check */
if (*h == NULL)
@@ -127,10 +163,13 @@
/* walk down through *next and free all memory */
for(i = 0; i < NBUCKETS; i++) {
+ rm_wlock(&ph[i].bl);
for(ipe = SLIST_FIRST(&((*h)[i].head)); ipe; ipe = nxt) {
nxt = SLIST_NEXT(ipe, next);
HASH_FREE(ipe);
}
+ rm_wunlock(&ph[i].bl);
+ rm_destroy(&ph[i].bl);
}
FREE(*h, M_NETGRAPH);
*h = NULL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment