Print this page
13902 Fix for 13717 may break 8-disk raidz2
13915 installctx() blocking allocate causes problems
Portions contributed by: Jerry Jelinek <gjelinek@gmail.com>
Change-Id: I934d69946cec42630fc541fa8c7385b862b69ca2

@@ -19,11 +19,11 @@
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2019 Joyent, Inc.
+ * Copyright 2021 Joyent, Inc.
  */
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/sysmacros.h>

@@ -1028,11 +1028,32 @@
 
         mutex_exit(&reaplock);
 }
 
 /*
+ * Provide an allocation function for callers of installctx() that, for
+ * reasons of incomplete context-op initialization, must call installctx()
+ * in a kpreempt_disable() block.  The caller, therefore, must call this
+ * without being in such a block.
+ */
+struct ctxop *
+installctx_preallocate(void)
+{
+        /*
+         * NOTE: We could ASSERT/VERIFY that we are not in a place where
+         * a KM_SLEEP allocation could block indefinitely.
+         *
+         * ASSERT(curthread->t_preempt == 0);
+         */
+
+        return (kmem_alloc(sizeof (struct ctxop), KM_SLEEP));
+}
+
+/*
  * Install thread context ops for the current thread.
+ * The caller can pass in a preallocated struct ctxop, eliminating the need
+ * for the requirement of entering with kernel preemption still enabled.
  */
 void
 installctx(
         kthread_t *t,
         void    *arg,

@@ -1039,15 +1060,16 @@
         void    (*save)(void *),
         void    (*restore)(void *),
         void    (*fork)(void *, void *),
         void    (*lwp_create)(void *, void *),
         void    (*exit)(void *),
-        void    (*free)(void *, int))
+        void    (*free)(void *, int),
+        struct ctxop *ctx)
 {
-        struct ctxop *ctx;
-
+        if (ctx == NULL)
         ctx = kmem_alloc(sizeof (struct ctxop), KM_SLEEP);
+
         ctx->save_op = save;
         ctx->restore_op = restore;
         ctx->fork_op = fork;
         ctx->lwp_create_op = lwp_create;
         ctx->exit_op = exit;