Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144972445
D15252.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D15252.diff
View Options
Index: head/sys/dev/null/null.c
===================================================================
--- head/sys/dev/null/null.c
+++ head/sys/dev/null/null.c
@@ -107,14 +107,14 @@
int flags __unused, struct thread *td)
{
int error;
- error = 0;
+ error = 0;
switch (cmd) {
#ifdef COMPAT_FREEBSD11
case DIOCSKERNELDUMP_FREEBSD11:
#endif
case DIOCSKERNELDUMP:
- error = set_dumper(NULL, NULL, td, 0, 0, NULL, 0, NULL);
+ error = clear_dumper(td);
break;
case FIONBIO:
break;
Index: head/sys/geom/geom_dev.c
===================================================================
--- head/sys/geom/geom_dev.c
+++ head/sys/geom/geom_dev.c
@@ -138,10 +138,11 @@
int error, len;
if (dev == NULL || kda == NULL)
- return (set_dumper(NULL, NULL, td, 0, 0, NULL, 0, NULL));
+ return (clear_dumper(td));
cp = dev->si_drv2;
len = sizeof(kd);
+ memset(&kd, 0, len);
kd.offset = 0;
kd.length = OFF_MAX;
error = g_io_getattr("GEOM::kerneldump", cp, &len, &kd);
@@ -833,7 +834,7 @@
/* Reset any dump-area set on this device */
if (dev->si_flags & SI_DUMPDEV)
- (void)set_dumper(NULL, NULL, curthread, 0, 0, NULL, 0, NULL);
+ (void)clear_dumper(curthread);
/* Destroy the struct cdev *so we get no more requests */
destroy_dev_sched_cb(dev, g_dev_callback, cp);
Index: head/sys/kern/kern_shutdown.c
===================================================================
--- head/sys/kern/kern_shutdown.c
+++ head/sys/kern/kern_shutdown.c
@@ -62,6 +62,7 @@
#include <sys/kthread.h>
#include <sys/ktr.h>
#include <sys/malloc.h>
+#include <sys/mbuf.h>
#include <sys/mount.h>
#include <sys/priv.h>
#include <sys/proc.h>
@@ -1090,10 +1091,6 @@
if (error != 0)
return (error);
- if (di == NULL) {
- error = 0;
- goto cleanup;
- }
if (dumper.dumper != NULL)
return (EBUSY);
dumper = *di;
@@ -1139,7 +1136,25 @@
dumper.blockbuf = malloc(di->blocksize, M_DUMPER, M_WAITOK | M_ZERO);
return (0);
+
cleanup:
+ (void)clear_dumper(td);
+ return (error);
+}
+
+int
+clear_dumper(struct thread *td)
+{
+ int error;
+
+ error = priv_check(td, PRIV_SETDUMPER);
+ if (error != 0)
+ return (error);
+
+#ifdef NETDUMP
+ netdump_mbuf_drain();
+#endif
+
#ifdef EKCD
if (dumper.kdcrypto != NULL) {
explicit_bzero(dumper.kdcrypto, sizeof(*dumper.kdcrypto) +
@@ -1156,14 +1171,14 @@
}
explicit_bzero(&dumper, sizeof(dumper));
dumpdevname[0] = '\0';
- return (error);
+ return (0);
}
static int
dump_check_bounds(struct dumperinfo *di, off_t offset, size_t length)
{
- if (length != 0 && (offset < di->mediaoffset ||
+ if (di->mediasize > 0 && length != 0 && (offset < di->mediaoffset ||
offset - di->mediaoffset + length > di->mediasize)) {
if (di->kdcomp != NULL && offset >= di->mediaoffset) {
printf(
@@ -1244,18 +1259,6 @@
return (0);
}
-
-static int
-dump_write_key(struct dumperinfo *di, off_t offset)
-{
- struct kerneldumpcrypto *kdc;
-
- kdc = di->kdcrypto;
- if (kdc == NULL)
- return (0);
- return (dump_write(di, kdc->kdc_dumpkey, 0, offset,
- kdc->kdc_dumpkeysize));
-}
#endif /* EKCD */
static int
@@ -1289,20 +1292,42 @@
}
/*
- * Write a kerneldumpheader at the specified offset. The header structure is 512
- * bytes in size, but we must pad to the device sector size.
+ * Write kernel dump headers at the beginning and end of the dump extent.
+ * Write the kernel dump encryption key after the leading header if we were
+ * configured to do so.
*/
static int
-dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh,
- off_t offset)
+dump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh)
{
- void *buf;
+#ifdef EKCD
+ struct kerneldumpcrypto *kdc;
+#endif
+ void *buf, *key;
size_t hdrsz;
+ uint64_t extent;
+ uint32_t keysize;
+ int error;
hdrsz = sizeof(*kdh);
if (hdrsz > di->blocksize)
return (ENOMEM);
+#ifdef EKCD
+ kdc = di->kdcrypto;
+ key = kdc->kdc_dumpkey;
+ keysize = kerneldumpcrypto_dumpkeysize(kdc);
+#else
+ key = NULL;
+ keysize = 0;
+#endif
+
+ /*
+ * If the dump device has special handling for headers, let it take care
+ * of writing them out.
+ */
+ if (di->dumper_hdr != NULL)
+ return (di->dumper_hdr(di, kdh, key, keysize));
+
if (hdrsz == di->blocksize)
buf = kdh;
else {
@@ -1311,7 +1336,24 @@
memcpy(buf, kdh, hdrsz);
}
- return (dump_write(di, buf, 0, offset, di->blocksize));
+ extent = dtoh64(kdh->dumpextent);
+#ifdef EKCD
+ if (kdc != NULL) {
+ error = dump_write(di, kdc->kdc_dumpkey, 0,
+ di->mediaoffset + di->mediasize - di->blocksize - extent -
+ keysize, keysize);
+ if (error != 0)
+ return (error);
+ }
+#endif
+
+ error = dump_write(di, buf, 0,
+ di->mediaoffset + di->mediasize - 2 * di->blocksize - extent -
+ keysize, di->blocksize);
+ if (error == 0)
+ error = dump_write(di, buf, 0, di->mediaoffset + di->mediasize -
+ di->blocksize, di->blocksize);
+ return (error);
}
/*
@@ -1336,26 +1378,37 @@
* Uncompressed dumps will use the entire extent, but compressed dumps typically
* will not. The true length of the dump is recorded in the leading and trailing
* headers once the dump has been completed.
+ *
+ * The dump device may provide a callback, in which case it will initialize
+ * dumpoff and take care of laying out the headers.
*/
int
dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh)
{
- uint64_t dumpextent;
+ uint64_t dumpextent, span;
uint32_t keysize;
+ int error;
#ifdef EKCD
- int error = kerneldumpcrypto_init(di->kdcrypto);
+ error = kerneldumpcrypto_init(di->kdcrypto);
if (error != 0)
return (error);
keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto);
#else
+ error = 0;
keysize = 0;
#endif
- dumpextent = dtoh64(kdh->dumpextent);
- if (di->mediasize < SIZEOF_METADATA + dumpextent + 2 * di->blocksize +
- keysize) {
- if (di->kdcomp != NULL) {
+ if (di->dumper_start != NULL) {
+ error = di->dumper_start(di);
+ } else {
+ dumpextent = dtoh64(kdh->dumpextent);
+ span = SIZEOF_METADATA + dumpextent + 2 * di->blocksize +
+ keysize;
+ if (di->mediasize < span) {
+ if (di->kdcomp == NULL)
+ return (E2BIG);
+
/*
* We don't yet know how much space the compressed dump
* will occupy, so try to use the whole swap partition
@@ -1364,18 +1417,18 @@
* be enough, the bounds checking in dump_write()
* will catch us and cause the dump to fail.
*/
- dumpextent = di->mediasize - SIZEOF_METADATA -
- 2 * di->blocksize - keysize;
+ dumpextent = di->mediasize - span + dumpextent;
kdh->dumpextent = htod64(dumpextent);
- } else
- return (E2BIG);
- }
+ }
- /* The offset at which to begin writing the dump. */
- di->dumpoff = di->mediaoffset + di->mediasize - di->blocksize -
- dumpextent;
-
- return (0);
+ /*
+ * The offset at which to begin writing the dump.
+ */
+ di->dumpoff = di->mediaoffset + di->mediasize - di->blocksize -
+ dumpextent;
+ }
+ di->origdumpoff = di->dumpoff;
+ return (error);
}
static int
@@ -1443,17 +1496,10 @@
dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh)
{
uint64_t extent;
- uint32_t keysize;
int error;
extent = dtoh64(kdh->dumpextent);
-#ifdef EKCD
- keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto);
-#else
- keysize = 0;
-#endif
-
if (di->kdcomp != NULL) {
error = compressor_flush(di->kdcomp->kdc_stream);
if (error == EAGAIN) {
@@ -1470,33 +1516,14 @@
* We now know the size of the compressed dump, so update the
* header accordingly and recompute parity.
*/
- kdh->dumplength = htod64(di->dumpoff -
- (di->mediaoffset + di->mediasize - di->blocksize - extent));
+ kdh->dumplength = htod64(di->dumpoff - di->origdumpoff);
kdh->parity = 0;
kdh->parity = kerneldump_parity(kdh);
compressor_reset(di->kdcomp->kdc_stream);
}
- /*
- * Write kerneldump headers at the beginning and end of the dump extent.
- * Write the key after the leading header.
- */
- error = dump_write_header(di, kdh,
- di->mediaoffset + di->mediasize - 2 * di->blocksize - extent -
- keysize);
- if (error != 0)
- return (error);
-
-#ifdef EKCD
- error = dump_write_key(di,
- di->mediaoffset + di->mediasize - di->blocksize - extent - keysize);
- if (error != 0)
- return (error);
-#endif
-
- error = dump_write_header(di, kdh,
- di->mediaoffset + di->mediasize - di->blocksize);
+ error = dump_write_headers(di, kdh);
if (error != 0)
return (error);
Index: head/sys/sys/conf.h
===================================================================
--- head/sys/sys/conf.h
+++ head/sys/sys/conf.h
@@ -101,6 +101,8 @@
struct bio;
struct buf;
+struct dumperinfo;
+struct kerneldumpheader;
struct thread;
struct uio;
struct knote;
@@ -131,6 +133,9 @@
vm_offset_t _physical, /* Physical address of virtual. */
off_t _offset, /* Byte-offset to write at. */
size_t _length); /* Number of bytes to dump. */
+typedef int dumper_start_t(struct dumperinfo *di);
+typedef int dumper_hdr_t(struct dumperinfo *di, struct kerneldumpheader *kdh,
+ void *key, uint32_t keylen);
#endif /* _KERNEL */
@@ -332,13 +337,18 @@
struct dumperinfo {
dumper_t *dumper; /* Dumping function. */
+ dumper_start_t *dumper_start; /* Dumper callback for dump_start(). */
+ dumper_hdr_t *dumper_hdr; /* Dumper callback for writing headers. */
void *priv; /* Private parts. */
u_int blocksize; /* Size of block in bytes. */
u_int maxiosize; /* Max size allowed for an individual I/O */
off_t mediaoffset; /* Initial offset in bytes. */
off_t mediasize; /* Space available in bytes. */
+
+ /* MI kernel dump state. */
void *blockbuf; /* Buffer for padding shorter dump blocks */
off_t dumpoff; /* Offset of ongoing kernel dump. */
+ off_t origdumpoff; /* Starting dump offset. */
struct kerneldumpcrypto *kdcrypto; /* Kernel dump crypto. */
struct kerneldumpcomp *kdcomp; /* Kernel dump compression. */
};
@@ -349,6 +359,7 @@
int set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
uint8_t compression, uint8_t encryption, const uint8_t *key,
uint32_t encryptedkeysize, const uint8_t *encryptedkey);
+int clear_dumper(struct thread *td);
int dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh);
int dump_append(struct dumperinfo *, void *, vm_offset_t, size_t);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 15, 3:29 PM (8 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28746226
Default Alt Text
D15252.diff (10 KB)
Attached To
Mode
D15252: Refactor the generic kernel dump code in preparation for netdump.
Attached
Detach File
Event Timeline
Log In to Comment