Index: sys/kern/subr_pool.c =================================================================== RCS file: /cvsroot/src/sys/kern/subr_pool.c,v retrieving revision 1.208 diff -p -u -r1.208 subr_pool.c --- sys/kern/subr_pool.c 8 Jun 2017 04:00:01 -0000 1.208 +++ sys/kern/subr_pool.c 24 Oct 2017 14:46:21 -0000 @@ -1051,6 +1051,23 @@ pool_grow(struct pool *pp, int flags) { struct pool_item_header *ph = NULL; char *cp; + int error; + + /* + * If there's a pool_grow in progress, wait for it to complete + * and try again from the top. + */ + if (pp->pr_flags & PR_GROWING) { + if (flags & PR_WAITOK) { + do { + cv_wait(&pp->pr_cv, &pp->pr_lock); + } while (pp->pr_flags & PR_GROWING); + return ERESTART; + } else { + return EWOULDBLOCK; + } + } + pp->pr_flags |= PR_GROWING; mutex_exit(&pp->pr_lock); cp = pool_allocator_alloc(pp, flags); @@ -1062,13 +1079,25 @@ pool_grow(struct pool *pp, int flags) pool_allocator_free(pp, cp); } mutex_enter(&pp->pr_lock); - return ENOMEM; + error = ENOMEM; + goto out; } mutex_enter(&pp->pr_lock); pool_prime_page(pp, cp, ph); pp->pr_npagealloc++; - return 0; + error = 0; + +out: + /* + * If anyone was waiting for pool_grow, notify them that we + * may have just done it. + */ + KASSERT(pp->pr_flags & PR_GROWING); + pp->pr_flags &= ~PR_GROWING; + cv_broadcast(&pp->pr_cv); + + return error; } /* Index: sys/sys/pool.h =================================================================== RCS file: /cvsroot/src/sys/sys/pool.h,v retrieving revision 1.79 diff -p -u -r1.79 pool.h --- sys/sys/pool.h 29 Jul 2015 00:10:25 -0000 1.79 +++ sys/sys/pool.h 24 Oct 2017 14:46:21 -0000 @@ -147,6 +147,7 @@ struct pool { #define PR_NOTOUCH 0x400 /* don't use free items to keep internal state*/ #define PR_NOALIGN 0x800 /* don't assume backend alignment */ #define PR_LARGECACHE 0x1000 /* use large cache groups */ +#define PR_GROWING 0x2000 /* pool_grow in progress */ /* * `pr_lock' protects the pool's data structures when removing