So it's not a good idea to perform long lasting operations in the kernel.  
The scheduler doesn't deal well with it and nobody else gets to run.

One of those long loops is loading a large table into pf.  If you're 
lucky, you'll run out of memory and pool will finally sleep.

I stuck a couple yield() calls into the long loops after sufficient 
iteration.

I also zapped PFR_FLAG_ATOMIC because it's not really atomic anyway.  I 
also couldn't find any callers.  Leftover?

Another thing to fix at some point is that we call splsoftnet and splx 
multiple times per address in some cases, but fixing that was getting too 
complicated and requires some more code shuffling.

Index: pf_table.c
===================================================================
RCS file: /home/tedu/cvs/src/sys/net/pf_table.c,v
retrieving revision 1.86
diff -u -r1.86 pf_table.c
--- pf_table.c  30 Sep 2010 07:14:02 -0000      1.86
+++ pf_table.c  13 Oct 2010 23:47:01 -0000
@@ -213,9 +213,8 @@
 {
        struct pfr_ktable       *kt;
        struct pfr_kentryworkq   workq;
-       int                      s;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
        if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
                return (EINVAL);
        kt = pfr_lookup_table(tbl);
@@ -226,11 +225,7 @@
        pfr_enqueue_addrs(kt, &workq, ndel, 0);
 
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_remove_kentries(kt, &workq);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
                if (kt->pfrkt_cnt) {
                        DPFPRINTF(LOG_NOTICE,
                            "pfr_clr_addrs: corruption detected (%d).",
@@ -249,11 +244,10 @@
        struct pfr_kentryworkq   workq;
        struct pfr_kentry       *p, *q;
        struct pfr_addr          ad;
-       int                      i, rv, s, xadd = 0;
+       int                      i, rv, xadd = 0;
        long                     tzero = time_second;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-           PFR_FLAG_FEEDBACK);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
        if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
                return (EINVAL);
        kt = pfr_lookup_table(tbl);
@@ -267,6 +261,8 @@
                return (ENOMEM);
        SLIST_INIT(&workq);
        for (i = 0; i < size; i++) {
+               if (i % 1000 == 0)
+                       yield();
                if (COPYIN(addr+i, &ad, sizeof(ad), flags))
                        senderr(EFAULT);
                if (pfr_validate_addr(&ad))
@@ -302,11 +298,7 @@
        }
        pfr_clean_node_mask(tmpkt, &workq);
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_insert_kentries(kt, &workq, tzero);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        } else
                pfr_destroy_kentries(&workq);
        if (nadd != NULL)
@@ -330,10 +322,9 @@
        struct pfr_kentryworkq   workq;
        struct pfr_kentry       *p;
        struct pfr_addr          ad;
-       int                      i, rv, s, xdel = 0, log = 1;
+       int                      i, rv, xdel = 0, log = 1;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-           PFR_FLAG_FEEDBACK);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
        if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
                return (EINVAL);
        kt = pfr_lookup_table(tbl);
@@ -399,11 +390,7 @@
                                senderr(EFAULT);
        }
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_remove_kentries(kt, &workq);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        }
        if (ndel != NULL)
                *ndel = xdel;
@@ -423,11 +410,10 @@
        struct pfr_kentryworkq   addq, delq, changeq;
        struct pfr_kentry       *p, *q;
        struct pfr_addr          ad;
-       int                      i, rv, s, xadd = 0, xdel = 0, xchange = 0;
+       int                      i, rv, xadd = 0, xdel = 0, xchange = 0;
        long                     tzero = time_second;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-           PFR_FLAG_FEEDBACK);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
        if (pfr_validate_table(tbl, ignore_pfrt_flags, flags &
            PFR_FLAG_USERIOCTL))
                return (EINVAL);
@@ -502,13 +488,9 @@
        }
        pfr_clean_node_mask(tmpkt, &addq);
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_insert_kentries(kt, &addq, tzero);
                pfr_remove_kentries(kt, &delq);
                pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        } else
                pfr_destroy_kentries(&addq);
        if (nadd != NULL)
@@ -615,11 +597,9 @@
        struct pfr_ktable       *kt;
        struct pfr_walktree      w;
        struct pfr_kentryworkq   workq;
-       int                      rv, s;
+       int                      rv;
        long                     tzero = time_second;
 
-       /* XXX PFR_FLAG_CLSTATS disabled */
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC);
        if (pfr_validate_table(tbl, 0, 0))
                return (EINVAL);
        kt = pfr_lookup_table(tbl);
