Index: sbin/savecore/savecore.c =================================================================== --- sbin/savecore/savecore.c +++ sbin/savecore/savecore.c @@ -436,7 +436,7 @@ { xo_handle_t *xostdout, *xoinfo; static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX]; - static char *buf = NULL; + static char *buf = NULL, *temp = NULL; struct kerneldumpheader kdhf, kdhl; off_t mediasize, dumpsize, firsthd, lasthd; FILE *info, *fp; @@ -490,14 +490,27 @@ printf("sectorsize = %u\n", sectorsize); } + if (sectorsize < sizeof kdhl) { + syslog(LOG_ERR, + "Sector size is less the kernel dump header %ld", + sizeof kdhl); + goto closefd; + } + lasthd = mediasize - sectorsize; + temp = malloc(sectorsize); + if (temp == NULL) { + syslog(LOG_ERR, "error allocating memory"); + return; + } if (lseek(fd, lasthd, SEEK_SET) != lasthd || - read(fd, &kdhl, sizeof(kdhl)) != sizeof(kdhl)) { + read(fd, temp, sectorsize) != sectorsize) { syslog(LOG_ERR, "error reading last dump header at offset %lld in %s: %m", (long long)lasthd, device); goto closefd; } + memcpy(&kdhl, temp, sizeof kdhl); istextdump = 0; if (strncmp(kdhl.magic, TEXTDUMPMAGIC, sizeof kdhl) == 0) { if (verbose) @@ -567,15 +580,16 @@ goto closefd; } dumpsize = dtoh64(kdhl.dumplength); - firsthd = lasthd - dumpsize - sizeof kdhf; + firsthd = lasthd - dumpsize - sectorsize; if (lseek(fd, firsthd, SEEK_SET) != firsthd || - read(fd, &kdhf, sizeof(kdhf)) != sizeof(kdhf)) { + read(fd, temp, sectorsize) != sectorsize) { syslog(LOG_ERR, "error reading first dump header at offset %lld in %s: %m", (long long)firsthd, device); nerr++; goto closefd; } + memcpy(&kdhf, temp, sizeof kdhf); if (verbose >= 2) { printf("First dump headers:\n"); @@ -725,11 +739,13 @@ if (verbose) printf("clearing dump header\n"); memcpy(kdhl.magic, KERNELDUMPMAGIC_CLEARED, sizeof kdhl.magic); + memcpy(temp, &kdhl, sizeof kdhl); if (lseek(fd, lasthd, SEEK_SET) != lasthd || - write(fd, &kdhl, sizeof(kdhl)) != sizeof(kdhl)) + write(fd, temp, sectorsize) != sectorsize) syslog(LOG_ERR, "error while clearing the dump header: %m"); } + free(temp); xo_close_container_h(xostdout, "crashdump"); xo_finish_h(xostdout); close(fd); Index: sys/amd64/amd64/minidump_machdep.c =================================================================== --- sys/amd64/amd64/minidump_machdep.c +++ sys/amd64/amd64/minidump_machdep.c @@ -57,7 +57,7 @@ #define SIZEOF_METADATA (64*1024) #define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK) -#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1)) +#define DEV_ALIGN(x) (((off_t)(x) + (di->blocksize-1)) & ~(di->blocksize-1)) uint64_t *vm_page_dump; int vm_page_dump_size; @@ -222,6 +222,7 @@ int error; uint64_t bits; uint64_t *pml4, *pdp, *pd, *pt, pa; + size_t size; int i, ii, j, k, n, bit; int retry_count; struct minidumphdr mdhdr; @@ -319,12 +320,12 @@ dumpsize += PAGE_SIZE; /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) { + if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2) { error = E2BIG; goto fail; } dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= sizeof(kdh) * 2; + dumplo -= di->blocksize * 2; progress = dumpsize; /* Initialize mdhdr */ @@ -344,10 +345,10 @@ ptoa((uintmax_t)physmem) / 1048576); /* Dump leader */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); + error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); if (error) goto fail; - dumplo += sizeof(kdh); + dumplo += size; /* Dump my header */ bzero(&fakepd, sizeof(fakepd)); @@ -432,10 +433,10 @@ goto fail; /* Dump trailer */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); + error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); if (error) goto fail; - dumplo += sizeof(kdh); + dumplo += size; /* Signal completion, signoff and exit stage left. */ dump_write(di, NULL, 0, 0, 0); Index: sys/dev/mrsas/mrsas.c =================================================================== --- sys/dev/mrsas/mrsas.c +++ sys/dev/mrsas/mrsas.c @@ -80,7 +80,7 @@ static int mrsas_alloc_mem(struct mrsas_softc *sc); static int mrsas_init_fw(struct mrsas_softc *sc); static int mrsas_setup_raidmap(struct mrsas_softc *sc); -static int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex); +int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex); static int mrsas_clear_intr(struct mrsas_softc *sc); static int mrsas_get_ctrl_info(struct mrsas_softc *sc); static void mrsas_update_ext_vd_details(struct mrsas_softc *sc); @@ -1484,7 +1484,7 @@ * perform the appropriate action. Before we return, we clear the response * interrupt. */ -static int +int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex) { Mpi2ReplyDescriptorsUnion_t *desc; @@ -3344,7 +3344,8 @@ while (1) { if (cmd->cmd_status == ECONNREFUSED) { - tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz); + /* DJA XXXX tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz); */ + DELAY(1000); } else break; total_time++; Index: sys/dev/mrsas/mrsas_cam.c =================================================================== --- sys/dev/mrsas/mrsas_cam.c +++ sys/dev/mrsas/mrsas_cam.c @@ -121,7 +121,7 @@ extern u_int8_t megasas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm, u_int64_t block, u_int32_t count); - +extern int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex); /* * mrsas_cam_attach: Main entry to CAM subsystem @@ -1171,8 +1171,13 @@ mrsas_cam_poll(struct cam_sim *sim) { struct mrsas_softc *sc = (struct mrsas_softc *)cam_sim_softc(sim); + int i; - mrsas_isr((void *)sc); + if (sc->msix_vectors != 0) + for(i = 0; i < sc->msix_vectors; i++) + mrsas_complete_cmd(sc, i); + else + mrsas_complete_cmd(sc, 0); } /* Index: sys/kern/kern_dump.c =================================================================== --- sys/kern/kern_dump.c +++ sys/kern/kern_dump.c @@ -49,6 +49,7 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512); +#define DEV_BSIZE_MAX 4096 /* * 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. @@ -56,12 +57,12 @@ #define SIZEOF_METADATA (64*1024) #define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK) -#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1)) +#define DEV_ALIGN(x) (((off_t)(x) + (di->blocksize-1)) & ~(di->blocksize-1)) off_t dumplo; /* Handle buffered writes. */ -static char buffer[DEV_BSIZE]; +static char buffer[DEV_BSIZE_MAX]; static size_t fragsz; struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; @@ -125,19 +126,23 @@ int error; while (sz) { - len = DEV_BSIZE - fragsz; + KASSERT(di->blocksize <= DEV_BSIZE_MAX, ("%u dump block size " + "is larger then max block size %d", di->blocksize, + DEV_BSIZE_MAX)); + + len = di->blocksize - fragsz; if (len > sz) len = sz; bcopy(ptr, buffer + fragsz, len); fragsz += len; ptr += len; sz -= len; - if (fragsz == DEV_BSIZE) { + if (fragsz == di->blocksize) { error = dump_write(di, buffer, 0, dumplo, - DEV_BSIZE); + di->blocksize); if (error) return (error); - dumplo += DEV_BSIZE; + dumplo += di->blocksize; fragsz = 0; } } @@ -152,8 +157,8 @@ if (fragsz == 0) return (0); - error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE); - dumplo += DEV_BSIZE; + error = dump_write(di, buffer, 0, dumplo, di->blocksize); + dumplo += di->blocksize; fragsz = 0; return (error); } @@ -168,7 +173,7 @@ vm_paddr_t pa; void *va; uint64_t pgs; - size_t counter, sz, chunk; + size_t counter, sz, chunk, size; int c, error; u_int maxdumppgs; @@ -201,11 +206,11 @@ wdog_kern_pat(WD_LASTVAL); #endif - error = dump_write(di, va, 0, dumplo, sz); + error = dump_write_pad(di, va, 0, dumplo, sz, &size); dumpsys_unmap_chunk(pa, chunk, va); if (error) break; - dumplo += sz; + dumplo += size; pgs -= chunk; pa += sz; @@ -286,7 +291,7 @@ Elf_Ehdr ehdr; uint64_t dumpsize; off_t hdrgap; - size_t hdrsz; + size_t hdrsz, size; int error; #ifndef __powerpc__ @@ -327,12 +332,12 @@ hdrgap = fileofs - DEV_ALIGN(hdrsz); /* Determine dump offset on device. */ - if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) { + if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2) { error = ENOSPC; goto fail; } dumplo = di->mediaoffset + di->mediasize - dumpsize; - dumplo -= sizeof(kdh) * 2; + dumplo -= di->blocksize * 2; mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, dumpsize, di->blocksize); @@ -341,10 +346,10 @@ ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); /* Dump leader */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); + error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); if (error) goto fail; - dumplo += sizeof(kdh); + dumplo += size; /* Dump ELF header */ error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); @@ -375,7 +380,7 @@ goto fail; /* Dump trailer */ - error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); + error = dump_write_pad(di, &kdh, 0, dumplo, sizeof(kdh), &size); if (error) goto fail; Index: sys/kern/kern_shutdown.c =================================================================== --- sys/kern/kern_shutdown.c +++ sys/kern/kern_shutdown.c @@ -880,6 +880,31 @@ return (di->dumper(di->priv, virtual, physical, offset, length)); } +/* Call dumper with bounds checking. */ +int +dump_write_pad(struct dumperinfo *di, void *virtual, vm_offset_t physical, + off_t offset, size_t length, size_t *size) +{ + int ret; + char *temp; + char buf[4096]; + + *size = ((length - 1) / di->blocksize + 1) * di->blocksize; + if (*size == length) + temp = virtual; + else { + if (length > sizeof(buf)) + return (ENOMEM); + temp = buf; + bzero(temp, sizeof(buf)); + bcopy(virtual, temp, length); + } + ret = dump_write(di, temp, physical, offset, *size); + + return (ret); +} + + void mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver, uint64_t dumplen, uint32_t blksz) Index: sys/sys/conf.h =================================================================== --- sys/sys/conf.h +++ sys/sys/conf.h @@ -337,6 +337,8 @@ int set_dumper(struct dumperinfo *, const char *_devname, struct thread *td); 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 doadump(boolean_t); extern int dumping; /* system is dumping */