Module Name:    src
Committed By:   mrg
Date:           Sat Dec 16 03:13:29 UTC 2017

Modified Files:
        src/sys/kern: subr_pool.c
        src/sys/sys: pool.h

Log Message:
hopefully workaround the irregularly "fork fails in init" problem.

if a pool is growing, and the grower is PR_NOWAIT, mark this.
if another caller wants to grow the pool and is also PR_NOWAIT,
busy-wait for the original caller, which should either succeed
or hard-fail fairly quickly.

implement the busy-wait by unlocking and relocking this pools
mutex and returning ERESTART.  other methods (such as having
the caller do this) were significantly more code and this hack
is fairly localised.

ok chs@ riastradh@


To generate a diff of this commit:
cvs rdiff -u -r1.218 -r1.219 src/sys/kern/subr_pool.c
cvs rdiff -u -r1.81 -r1.82 src/sys/sys/pool.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/subr_pool.c
diff -u src/sys/kern/subr_pool.c:1.218 src/sys/kern/subr_pool.c:1.219
--- src/sys/kern/subr_pool.c:1.218	Mon Dec  4 03:05:24 2017
+++ src/sys/kern/subr_pool.c	Sat Dec 16 03:13:29 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_pool.c,v 1.218 2017/12/04 03:05:24 mrg Exp $	*/
+/*	$NetBSD: subr_pool.c,v 1.219 2017/12/16 03:13:29 mrg Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1999, 2000, 2002, 2007, 2008, 2010, 2014, 2015
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_pool.c,v 1.218 2017/12/04 03:05:24 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_pool.c,v 1.219 2017/12/16 03:13:29 mrg Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -1073,10 +1073,23 @@ pool_grow(struct pool *pp, int flags)
 			} while (pp->pr_flags & PR_GROWING);
 			return ERESTART;
 		} else {
+			if (pp->pr_flags & PR_GROWINGNOWAIT) {
+				/*
+				 * This needs an unlock/relock dance so
+				 * that the other caller has a chance to
+				 * run and actually do the thing.  Note
+				 * that this is effectively a busy-wait.
+				 */
+				mutex_exit(&pp->pr_lock);
+				mutex_enter(&pp->pr_lock);
+				return ERESTART;
+			}
 			return EWOULDBLOCK;
 		}
 	}
 	pp->pr_flags |= PR_GROWING;
+	if ((flags & PR_WAITOK) == 0)
+		pp->pr_flags |= PR_GROWINGNOWAIT;
 
 	mutex_exit(&pp->pr_lock);
 	char *cp = pool_allocator_alloc(pp, flags);
@@ -1093,7 +1106,7 @@ pool_grow(struct pool *pp, int flags)
 	pool_prime_page(pp, cp, ph);
 	pp->pr_npagealloc++;
 	KASSERT(pp->pr_flags & PR_GROWING);
-	pp->pr_flags &= ~PR_GROWING;
+	pp->pr_flags &= ~(PR_GROWING|PR_GROWINGNOWAIT);
 	/*
 	 * If anyone was waiting for pool_grow, notify them that we
 	 * may have just done it.
@@ -1102,7 +1115,7 @@ pool_grow(struct pool *pp, int flags)
 	return 0;
 out:
 	KASSERT(pp->pr_flags & PR_GROWING);
-	pp->pr_flags &= ~PR_GROWING;
+	pp->pr_flags &= ~(PR_GROWING|PR_GROWINGNOWAIT);
 	mutex_enter(&pp->pr_lock);
 	return ENOMEM;
 }

Index: src/sys/sys/pool.h
diff -u src/sys/sys/pool.h:1.81 src/sys/sys/pool.h:1.82
--- src/sys/sys/pool.h:1.81	Sat Dec  2 08:15:43 2017
+++ src/sys/sys/pool.h	Sat Dec 16 03:13:29 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: pool.h,v 1.81 2017/12/02 08:15:43 mrg Exp $	*/
+/*	$NetBSD: pool.h,v 1.82 2017/12/16 03:13:29 mrg Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 1999, 2000, 2007 The NetBSD Foundation, Inc.
@@ -148,6 +148,7 @@ struct pool {
 #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 */
+#define	PR_GROWINGNOWAIT 0x4000	/* pool_grow in progress by PR_NOWAIT alloc */
 
 	/*
 	 * `pr_lock' protects the pool's data structures when removing

Reply via email to