Date: Tue, 24 Apr 2012 13:13:42 +0000 (UTC) From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r234651 - projects/pf/head/sys/contrib/pf/net Message-ID: <201204241313.q3ODDgjs049959@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: glebius Date: Tue Apr 24 13:13:42 2012 New Revision: 234651 URL: http://svn.freebsd.org/changeset/base/234651 Log: States and source nodes reference rules, so when state or source node is expired a rule may potentially be deleted. In the new locking scheme this is a problem, since we don't have writer lock on rules in packet processing, and we don't like any additional atomic operations in forwarding path. To cope with that, pf_rm_rule() was split into two pieces - pf_unlink_rule(), that removes a rule from the ruleset, and pf_free_rule() that does actual freeing. Freeing of once used rules is performed solely by the pf expiry thread. It now performs naive mark-and-sweep algorithm, based on states and source nodes expiry run. We still account number of states per rule and number of source nodes, since they are important to drive adaptive expiry and 'max-src-conn' rules. When we get rid of pf giant lock, these increments/decrements should be reconsidered and probably made atomic. Also: - Migrate from PF_LOCK() to PF_RULES_WLOCK() in all rule manipulating ioctls. Modified: projects/pf/head/sys/contrib/pf/net/pf.c projects/pf/head/sys/contrib/pf/net/pf_ioctl.c projects/pf/head/sys/contrib/pf/net/pfvar.h Modified: projects/pf/head/sys/contrib/pf/net/pf.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf.c Tue Apr 24 12:54:04 2012 (r234650) +++ projects/pf/head/sys/contrib/pf/net/pf.c Tue Apr 24 13:13:42 2012 (r234651) @@ -187,6 +187,9 @@ static struct mtx pf_sendqueue_mtx; #define PF_QUEUE_LOCK() mtx_lock(&pf_sendqueue_mtx) #define PF_QUEUE_UNLOCK() mtx_unlock(&pf_sendqueue_mtx) +VNET_DEFINE(struct pf_rulequeue, pf_unlinked_rules); +struct mtx pf_unlnkdrules_mtx; + VNET_DEFINE(uma_zone_t, pf_sources_z); VNET_DEFINE(uma_zone_t, pf_rule_z); VNET_DEFINE(uma_zone_t, pf_pooladdr_z); @@ -291,7 +294,8 @@ static struct pf_state *pf_find_state(st static int pf_src_connlimit(struct pf_state **); static int pf_insert_src_node(struct pf_src_node **, struct pf_rule *, struct pf_addr *, sa_family_t); -static void pf_purge_expired_states(int); +static int pf_purge_expired_states(int); +static void pf_purge_unlinked_rules(void); int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len); @@ -709,6 +713,10 @@ pf_initialize() STAILQ_INIT(&V_pf_sendqueue); mtx_init(&pf_sendqueue_mtx, "pf send queue", NULL, MTX_DEF); + /* Unlinked, but may be referenced rules. */ + TAILQ_INIT(&V_pf_unlinked_rules); + mtx_init(&pf_unlnkdrules_mtx, "pf unlinked rules", NULL, MTX_DEF); + /* XXXGL: sort this out */ V_pf_rule_z = uma_zcreate("pf rules", sizeof(struct pf_rule), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); @@ -761,6 +769,8 @@ pf_cleanup() } mtx_destroy(&pf_sendqueue_mtx); + mtx_destroy(&pf_unlnkdrules_mtx); + uma_zdestroy(V_pf_sources_z); uma_zdestroy(V_pf_rule_z); uma_zdestroy(V_pf_state_z); @@ -1278,7 +1288,7 @@ pf_intr(void *v) void pf_purge_thread(void *v) { - int nloops = 0; + int fullrun; CURVNET_SET((struct vnet *)v); @@ -1298,14 +1308,15 @@ pf_purge_thread(void *v) } /* Process a fraction of the state table every second. */ - pf_purge_expired_states(V_pf_hashmask / + fullrun = pf_purge_expired_states(V_pf_hashmask / V_pf_default_rule.timeout[PFTM_INTERVAL]); /* Purge other expired types every PFTM_INTERVAL seconds. */ - if (++nloops >= V_pf_default_rule.timeout[PFTM_INTERVAL]) { + if (fullrun) { + /* Order important: rules should be the last. */ pf_purge_expired_fragments(); pf_purge_expired_src_nodes(); - nloops = 0; + pf_purge_unlinked_rules(); } PF_UNLOCK(); @@ -1364,17 +1375,14 @@ pf_purge_expired_src_nodes() PF_HASHROW_LOCK(sh); LIST_FOREACH_SAFE(cur, &sh->nodes, entry, next) if (cur->states <= 0 && cur->expire <= time_uptime) { - if (cur->rule.ptr != NULL) { + if (cur->rule.ptr != NULL) cur->rule.ptr->src_nodes--; - if (cur->rule.ptr->states_cur <= 0 && - cur->rule.ptr->max_src_nodes <= 0) - pf_rm_rule(NULL, cur->rule.ptr); - } LIST_REMOVE(cur, entry); V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++; V_pf_status.src_nodes--; uma_zfree(V_pf_sources_z, cur); - } + } else if (cur->rule.ptr != NULL) + cur->rule.ptr->rule_flag |= PFRULE_REFS; PF_HASHROW_UNLOCK(sh); } } @@ -1458,16 +1466,11 @@ pf_free_state(struct pf_state *cur) KASSERT(cur->refs == 0, ("%s: %p has refs", __func__, cur)); KASSERT(cur->timeout == PFTM_UNLINKED, ("%s: timeout %u", __func__, cur->timeout)); - if (--cur->rule.ptr->states_cur <= 0 && - cur->rule.ptr->src_nodes <= 0) - pf_rm_rule(NULL, cur->rule.ptr); + --cur->rule.ptr->states_cur; if (cur->nat_rule.ptr != NULL) - if (--cur->nat_rule.ptr->states_cur <= 0 && - cur->nat_rule.ptr->src_nodes <= 0) - pf_rm_rule(NULL, cur->nat_rule.ptr); + --cur->nat_rule.ptr->states_cur; if (cur->anchor.ptr != NULL) - if (--cur->anchor.ptr->states_cur <= 0) - pf_rm_rule(NULL, cur->anchor.ptr); + --cur->anchor.ptr->states_cur; pf_normalize_tcp_cleanup(cur); pfi_kif_unref(cur->kif, PFI_KIF_REF_STATE); if (cur->tag) @@ -1480,13 +1483,14 @@ pf_free_state(struct pf_state *cur) /* * Called only from pf_purge_thread(), thus serialized. */ -static void +static int pf_purge_expired_states(int maxcheck) { static u_int i = 0; struct pf_idhash *ih; struct pf_state *s; + int rv = 0; /* * Go through hash and unlink states that expire now. @@ -1494,8 +1498,10 @@ pf_purge_expired_states(int maxcheck) while (maxcheck > 0) { /* Wrap to start of hash when we hit the end. */ - if (i > V_pf_hashmask) + if (i > V_pf_hashmask) { i = 0; + rv = 1; + } ih = &V_pf_idhash[i]; relock: @@ -1505,11 +1511,40 @@ relock: pf_unlink_state(s, PF_ENTER_LOCKED); goto relock; } + s->rule.ptr->rule_flag |= PFRULE_REFS; + if (s->nat_rule.ptr != NULL) + s->nat_rule.ptr->rule_flag |= PFRULE_REFS; + if (s->anchor.ptr != NULL) + s->anchor.ptr->rule_flag |= PFRULE_REFS; + } PF_HASHROW_UNLOCK(ih); i++; maxcheck--; } + + return (rv); +} + +static void +pf_purge_unlinked_rules() +{ + struct pf_rule *r, *r1; + + /* + * Do naive mark-and-sweep garbage collecting of old rules. + * Reference flag is raised by pf_purge_expired_states() + * and pf_purge_expired_src_nodes(). + */ + PF_UNLNKDRULES_LOCK(); + TAILQ_FOREACH_SAFE(r, &V_pf_unlinked_rules, entries, r1) { + if (!(r->rule_flag & PFRULE_REFS)) { + TAILQ_REMOVE(&V_pf_unlinked_rules, r, entries); + pf_free_rule(r); + } else + r->rule_flag &= ~PFRULE_REFS; + } + PF_UNLNKDRULES_UNLOCK(); } void Modified: projects/pf/head/sys/contrib/pf/net/pf_ioctl.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf_ioctl.c Tue Apr 24 12:54:04 2012 (r234650) +++ projects/pf/head/sys/contrib/pf/net/pf_ioctl.c Tue Apr 24 13:13:42 2012 (r234651) @@ -385,29 +385,24 @@ pf_empty_pool(struct pf_palist *poola) } } +static void +pf_unlink_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) +{ + + PF_RULES_WASSERT(); + + TAILQ_REMOVE(rulequeue, rule, entries); + + PF_UNLNKDRULES_LOCK(); + rule->rule_flag |= PFRULE_REFS; + TAILQ_INSERT_TAIL(&V_pf_unlinked_rules, rule, entries); + PF_UNLNKDRULES_UNLOCK(); +} + void -pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) +pf_free_rule(struct pf_rule *rule) { - if (rulequeue != NULL) { - if (rule->states_cur <= 0) { - /* - * XXX - we need to remove the table *before* detaching - * the rule to make sure the table code does not delete - * the anchor under our feet. - */ - pf_tbladdr_remove(&rule->src.addr); - pf_tbladdr_remove(&rule->dst.addr); - if (rule->overload_tbl) - pfr_detach_table(rule->overload_tbl); - } - TAILQ_REMOVE(rulequeue, rule, entries); - rule->entries.tqe_prev = NULL; - rule->nr = -1; - } - if (rule->states_cur > 0 || rule->src_nodes > 0 || - rule->entries.tqe_prev != NULL) - return; pf_tag_unref(rule->tag); pf_tag_unref(rule->match_tag); #ifdef ALTQ @@ -419,12 +414,10 @@ pf_rm_rule(struct pf_rulequeue *rulequeu pf_rtlabel_remove(&rule->dst.addr); pfi_dynaddr_remove(&rule->src.addr); pfi_dynaddr_remove(&rule->dst.addr); - if (rulequeue == NULL) { - pf_tbladdr_remove(&rule->src.addr); - pf_tbladdr_remove(&rule->dst.addr); - if (rule->overload_tbl) - pfr_detach_table(rule->overload_tbl); - } + pf_tbladdr_remove(&rule->src.addr); + pf_tbladdr_remove(&rule->dst.addr); + if (rule->overload_tbl) + pfr_detach_table(rule->overload_tbl); pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE); pf_anchor_remove(rule); pf_empty_pool(&rule->rpool.list); @@ -781,13 +774,15 @@ pf_begin_rules(u_int32_t *ticket, int rs struct pf_ruleset *rs; struct pf_rule *rule; + PF_RULES_WASSERT(); + if (rs_num < 0 || rs_num >= PF_RULESET_MAX) return (EINVAL); rs = pf_find_or_create_ruleset(anchor); if (rs == NULL) return (EINVAL); while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) { - pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule); + pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule); rs->rules[rs_num].inactive.rcount--; } *ticket = ++rs->rules[rs_num].inactive.ticket; @@ -801,6 +796,8 @@ pf_rollback_rules(u_int32_t ticket, int struct pf_ruleset *rs; struct pf_rule *rule; + PF_RULES_WASSERT(); + if (rs_num < 0 || rs_num >= PF_RULESET_MAX) return (EINVAL); rs = pf_find_ruleset(anchor); @@ -808,7 +805,7 @@ pf_rollback_rules(u_int32_t ticket, int rs->rules[rs_num].inactive.ticket != ticket) return (0); while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) { - pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule); + pf_unlink_rule(rs->rules[rs_num].inactive.ptr, rule); rs->rules[rs_num].inactive.rcount--; } rs->rules[rs_num].inactive.open = 0; @@ -907,6 +904,8 @@ pf_commit_rules(u_int32_t ticket, int rs int error; u_int32_t old_rcount; + PF_RULES_WASSERT(); + if (rs_num < 0 || rs_num >= PF_RULESET_MAX) return (EINVAL); rs = pf_find_ruleset(anchor); @@ -943,7 +942,7 @@ pf_commit_rules(u_int32_t ticket, int rs /* Purge the old rule list. */ while ((rule = TAILQ_FIRST(old_rules)) != NULL) - pf_rm_rule(old_rules, rule); + pf_unlink_rule(old_rules, rule); if (rs->rules[rs_num].inactive.ptr_array) free(rs->rules[rs_num].inactive.ptr_array, M_TEMP); rs->rules[rs_num].inactive.ptr_array = NULL; @@ -1183,27 +1182,27 @@ pfioctl(struct cdev *dev, u_long cmd, ca struct pf_pooladdr *pa; int rs_num; - PF_LOCK(); + PF_RULES_WLOCK(); pr->anchor[sizeof(pr->anchor) - 1] = 0; ruleset = pf_find_ruleset(pr->anchor); if (ruleset == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } rs_num = pf_get_ruleset_number(pr->rule.action); if (rs_num >= PF_RULESET_MAX) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); DPFPRINTF(PF_DEBUG_MISC, ("ticket: %d != [%d]%d\n", pr->ticket, rs_num, ruleset->rules[rs_num].inactive.ticket)); @@ -1211,7 +1210,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca break; } if (pr->pool_ticket != V_ticket_pabuf) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); DPFPRINTF(PF_DEBUG_MISC, ("pool_ticket: %d != %d\n", pr->pool_ticket, V_ticket_pabuf)); @@ -1220,7 +1219,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca } rule = uma_zalloc(V_pf_rule_z, M_NOWAIT); if (rule == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = ENOMEM; break; } @@ -1236,7 +1235,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca rule->entries.tqe_prev = NULL; #ifndef INET if (rule->af == AF_INET) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); uma_zfree(V_pf_rule_z, rule); error = EAFNOSUPPORT; break; @@ -1244,7 +1243,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca #endif /* INET */ #ifndef INET6 if (rule->af == AF_INET6) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); uma_zfree(V_pf_rule_z, rule); error = EAFNOSUPPORT; break; @@ -1259,7 +1258,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca if (rule->ifname[0]) { rule->kif = pfi_kif_get(rule->ifname); if (rule->kif == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); uma_zfree(V_pf_rule_z, rule); error = EINVAL; break; @@ -1328,8 +1327,8 @@ pfioctl(struct cdev *dev, u_long cmd, ca error = EINVAL; if (error) { - pf_rm_rule(NULL, rule); - PF_UNLOCK(); + pf_free_rule(rule); + PF_RULES_WUNLOCK(); break; } @@ -1339,7 +1338,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr, rule, entries); ruleset->rules[rs_num].inactive.rcount++; - PF_UNLOCK(); + PF_RULES_WUNLOCK(); break; } @@ -1349,17 +1348,17 @@ pfioctl(struct cdev *dev, u_long cmd, ca struct pf_rule *tail; int rs_num; - PF_LOCK(); + PF_RULES_WLOCK(); pr->anchor[sizeof(pr->anchor) - 1] = 0; ruleset = pf_find_ruleset(pr->anchor); if (ruleset == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } rs_num = pf_get_ruleset_number(pr->rule.action); if (rs_num >= PF_RULESET_MAX) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } @@ -1370,7 +1369,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca else pr->nr = 0; pr->ticket = ruleset->rules[rs_num].active.ticket; - PF_UNLOCK(); + PF_RULES_WUNLOCK(); break; } @@ -1380,22 +1379,22 @@ pfioctl(struct cdev *dev, u_long cmd, ca struct pf_rule *rule; int rs_num, i; - PF_LOCK(); + PF_RULES_WLOCK(); pr->anchor[sizeof(pr->anchor) - 1] = 0; ruleset = pf_find_ruleset(pr->anchor); if (ruleset == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } rs_num = pf_get_ruleset_number(pr->rule.action); if (rs_num >= PF_RULESET_MAX) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } if (pr->ticket != ruleset->rules[rs_num].active.ticket) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EBUSY; break; } @@ -1403,13 +1402,13 @@ pfioctl(struct cdev *dev, u_long cmd, ca while ((rule != NULL) && (rule->nr != pr->nr)) rule = TAILQ_NEXT(rule, entries); if (rule == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EBUSY; break; } bcopy(rule, &pr->rule, sizeof(struct pf_rule)); if (pf_anchor_copyout(ruleset, rule, pr)) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EBUSY; break; } @@ -1428,7 +1427,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca rule->bytes[0] = rule->bytes[1] = 0; rule->states_tot = 0; } - PF_UNLOCK(); + PF_RULES_WUNLOCK(); break; } @@ -1439,47 +1438,47 @@ pfioctl(struct cdev *dev, u_long cmd, ca u_int32_t nr = 0; int rs_num; - PF_LOCK(); + PF_RULES_WLOCK(); if (!(pcr->action == PF_CHANGE_REMOVE || pcr->action == PF_CHANGE_GET_TICKET) && pcr->pool_ticket != V_ticket_pabuf) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EBUSY; break; } if (pcr->action < PF_CHANGE_ADD_HEAD || pcr->action > PF_CHANGE_GET_TICKET) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } ruleset = pf_find_ruleset(pcr->anchor); if (ruleset == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } rs_num = pf_get_ruleset_number(pcr->rule.action); if (rs_num >= PF_RULESET_MAX) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } if (pcr->action == PF_CHANGE_GET_TICKET) { pcr->ticket = ++ruleset->rules[rs_num].active.ticket; - PF_UNLOCK(); + PF_RULES_WUNLOCK(); break; } else { if (pcr->ticket != ruleset->rules[rs_num].active.ticket) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = EINVAL; break; } @@ -1488,7 +1487,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca if (pcr->action != PF_CHANGE_REMOVE) { newrule = uma_zalloc(V_pf_rule_z, M_NOWAIT); if (newrule == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = ENOMEM; break; } @@ -1501,7 +1500,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca newrule->entries.tqe_prev = NULL; #ifndef INET if (newrule->af == AF_INET) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); uma_zfree(V_pf_rule_z, newrule); error = EAFNOSUPPORT; break; @@ -1509,7 +1508,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca #endif /* INET */ #ifndef INET6 if (newrule->af == AF_INET6) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); uma_zfree(V_pf_rule_z, newrule); error = EAFNOSUPPORT; break; @@ -1518,7 +1517,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca if (newrule->ifname[0]) { newrule->kif = pfi_kif_get(newrule->ifname); if (newrule->kif == NULL) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); uma_zfree(V_pf_rule_z, newrule); error = EINVAL; break; @@ -1594,8 +1593,8 @@ pfioctl(struct cdev *dev, u_long cmd, ca error = EINVAL; if (error) { - pf_rm_rule(NULL, newrule); - PF_UNLOCK(); + pf_free_rule(newrule); + PF_RULES_WUNLOCK(); break; } @@ -1619,15 +1618,16 @@ pfioctl(struct cdev *dev, u_long cmd, ca oldrule = TAILQ_NEXT(oldrule, entries); if (oldrule == NULL) { if (newrule != NULL) - pf_rm_rule(NULL, newrule); - PF_UNLOCK(); + pf_free_rule(newrule); + PF_RULES_WUNLOCK(); error = EINVAL; break; } } if (pcr->action == PF_CHANGE_REMOVE) { - pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule); + pf_unlink_rule(ruleset->rules[rs_num].active.ptr, + oldrule); ruleset->rules[rs_num].active.rcount--; } else { if (oldrule == NULL) @@ -1654,7 +1654,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); pf_remove_if_empty_ruleset(ruleset); - PF_UNLOCK(); + PF_RULES_WUNLOCK(); break; } @@ -2920,7 +2920,7 @@ DIOCGETSTATES_full: free(ioes, M_TEMP); break; } - PF_LOCK(); + PF_RULES_WLOCK(); for (i = 0, ioe = ioes; i < io->size; i++, ioe++) { switch (ioe->rs_num) { #ifdef ALTQ @@ -2947,7 +2947,7 @@ DIOCGETSTATES_full: sizeof(table.pfrt_anchor)); if ((error = pfr_ina_begin(&table, &ioe->ticket, NULL, 0))) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); goto fail; } @@ -2956,14 +2956,14 @@ DIOCGETSTATES_full: default: if ((error = pf_begin_rules(&ioe->ticket, ioe->rs_num, ioe->anchor))) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); goto fail; } break; } } - PF_UNLOCK(); + PF_RULES_WUNLOCK(); error = copyout(ioes, io->array, totlen); free(ioes, M_TEMP); break; @@ -2986,19 +2986,19 @@ DIOCGETSTATES_full: free(ioes, M_TEMP); break; } - PF_LOCK(); + PF_RULES_WLOCK(); for (i = 0, ioe = ioes; i < io->size; i++, ioe++) { switch (ioe->rs_num) { #ifdef ALTQ case PF_RULESET_ALTQ: if (ioe->anchor[0]) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); error = EINVAL; goto fail; } if ((error = pf_rollback_altq(ioe->ticket))) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); goto fail; /* really bad */ } @@ -3013,7 +3013,7 @@ DIOCGETSTATES_full: sizeof(table.pfrt_anchor)); if ((error = pfr_ina_rollback(&table, ioe->ticket, NULL, 0))) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); goto fail; /* really bad */ } @@ -3022,14 +3022,14 @@ DIOCGETSTATES_full: default: if ((error = pf_rollback_rules(ioe->ticket, ioe->rs_num, ioe->anchor))) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); goto fail; /* really bad */ } break; } } - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); break; } @@ -3052,21 +3052,21 @@ DIOCGETSTATES_full: free(ioes, M_TEMP); break; } - PF_LOCK(); + PF_RULES_WLOCK(); /* First makes sure everything will succeed. */ for (i = 0, ioe = ioes; i < io->size; i++, ioe++) { switch (ioe->rs_num) { #ifdef ALTQ case PF_RULESET_ALTQ: if (ioe->anchor[0]) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); error = EINVAL; goto fail; } if (!V_altqs_inactive_open || ioe->ticket != V_ticket_altqs_inactive) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); error = EBUSY; goto fail; @@ -3077,7 +3077,7 @@ DIOCGETSTATES_full: rs = pf_find_ruleset(ioe->anchor); if (rs == NULL || !rs->topen || ioe->ticket != rs->tticket) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); error = EBUSY; goto fail; @@ -3086,7 +3086,7 @@ DIOCGETSTATES_full: default: if (ioe->rs_num < 0 || ioe->rs_num >= PF_RULESET_MAX) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); error = EINVAL; goto fail; @@ -3096,7 +3096,7 @@ DIOCGETSTATES_full: !rs->rules[ioe->rs_num].inactive.open || rs->rules[ioe->rs_num].inactive.ticket != ioe->ticket) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); error = EBUSY; goto fail; @@ -3110,7 +3110,7 @@ DIOCGETSTATES_full: #ifdef ALTQ case PF_RULESET_ALTQ: if ((error = pf_commit_altq(ioe->ticket))) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); goto fail; /* really bad */ } @@ -3125,7 +3125,7 @@ DIOCGETSTATES_full: sizeof(table.pfrt_anchor)); if ((error = pfr_ina_commit(&table, ioe->ticket, NULL, NULL, 0))) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); goto fail; /* really bad */ } @@ -3134,14 +3134,14 @@ DIOCGETSTATES_full: default: if ((error = pf_commit_rules(ioe->ticket, ioe->rs_num, ioe->anchor))) { - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); goto fail; /* really bad */ } break; } } - PF_UNLOCK(); + PF_RULES_WUNLOCK(); free(ioes, M_TEMP); break; } Modified: projects/pf/head/sys/contrib/pf/net/pfvar.h ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pfvar.h Tue Apr 24 12:54:04 2012 (r234650) +++ projects/pf/head/sys/contrib/pf/net/pfvar.h Tue Apr 24 13:13:42 2012 (r234651) @@ -234,6 +234,10 @@ extern struct mtx pf_mtx; #define PF_STATE_LOCK_ASSERT(s) do {} while (0) #endif /* INVARIANTS */ +extern struct mtx pf_unlnkdrules_mtx; +#define PF_UNLNKDRULES_LOCK() mtx_lock(&pf_unlnkdrules_mtx) +#define PF_UNLNKDRULES_UNLOCK() mtx_unlock(&pf_unlnkdrules_mtx) + extern struct rwlock pf_rules_lock; #define PF_RULES_RLOCK() rw_rlock(&pf_rules_lock) #define PF_RULES_RUNLOCK() rw_runlock(&pf_rules_lock) @@ -685,6 +689,7 @@ struct pf_rule { #define PFRULE_NOSYNC 0x0010 #define PFRULE_SRCTRACK 0x0020 /* track source states */ #define PFRULE_RULESRCTRACK 0x0040 /* per rule */ +#define PFRULE_REFS 0x0080 /* rule has references */ /* scrub flags */ #define PFRULE_NODF 0x0100 @@ -1753,6 +1758,9 @@ VNET_DECLARE(struct pf_poolqueue *, pf_ VNET_DECLARE(struct pf_poolqueue *, pf_pools_inactive); #define V_pf_pools_inactive VNET(pf_pools_inactive) +VNET_DECLARE(struct pf_rulequeue, pf_unlinked_rules); +#define V_pf_unlinked_rules VNET(pf_unlinked_rules) + void pf_initialize(void); void pf_cleanup(void); @@ -1844,8 +1852,8 @@ VNET_DECLARE(struct pf_rule, pf_defaul #define V_pf_default_rule VNET(pf_default_rule) extern void pf_addrcpy(struct pf_addr *, struct pf_addr *, u_int8_t); -void pf_rm_rule(struct pf_rulequeue *, - struct pf_rule *); +void pf_free_rule(struct pf_rule *); + #ifdef INET int pf_test(int, struct ifnet *, struct mbuf **, struct inpcb *); #endif /* INET */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204241313.q3ODDgjs049959>