git: a8cbb835bfdf - main - uma_zalloc: assert M_NOWAIT ^ M_WAITOK

From: Eric van Gyzen <vangyzen_at_FreeBSD.org>
Date: Sat, 26 Mar 2022 01:11:44 UTC
The branch main has been updated by vangyzen:

URL: https://cgit.FreeBSD.org/src/commit/?id=a8cbb835bfdf086249fab8f9cb3d2a3533214eac

commit a8cbb835bfdf086249fab8f9cb3d2a3533214eac
Author:     Eric van Gyzen <vangyzen@FreeBSD.org>
AuthorDate: 2022-03-04 11:23:08 +0000
Commit:     Eric van Gyzen <vangyzen@FreeBSD.org>
CommitDate: 2022-03-26 01:10:37 +0000

    uma_zalloc: assert M_NOWAIT ^ M_WAITOK
    
    The uma_zalloc functions expect exactly one of [M_NOWAIT, M_WAITOK].
    If neither or both are passed, print an error and a stack dump.
    Only do this ten times, to prevent livelock.  In the future, after
    this exposes enough bad callers, this will be changed to a KASSERT().
    
    Reviewed by:    rstone, markj
    MFC after:      1 month
    Sponsored by:   Dell EMC Isilon
    Differential Revision:  https://reviews.freebsd.org/D34452
---
 sys/vm/uma_core.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 341b12209f9d..9fd2fd5e5d03 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -3494,6 +3494,9 @@ item_domain(void *item)
 #endif
 
 #if defined(INVARIANTS) || defined(DEBUG_MEMGUARD) || defined(WITNESS)
+#if defined(INVARIANTS) && (defined(DDB) || defined(STACK))
+#include <sys/stack.h>
+#endif
 #define	UMA_ZALLOC_DEBUG
 static int
 uma_zalloc_debug(uma_zone_t zone, void **itemp, void *udata, int flags)
@@ -3515,6 +3518,31 @@ uma_zalloc_debug(uma_zone_t zone, void **itemp, void *udata, int flags)
 	    ("uma_zalloc_debug: called within spinlock or critical section"));
 	KASSERT((zone->uz_flags & UMA_ZONE_PCPU) == 0 || (flags & M_ZERO) == 0,
 	    ("uma_zalloc_debug: allocating from a pcpu zone with M_ZERO"));
+
+	_Static_assert(M_NOWAIT != 0 && M_WAITOK != 0,
+	    "M_NOWAIT and M_WAITOK must be non-zero for this assertion:");
+#if 0
+	/*
+	 * Give the #elif clause time to find problems, then remove it
+	 * and enable this.  (Remove <sys/stack.h> above, too.)
+	 */
+	KASSERT((flags & (M_NOWAIT|M_WAITOK)) == M_NOWAIT ||
+	    (flags & (M_NOWAIT|M_WAITOK)) == M_WAITOK,
+	    ("uma_zalloc_debug: must pass one of M_NOWAIT or M_WAITOK"));
+#elif defined(DDB) || defined(STACK)
+	if (__predict_false((flags & (M_NOWAIT|M_WAITOK)) != M_NOWAIT &&
+	    (flags & (M_NOWAIT|M_WAITOK)) != M_WAITOK)) {
+		static int stack_count;
+		struct stack st;
+
+		if (stack_count < 10) {
+			++stack_count;
+			printf("uma_zalloc* called with bad WAIT flags:\n");
+			stack_save(&st);
+			stack_print(&st);
+		}
+	}
+#endif
 #endif
 
 #ifdef DEBUG_MEMGUARD