Index: head/sys/amd64/amd64/minidump_machdep.c =================================================================== --- head/sys/amd64/amd64/minidump_machdep.c +++ head/sys/amd64/amd64/minidump_machdep.c @@ -52,12 +52,6 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); -/* - * Don't touch the first SIZEOF_METADATA bytes on the dump device. This - * is to protect us from metadata and to protect metadata from us. - */ -#define SIZEOF_METADATA (64*1024) - uint64_t *vm_page_dump; int vm_page_dump_size; @@ -320,22 +314,8 @@ } dumpsize += PAGE_SIZE; - /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + - kerneldumpcrypto_dumpkeysize(di->kdc)) { - error = E2BIG; - goto fail; - } - dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= di->blocksize * 2; - dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); progress = dumpsize; - /* Initialize kernel dump crypto. */ - error = kerneldumpcrypto_init(di->kdc); - if (error) - goto fail; - /* Initialize mdhdr */ bzero(&mdhdr, sizeof(mdhdr)); strcpy(mdhdr.magic, MINIDUMP_MAGIC); @@ -353,18 +333,10 @@ printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20, ptoa((uintmax_t)physmem) / 1048576); - /* Dump leader */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_start(di, &kdh, &dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Dump key */ - error = dump_write_key(di, 0, dumplo); - if (error) - goto fail; - dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); - /* Dump my header */ bzero(&fakepd, sizeof(fakepd)); bcopy(&mdhdr, &fakepd, sizeof(mdhdr)); @@ -447,14 +419,10 @@ if (error) goto fail; - /* Dump trailer */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_finish(di, &kdh, dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Signal completion, signoff and exit stage left. */ - dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return (0); Index: head/sys/arm/arm/minidump_machdep.c =================================================================== --- head/sys/arm/arm/minidump_machdep.c +++ head/sys/arm/arm/minidump_machdep.c @@ -53,12 +53,6 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); -/* - * Don't touch the first SIZEOF_METADATA bytes on the dump device. This - * is to protect us from metadata and to protect metadata from us. - */ -#define SIZEOF_METADATA (64*1024) - uint32_t *vm_page_dump; int vm_page_dump_size; @@ -219,7 +213,6 @@ dumpsize = ptesize; dumpsize += round_page(msgbufp->msg_size); dumpsize += round_page(vm_page_dump_size); - for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) { bits = vm_page_dump[i]; while (bits) { @@ -234,26 +227,10 @@ bits &= ~(1ul << bit); } } - dumpsize += PAGE_SIZE; - /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + - kerneldumpcrypto_dumpkeysize(di->kdc)) { - error = ENOSPC; - goto fail; - } - - dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= di->blocksize * 2; - dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); progress = dumpsize; - /* Initialize kernel dump crypto. */ - error = kerneldumpcrypto_init(di->kdc); - if (error) - goto fail; - /* Initialize mdhdr */ bzero(&mdhdr, sizeof(mdhdr)); strcpy(mdhdr.magic, MINIDUMP_MAGIC); @@ -274,18 +251,10 @@ printf("Physical memory: %u MB\n", ptoa((uintmax_t)physmem) / 1048576); printf("Dumping %llu MB:", (long long)dumpsize >> 20); - /* Dump leader */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_start(di, &kdh, &dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Dump key */ - error = dump_write_key(di, 0, dumplo); - if (error) - goto fail; - dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); - /* Dump my header */ bzero(dumpbuf, sizeof(dumpbuf)); bcopy(&mdhdr, dumpbuf, sizeof(mdhdr)); @@ -360,14 +329,10 @@ if (error) goto fail; - /* Dump trailer */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_finish(di, &kdh, dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Signal completion, signoff and exit stage left. */ - dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return (0); @@ -377,7 +342,7 @@ if (error == ECANCELED) printf("\nDump aborted\n"); - else if (error == ENOSPC) + else if (error == E2BIG || error == ENOSPC) printf("\nDump failed. Partition too small.\n"); else printf("\n** DUMP FAILED (ERROR %d) **\n", error); Index: head/sys/arm64/arm64/minidump_machdep.c =================================================================== --- head/sys/arm64/arm64/minidump_machdep.c +++ head/sys/arm64/arm64/minidump_machdep.c @@ -58,12 +58,6 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); -/* - * Don't touch the first SIZEOF_METADATA bytes on the dump device. This - * is to protect us from metadata and to protect metadata from us. - */ -#define SIZEOF_METADATA (64*1024) - uint64_t *vm_page_dump; int vm_page_dump_size; @@ -281,22 +275,8 @@ } dumpsize += PAGE_SIZE; - /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + - kerneldumpcrypto_dumpkeysize(di->kdc)) { - error = E2BIG; - goto fail; - } - dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= di->blocksize * 2; - dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); progress = dumpsize; - /* Initialize kernel dump crypto. */ - error = kerneldumpcrypto_init(di->kdc); - if (error) - goto fail; - /* Initialize mdhdr */ bzero(&mdhdr, sizeof(mdhdr)); strcpy(mdhdr.magic, MINIDUMP_MAGIC); @@ -315,18 +295,10 @@ printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20, ptoa((uintmax_t)physmem) / 1048576); - /* Dump leader */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_start(di, &kdh, &dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Dump key */ - error = dump_write_key(di, 0, dumplo); - if (error) - goto fail; - dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); - /* Dump my header */ bzero(&tmpbuffer, sizeof(tmpbuffer)); bcopy(&mdhdr, &tmpbuffer, sizeof(mdhdr)); @@ -423,18 +395,14 @@ if (error) goto fail; - /* Dump trailer */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_finish(di, &kdh, dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Signal completion, signoff and exit stage left. */ - dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return (0); - fail: +fail: if (error < 0) error = -error; Index: head/sys/i386/i386/minidump_machdep.c =================================================================== --- head/sys/i386/i386/minidump_machdep.c +++ head/sys/i386/i386/minidump_machdep.c @@ -47,12 +47,6 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); -/* - * Don't touch the first SIZEOF_METADATA bytes on the dump device. This - * is to protect us from metadata and to protect metadata from us. - */ -#define SIZEOF_METADATA (64*1024) - #define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK) #define DEV_ALIGN(x) roundup2((off_t)(x), DEV_BSIZE) @@ -244,22 +238,8 @@ } dumpsize += PAGE_SIZE; - /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + - kerneldumpcrypto_dumpkeysize(di->kdc)) { - error = ENOSPC; - goto fail; - } - dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= di->blocksize * 2; - dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); progress = dumpsize; - /* Initialize kernel dump crypto. */ - error = kerneldumpcrypto_init(di->kdc); - if (error) - goto fail; - /* Initialize mdhdr */ bzero(&mdhdr, sizeof(mdhdr)); strcpy(mdhdr.magic, MINIDUMP_MAGIC); @@ -278,18 +258,10 @@ printf("Physical memory: %ju MB\n", ptoa((uintmax_t)physmem) / 1048576); printf("Dumping %llu MB:", (long long)dumpsize >> 20); - /* Dump leader */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_start(di, &kdh, &dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Dump key */ - error = dump_write_key(di, 0, dumplo); - if (error) - goto fail; - dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); - /* Dump my header */ bzero(&fakept, sizeof(fakept)); bcopy(&mdhdr, &fakept, sizeof(mdhdr)); @@ -362,14 +334,10 @@ if (error) goto fail; - /* Dump trailer */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_finish(di, &kdh, dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Signal completion, signoff and exit stage left. */ - dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return (0); @@ -379,7 +347,7 @@ if (error == ECANCELED) printf("\nDump aborted\n"); - else if (error == ENOSPC) + else if (error == E2BIG || error == ENOSPC) printf("\nDump failed. Partition too small.\n"); else printf("\n** DUMP FAILED (ERROR %d) **\n", error); Index: head/sys/kern/kern_dump.c =================================================================== --- head/sys/kern/kern_dump.c +++ head/sys/kern/kern_dump.c @@ -49,12 +49,6 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); -/* - * Don't touch the first SIZEOF_METADATA bytes on the dump device. This - * is to protect us from metadata and to protect metadata from us. - */ -#define SIZEOF_METADATA (64*1024) - #define MD_ALIGN(x) roundup2((off_t)(x), PAGE_SIZE) off_t dumplo; @@ -347,39 +341,16 @@ dumpsize += fileofs; hdrgap = fileofs - roundup2((off_t)hdrsz, di->blocksize); - /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + - kerneldumpcrypto_dumpkeysize(di->kdc)) { - error = ENOSPC; - goto fail; - } - dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= di->blocksize * 2; - dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); - - /* Initialize kernel dump crypto. */ - error = kerneldumpcrypto_init(di->kdc); - if (error) - goto fail; - mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize, kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize); printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20, ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); - /* Dump leader */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_start(di, &kdh, &dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Dump key */ - error = dump_write_key(di, 0, dumplo); - if (error) - goto fail; - dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); - /* Dump ELF header */ error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); if (error) @@ -410,14 +381,10 @@ if (error < 0) goto fail; - /* Dump trailer */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_finish(di, &kdh, dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Signal completion, signoff and exit stage left. */ - dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return (0); @@ -427,7 +394,7 @@ if (error == ECANCELED) printf("\nDump aborted\n"); - else if (error == ENOSPC) + else if (error == E2BIG || error == ENOSPC) printf("\nDump failed. Partition too small.\n"); else printf("\n** DUMP FAILED (ERROR %d) **\n", error); Index: head/sys/kern/kern_shutdown.c =================================================================== --- head/sys/kern/kern_shutdown.c +++ head/sys/kern/kern_shutdown.c @@ -897,7 +897,7 @@ } #endif /* EKCD */ -int +static int kerneldumpcrypto_init(struct kerneldumpcrypto *kdc) { #ifndef EKCD @@ -1180,21 +1180,7 @@ return (dump_raw_write(di, buf, physical, offset, *size)); } -int -dump_write_pad(struct dumperinfo *di, void *virtual, vm_offset_t physical, - off_t offset, size_t length, size_t *size) -{ - void *buf; - int error; - - error = dump_pad(di, virtual, length, &buf, size); - if (error != 0) - return (error); - - return (dump_write(di, buf, physical, offset, *size)); -} - -int +static int dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh, vm_offset_t physical, off_t offset) { @@ -1208,7 +1194,7 @@ return (ret); } -int +static int dump_write_key(struct dumperinfo *di, vm_offset_t physical, off_t offset) { #ifndef EKCD @@ -1223,6 +1209,64 @@ return (dump_raw_write(di, kdc->kdc_dumpkey, physical, offset, kdc->kdc_dumpkeysize)); #endif /* !EKCD */ +} + +/* + * Don't touch the first SIZEOF_METADATA bytes on the dump device. This is to + * protect us from metadata and metadata from us. + */ +#define SIZEOF_METADATA (64 * 1024) + +/* + * Do some preliminary setup for a kernel dump: verify that we have enough space + * on the dump device, write the leading header, and optionally write the crypto + * key. + */ +int +dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh, off_t *dumplop) +{ + uint64_t dumpsize; + int error; + + error = kerneldumpcrypto_init(di->kdc); + if (error != 0) + return (error); + + dumpsize = dtoh64(kdh->dumplength) + 2 * di->blocksize + + kerneldumpcrypto_dumpkeysize(di->kdc); + if (di->mediasize < SIZEOF_METADATA + dumpsize) + return (E2BIG); + + *dumplop = di->mediaoffset + di->mediasize - dumpsize; + + error = dump_write_header(di, kdh, 0, *dumplop); + if (error != 0) + return (error); + *dumplop += di->blocksize; + + error = dump_write_key(di, 0, *dumplop); + if (error != 0) + return (error); + *dumplop += kerneldumpcrypto_dumpkeysize(di->kdc); + + return (0); +} + +/* + * Write the trailing kernel dump header and signal to the lower layers that the + * dump has completed. + */ +int +dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh, off_t dumplo) +{ + int error; + + error = dump_write_header(di, kdh, 0, dumplo); + if (error != 0) + return (error); + + (void)dump_write(di, NULL, 0, 0, 0); + return (0); } void Index: head/sys/mips/mips/minidump_machdep.c =================================================================== --- head/sys/mips/mips/minidump_machdep.c +++ head/sys/mips/mips/minidump_machdep.c @@ -52,18 +52,11 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); -/* - * Don't touch the first SIZEOF_METADATA bytes on the dump device. This - * is to protect us from metadata and to protect metadata from us. - */ -#define SIZEOF_METADATA (64*1024) - uint32_t *vm_page_dump; int vm_page_dump_size; static struct kerneldumpheader kdh; static off_t dumplo; -static off_t origdumplo; /* Handle chunked writes. */ static uint64_t counter, progress, dumpsize; @@ -241,7 +234,6 @@ dumpsize = ptesize; dumpsize += round_page(msgbufp->msg_size); dumpsize += round_page(vm_page_dump_size); - for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) { bits = vm_page_dump[i]; while (bits) { @@ -256,26 +248,10 @@ bits &= ~(1ul << bit); } } - dumpsize += PAGE_SIZE; - /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + - kerneldumpcrypto_dumpkeysize(di->kdc)) { - error = ENOSPC; - goto fail; - } - - origdumplo = dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= di->blocksize * 2; - dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); progress = dumpsize; - /* Initialize kernel dump crypto. */ - error = kerneldumpcrypto_init(di->kdc); - if (error) - goto fail; - /* Initialize mdhdr */ bzero(&mdhdr, sizeof(mdhdr)); strcpy(mdhdr.magic, MINIDUMP_MAGIC); @@ -291,18 +267,10 @@ printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20, ptoa((uintmax_t)physmem) / 1048576); - /* Dump leader */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_start(di, &kdh, &dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Dump key */ - error = dump_write_key(di, 0, dumplo); - if (error) - goto fail; - dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); - /* Dump my header */ bzero(tmpbuffer, sizeof(tmpbuffer)); bcopy(&mdhdr, tmpbuffer, sizeof(mdhdr)); @@ -329,8 +297,7 @@ if (!count) { prev_pte = (vm_offset_t)pte; count++; - } - else { + } else { if ((vm_offset_t)pte == (prev_pte + count * PAGE_SIZE)) count++; else { @@ -368,14 +335,10 @@ } } - /* Dump trailer */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_finish(di, &kdh, dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Signal completion, signoff and exit stage left. */ - dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return (0); @@ -385,7 +348,7 @@ if (error == ECANCELED) printf("\nDump aborted\n"); - else if (error == ENOSPC) + else if (error == E2BIG || error == ENOSPC) printf("\nDump failed. Partition too small.\n"); else printf("\n** DUMP FAILED (ERROR %d) **\n", error); Index: head/sys/sparc64/sparc64/dump_machdep.c =================================================================== --- head/sys/sparc64/sparc64/dump_machdep.c +++ head/sys/sparc64/sparc64/dump_machdep.c @@ -78,7 +78,7 @@ { static struct kerneldumpheader kdh; struct sparc64_dump_hdr hdr; - vm_size_t size, totsize, hdrsize; + vm_size_t size, hdrsize; int error, i, nreg; /* Set up dump_map and calculate dump size. */ @@ -94,41 +94,15 @@ DEV_BSIZE); size += hdrsize; - totsize = size + 2 * di->blocksize + - kerneldumpcrypto_dumpkeysize(di->kdc); - if (totsize > di->mediasize) { - printf("Insufficient space on device (need %ld, have %ld), " - "refusing to dump.\n", (long)totsize, - (long)di->mediasize); - error = ENOSPC; - goto fail; - } - - /* Determine dump offset on device. */ - dumplo = di->mediaoffset + di->mediasize - totsize; - - /* Initialize kernel dump crypto. */ - error = kerneldumpcrypto_init(di->kdc); - if (error) - goto fail; - mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_SPARC64_VERSION, size, kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize); printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg); - /* Dump leader */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_start(di, &kdh, &dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Dump key */ - error = dump_write_key(di, 0, dumplo); - if (error) - goto fail; - dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); - /* Dump the private header. */ hdr.dh_hdr_size = hdrsize; hdr.dh_tsb_pa = tsb_kernel_phys; @@ -154,14 +128,10 @@ if (error < 0) goto fail; - /* Dump trailer */ - error = dump_write_header(di, &kdh, 0, dumplo); - if (error) + error = dump_finish(di, &kdh, dumplo); + if (error != 0) goto fail; - dumplo += di->blocksize; - /* Signal completion, signoff and exit stage left. */ - dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return (0); Index: head/sys/sys/conf.h =================================================================== --- head/sys/sys/conf.h +++ head/sys/sys/conf.h @@ -342,12 +342,11 @@ int set_dumper(struct dumperinfo *di, const char *devname, struct thread *td, uint8_t encrypt, const uint8_t *key, uint32_t encryptedkeysize, const uint8_t *encryptedkey); +int dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh, + off_t *dumplop); +int dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh, + off_t dumplo); int dump_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t); -int dump_write_pad(struct dumperinfo *, void *, vm_offset_t, off_t, size_t, - size_t *); -int dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh, - vm_offset_t physical, off_t offset); -int dump_write_key(struct dumperinfo *di, vm_offset_t physical, off_t offset); int doadump(boolean_t); extern int dumping; /* system is dumping */ Index: head/sys/sys/kerneldump.h =================================================================== --- head/sys/sys/kerneldump.h +++ head/sys/sys/kerneldump.h @@ -125,7 +125,6 @@ vm_paddr_t pa_size; }; -int kerneldumpcrypto_init(struct kerneldumpcrypto *kdc); uint32_t kerneldumpcrypto_dumpkeysize(const struct kerneldumpcrypto *kdc); void mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver,