git: 6d26e87f4833 - stable/13 - Split out dumper allocation from list insertion

From: Mitchell Horne <mhorne_at_FreeBSD.org>
Date: Mon, 27 Jun 2022 19:35:33 UTC
The branch stable/13 has been updated by mhorne:

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

commit 6d26e87f48334ae4b30426a8a8bb0ba354d9689e
Author:     Mitchell Horne <mhorne@FreeBSD.org>
AuthorDate: 2021-08-09 17:21:07 +0000
Commit:     Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2022-06-27 19:32:06 +0000

    Split out dumper allocation from list insertion
    
    Add a new function, dumper_create(), to allocate a dumper.
    dumper_insert() will call this function and retains the existing
    behaviour.
    
    This is desirable for performing live dumps of the system. Here, there
    is a need to allocate and configure a dumper structure that is invoked
    outside of the typical debugger context. Therefore, it should be
    excluded from the list of panic-time dumpers.
    
    free_single_dumper() is made public and renamed to dumper_destroy().
    
    Reviewed by:    kib, markj
    MFC after:      1 week
    Sponsored by:   Juniper Networks, Inc.
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D34068
    
    (cherry picked from commit 59c27ea18c32f5db2c2f9e8213b3ed4219e70704)
---
 sys/kern/kern_shutdown.c | 79 +++++++++++++++++++++++++++++++-----------------
 sys/sys/conf.h           |  3 ++
 2 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 0c87ecb9bb67..37544e364ee2 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -1167,45 +1167,39 @@ kerneldumpcomp_destroy(struct dumperinfo *di)
 }
 
 /*
- * Must not be present on global list.
+ * Free a dumper. Must not be present on global list.
  */
-static void
-free_single_dumper(struct dumperinfo *di)
+void
+dumper_destroy(struct dumperinfo *di)
 {
 
 	if (di == NULL)
 		return;
 
 	zfree(di->blockbuf, M_DUMPER);
-
 	kerneldumpcomp_destroy(di);
-
 #ifdef EKCD
 	zfree(di->kdcrypto, M_EKCD);
 #endif
 	zfree(di, M_DUMPER);
 }
 
-/* Registration of dumpers */
+/*
+ * Allocate and set up a new dumper from the provided template.
+ */
 int
-dumper_insert(const struct dumperinfo *di_template, const char *devname,
-    const struct diocskerneldump_arg *kda)
+dumper_create(const struct dumperinfo *di_template, const char *devname,
+    const struct diocskerneldump_arg *kda, struct dumperinfo **dip)
 {
-	struct dumperinfo *newdi, *listdi;
-	bool inserted;
-	uint8_t index;
-	int error;
+	struct dumperinfo *newdi;
+	int error = 0;
 
-	index = kda->kda_index;
-	MPASS(index != KDA_REMOVE && index != KDA_REMOVE_DEV &&
-	    index != KDA_REMOVE_ALL);
-
-	error = priv_check(curthread, PRIV_SETDUMPER);
-	if (error != 0)
-		return (error);
+	if (dip == NULL)
+		return (EINVAL);
 
-	newdi = malloc(sizeof(*newdi) + strlen(devname) + 1, M_DUMPER, M_WAITOK
-	    | M_ZERO);
+	/* Allocate a new dumper */
+	newdi = malloc(sizeof(*newdi) + strlen(devname) + 1, M_DUMPER,
+	    M_WAITOK | M_ZERO);
 	memcpy(newdi, di_template, sizeof(*newdi));
 	newdi->blockbuf = NULL;
 	newdi->kdcrypto = NULL;
@@ -1214,7 +1208,7 @@ dumper_insert(const struct dumperinfo *di_template, const char *devname,
 
 	if (kda->kda_encryption != KERNELDUMP_ENC_NONE) {
 #ifdef EKCD
-		newdi->kdcrypto = kerneldumpcrypto_create(di_template->blocksize,
+		newdi->kdcrypto = kerneldumpcrypto_create(newdi->blocksize,
 		    kda->kda_encryption, kda->kda_key,
 		    kda->kda_encryptedkeysize, kda->kda_encryptedkey);
 		if (newdi->kdcrypto == NULL) {
@@ -1246,9 +1240,39 @@ dumper_insert(const struct dumperinfo *di_template, const char *devname,
 			goto cleanup;
 		}
 	}
-
 	newdi->blockbuf = malloc(newdi->blocksize, M_DUMPER, M_WAITOK | M_ZERO);
 
+	*dip = newdi;
+	return (0);
+cleanup:
+	dumper_destroy(newdi);
+	return (error);
+}
+
+/*
+ * Create a new dumper and register it in the global list.
+ */
+int
+dumper_insert(const struct dumperinfo *di_template, const char *devname,
+    const struct diocskerneldump_arg *kda)
+{
+	struct dumperinfo *newdi, *listdi;
+	bool inserted;
+	uint8_t index;
+	int error;
+
+	index = kda->kda_index;
+	MPASS(index != KDA_REMOVE && index != KDA_REMOVE_DEV &&
+	    index != KDA_REMOVE_ALL);
+
+	error = priv_check(curthread, PRIV_SETDUMPER);
+	if (error != 0)
+		return (error);
+
+	error = dumper_create(di_template, devname, kda, &newdi);
+	if (error != 0)
+		return (error);
+
 	/* Add the new configuration to the queue */
 	mtx_lock(&dumpconf_list_lk);
 	inserted = false;
@@ -1265,10 +1289,6 @@ dumper_insert(const struct dumperinfo *di_template, const char *devname,
 	mtx_unlock(&dumpconf_list_lk);
 
 	return (0);
-
-cleanup:
-	free_single_dumper(newdi);
-	return (error);
 }
 
 #ifdef DDB
@@ -1323,6 +1343,9 @@ dumper_config_match(const struct dumperinfo *di, const char *devname,
 	return (true);
 }
 
+/*
+ * Remove and free the requested dumper(s) from the global list.
+ */
 int
 dumper_remove(const char *devname, const struct diocskerneldump_arg *kda)
 {
@@ -1346,7 +1369,7 @@ dumper_remove(const char *devname, const struct diocskerneldump_arg *kda)
 		if (dumper_config_match(di, devname, kda)) {
 			found = true;
 			TAILQ_REMOVE(&dumper_configs, di, di_next);
-			free_single_dumper(di);
+			dumper_destroy(di);
 		}
 	}
 	mtx_unlock(&dumpconf_list_lk);
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index b6be85697405..7e9631154802 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -364,6 +364,9 @@ extern int dumping;		/* system is dumping */
 
 int doadump(boolean_t);
 struct diocskerneldump_arg;
+int dumper_create(const struct dumperinfo *di_template, const char *devname,
+    const struct diocskerneldump_arg *kda, struct dumperinfo **dip);
+void dumper_destroy(struct dumperinfo *di);
 int dumper_insert(const struct dumperinfo *di_template, const char *devname,
     const struct diocskerneldump_arg *kda);
 int dumper_remove(const char *devname, const struct diocskerneldump_arg *kda);