Print this page
NEX-18463 Parallel dump produces corrupted dump file
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17845 Remove support for BZIP2 from dump
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-17857 Parallel dump threshold (dump_ncpu_low) is not applied
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17501 Enable parallel crash dump
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-17762 After a live dump (savecore -L) a subsequent panic will be saved in wrong directory
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Alexander Eremin <alexander.eremin@nexenta.com>
NEX-17182 Parallel dump hangs (fix typo)
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-17182 Parallel dump hangs
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-9338 improve the layout of the crash directory (use sys/uuid.h)
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-9338 improve the layout of the crash directory
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-5164 backport illumos 6514 AS_* lock macros simplification
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
6514 AS_* lock macros simplification
Reviewed by: Piotr Jasiukajtis <estibi@me.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Albert Lee <trisk@omniti.com>
Approved by: Dan McDonald <danmcd@omniti.com>

*** 20,29 **** --- 20,30 ---- */ /* * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2016 Joyent, Inc. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h>
*** 69,100 **** #include <vm/pvn.h> #include <vm/seg.h> #include <vm/seg_kmem.h> #include <sys/clock_impl.h> #include <sys/hold_page.h> ! #include <bzip2/bzlib.h> /* ! * Crash dump time is dominated by disk write time. To reduce this, ! * the stronger compression method bzip2 is applied to reduce the dump ! * size and hence reduce I/O time. However, bzip2 is much more ! * computationally expensive than the existing lzjb algorithm, so to ! * avoid increasing compression time, CPUs that are otherwise idle ! * during panic are employed to parallelize the compression task. ! * Many helper CPUs are needed to prevent bzip2 from being a ! * bottleneck, and on systems with too few CPUs, the lzjb algorithm is ! * parallelized instead. Lastly, I/O and compression are performed by ! * different CPUs, and are hence overlapped in time, unlike the older ! * serial code. ! * ! * Another important consideration is the speed of the dump ! * device. Faster disks need less CPUs in order to benefit from ! * parallel lzjb versus parallel bzip2. Therefore, the CPU count ! * threshold for switching from parallel lzjb to paralled bzip2 is ! * elevated for faster disks. The dump device speed is adduced from ! * the setting for dumpbuf.iosize, see dump_update_clevel. */ /* * exported vars */ --- 70,88 ---- #include <vm/pvn.h> #include <vm/seg.h> #include <vm/seg_kmem.h> #include <sys/clock_impl.h> #include <sys/hold_page.h> + #include <sys/cpu.h> ! #include <sys/uuid.h> /* ! * Parallel Dump: ! * CPUs that are otherwise idle during panic are employed to parallelize ! * the compression task. I/O and compression are performed by different ! * CPUs, and are hence overlapped in time, unlike the older serial code. */ /* * exported vars */
*** 109,153 **** int dump_ioerr; /* dump i/o error */ int dump_check_used; /* enable check for used pages */ char *dump_stack_scratch; /* scratch area for saving stack summary */ /* ! * Tunables for dump compression and parallelism. These can be set via ! * /etc/system. * ! * dump_ncpu_low number of helpers for parallel lzjb ! * This is also the minimum configuration. * ! * dump_bzip2_level bzip2 compression level: 1-9 ! * Higher numbers give greater compression, but take more memory ! * and time. Memory used per helper is ~(dump_bzip2_level * 1MB). ! * ! * dump_plat_mincpu the cross-over limit for using bzip2 (per platform): ! * if dump_plat_mincpu == 0, then always do single threaded dump ! * if ncpu >= dump_plat_mincpu then try to use bzip2 ! * ! * dump_metrics_on if set, metrics are collected in the kernel, passed ! * to savecore via the dump file, and recorded by savecore in ! * METRICS.txt. */ uint_t dump_ncpu_low = 4; /* minimum config for parallel lzjb */ - uint_t dump_bzip2_level = 1; /* bzip2 level (1-9) */ - /* Use dump_plat_mincpu_default unless this variable is set by /etc/system */ - #define MINCPU_NOT_SET ((uint_t)-1) - uint_t dump_plat_mincpu = MINCPU_NOT_SET; - /* tunables for pre-reserved heap */ uint_t dump_kmem_permap = 1024; uint_t dump_kmem_pages = 8; /* Define multiple buffers per helper to avoid stalling */ #define NCBUF_PER_HELPER 2 #define NCMAP_PER_HELPER 4 /* minimum number of helpers configured */ ! #define MINHELPERS (dump_ncpu_low) #define MINCBUFS (MINHELPERS * NCBUF_PER_HELPER) /* * Define constant parameters. * --- 97,129 ---- int dump_ioerr; /* dump i/o error */ int dump_check_used; /* enable check for used pages */ char *dump_stack_scratch; /* scratch area for saving stack summary */ /* ! * Tunables for dump compression and parallelism. ! * These can be set via /etc/system. * ! * dump_ncpu_low: ! * This is the minimum configuration for parallel lzjb. ! * A special value of 0 means that parallel dump will not be used. * ! * dump_metrics_on: ! * If set, metrics are collected in the kernel, passed to savecore ! * via the dump file, and recorded by savecore in METRICS.txt. */ uint_t dump_ncpu_low = 4; /* minimum config for parallel lzjb */ /* tunables for pre-reserved heap */ uint_t dump_kmem_permap = 1024; uint_t dump_kmem_pages = 8; /* Define multiple buffers per helper to avoid stalling */ #define NCBUF_PER_HELPER 2 #define NCMAP_PER_HELPER 4 /* minimum number of helpers configured */ ! #define MINHELPERS (MAX(dump_ncpu_low, 1)) #define MINCBUFS (MINHELPERS * NCBUF_PER_HELPER) /* * Define constant parameters. *
*** 258,268 **** pgcnt_t bitnum; /* first set bitnum */ pfn_t pfn; /* first pfn in mapped range */ int off; /* byte offset to first pfn */ }; ! static char dump_osimage_uuid[36 + 1]; #define isdigit(ch) ((ch) >= '0' && (ch) <= '9') #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \ ((ch) >= 'A' && (ch) <= 'F')) --- 234,244 ---- pgcnt_t bitnum; /* first set bitnum */ pfn_t pfn; /* first pfn in mapped range */ int off; /* byte offset to first pfn */ }; ! static char dump_osimage_uuid[UUID_PRINTABLE_STRING_LENGTH]; #define isdigit(ch) ((ch) >= '0' && (ch) <= '9') #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \ ((ch) >= 'A' && (ch) <= 'F'))
*** 378,388 **** cbuf_t *cpin, *cpout, *cperr; /* cbuf objects in process */ dumpsync_t *ds; /* pointer to sync vars */ size_t used; /* counts input consumed */ char *page; /* buffer for page copy */ char *lzbuf; /* lzjb output */ - bz_stream bzstream; /* bzip2 state */ } helper_t; #define MAINHELPER (-1) /* helper is also the main task */ #define FREEHELPER (-2) /* unbound helper */ #define DONEHELPER (-3) /* helper finished */ --- 354,363 ----
*** 389,399 **** /* * configuration vars for dumpsys */ typedef struct dumpcfg { - int threshold; /* ncpu threshold for bzip2 */ int nhelper; /* number of helpers */ int nhelper_used; /* actual number of helpers used */ int ncmap; /* number VA pages for compression */ int ncbuf; /* number of bufs for compression */ int ncbuf_used; /* number of bufs in use */ --- 364,373 ----
*** 436,445 **** --- 410,427 ---- } dumpbuf_t; dumpbuf_t dumpbuf; /* I/O buffer */ /* + * DUMP_HELPER_MAX_WAIT + * For parallel dump, defines maximum time main task thread will wait + * for at least one helper to register in dumpcfg.helpermap, before + * assuming there are no helpers and falling back to serial mode. + */ + #define DUMP_HELPER_MAX_WAIT 1000 /* millisec */ + + /* * The dump I/O buffer must be at least one page, at most xfer_size * bytes, and should scale with physmem in between. The transfer size * passed in will either represent a global default (maxphys) or the * best size for the device. The size of the dumpbuf I/O buffer is * limited by dumpbuf_limit (8MB by default) because the dump
*** 487,496 **** --- 469,481 ---- kmem_free(old_buf, old_size); } /* * dump_update_clevel is called when dumpadm configures the dump device. + * Determine the compression level / type + * - DUMP_CLEVEL_SERIAL is single threaded lzjb + * - DUMP_CLEVEL_LZJB is parallel lzjb * Calculate number of helpers and buffers. * Allocate the minimum configuration for now. * * When the dump file is configured we reserve a minimum amount of * memory for use at crash time. But we reserve VA for all the memory
*** 499,535 **** * there is insufficient spare memory, however, we fall back to the * minimum. * * Live dump (savecore -L) always uses the minimum config. * - * clevel 0 is single threaded lzjb - * clevel 1 is parallel lzjb - * clevel 2 is parallel bzip2 - * - * The ncpu threshold is selected with dump_plat_mincpu. - * On OPL, set_platform_defaults() overrides the sun4u setting. - * The actual values are defined via DUMP_PLAT_*_MINCPU macros. - * - * Architecture Threshold Algorithm - * sun4u < 51 parallel lzjb - * sun4u >= 51 parallel bzip2(*) - * sun4u OPL < 8 parallel lzjb - * sun4u OPL >= 8 parallel bzip2(*) - * sun4v < 128 parallel lzjb - * sun4v >= 128 parallel bzip2(*) - * x86 < 11 parallel lzjb - * x86 >= 11 parallel bzip2(*) - * 32-bit N/A single-threaded lzjb - * - * (*) bzip2 is only chosen if there is sufficient available - * memory for buffers at dump time. See dumpsys_get_maxmem(). - * - * Faster dump devices have larger I/O buffers. The threshold value is - * increased according to the size of the dump I/O buffer, because - * parallel lzjb performs better with faster disks. For buffers >= 1MB - * the threshold is 3X; for buffers >= 256K threshold is 2X. - * * For parallel dumps, the number of helpers is ncpu-1. The CPU * running panic runs the main task. For single-threaded dumps, the * panic CPU does lzjb compression (it is tagged as MAINHELPER.) * * Need multiple buffers per helper so that they do not block waiting --- 484,493 ----
*** 541,551 **** */ static void dump_update_clevel() { int tag; - size_t bz2size; helper_t *hp, *hpend; cbuf_t *cp, *cpend; dumpcfg_t *old = &dumpcfg; dumpcfg_t newcfg = *old; dumpcfg_t *new = &newcfg; --- 499,508 ----
*** 594,637 **** new->nhelper = 1; if (new->nhelper > DUMP_MAX_NHELPER) new->nhelper = DUMP_MAX_NHELPER; ! /* use platform default, unless /etc/system overrides */ ! if (dump_plat_mincpu == MINCPU_NOT_SET) ! dump_plat_mincpu = dump_plat_mincpu_default; ! ! /* increase threshold for faster disks */ ! new->threshold = dump_plat_mincpu; ! if (dumpbuf.iosize >= DUMP_1MB) ! new->threshold *= 3; ! else if (dumpbuf.iosize >= (256 * DUMP_1KB)) ! new->threshold *= 2; ! ! /* figure compression level based upon the computed threshold. */ ! if (dump_plat_mincpu == 0 || new->nhelper < 2) { ! new->clevel = 0; new->nhelper = 1; - } else if ((new->nhelper + 1) >= new->threshold) { - new->clevel = DUMP_CLEVEL_BZIP2; - } else { - new->clevel = DUMP_CLEVEL_LZJB; - } - - if (new->clevel == 0) { new->ncbuf = 1; new->ncmap = 1; } else { new->ncbuf = NCBUF_PER_HELPER * new->nhelper; new->ncmap = NCMAP_PER_HELPER * new->nhelper; } /* * Allocate new data structures and buffers for MINHELPERS, * and also figure the max desired size. */ - bz2size = BZ2_bzCompressInitSize(dump_bzip2_level); new->maxsize = 0; new->maxvmsize = 0; new->maxvm = NULL; tag = 1; new->helper = kmem_zalloc(new->nhelper * sizeof (helper_t), KM_SLEEP); --- 551,576 ---- new->nhelper = 1; if (new->nhelper > DUMP_MAX_NHELPER) new->nhelper = DUMP_MAX_NHELPER; ! /* If dump_ncpu_low is 0 or greater than ncpus, do serial dump */ ! if (dump_ncpu_low == 0 || dump_ncpu_low > ncpus || new->nhelper < 2) { ! new->clevel = DUMP_CLEVEL_SERIAL; new->nhelper = 1; new->ncbuf = 1; new->ncmap = 1; } else { + new->clevel = DUMP_CLEVEL_LZJB; new->ncbuf = NCBUF_PER_HELPER * new->nhelper; new->ncmap = NCMAP_PER_HELPER * new->nhelper; } /* * Allocate new data structures and buffers for MINHELPERS, * and also figure the max desired size. */ new->maxsize = 0; new->maxvmsize = 0; new->maxvm = NULL; tag = 1; new->helper = kmem_zalloc(new->nhelper * sizeof (helper_t), KM_SLEEP);
*** 639,655 **** for (hp = new->helper; hp != hpend; hp++) { hp->tag = tag++; if (hp < &new->helper[MINHELPERS]) { hp->lzbuf = kmem_alloc(PAGESIZE, KM_SLEEP); hp->page = kmem_alloc(PAGESIZE, KM_SLEEP); - } else if (new->clevel < DUMP_CLEVEL_BZIP2) { - new->maxsize += 2 * PAGESIZE; } else { ! new->maxsize += PAGESIZE; } - if (new->clevel >= DUMP_CLEVEL_BZIP2) - new->maxsize += bz2size; } new->cbuf = kmem_zalloc(new->ncbuf * sizeof (cbuf_t), KM_SLEEP); cpend = &new->cbuf[new->ncbuf]; for (cp = new->cbuf; cp != cpend; cp++) { --- 578,590 ---- for (hp = new->helper; hp != hpend; hp++) { hp->tag = tag++; if (hp < &new->helper[MINHELPERS]) { hp->lzbuf = kmem_alloc(PAGESIZE, KM_SLEEP); hp->page = kmem_alloc(PAGESIZE, KM_SLEEP); } else { ! new->maxsize += 2 * PAGESIZE; } } new->cbuf = kmem_zalloc(new->ncbuf * sizeof (cbuf_t), KM_SLEEP); cpend = &new->cbuf[new->ncbuf]; for (cp = new->cbuf; cp != cpend; cp++) {
*** 798,832 **** return (BT_TEST(dumpcfg.rbitmap, rbitnum)); } /* - * dumpbzalloc and dumpbzfree are callbacks from the bzip2 library. - * dumpsys_get_maxmem() uses them for BZ2_bzCompressInit(). - */ - static void * - dumpbzalloc(void *opaque, int items, int size) - { - size_t *sz; - char *ret; - - ASSERT(opaque != NULL); - sz = opaque; - ret = dumpcfg.maxvm + *sz; - *sz += items * size; - *sz = P2ROUNDUP(*sz, BZ2_BZALLOC_ALIGN); - ASSERT(*sz <= dumpcfg.maxvmsize); - return (ret); - } - - /*ARGSUSED*/ - static void - dumpbzfree(void *opaque, void *addr) - { - } - - /* * Perform additional checks on the page to see if we can really use * it. The kernel (kas) pages are always set in the bitmap. However, * boot memory pages (prom_ppages or P_BOOTPAGES) are not in the * bitmap. So we check for them. */ --- 733,742 ----
*** 861,873 **** return (1); } /* * dumpsys_get_maxmem() is called during panic. Find unused ranges ! * and use them for buffers. If we find enough memory switch to ! * parallel bzip2, otherwise use parallel lzjb. ! * * It searches the dump bitmap in 2 passes. The first time it looks * for CBUF_MAPSIZE ranges. On the second pass it uses small pages. */ static void dumpsys_get_maxmem() --- 771,781 ---- return (1); } /* * dumpsys_get_maxmem() is called during panic. Find unused ranges ! * and use them for buffers. * It searches the dump bitmap in 2 passes. The first time it looks * for CBUF_MAPSIZE ranges. On the second pass it uses small pages. */ static void dumpsys_get_maxmem()
*** 874,908 **** { dumpcfg_t *cfg = &dumpcfg; cbuf_t *endcp = &cfg->cbuf[cfg->ncbuf]; helper_t *endhp = &cfg->helper[cfg->nhelper]; pgcnt_t bitnum, end; ! size_t sz, endsz, bz2size; pfn_t pfn, off; cbuf_t *cp; ! helper_t *hp, *ohp; dumpmlw_t mlw; int k; /* ! * Setting dump_plat_mincpu to 0 at any time forces a serial ! * dump. */ ! if (dump_plat_mincpu == 0) { ! cfg->clevel = 0; return; } /* * There may be no point in looking for spare memory. If * dumping all memory, then none is spare. If doing a serial * dump, then already have buffers. */ ! if (cfg->maxsize == 0 || cfg->clevel < DUMP_CLEVEL_LZJB || (dump_conflags & DUMP_ALL) != 0) { - if (cfg->clevel > DUMP_CLEVEL_LZJB) - cfg->clevel = DUMP_CLEVEL_LZJB; return; } sz = 0; cfg->found4m = 0; --- 782,813 ---- { dumpcfg_t *cfg = &dumpcfg; cbuf_t *endcp = &cfg->cbuf[cfg->ncbuf]; helper_t *endhp = &cfg->helper[cfg->nhelper]; pgcnt_t bitnum, end; ! size_t sz, endsz; pfn_t pfn, off; cbuf_t *cp; ! helper_t *hp; dumpmlw_t mlw; int k; /* ! * Setting dump_ncpu_low to 0 forces a single threaded dump. */ ! if (dump_ncpu_low == 0) { ! cfg->clevel = DUMP_CLEVEL_SERIAL; return; } /* * There may be no point in looking for spare memory. If * dumping all memory, then none is spare. If doing a serial * dump, then already have buffers. */ ! if (cfg->maxsize == 0 || cfg->clevel == DUMP_CLEVEL_SERIAL || (dump_conflags & DUMP_ALL) != 0) { return; } sz = 0; cfg->found4m = 0;
*** 982,1041 **** if (sz >= cfg->maxsize) goto foundmax; } } - /* Fall back to lzjb if we did not get enough memory for bzip2. */ - endsz = (cfg->maxsize * cfg->threshold) / cfg->nhelper; - if (sz < endsz) { - cfg->clevel = DUMP_CLEVEL_LZJB; - } - /* Allocate memory for as many helpers as we can. */ foundmax: /* Byte offsets into memory found and mapped above */ endsz = sz; sz = 0; - /* Set the size for bzip2 state. Only bzip2 needs it. */ - bz2size = BZ2_bzCompressInitSize(dump_bzip2_level); - /* Skip the preallocate output buffers. */ cp = &cfg->cbuf[MINCBUFS]; - /* Use this to move memory up from the preallocated helpers. */ - ohp = cfg->helper; - /* Loop over all helpers and allocate memory. */ for (hp = cfg->helper; hp < endhp; hp++) { /* Skip preallocated helpers by checking hp->page. */ if (hp->page == NULL) { - if (cfg->clevel <= DUMP_CLEVEL_LZJB) { /* lzjb needs 2 1-page buffers */ if ((sz + (2 * PAGESIZE)) > endsz) break; hp->page = cfg->maxvm + sz; sz += PAGESIZE; hp->lzbuf = cfg->maxvm + sz; sz += PAGESIZE; - - } else if (ohp->lzbuf != NULL) { - /* re-use the preallocted lzjb page for bzip2 */ - hp->page = ohp->lzbuf; - ohp->lzbuf = NULL; - ++ohp; - - } else { - /* bzip2 needs a 1-page buffer */ - if ((sz + PAGESIZE) > endsz) - break; - hp->page = cfg->maxvm + sz; - sz += PAGESIZE; } - } /* * Add output buffers per helper. The number of * buffers per helper is determined by the ratio of * ncbuf to nhelper. --- 887,919 ----
*** 1046,1075 **** cp->size = CBUF_SIZE; cp->buf = cfg->maxvm + sz; sz += CBUF_SIZE; ++cp; } - - /* - * bzip2 needs compression state. Use the dumpbzalloc - * and dumpbzfree callbacks to allocate the memory. - * bzip2 does allocation only at init time. - */ - if (cfg->clevel >= DUMP_CLEVEL_BZIP2) { - if ((sz + bz2size) > endsz) { - hp->page = NULL; - break; - } else { - hp->bzstream.opaque = &sz; - hp->bzstream.bzalloc = dumpbzalloc; - hp->bzstream.bzfree = dumpbzfree; - (void) BZ2_bzCompressInit(&hp->bzstream, - dump_bzip2_level, 0, 0); - hp->bzstream.opaque = NULL; } - } - } /* Finish allocating output buffers */ for (; cp < endcp && (sz + CBUF_SIZE) <= endsz; cp++) { cp->state = CBUF_FREEBUF; cp->size = CBUF_SIZE; --- 924,934 ----
*** 1908,1919 **** /* * Done with the input. Flush the VM and * return the buffer to the main task. */ if (panicstr && hp->helper != MAINHELPER) ! hat_flush_range(kas.a_hat, ! hp->cpin->buf, hp->cpin->size); dumpsys_errmsg(hp, NULL); CQ_PUT(mainq, hp->cpin, CBUF_USEDMAP); hp->cpin = NULL; } } --- 1767,1777 ---- /* * Done with the input. Flush the VM and * return the buffer to the main task. */ if (panicstr && hp->helper != MAINHELPER) ! hat_flush(); dumpsys_errmsg(hp, NULL); CQ_PUT(mainq, hp->cpin, CBUF_USEDMAP); hp->cpin = NULL; } }
*** 1920,2059 **** return (hp->cpin != NULL); } /* - * Compress size bytes starting at buf with bzip2 - * mode: - * BZ_RUN add one more compressed page - * BZ_FINISH no more input, flush the state - */ - static void - dumpsys_bzrun(helper_t *hp, void *buf, size_t size, int mode) - { - dumpsync_t *ds = hp->ds; - const int CSIZE = sizeof (dumpcsize_t); - bz_stream *ps = &hp->bzstream; - int rc = 0; - uint32_t csize; - dumpcsize_t cs; - - /* Set input pointers to new input page */ - if (size > 0) { - ps->avail_in = size; - ps->next_in = buf; - } - - /* CONSTCOND */ - while (1) { - - /* Quit when all input has been consumed */ - if (ps->avail_in == 0 && mode == BZ_RUN) - break; - - /* Get a new output buffer */ - if (hp->cpout == NULL) { - HRSTART(hp->perpage, outwait); - hp->cpout = CQ_GET(freebufq); - HRSTOP(hp->perpage, outwait); - ps->avail_out = hp->cpout->size - CSIZE; - ps->next_out = hp->cpout->buf + CSIZE; - } - - /* Compress input, or finalize */ - HRSTART(hp->perpage, compress); - rc = BZ2_bzCompress(ps, mode); - HRSTOP(hp->perpage, compress); - - /* Check for error */ - if (mode == BZ_RUN && rc != BZ_RUN_OK) { - dumpsys_errmsg(hp, "%d: BZ_RUN error %s at page %lx\n", - hp->helper, BZ2_bzErrorString(rc), - hp->cpin->pagenum); - break; - } - - /* Write the buffer if it is full, or we are flushing */ - if (ps->avail_out == 0 || mode == BZ_FINISH) { - csize = hp->cpout->size - CSIZE - ps->avail_out; - cs = DUMP_SET_TAG(csize, hp->tag); - if (csize > 0) { - (void) memcpy(hp->cpout->buf, &cs, CSIZE); - dumpsys_swrite(hp, hp->cpout, csize + CSIZE); - hp->cpout = NULL; - } - } - - /* Check for final complete */ - if (mode == BZ_FINISH) { - if (rc == BZ_STREAM_END) - break; - if (rc != BZ_FINISH_OK) { - dumpsys_errmsg(hp, "%d: BZ_FINISH error %s\n", - hp->helper, BZ2_bzErrorString(rc)); - break; - } - } - } - - /* Cleanup state and buffers */ - if (mode == BZ_FINISH) { - - /* Reset state so that it is re-usable. */ - (void) BZ2_bzCompressReset(&hp->bzstream); - - /* Give any unused outout buffer to the main task */ - if (hp->cpout != NULL) { - hp->cpout->used = 0; - CQ_PUT(mainq, hp->cpout, CBUF_ERRMSG); - hp->cpout = NULL; - } - } - } - - static void - dumpsys_bz2compress(helper_t *hp) - { - dumpsync_t *ds = hp->ds; - dumpstreamhdr_t sh; - - (void) strcpy(sh.stream_magic, DUMP_STREAM_MAGIC); - sh.stream_pagenum = (pgcnt_t)-1; - sh.stream_npages = 0; - hp->cpin = NULL; - hp->cpout = NULL; - hp->cperr = NULL; - hp->in = 0; - hp->out = 0; - hp->bzstream.avail_in = 0; - - /* Bump reference to mainq while we are running */ - CQ_OPEN(mainq); - - /* Get one page at a time */ - while (dumpsys_sread(hp)) { - if (sh.stream_pagenum != hp->cpin->pagenum) { - sh.stream_pagenum = hp->cpin->pagenum; - sh.stream_npages = btop(hp->cpin->used); - dumpsys_bzrun(hp, &sh, sizeof (sh), BZ_RUN); - } - dumpsys_bzrun(hp, hp->page, PAGESIZE, 0); - } - - /* Done with input, flush any partial buffer */ - if (sh.stream_pagenum != (pgcnt_t)-1) { - dumpsys_bzrun(hp, NULL, 0, BZ_FINISH); - dumpsys_errmsg(hp, NULL); - } - - ASSERT(hp->cpin == NULL && hp->cpout == NULL && hp->cperr == NULL); - - /* Decrement main queue count, we are done */ - CQ_CLOSE(mainq); - } - - /* * Compress with lzjb * write stream block if full or size==0 * if csize==0 write stream header, else write <csize, data> * size==0 is a call to flush a buffer * hp->cpout is the buffer we are flushing or filling --- 1778,1787 ----
*** 2191,2208 **** for (hp = dumpcfg.helper; hp != hpend; hp++) { if (hp->helper == FREEHELPER) { hp->helper = CPU->cpu_id; BT_SET(dumpcfg.helpermap, CPU->cpu_seqid); - dumpsys_spinunlock(&dumpcfg.helper_lock); - - if (dumpcfg.clevel < DUMP_CLEVEL_BZIP2) dumpsys_lzjbcompress(hp); - else - dumpsys_bz2compress(hp); - hp->helper = DONEHELPER; return; } } --- 1919,1930 ----
*** 2235,2248 **** dumpsys_live_helper(void *arg) { helper_t *hp = arg; BT_ATOMIC_SET(dumpcfg.helpermap, CPU->cpu_seqid); - if (dumpcfg.clevel < DUMP_CLEVEL_BZIP2) dumpsys_lzjbcompress(hp); - else - dumpsys_bz2compress(hp); } /* * Compress one page with lzjb (single threaded case) */ --- 1957,1967 ----
*** 2285,2317 **** pgcnt_t pagenum = 0, bitnum = 0, hibitnum; dumpmlw_t mlw; cbuf_t *cp; pgcnt_t baseoff, pfnoff; pfn_t base, pfn; ! int i, dumpserial; /* * Fall back to serial mode if there are no helpers. ! * dump_plat_mincpu can be set to 0 at any time. * dumpcfg.helpermap must contain at least one member. */ ! dumpserial = 1; ! if (dump_plat_mincpu != 0 && dumpcfg.clevel != 0) { for (i = 0; i < BT_BITOUL(NCPU); ++i) { if (dumpcfg.helpermap[i] != 0) { ! dumpserial = 0; break; } } } if (dumpserial) { ! dumpcfg.clevel = 0; ! if (dumpcfg.helper[0].lzbuf == NULL) ! dumpcfg.helper[0].lzbuf = dumpcfg.helper[1].page; } dump_init_memlist_walker(&mlw); for (;;) { int sec = (gethrtime() - ds->start) / NANOSEC; --- 2004,2052 ---- pgcnt_t pagenum = 0, bitnum = 0, hibitnum; dumpmlw_t mlw; cbuf_t *cp; pgcnt_t baseoff, pfnoff; pfn_t base, pfn; ! int i; /* * Fall back to serial mode if there are no helpers. ! * dump_ncpu_low can be set to 0 at any time. * dumpcfg.helpermap must contain at least one member. + * + * It is possible that the helpers haven't registered + * in helpermap yet; wait up to DUMP_HELPER_MAX_WAIT. */ ! if (dump_ncpu_low != 0 && dumpcfg.clevel != DUMP_CLEVEL_SERIAL) { ! boolean_t dumpserial = B_TRUE; ! hrtime_t hrtmax = MSEC2NSEC(DUMP_HELPER_MAX_WAIT); ! hrtime_t hrtstart = gethrtime(); ! for (;;) { for (i = 0; i < BT_BITOUL(NCPU); ++i) { if (dumpcfg.helpermap[i] != 0) { ! dumpserial = B_FALSE; break; } } + + if ((!dumpserial) || + ((gethrtime() - hrtstart) >= hrtmax)) { + break; } + ht_pause(); + } + if (dumpserial) { ! dumpcfg.clevel = DUMP_CLEVEL_SERIAL; ! if (dumpcfg.helper[0].lzbuf == NULL) { ! dumpcfg.helper[0].lzbuf = ! dumpcfg.helper[1].page; } + } + } dump_init_memlist_walker(&mlw); for (;;) { int sec = (gethrtime() - ds->start) / NANOSEC;
*** 2449,2465 **** /* * If there are no helpers the main task does * non-streams lzjb compress. */ ! if (dumpserial) { dumpsys_lzjb_page(dumpcfg.helper, cp); ! break; ! } ! /* pass mapped pages to a helper */ CQ_PUT(helperq, cp, CBUF_INREADY); /* the last page was done */ if (bitnum >= dumpcfg.bitmapsize) CQ_CLOSE(helperq); --- 2184,2199 ---- /* * If there are no helpers the main task does * non-streams lzjb compress. */ ! if (dumpcfg.clevel == DUMP_CLEVEL_SERIAL) { dumpsys_lzjb_page(dumpcfg.helper, cp); ! } else { /* pass mapped pages to a helper */ CQ_PUT(helperq, cp, CBUF_INREADY); + } /* the last page was done */ if (bitnum >= dumpcfg.bitmapsize) CQ_CLOSE(helperq);
*** 2561,2572 **** P("Found %ldM ranges,%ld\n", (CBUF_MAPSIZE / DUMP_1MB), cfg->found4m); P("Found small pages,%ld\n", cfg->foundsm); P("Compression level,%d\n", cfg->clevel); ! P("Compression type,%s %s\n", cfg->clevel == 0 ? "serial" : "parallel", ! cfg->clevel >= DUMP_CLEVEL_BZIP2 ? "bzip2" : "lzjb"); P("Compression ratio,%d.%02d\n", compress_ratio / 100, compress_ratio % 100); P("nhelper_used,%d\n", cfg->nhelper_used); P("Dump I/O rate MBS,%d.%02d\n", iorate / 100, iorate % 100); --- 2295,2306 ---- P("Found %ldM ranges,%ld\n", (CBUF_MAPSIZE / DUMP_1MB), cfg->found4m); P("Found small pages,%ld\n", cfg->foundsm); P("Compression level,%d\n", cfg->clevel); ! P("Compression type,%s lzjb\n", ! cfg->clevel == DUMP_CLEVEL_SERIAL ? "serial" : "parallel"); P("Compression ratio,%d.%02d\n", compress_ratio / 100, compress_ratio % 100); P("nhelper_used,%d\n", cfg->nhelper_used); P("Dump I/O rate MBS,%d.%02d\n", iorate / 100, iorate % 100);
*** 2670,2680 **** dumphdr->dump_flags &= ~DF_LIVE; (void) VOP_DUMPCTL(dumpvp, DUMP_FREE, NULL, NULL); (void) VOP_DUMPCTL(dumpvp, DUMP_ALLOC, NULL, NULL); (void) vsnprintf(dumphdr->dump_panicstring, DUMP_PANICSIZE, panicstr, panicargs); ! } if (dump_conflags & DUMP_ALL) content = "all"; else if (dump_conflags & DUMP_CURPROC) --- 2404,2415 ---- dumphdr->dump_flags &= ~DF_LIVE; (void) VOP_DUMPCTL(dumpvp, DUMP_FREE, NULL, NULL); (void) VOP_DUMPCTL(dumpvp, DUMP_ALLOC, NULL, NULL); (void) vsnprintf(dumphdr->dump_panicstring, DUMP_PANICSIZE, panicstr, panicargs); ! (void) strncpy(dumphdr->dump_uuid, dump_get_uuid(), ! sizeof (dumphdr->dump_uuid)); } if (dump_conflags & DUMP_ALL) content = "all"; else if (dump_conflags & DUMP_CURPROC)
*** 2715,2729 **** * Store a hires timestamp so we can look it up during debugging. */ lbolt_debug_entry(); /* ! * Leave room for the message and ereport save areas and terminal dump ! * header. */ dumpbuf.vp_limit = dumpvp_size - DUMP_LOGSIZE - DUMP_OFFSET - ! DUMP_ERPTSIZE; /* * Write out the symbol table. It's no longer compressed, * so its 'size' and 'csize' are equal. */ --- 2450,2464 ---- * Store a hires timestamp so we can look it up during debugging. */ lbolt_debug_entry(); /* ! * Leave room for the summary, message and ereport save areas ! * and terminal dump header. */ dumpbuf.vp_limit = dumpvp_size - DUMP_LOGSIZE - DUMP_OFFSET - ! DUMP_ERPTSIZE - DUMP_SUMMARYSIZE; /* * Write out the symbol table. It's no longer compressed, * so its 'size' and 'csize' are equal. */
*** 2823,2840 **** * Cooperate with any helpers running on CPUs in panic_idle(). */ dumphdr->dump_data = dumpvp_flush(); bzero(dumpcfg.helpermap, BT_SIZEOFMAP(NCPU)); ! ds->live = dumpcfg.clevel > 0 && (dumphdr->dump_flags & DF_LIVE) != 0; save_dump_clevel = dumpcfg.clevel; if (panicstr) dumpsys_get_maxmem(); - else if (dumpcfg.clevel >= DUMP_CLEVEL_BZIP2) - dumpcfg.clevel = DUMP_CLEVEL_LZJB; dumpcfg.nhelper_used = 0; for (hp = dumpcfg.helper; hp != hpend; hp++) { if (hp->page == NULL) { hp->helper = DONEHELPER; --- 2558,2573 ---- * Cooperate with any helpers running on CPUs in panic_idle(). */ dumphdr->dump_data = dumpvp_flush(); bzero(dumpcfg.helpermap, BT_SIZEOFMAP(NCPU)); ! ds->live = dumpcfg.clevel > DUMP_CLEVEL_SERIAL && (dumphdr->dump_flags & DF_LIVE) != 0; save_dump_clevel = dumpcfg.clevel; if (panicstr) dumpsys_get_maxmem(); dumpcfg.nhelper_used = 0; for (hp = dumpcfg.helper; hp != hpend; hp++) { if (hp->page == NULL) { hp->helper = DONEHELPER;
*** 2843,2854 **** ++dumpcfg.nhelper_used; hp->helper = FREEHELPER; hp->taskqid = NULL; hp->ds = ds; bzero(&hp->perpage, sizeof (hp->perpage)); - if (dumpcfg.clevel >= DUMP_CLEVEL_BZIP2) - (void) BZ2_bzCompressReset(&hp->bzstream); } CQ_OPEN(freebufq); CQ_OPEN(helperq); --- 2576,2585 ----
*** 2882,2892 **** } } else { if (panicstr) kmem_dump_begin(); ! dumpcfg.helpers_wanted = dumpcfg.clevel > 0; dumpsys_spinunlock(&dumpcfg.helper_lock); } /* run main task */ dumpsys_main_task(ds); --- 2613,2623 ---- } } else { if (panicstr) kmem_dump_begin(); ! dumpcfg.helpers_wanted = dumpcfg.clevel > DUMP_CLEVEL_SERIAL; dumpsys_spinunlock(&dumpcfg.helper_lock); } /* run main task */ dumpsys_main_task(ds);
*** 3043,3063 **** dumpvp_size = vattr.va_size & -DUMP_OFFSET; mutex_exit(&dump_lock); return (0); } ! int ! dump_set_uuid(const char *uuidstr) { const char *ptr; int i; ! if (uuidstr == NULL || strnlen(uuidstr, 36 + 1) != 36) return (EINVAL); /* uuid_parse is not common code so check manually */ ! for (i = 0, ptr = uuidstr; i < 36; i++, ptr++) { switch (i) { case 8: case 13: case 18: case 23: --- 2774,2796 ---- dumpvp_size = vattr.va_size & -DUMP_OFFSET; mutex_exit(&dump_lock); return (0); } ! static int ! dump_validate_uuid(const char *uuidstr) { const char *ptr; int i; ! if (uuidstr == NULL || strlen(uuidstr) != ! UUID_PRINTABLE_STRING_LENGTH - 1) return (EINVAL); /* uuid_parse is not common code so check manually */ ! for (i = 0, ptr = uuidstr; i < UUID_PRINTABLE_STRING_LENGTH - 1; ! i++, ptr++) { switch (i) { case 8: case 13: case 18: case 23:
*** 3070,3083 **** return (EINVAL); break; } } if (dump_osimage_uuid[0] != '\0') return (EALREADY); ! (void) strncpy(dump_osimage_uuid, uuidstr, 36 + 1); cmn_err(CE_CONT, "?This Solaris instance has UUID %s\n", dump_osimage_uuid); return (0); --- 2803,2840 ---- return (EINVAL); break; } } + return (0); + } + + int + dump_update_uuid(const char *uuidstr) + { + + if (dump_validate_uuid(uuidstr) != 0 || dumphdr == NULL) + return (EINVAL); + + bzero(dumphdr->dump_uuid, sizeof (dumphdr->dump_uuid)); + (void) strncpy(dumphdr->dump_uuid, uuidstr, + sizeof (dumphdr->dump_uuid)); + + return (0); + } + + int + dump_set_uuid(const char *uuidstr) + { + if (dump_validate_uuid(uuidstr) != 0) + return (EINVAL); + if (dump_osimage_uuid[0] != '\0') return (EALREADY); ! (void) strncpy(dump_osimage_uuid, uuidstr, ! UUID_PRINTABLE_STRING_LENGTH); cmn_err(CE_CONT, "?This Solaris instance has UUID %s\n", dump_osimage_uuid); return (0);