Last active
December 21, 2015 00:49
-
-
Save vstakhov/6223170 to your computer and use it in GitHub Desktop.
ng_ipacct locking improvement
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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