aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Horne <mhorne@FreeBSD.org>2021-08-09 17:21:07 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2022-06-27 19:32:06 +0000
commit6d26e87f48334ae4b30426a8a8bb0ba354d9689e (patch)
treee220c25aaa92364d44249f978bcc2c8f89ead8c0
parent8320036255f0c9b42634479efafc2268ab7af6df (diff)
downloadsrc-6d26e87f48334ae4b30426a8a8bb0ba354d9689e.tar.gz
src-6d26e87f48334ae4b30426a8a8bb0ba354d9689e.zip
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)
-rw-r--r--sys/kern/kern_shutdown.c79
-rw-r--r--sys/sys/conf.h3
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);