Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Feb 2018 21:37:48 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r328752 - in user/markj/netdump/sys: geom kern netinet/netdump sys
Message-ID:  <201802012137.w11LbmjK089602@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802012137.w11LbmjK089602>