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>