Hi,

When the kernel reaches the sysclt kern.maxclusters limit, operations
get stuck while holding the net lock.  Increasing the limit does
not help as there is no wakeup of the pools.  So run through the
mbuf pool request list when the limit changes.

There seem to more problems when recovering from mbuf shortage, but
this is the most obvious one.

ok?

bluhm

Index: kern/subr_pool.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/subr_pool.c,v
retrieving revision 1.227
diff -u -p -r1.227 subr_pool.c
--- kern/subr_pool.c    23 Apr 2019 13:35:12 -0000      1.227
+++ kern/subr_pool.c    16 Jul 2019 18:02:08 -0000
@@ -815,6 +815,12 @@ pool_put(struct pool *pp, void *v)
        if (freeph != NULL)
                pool_p_free(pp, freeph);

+       pool_wakeup(pp);
+}
+
+void
+pool_wakeup(struct pool *pp)
+{
        if (!TAILQ_EMPTY(&pp->pr_requests)) {
                pl_enter(pp, &pp->pr_requests_lock);
                pool_runqueue(pp, PR_NOWAIT);
Index: kern/uipc_mbuf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_mbuf.c,v
retrieving revision 1.270
diff -u -p -r1.270 uipc_mbuf.c
--- kern/uipc_mbuf.c    16 Jul 2019 17:39:02 -0000      1.270
+++ kern/uipc_mbuf.c    16 Jul 2019 18:04:33 -0000
@@ -167,8 +167,6 @@ mbinit(void)

        m_pool_allocator.pa_pagesz = pool_allocator_multi.pa_pagesz;

-       error = nmbclust_update(nmbclust);
-       KASSERT(error == 0);
        mbuf_mem_alloc = 0;

 #if DIAGNOSTIC
@@ -196,6 +194,9 @@ mbinit(void)
                m_pool_init(&mclpools[i], mclsizes[i], 64, mclnames[i]);
        }

+       error = nmbclust_update(nmbclust);
+       KASSERT(error == 0);
+
        (void)mextfree_register(m_extfree_pool);
        KASSERT(num_extfree_fns == 1);
 }
@@ -217,11 +218,18 @@ mbcpuinit()
 int
 nmbclust_update(long newval)
 {
+       int i;
+
        if (newval < 0 || newval > LONG_MAX / MCLBYTES)
                return ERANGE;
        /* update the global mbuf memory limit */
        nmbclust = newval;
        mbuf_mem_limit = nmbclust * MCLBYTES;
+
+       pool_wakeup(&mbpool);
+       for (i = 0; i < nitems(mclsizes); i++)
+               pool_wakeup(&mclpools[i]);
+
        return 0;
 }

Index: sys/pool.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/sys/pool.h,v
retrieving revision 1.76
diff -u -p -r1.76 pool.h
--- sys/pool.h  10 Feb 2019 22:45:58 -0000      1.76
+++ sys/pool.h  16 Jul 2019 18:02:08 -0000
@@ -271,6 +271,7 @@ void                pool_request_init(struct pool_requ
                    void (*)(struct pool *, void *, void *), void *);
 void           pool_request(struct pool *, struct pool_request *);
 void           pool_put(struct pool *, void *);
+void           pool_wakeup(struct pool *);
 int            pool_reclaim(struct pool *);
 void           pool_reclaim_all(void);
 int            pool_prime(struct pool *, int);

Reply via email to