Print this page
10654 savecore(1M) should be able to work on read-only dump devices
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: John Levon <john.levon@joyent.com>
Reviewed by: Andy Stormont <astormont@racktopsystems.com>
Reviewed by: Gergő Doma <domag02@gmail.com>
Reviewed by: Toomas Soome <tsoome@me.com>
@@ -18,11 +18,11 @@
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
*/
/*
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
*/
@@ -90,10 +90,11 @@
static volatile uint64_t zpages; /* count of zero pages not written */
static dumpdatahdr_t datahdr; /* compression info */
static long coreblksize; /* preferred write size (st_blksize) */
static int cflag; /* run as savecore -c */
static int mflag; /* run as savecore -m */
+static int rflag; /* run as savecore -r */
/*
* Payload information for the events we raise. These are used
* in raise_event to determine what payload to include.
*/
@@ -162,11 +163,11 @@
static void
usage(void)
{
(void) fprintf(stderr,
- "usage: %s [-Lvd] [-f dumpfile] [dirname]\n", progname);
+ "usage: %s [-L | -r] [-vd] [-f dumpfile] [dirname]\n", progname);
exit(1);
}
#define SC_SL_NONE 0x0001 /* no syslog */
#define SC_SL_ERR 0x0002 /* syslog if !interactive, LOG_ERR */
@@ -227,11 +228,11 @@
/*
* Raise an ireport saying why we are exiting. Do not
* raise if run as savecore -m. If something in the
* raise_event codepath calls logprint avoid recursion.
*/
- if (!mflag && logprint_raised++ == 0)
+ if (!mflag && !rflag && logprint_raised++ == 0)
raise_event(SC_EVENT_SAVECORE_FAILURE, buf);
code = 2;
break;
case SC_EXIT_FM:
@@ -238,11 +239,11 @@
code = 3;
break;
case SC_EXIT_ERR:
default:
- if (!mflag && logprint_raised++ == 0 && have_dumpfile)
+ if (!mflag && !rflag && logprint_raised++ == 0 && have_dumpfile)
raise_event(SC_EVENT_SAVECORE_FAILURE, buf);
code = 1;
break;
}
@@ -353,11 +354,11 @@
}
static void
read_dumphdr(void)
{
- if (filemode)
+ if (filemode || rflag)
dumpfd = Open(dumpfile, O_RDONLY, 0644);
else
dumpfd = Open(dumpfile, O_RDWR | O_DSYNC, 0644);
endoff = llseek(dumpfd, -DUMP_OFFSET, SEEK_END) & -DUMP_OFFSET;
Pread(dumpfd, &dumphdr, sizeof (dumphdr), endoff);
@@ -406,11 +407,11 @@
if (memcmp(&corehdr, &dumphdr, sizeof (dumphdr_t)) != 0) {
/*
* Clear valid bit so we don't complain on every invocation.
*/
- if (!filemode)
+ if (!filemode && !rflag)
Pwrite(dumpfd, &dumphdr, sizeof (dumphdr), endoff);
logprint(SC_SL_ERR | SC_EXIT_ERR,
"initial dump header corrupt");
}
}
@@ -658,11 +659,11 @@
/*
* Write out the modified dump header to the dump device.
* The dump device has been processed, so DF_VALID is clear.
*/
- if (!filemode)
+ if (!filemode && !rflag)
Pwrite(dumpfd, &dumphdr, sizeof (dumphdr), endoff);
(void) close(corefd);
}
@@ -1420,11 +1421,11 @@
/*
* Write out the modified dump headers.
*/
Pwrite(corefd, &corehdr, sizeof (corehdr), 0);
- if (!filemode)
+ if (!filemode && !rflag)
Pwrite(dumpfd, &dumphdr, sizeof (dumphdr), endoff);
(void) close(corefd);
}
@@ -1529,10 +1530,13 @@
summary_dump_t sd;
offset_t dumpoff = -(DUMP_OFFSET + DUMP_LOGSIZE +
DUMP_ERPTSIZE);
dumpoff -= DUMP_SUMMARYSIZE;
+ if (rflag)
+ dumpfd = Open(dumpfile, O_RDONLY, 0644);
+ else
dumpfd = Open(dumpfile, O_RDWR | O_DSYNC, 0644);
dumpoff = llseek(dumpfd, dumpoff, SEEK_END) & -DUMP_OFFSET;
Pread(dumpfd, &sd, sizeof (summary_dump_t), dumpoff);
dumpoff += sizeof (summary_dump_t);
@@ -1666,11 +1670,11 @@
(void) defopen("/etc/dumpadm.conf");
savedir = defread("DUMPADM_SAVDIR=");
if (savedir != NULL)
savedir = strdup(savedir);
- while ((c = getopt(argc, argv, "Lvcdmf:")) != EOF) {
+ while ((c = getopt(argc, argv, "Lvcdmf:r")) != EOF) {
switch (c) {
case 'L':
livedump++;
break;
case 'v':
@@ -1683,10 +1687,13 @@
disregard_valid_flag++;
break;
case 'm':
mflag++;
break;
+ case 'r':
+ rflag++;
+ break;
case 'f':
dumpfile = optarg;
filebounds = getbounds(dumpfile);
break;
case '?':
@@ -1707,10 +1714,13 @@
interactive = isatty(STDOUT_FILENO);
if (cflag && livedump)
usage();
+ if (rflag && (cflag || mflag || livedump))
+ usage();
+
if (dumpfile == NULL || livedump)
dumpfd = Open("/dev/dump", O_RDONLY, 0444);
if (dumpfile == NULL) {
dumpfile = Zalloc(MAXPATHLEN);
@@ -1750,11 +1760,11 @@
* We want this message to go to the log file, but not the console.
* There's no good way to do that with the existing syslog facility.
* We could extend it to handle this, but there doesn't seem to be
* a general need for it, so we isolate the complexity here instead.
*/
- if (dumphdr.dump_panicstring[0] != '\0') {
+ if (dumphdr.dump_panicstring[0] != '\0' && !rflag) {
int logfd = Open("/dev/conslog", O_WRONLY, 0644);
log_ctl_t lc;
struct strbuf ctl, dat;
char msg[DUMP_PANICSIZE + 100];
char fmt[] = "reboot after panic: %s";
@@ -1799,11 +1809,11 @@
* ereports off the dump device independently of savecore and
* will make a diagnosis, so we don't want to open two cases
* for the same event. Also avoid raising an event for a
* livedump, or when we inflating a compressed dump.
*/
- if (!fm_panic && !livedump && !filemode)
+ if (!fm_panic && !livedump && !filemode && !rflag)
raise_event(SC_EVENT_DUMP_PENDING, NULL);
logprint(SC_SL_WARN, "System dump time: %s",
ctime(&dumphdr.dump_crashtime));
@@ -1855,11 +1865,11 @@
/*
* Raise a fault management event that indicates the system
* has panicked. We know a reasonable amount about the
* condition at this time, but the dump is still compressed.
*/
- if (!livedump && !fm_panic)
+ if (!livedump && !fm_panic && !rflag)
raise_event(SC_EVENT_DUMP_AVAILABLE, NULL);
if (metrics_size > 0) {
int sec = (gethrtime() - startts) / 1000 / 1000 / 1000;
FILE *mfile = fopen(METRICSFILE, "a");
@@ -1924,11 +1934,11 @@
"saving system crash dump in %s/{unix,vmcore}.%ld",
savedir, bounds);
build_corefile(namelist, corefile);
- if (!livedump && !filemode && !fm_panic)
+ if (!livedump && !filemode && !fm_panic && !rflag)
raise_event(SC_EVENT_DUMP_AVAILABLE, NULL);
if (access(METRICSFILE, F_OK) == 0) {
int sec = (gethrtime() - startts) / 1000 / 1000 / 1000;
FILE *mfile = fopen(METRICSFILE, "a");