@@ -635,8 +615,6 @@
        w.pfrw_astats = addr;
        w.pfrw_free = kt->pfrkt_cnt;
        w.pfrw_flags = flags;
-       if (flags & PFR_FLAG_ATOMIC)
-               s = splsoftnet();
        rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
        if (!rv)
                rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
@@ -644,8 +622,6 @@
                pfr_enqueue_addrs(kt, &workq, NULL, 0);
                pfr_clstats_kentries(&workq, tzero, 0);
        }
-       if (flags & PFR_FLAG_ATOMIC)
-               splx(s);
        if (rv)
                return (rv);
 
@@ -666,10 +642,9 @@
        struct pfr_kentryworkq   workq;
        struct pfr_kentry       *p;
        struct pfr_addr          ad;
-       int                      i, rv, s, xzero = 0;
+       int                      i, rv, xzero = 0;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-           PFR_FLAG_FEEDBACK);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK);
        if (pfr_validate_table(tbl, 0, 0))
                return (EINVAL);
        kt = pfr_lookup_table(tbl);
@@ -695,11 +670,7 @@
        }
 
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_clstats_kentries(&workq, 0, 0);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        }
        if (nzero != NULL)
                *nzero = xzero;
@@ -854,10 +825,13 @@
 pfr_destroy_kentries(struct pfr_kentryworkq *workq)
 {
        struct pfr_kentry       *p, *q;
+       int                      n = 0;
 
        for (p = SLIST_FIRST(workq); p != NULL; p = q) {
                q = SLIST_NEXT(p, pfrke_workq);
                pfr_destroy_kentry(p);
+               if (++n % 1000 == 0)
+                       yield();
        }
 }
 
@@ -885,7 +859,8 @@
                        break;
                }
                p->pfrke_tzero = tzero;
-               n++;
+               if (++n % 1000 == 0)
+                       yield();
        }
        kt->pfrkt_cnt += n;
 }
@@ -922,7 +897,8 @@
 
        SLIST_FOREACH(p, workq, pfrke_workq) {
                pfr_unroute_kentry(kt, p);
-               n++;
+               if (++n % 1000 == 0)
+                       yield();
        }
        kt->pfrkt_cnt -= n;
        pfr_destroy_kentries(workq);
@@ -933,9 +909,13 @@
     struct pfr_kentryworkq *workq)
 {
        struct pfr_kentry       *p;
+       int                      n = 0;
 
-       SLIST_FOREACH(p, workq, pfrke_workq)
+       SLIST_FOREACH(p, workq, pfrke_workq) {
                pfr_unroute_kentry(kt, p);
+               if (++n % 1000 == 0)
+                       yield();
+       }
 }
 
 void
@@ -1161,10 +1141,9 @@
 {
        struct pfr_ktableworkq   workq;
        struct pfr_ktable       *p;
-       int                      s, xdel = 0;
+       int                      xdel = 0;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-           PFR_FLAG_ALLRSETS);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ALLRSETS);
        if (pfr_fix_anchor(filter->pfrt_anchor))
                return (EINVAL);
        if (pfr_table_count(filter, flags) < 0)
@@ -1183,11 +1162,7 @@
                xdel++;
        }
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_setflags_ktables(&workq);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        }
        if (ndel != NULL)
                *ndel = xdel;
@@ -1199,10 +1174,10 @@
 {
        struct pfr_ktableworkq   addq, changeq;
        struct pfr_ktable       *p, *q, *r, key;
-       int                      i, rv, s, xadd = 0;
+       int                      i, rv, xadd = 0;
        long                     tzero = time_second;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
        SLIST_INIT(&addq);
        SLIST_INIT(&changeq);
        for (i = 0; i < size; i++) {
@@ -1260,12 +1235,8 @@
        ;
        }
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_insert_ktables(&addq);
                pfr_setflags_ktables(&changeq);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        } else
                 pfr_destroy_ktables(&addq, 0);
        if (nadd != NULL)
@@ -1281,9 +1252,9 @@
 {
        struct pfr_ktableworkq   workq;
        struct pfr_ktable       *p, *q, key;
-       int                      i, s, xdel = 0;
+       int                      i, xdel = 0;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
        SLIST_INIT(&workq);
        for (i = 0; i < size; i++) {
                if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
@@ -1305,11 +1276,7 @@
        }
 
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_setflags_ktables(&workq);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        }
        if (ndel != NULL)
                *ndel = xdel;
@@ -1360,7 +1327,7 @@
        long                     tzero = time_second;
 
        /* XXX PFR_FLAG_CLSTATS disabled */
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_ALLRSETS);
+       ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS);
        if (pfr_fix_anchor(filter->pfrt_anchor))
                return (EINVAL);
        n = nn = pfr_table_count(filter, flags);
@@ -1371,28 +1338,22 @@
                return (0);
        }
        SLIST_INIT(&workq);
-       if (flags & PFR_FLAG_ATOMIC)
-               s = splsoftnet();
        RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
                if (pfr_skip_table(filter, p, flags))
                        continue;
                if (n-- <= 0)
                        continue;
-               if (!(flags & PFR_FLAG_ATOMIC))
-                       s = splsoftnet();
+               s = splsoftnet();
                if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl), flags)) {
                        splx(s);
                        return (EFAULT);
                }
-               if (!(flags & PFR_FLAG_ATOMIC))
-                       splx(s);
+               splx(s);
                SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
        }
        if (flags & PFR_FLAG_CLSTATS)
                pfr_clstats_ktables(&workq, tzero,
                    flags & PFR_FLAG_ADDRSTOO);
-       if (flags & PFR_FLAG_ATOMIC)
-               splx(s);
        if (n) {
                DPFPRINTF(LOG_ERR,
                    "pfr_get_tstats: corruption detected (%d).", n);
@@ -1407,11 +1368,10 @@
 {
        struct pfr_ktableworkq   workq;
        struct pfr_ktable       *p, key;
-       int                      i, s, xzero = 0;
+       int                      i, xzero = 0;
        long                     tzero = time_second;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
-           PFR_FLAG_ADDRSTOO);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO);
        SLIST_INIT(&workq);
        for (i = 0; i < size; i++) {
                if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
@@ -1425,11 +1385,7 @@
                }
        }
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_clstats_ktables(&workq, tzero, flags & PFR_FLAG_ADDRSTOO);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        }
        if (nzero != NULL)
                *nzero = xzero;
@@ -1442,9 +1398,9 @@
 {
        struct pfr_ktableworkq   workq;
        struct pfr_ktable       *p, *q, key;
-       int                      i, s, xchange = 0, xdel = 0;
+       int                      i, xchange = 0, xdel = 0;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
        if ((setflag & ~PFR_TFLAG_USRMASK) ||
            (clrflag & ~PFR_TFLAG_USRMASK) ||
            (setflag & clrflag))
@@ -1477,11 +1433,7 @@
        ;
        }
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                pfr_setflags_ktables(&workq);
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
        }
        if (nchange != NULL)
                *nchange = xchange;
@@ -1663,10 +1615,10 @@
        struct pfr_ktable       *p, *q;
        struct pfr_ktableworkq   workq;
        struct pf_ruleset       *rs;
-       int                      s, xadd = 0, xchange = 0;
+       int                      xadd = 0, xchange = 0;
        long                     tzero = time_second;
 
-       ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
+       ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
        rs = pf_find_ruleset(trs->pfrt_anchor);
        if (rs == NULL || !rs->topen || ticket != rs->tticket)
                return (EBUSY);
@@ -1684,14 +1636,10 @@
        }
 
        if (!(flags & PFR_FLAG_DUMMY)) {
-               if (flags & PFR_FLAG_ATOMIC)
-                       s = splsoftnet();
                for (p = SLIST_FIRST(&workq); p != NULL; p = q) {
                        q = SLIST_NEXT(p, pfrkt_workq);
                        pfr_commit_ktable(p, tzero);
                }
-               if (flags & PFR_FLAG_ATOMIC)
-                       splx(s);
                rs->topen = 0;
                pf_remove_if_empty_ruleset(rs);
        }
Index: pfvar.h
===================================================================
RCS file: /home/tedu/cvs/src/sys/net/pfvar.h,v
retrieving revision 1.315
diff -u -r1.315 pfvar.h
--- pfvar.h     22 Sep 2010 05:58:29 -0000      1.315
+++ pfvar.h     13 Oct 2010 23:34:23 -0000
@@ -1562,7 +1562,6 @@
        }               *array;
 };
 
-#define PFR_FLAG_ATOMIC                0x00000001
 #define PFR_FLAG_DUMMY         0x00000002
 #define PFR_FLAG_FEEDBACK      0x00000004
 #define PFR_FLAG_CLSTATS       0x00000008

Reply via email to