Index: sys/amd64/amd64/minidump_machdep.c =================================================================== --- sys/amd64/amd64/minidump_machdep.c +++ sys/amd64/amd64/minidump_machdep.c @@ -56,7 +56,6 @@ int vm_page_dump_size; static struct kerneldumpheader kdh; -static off_t dumplo; /* Handle chunked writes. */ static size_t fragsz; @@ -93,8 +92,7 @@ if (fragsz == 0) return (0); - error = dump_write(di, dump_va, 0, dumplo, fragsz); - dumplo += fragsz; + error = dump_write(di, dump_va, 0, fragsz); fragsz = 0; return (error); } @@ -177,10 +175,9 @@ wdog_kern_pat(WD_LASTVAL); if (ptr) { - error = dump_write(di, ptr, 0, dumplo, len); + error = dump_write(di, ptr, 0, len); if (error) return (error); - dumplo += len; ptr += len; sz -= len; } else { @@ -333,7 +330,7 @@ printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20, ptoa((uintmax_t)physmem) / 1048576); - error = dump_start(di, &kdh, &dumplo); + error = dump_start(di, &kdh); if (error != 0) goto fail; @@ -419,7 +416,7 @@ if (error) goto fail; - error = dump_finish(di, &kdh, dumplo); + error = dump_finish(di, &kdh); if (error != 0) goto fail; Index: sys/arm/arm/minidump_machdep.c =================================================================== --- sys/arm/arm/minidump_machdep.c +++ sys/arm/arm/minidump_machdep.c @@ -58,8 +58,6 @@ static struct kerneldumpheader kdh; -static off_t dumplo; - /* Handle chunked writes. */ static size_t fragsz; static void *dump_va; @@ -89,8 +87,7 @@ if (fragsz == 0) return (0); - error = dump_write(di, dump_va, 0, dumplo, fragsz); - dumplo += fragsz; + error = dump_write(di, dump_va, 0, fragsz); fragsz = 0; return (error); } @@ -141,10 +138,9 @@ wdog_kern_pat(WD_LASTVAL); #endif if (ptr) { - error = dump_write(di, ptr, 0, dumplo, len); + error = dump_write(di, ptr, 0, len); if (error) return (error); - dumplo += len; ptr += len; sz -= len; } else { @@ -251,7 +247,7 @@ printf("Physical memory: %u MB\n", ptoa((uintmax_t)physmem) / 1048576); printf("Dumping %llu MB:", (long long)dumpsize >> 20); - error = dump_start(di, &kdh, &dumplo); + error = dump_start(di, &kdh); if (error != 0) goto fail; @@ -329,7 +325,7 @@ if (error) goto fail; - error = dump_finish(di, &kdh, dumplo); + error = dump_finish(di, &kdh); if (error != 0) goto fail; Index: sys/arm64/arm64/minidump_machdep.c =================================================================== --- sys/arm64/arm64/minidump_machdep.c +++ sys/arm64/arm64/minidump_machdep.c @@ -62,7 +62,6 @@ int vm_page_dump_size; static struct kerneldumpheader kdh; -static off_t dumplo; /* Handle chunked writes. */ static size_t fragsz; @@ -96,8 +95,7 @@ if (fragsz == 0) return (0); - error = dump_write(di, dump_va, 0, dumplo, fragsz); - dumplo += fragsz; + error = dump_write(di, dump_va, 0, fragsz); fragsz = 0; return (error); } @@ -183,10 +181,9 @@ wdog_kern_pat(WD_LASTVAL); if (ptr) { - error = dump_write(di, ptr, 0, dumplo, len); + error = dump_write(di, ptr, 0, len); if (error) return (error); - dumplo += len; ptr += len; sz -= len; } else { @@ -295,7 +292,7 @@ printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20, ptoa((uintmax_t)physmem) / 1048576); - error = dump_start(di, &kdh, &dumplo); + error = dump_start(di, &kdh); if (error != 0) goto fail; @@ -395,7 +392,7 @@ if (error) goto fail; - error = dump_finish(di, &kdh, dumplo); + error = dump_finish(di, &kdh); if (error != 0) goto fail; Index: sys/ddb/db_textdump.c =================================================================== --- sys/ddb/db_textdump.c +++ sys/ddb/db_textdump.c @@ -245,7 +245,7 @@ return (EIO); if (offset < SIZEOF_METADATA) return (ENOSPC); - textdump_error = dump_write(di, buffer, 0, offset + di->mediaoffset, + textdump_error = dump_raw_write(di, buffer, 0, offset + di->mediaoffset, TEXTDUMP_BLOCKSIZE); if (textdump_error) printf("textdump_writeblock: offset %jd, error %d\n", (intmax_t)offset, @@ -499,7 +499,7 @@ * Terminate the dump, report any errors, and clear the pending flag. */ if (textdump_error == 0) - (void)dump_write(di, NULL, 0, 0, 0); + (void)dump_raw_write(di, NULL, 0, 0, 0); if (textdump_error == ENOSPC) printf("Textdump: Insufficient space on dump partition\n"); else if (textdump_error != 0) Index: sys/geom/raid/g_raid.c =================================================================== --- sys/geom/raid/g_raid.c +++ sys/geom/raid/g_raid.c @@ -1419,7 +1419,7 @@ return (ENXIO); if (sd->sd_disk->d_kd.di.dumper == NULL) return (EOPNOTSUPP); - return (dump_write(&sd->sd_disk->d_kd.di, + return (dump_raw_write(&sd->sd_disk->d_kd.di, virtual, physical, sd->sd_disk->d_kd.di.mediaoffset + sd->sd_offset + offset, length)); Index: sys/i386/i386/minidump_machdep.c =================================================================== --- sys/i386/i386/minidump_machdep.c +++ sys/i386/i386/minidump_machdep.c @@ -54,7 +54,6 @@ int vm_page_dump_size; static struct kerneldumpheader kdh; -static off_t dumplo; /* Handle chunked writes. */ static size_t fragsz; @@ -86,8 +85,7 @@ if (fragsz == 0) return (0); - error = dump_write(di, dump_va, 0, dumplo, fragsz); - dumplo += fragsz; + error = dump_write(di, dump_va, 0, fragsz); fragsz = 0; return (error); } @@ -135,10 +133,9 @@ wdog_kern_pat(WD_LASTVAL); if (ptr) { - error = dump_write(di, ptr, 0, dumplo, len); + error = dump_write(di, ptr, 0, len); if (error) return (error); - dumplo += len; ptr += len; sz -= len; } else { @@ -258,7 +255,7 @@ printf("Physical memory: %ju MB\n", ptoa((uintmax_t)physmem) / 1048576); printf("Dumping %llu MB:", (long long)dumpsize >> 20); - error = dump_start(di, &kdh, &dumplo); + error = dump_start(di, &kdh); if (error != 0) goto fail; @@ -334,7 +331,7 @@ if (error) goto fail; - error = dump_finish(di, &kdh, dumplo); + error = dump_finish(di, &kdh); if (error != 0) goto fail; Index: sys/kern/kern_dump.c =================================================================== --- sys/kern/kern_dump.c +++ sys/kern/kern_dump.c @@ -51,8 +51,6 @@ #define MD_ALIGN(x) roundup2((off_t)(x), PAGE_SIZE) -off_t dumplo; - /* Handle buffered writes. */ static size_t fragsz; @@ -122,11 +120,9 @@ while (sz > 0) { nbytes = MIN(sz, sizeof(buf)); - error = dump_write(di, buf, 0, dumplo, nbytes); + error = dump_write(di, buf, 0, nbytes); if (error) return (error); - dumplo += nbytes; - sz -= nbytes; } @@ -148,11 +144,9 @@ ptr += len; sz -= len; if (fragsz == di->blocksize) { - error = dump_write(di, di->blockbuf, 0, dumplo, - di->blocksize); + error = dump_write(di, di->blockbuf, 0, di->blocksize); if (error) return (error); - dumplo += di->blocksize; fragsz = 0; } } @@ -167,8 +161,7 @@ if (fragsz == 0) return (0); - error = dump_write(di, di->blockbuf, 0, dumplo, di->blocksize); - dumplo += di->blocksize; + error = dump_write(di, di->blockbuf, 0, di->blocksize); fragsz = 0; return (error); } @@ -216,11 +209,10 @@ wdog_kern_pat(WD_LASTVAL); #endif - error = dump_write(di, va, 0, dumplo, sz); + error = dump_write(di, va, 0, sz); dumpsys_unmap_chunk(pa, chunk, va); if (error) break; - dumplo += sz; pgs -= chunk; pa += sz; @@ -347,7 +339,7 @@ printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20, ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); - error = dump_start(di, &kdh, &dumplo); + error = dump_start(di, &kdh); if (error != 0) goto fail; @@ -369,19 +361,18 @@ * All headers are written using blocked I/O, so we know the * current offset is (still) block aligned. Skip the alignement * in the file to have the segment contents aligned at page - * boundary. We cannot use MD_ALIGN on dumplo, because we don't - * care and may very well be unaligned within the dump device. + * boundary. */ error = dumpsys_buf_seek(di, (size_t)hdrgap); if (error) goto fail; - /* Dump memory chunks (updates dumplo) */ + /* Dump memory chunks. */ error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); if (error < 0) goto fail; - error = dump_finish(di, &kdh, dumplo); + error = dump_finish(di, &kdh); if (error != 0) goto fail; Index: sys/kern/kern_shutdown.c =================================================================== --- sys/kern/kern_shutdown.c +++ sys/kern/kern_shutdown.c @@ -157,7 +157,6 @@ uint8_t kdc_iv[KERNELDUMP_IV_MAX_SIZE]; keyInstance kdc_ki; cipherInstance kdc_ci; - off_t kdc_nextoffset; uint32_t kdc_dumpkeysize; struct kerneldumpkey kdc_dumpkey[]; }; @@ -172,6 +171,7 @@ int dumping; /* system is dumping */ int rebooting; /* system is rebooting */ static struct dumperinfo dumper; /* our selected dumper */ +static off_t dumpoff; /* current dump offset */ /* Context information for dump-debuggers. */ static struct pcb dumppcb; /* Registers. */ @@ -931,8 +931,6 @@ goto out; } - kdc->kdc_nextoffset = 0; - kdk = kdc->kdc_dumpkey; memcpy(kdk->kdk_iv, kdc->kdc_iv, sizeof(kdk->kdk_iv)); out: @@ -1024,24 +1022,20 @@ (uintmax_t)length, (intmax_t)di->mediasize); return (ENOSPC); } + if (length % di->blocksize != 0) { + printf("Attempt to write partial block of length %ju.\n", + (uintmax_t)length); + return (EINVAL); + } + if (offset % di->blocksize != 0) { + printf("Attempt to write at unaligned offset %jd.\n", + (intmax_t)offset); + return (EINVAL); + } return (0); } -/* Call dumper with bounds checking. */ -static int -dump_raw_write(struct dumperinfo *di, void *virtual, vm_offset_t physical, - off_t offset, size_t length) -{ - int error; - - error = dump_check_bounds(di, offset, length); - if (error != 0) - return (error); - - return (di->dumper(di->priv, virtual, physical, offset, length)); -} - #ifdef EKCD static int dump_encrypt(struct kerneldumpcrypto *kdc, uint8_t *buf, size_t size) @@ -1074,33 +1068,9 @@ struct kerneldumpcrypto *kdc; int error; size_t nbytes; - off_t nextoffset; kdc = di->kdc; - error = dump_check_bounds(di, offset, length); - if (error != 0) - return (error); - - /* Signal completion. */ - if (virtual == NULL && physical == 0 && offset == 0 && length == 0) { - return (di->dumper(di->priv, virtual, physical, offset, - length)); - } - - /* Data have to be aligned to block size. */ - if ((length % di->blocksize) != 0) - return (EINVAL); - - /* - * Data have to be written continuously becase we're encrypting using - * CBC mode which has this assumption. - */ - if (kdc->kdc_nextoffset != 0 && kdc->kdc_nextoffset != offset) - return (EINVAL); - - nextoffset = offset + (off_t)length; - while (length > 0) { nbytes = MIN(length, sizeof(buf)); bcopy(virtual, buf, nbytes); @@ -1108,7 +1078,7 @@ if (dump_encrypt(kdc, buf, nbytes) != 0) return (EIO); - error = di->dumper(di->priv, buf, physical, offset, nbytes); + error = dump_raw_write(di, buf, physical, offset, nbytes); if (error != 0) return (error); @@ -1117,8 +1087,6 @@ length -= nbytes; } - kdc->kdc_nextoffset = nextoffset; - return (0); } @@ -1136,21 +1104,6 @@ } #endif /* EKCD */ -int -dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical, - off_t offset, size_t length) -{ - -#ifdef EKCD - if (di->kdc != NULL) { - return (dump_encrypted_write(di, virtual, physical, offset, - length)); - } -#endif - - return (dump_raw_write(di, virtual, physical, offset, length)); -} - static int dump_write_header(struct dumperinfo *di, struct kerneldumpheader *kdh, vm_offset_t physical, off_t offset) @@ -1185,7 +1138,7 @@ * key. */ int -dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh, off_t *dumplop) +dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh) { uint64_t dumpsize; uint32_t keysize; @@ -1204,18 +1157,18 @@ if (di->mediasize < SIZEOF_METADATA + dumpsize) return (ENOSPC); - *dumplop = di->mediaoffset + di->mediasize - dumpsize; + dumpoff = di->mediaoffset + di->mediasize - dumpsize; - error = dump_write_header(di, kdh, 0, *dumplop); + error = dump_write_header(di, kdh, 0, dumpoff); if (error != 0) return (error); - *dumplop += di->blocksize; + dumpoff += di->blocksize; #ifdef EKCD - error = dump_write_key(di, 0, *dumplop); + error = dump_write_key(di, 0, dumpoff); if (error != 0) return (error); - *dumplop += keysize; + dumpoff += keysize; #endif return (0); @@ -1226,15 +1179,46 @@ * dump has completed. */ int -dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh, off_t dumplo) +dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical, + size_t length) +{ + int error; + +#ifdef EKCD + if (di->kdc != NULL) + error = dump_encrypted_write(di, virtual, physical, dumpoff, + length); + else +#endif + error = dump_raw_write(di, virtual, physical, dumpoff, length); + if (error == 0) + dumpoff += length; + return (error); +} + +int +dump_raw_write(struct dumperinfo *di, void *virtual, vm_offset_t physical, + off_t offset, size_t length) +{ + int error; + + error = dump_check_bounds(di, offset, length); + if (error != 0) + return (error); + + return (di->dumper(di->priv, virtual, physical, offset, length)); +} + +int +dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh) { int error; - error = dump_write_header(di, kdh, 0, dumplo); + error = dump_write_header(di, kdh, 0, dumpoff); if (error != 0) return (error); - (void)dump_write(di, NULL, 0, 0, 0); + (void)dump_raw_write(di, NULL, 0, 0, 0); return (0); } Index: sys/mips/mips/minidump_machdep.c =================================================================== --- sys/mips/mips/minidump_machdep.c +++ sys/mips/mips/minidump_machdep.c @@ -56,7 +56,6 @@ int vm_page_dump_size; static struct kerneldumpheader kdh; -static off_t dumplo; /* Handle chunked writes. */ static uint64_t counter, progress, dumpsize; @@ -166,10 +165,9 @@ wdog_kern_pat(WD_LASTVAL); if (ptr) { - error = dump_write(di, ptr, 0, dumplo, len); + error = dump_write(di, ptr, 0, len); if (error) return (error); - dumplo += len; ptr += len; sz -= len; } else { @@ -267,7 +265,7 @@ printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20, ptoa((uintmax_t)physmem) / 1048576); - error = dump_start(di, &kdh, &dumplo); + error = dump_start(di, &kdh); if (error != 0) goto fail; @@ -335,7 +333,7 @@ } } - error = dump_finish(di, &kdh, dumplo); + error = dump_finish(di, &kdh); if (error != 0) goto fail; Index: sys/sparc64/sparc64/dump_machdep.c =================================================================== --- sys/sparc64/sparc64/dump_machdep.c +++ sys/sparc64/sparc64/dump_machdep.c @@ -49,7 +49,6 @@ static off_t fileofs; -extern off_t dumplo; extern struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; int do_minidump = 0; @@ -99,7 +98,7 @@ printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg); - error = dump_start(di, &kdh, &dumplo); + error = dump_start(di, &kdh); if (error != 0) goto fail; @@ -128,7 +127,7 @@ if (error < 0) goto fail; - error = dump_finish(di, &kdh, dumplo); + error = dump_finish(di, &kdh); if (error != 0) goto fail; Index: sys/sys/conf.h =================================================================== --- sys/sys/conf.h +++ sys/sys/conf.h @@ -342,11 +342,10 @@ 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_start(struct dumperinfo *di, struct kerneldumpheader *kdh); +int dump_finish(struct dumperinfo *di, struct kerneldumpheader *kdh); +int dump_write(struct dumperinfo *, void *, vm_offset_t, size_t); +int dump_raw_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t); int doadump(boolean_t); extern int dumping; /* system is dumping */