svn commit: r328752 - in user/markj/netdump/sys: geom kern netinet/netdump sys
Mark Johnston
markj at FreeBSD.org
Thu Feb 1 21:37:49 UTC 2018
Author: markj
Date: Thu Feb 1 21:37:47 2018
New Revision: 328752
URL: https://svnweb.freebsd.org/changeset/base/328752
Log:
Try to clean up integration with the generic kerneldump code.
Modified:
user/markj/netdump/sys/geom/geom_dev.c
user/markj/netdump/sys/kern/kern_shutdown.c
user/markj/netdump/sys/netinet/netdump/netdump_client.c
user/markj/netdump/sys/sys/conf.h
Modified: user/markj/netdump/sys/geom/geom_dev.c
==============================================================================
--- user/markj/netdump/sys/geom/geom_dev.c Thu Feb 1 21:34:50 2018 (r328751)
+++ user/markj/netdump/sys/geom/geom_dev.c Thu Feb 1 21:37:47 2018 (r328752)
@@ -144,6 +144,7 @@ g_dev_setdumpdev(struct cdev *dev, struct diocskerneld
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);
Modified: user/markj/netdump/sys/kern/kern_shutdown.c
==============================================================================
--- user/markj/netdump/sys/kern/kern_shutdown.c Thu Feb 1 21:34:50 2018 (r328751)
+++ user/markj/netdump/sys/kern/kern_shutdown.c Thu Feb 1 21:37:47 2018 (r328752)
@@ -1176,18 +1176,6 @@ dump_encrypted_write(struct dumperinfo *di, void *virt
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
@@ -1221,20 +1209,42 @@ kerneldumpcomp_write_cb(void *base, size_t length, off
}
/*
- * 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 {
@@ -1243,7 +1253,24 @@ dump_write_header(struct dumperinfo *di, struct kernel
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);
}
/*
@@ -1268,11 +1295,14 @@ dump_write_header(struct dumperinfo *di, struct kernel
* 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;
@@ -1282,20 +1312,20 @@ dump_start(struct dumperinfo *di, struct kerneldumphea
return (error);
keysize = kerneldumpcrypto_dumpkeysize(di->kdcrypto);
#else
+ error = 0;
keysize = 0;
#endif
- if (di->dumper_init != NULL) {
- error = di->dumper_init(di->priv);
- if (error != 0)
- return (error);
- }
+ 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);
- dumpextent = dtoh64(kdh->dumpextent);
- if (di->mediasize > 0 &&
- di->mediasize < SIZEOF_METADATA + dumpextent + 2 * di->blocksize +
- keysize) {
- if (di->kdcomp != NULL) {
/*
* We don't yet know how much space the compressed dump
* will occupy, so try to use the whole swap partition
@@ -1304,22 +1334,16 @@ dump_start(struct dumperinfo *di, struct kerneldumphea
* be enouch, 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. */
- /* XXXMJ ugly */
- if (di->mediasize == 0)
- di->dumpoff = di->blocksize;
- else
+ /* The offset at which to begin writing the dump. */
di->dumpoff = di->mediaoffset + di->mediasize - di->blocksize -
dumpextent;
+ }
- return (0);
+ return (error);
}
static int
@@ -1387,17 +1411,10 @@ int
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) {
@@ -1425,33 +1442,10 @@ dump_finish(struct dumperinfo *di, struct kerneldumphe
/*
* Write kerneldump headers at the beginning and end of the dump extent.
* Write the key after the leading header.
- * XXXMJ quite ugly
*/
- if (di->mediasize == 0)
- error = dump_write_header(di, kdh, 0);
- else
- error = dump_write_header(di, kdh,
- di->mediaoffset + di->mediasize - 2 * di->blocksize - extent -
- keysize);
+ error = dump_write_headers(di, kdh);
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
-
- /* XXX comment */
- if (di->dumper_fini != NULL)
- di->dumper_fini(di->priv);
- else {
- error = dump_write_header(di, kdh,
- di->mediaoffset + di->mediasize - di->blocksize);
- if (error != 0)
- return (error);
- }
(void)dump_write(di, NULL, 0, 0, 0);
return (0);
Modified: user/markj/netdump/sys/netinet/netdump/netdump_client.c
==============================================================================
--- user/markj/netdump/sys/netinet/netdump/netdump_client.c Thu Feb 1 21:34:50 2018 (r328751)
+++ user/markj/netdump/sys/netinet/netdump/netdump_client.c Thu Feb 1 21:37:47 2018 (r328752)
@@ -104,10 +104,8 @@ static int netdump_dumper(void *priv __unused, void *
vm_offset_t physical __unused, off_t offset, size_t length);
static int netdump_ether_output(struct mbuf *m, struct ifnet *ifp,
struct ether_addr dst, u_short etype);
-static void netdump_fini(void *priv __unused);
static void netdump_handle_arp(struct mbuf **mb);
static void netdump_handle_ip(struct mbuf **mb);
-static int netdump_init(void *priv __unused);
static int netdump_ioctl(struct cdev *dev __unused, u_long cmd,
caddr_t addr, int flags __unused, struct thread *td);
static int netdump_modevent(module_t mod, int type, void *priv);
@@ -116,6 +114,7 @@ static void netdump_pkt_in(struct ifnet *ifp, struct
static int netdump_send(uint32_t type, off_t offset, unsigned char *data,
uint32_t datalen);
static int netdump_send_arp(in_addr_t dst);
+static int netdump_start(struct dumperinfo *di);
static int netdump_udp_output(struct mbuf *m);
/* Must be at least as big as the chunks dumpsys() gives us. */
@@ -343,15 +342,15 @@ static int
netdump_arp_gw(void)
{
in_addr_t dst;
- int err, polls, retries;
+ int error, polls, retries;
dst = nd_server.s_addr;
restart:
for (retries = 0; retries < nd_arp_retries && have_gw_mac == 0;
retries++) {
- err = netdump_send_arp(dst);
- if (err != 0)
- return (err);
+ error = netdump_send_arp(dst);
+ if (error != 0)
+ return (error);
for (polls = 0; polls < nd_polls && have_gw_mac == 0; polls++) {
netdump_network_poll();
DELAY(500);
@@ -893,34 +892,29 @@ static int
netdump_dumper(void *priv __unused, void *virtual,
vm_offset_t physical __unused, off_t offset, size_t length)
{
- int err, msgtype;
+ int error;
NETDDEBUGV("netdump_dumper(NULL, %p, NULL, %ju, %zu)\n",
virtual, (uintmax_t)offset, length);
- if (virtual == NULL)
- /* XXX why don't we need this in onefs? */
+ if (virtual == NULL) {
+ if (dump_failed != 0)
+ printf("failed to dump the kernel core\n");
+ else if (netdump_send(NETDUMP_FINISHED, 0, NULL, 0) != 0)
+ printf("failed to close the transaction\n");
+ else
+ printf("\nnetdump finished.\n");
+ netdump_cleanup();
return (0);
+ }
if (length > sizeof(nd_buf))
return (ENOSPC);
- /*
- * The first write (at offset 0) is the kernel dump header. Flag it
- * for the server to treat specially.
- * XXX: This doesn't strip out the footer KDH, although it
- * should not hurt anything.
- */
- msgtype = NETDUMP_VMCORE;
- if (offset == 0 && length > 0) {
- length = sizeof(struct kerneldumpheader);
- msgtype = NETDUMP_KDH;
- } else if (offset > 0)
- offset -= NETDUMP_DATASIZE; /* di->blocksize */
memmove(nd_buf, virtual, length);
- err = netdump_send(msgtype, offset, nd_buf, length);
- if (err != 0) {
+ error = netdump_send(NETDUMP_VMCORE, offset, nd_buf, length);
+ if (error != 0) {
dump_failed = 1;
- return (err);
+ return (error);
}
return (0);
}
@@ -928,8 +922,8 @@ netdump_dumper(void *priv __unused, void *virtual,
/*
* Perform any initalization needed prior to transmitting the kernel core.
*/
-int
-netdump_init(void *priv __unused)
+static int
+netdump_start(struct dumperinfo *di)
{
char *path;
char buf[INET_ADDRSTRLEN];
@@ -945,14 +939,17 @@ netdump_init(void *priv __unused)
MPASS(nd_ifp != NULL);
if (nd_server.s_addr == INADDR_ANY) {
- printf("netdump_init: can't netdump; no server IP given\n");
+ printf("netdump_start: can't netdump; no server IP given\n");
return (EINVAL);
}
if (nd_client.s_addr == INADDR_ANY) {
- printf("netdump_init: can't netdump; no client IP given\n");
+ printf("netdump_start: can't netdump; no client IP given\n");
return (EINVAL);
}
+ /* We start dumping at offset 0. */
+ di->dumpoff = 0;
+
nd_seqno = 1;
/*
@@ -1003,20 +1000,18 @@ trig_abort:
return (error);
}
-/*
- * Completion routine for a netdump.
- */
-static void
-netdump_fini(void *priv __unused)
+static int
+netdump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh,
+ void *key, uint32_t keysize)
{
- if (dump_failed != 0)
- printf("failed to dump the kernel core\n");
- else if (netdump_send(NETDUMP_FINISHED, 0, NULL, 0) != 0)
- printf("failed to close the transaction\n");
- else
- printf("\nnetdump finished.\n");
- netdump_cleanup();
+ if (sizeof(*kdh) + keysize > sizeof(nd_buf))
+ return (EINVAL);
+
+ memcpy(nd_buf, kdh, sizeof(*kdh));
+ if (key != NULL)
+ memcpy(nd_buf + sizeof(*kdh), key, keysize);
+ return (netdump_send(NETDUMP_KDH, 0, nd_buf, sizeof(*kdh) + keysize));
}
/*
@@ -1148,9 +1143,9 @@ netdump_ioctl(struct cdev *dev __unused, u_long cmd, c
break;
}
- dumper.dumper_init = netdump_init;
+ dumper.dumper_start = netdump_start;
+ dumper.dumper_hdr = netdump_write_headers;
dumper.dumper = netdump_dumper;
- dumper.dumper_fini = netdump_fini;
dumper.priv = NULL;
dumper.blocksize = NETDUMP_DATASIZE;
dumper.maxiosize = MAXDUMPPGS * PAGE_SIZE;
Modified: user/markj/netdump/sys/sys/conf.h
==============================================================================
--- user/markj/netdump/sys/sys/conf.h Thu Feb 1 21:34:50 2018 (r328751)
+++ user/markj/netdump/sys/sys/conf.h Thu Feb 1 21:37:47 2018 (r328752)
@@ -101,6 +101,8 @@ struct cdev {
struct bio;
struct buf;
+struct dumperinfo;
+struct kerneldumpheader;
struct thread;
struct uio;
struct knote;
@@ -125,14 +127,15 @@ typedef int d_mmap_single_t(struct cdev *cdev, vm_ooff
vm_size_t size, struct vm_object **object, int nprot);
typedef void d_purge_t(struct cdev *dev);
-typedef int dumper_init_t(void *priv);
-typedef void dumper_fini_t(void *priv);
typedef int dumper_t(
void *_priv, /* Private to the driver. */
void *_virtual, /* Virtual (mapped) address. */
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 */
@@ -333,9 +336,9 @@ struct kerneldumpcrypto;
struct kerneldumpheader;
struct dumperinfo {
- dumper_init_t *dumper_init; /* Dump device init callback. */
dumper_t *dumper; /* Dumping function. */
- dumper_fini_t *dumper_fini; /* Dump device completion callback. */
+ 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 */
More information about the svn-src-user
mailing list