From owner-svn-src-head@FreeBSD.ORG Sun Dec 16 23:06:13 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 7D1FDDE2; Sun, 16 Dec 2012 23:06:13 +0000 (UTC) (envelope-from pjd@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 616548FC14; Sun, 16 Dec 2012 23:06:13 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qBGN6DT7069282; Sun, 16 Dec 2012 23:06:13 GMT (envelope-from pjd@svn.freebsd.org) Received: (from pjd@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qBGN6CZR069280; Sun, 16 Dec 2012 23:06:12 GMT (envelope-from pjd@svn.freebsd.org) Message-Id: <201212162306.qBGN6CZR069280@svn.freebsd.org> From: Pawel Jakub Dawidek Date: Sun, 16 Dec 2012 23:06:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r244320 - head/sbin/savecore X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 16 Dec 2012 23:06:13 -0000 Author: pjd Date: Sun Dec 16 23:06:12 2012 New Revision: 244320 URL: http://svnweb.freebsd.org/changeset/base/244320 Log: Implement -m option to savecore(8) that allows to limit number of kernel dumps stored. Once the limit is reached it restarts from 0. Reviewed by: avg Obtained from: WHEEL Systems Modified: head/sbin/savecore/savecore.8 head/sbin/savecore/savecore.c Modified: head/sbin/savecore/savecore.8 ============================================================================== --- head/sbin/savecore/savecore.8 Sun Dec 16 23:04:31 2012 (r244319) +++ head/sbin/savecore/savecore.8 Sun Dec 16 23:06:12 2012 (r244320) @@ -28,7 +28,7 @@ .\" From: @(#)savecore.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd December 14, 2012 +.Dd December 17, 2012 .Dt SAVECORE 8 .Os .Sh NAME @@ -45,6 +45,7 @@ .Op Ar device ... .Nm .Op Fl fkvz +.Op Fl m Ar maxdumps .Op Ar directory Op Ar device ... .Sh DESCRIPTION The @@ -59,7 +60,7 @@ and enters a reboot message and informat the system log. .Pp The options are as follows: -.Bl -tag -width indent +.Bl -tag -width ".Fl m Ar maxdumps" .It Fl C Check to see if a dump exists, and display a brief message to indicate the status. @@ -77,6 +78,12 @@ Force a dump to be taken even if either dump header information is inconsistent. .It Fl k Do not clear the dump after saving it. +.It Fl m Ar maxdumps +Maximum number of dumps to store. +Once the number of stored dumps is equal to +.Ar maxdumps +the counter will restart from +.Dv 0 . .It Fl v Print out some additional debugging information. Specify twice for more information. Modified: head/sbin/savecore/savecore.c ============================================================================== --- head/sbin/savecore/savecore.c Sun Dec 16 23:04:31 2012 (r244319) +++ head/sbin/savecore/savecore.c Sun Dec 16 23:06:12 2012 (r244320) @@ -90,6 +90,7 @@ __FBSDID("$FreeBSD$"); static int checkfor, compress, clear, force, keep, verbose; /* flags */ static int nfound, nsaved, nerr; /* statistics */ +static int maxdumps; extern FILE *zopen(const char *, const char *); @@ -178,12 +179,62 @@ writebounds(int bounds) { fclose(fp); } +static off_t +file_size(const char *path) +{ + struct stat sb; + + /* Ignore all errors, those file may not exists. */ + if (stat(path, &sb) == -1) + return (0); + return (sb.st_size); +} + +static off_t +saved_dump_size(int bounds) +{ + static char path[PATH_MAX]; + off_t dumpsize; + + dumpsize = 0; + + (void)snprintf(path, sizeof(path), "info.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "vmcore.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds); + dumpsize += file_size(path); + + return (dumpsize); +} + +static void +saved_dump_remove(int bounds) +{ + static char path[PATH_MAX]; + + (void)snprintf(path, sizeof(path), "info.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "vmcore.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds); + (void)unlink(path); +} + /* * Check that sufficient space is available on the disk that holds the * save directory. */ static int -check_space(const char *savedir, off_t dumpsize) +check_space(const char *savedir, off_t dumpsize, int bounds) { FILE *fp; off_t minfree, spacefree, totfree, needed; @@ -208,7 +259,8 @@ check_space(const char *savedir, off_t d } needed = dumpsize / 1024 + 2; /* 2 for info file */ - if (((minfree > 0) ? spacefree : totfree) - needed < minfree) { + needed -= saved_dump_size(bounds); + if ((minfree > 0 ? spacefree : totfree) - needed < minfree) { syslog(LOG_WARNING, "no dump, not enough free space on device (%lld available, need %lld)", (long long)(minfree > 0 ? spacefree : totfree), @@ -367,7 +419,7 @@ DoTextdumpFile(int fd, off_t dumpsize, o static void DoFile(const char *savedir, const char *device) { - static char filename[PATH_MAX]; + static char infoname[PATH_MAX], corename[PATH_MAX]; static char *buf = NULL; struct kerneldumpheader kdhf, kdhl; off_t mediasize, dumpsize, firsthd, lasthd; @@ -382,6 +434,9 @@ DoFile(const char *savedir, const char * mediasize = 0; status = STATUS_UNKNOWN; + if (maxdumps > 0 && bounds == maxdumps) + bounds = 0; + if (buf == NULL) { buf = malloc(BUFFERSIZE); if (buf == NULL) { @@ -535,19 +590,22 @@ DoFile(const char *savedir, const char * if (verbose) printf("Checking for available free space\n"); - if (!check_space(savedir, dumpsize)) { + + if (!check_space(savedir, dumpsize, bounds)) { nerr++; goto closefd; } writebounds(bounds + 1); - snprintf(buf, sizeof(buf), "info.%d", bounds); + saved_dump_remove(bounds); + + snprintf(infoname, sizeof(infoname), "info.%d", bounds); /* * Create or overwrite any existing dump header files. */ - fdinfo = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fdinfo = open(infoname, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fdinfo < 0) { syslog(LOG_ERR, "%s: %m", buf); nerr++; @@ -555,16 +613,16 @@ DoFile(const char *savedir, const char * } oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ if (compress) { - snprintf(filename, sizeof(filename), "%s.%d.gz", + snprintf(corename, sizeof(corename), "%s.%d.gz", istextdump ? "textdump.tar" : "vmcore", bounds); - fp = zopen(filename, "w"); + fp = zopen(corename, "w"); } else { - snprintf(filename, sizeof(filename), "%s.%d", + snprintf(corename, sizeof(corename), "%s.%d", istextdump ? "textdump.tar" : "vmcore", bounds); - fp = fopen(filename, "w"); + fp = fopen(corename, "w"); } if (fp == NULL) { - syslog(LOG_ERR, "%s: %m", filename); + syslog(LOG_ERR, "%s: %m", corename); close(fdinfo); nerr++; goto closefd; @@ -585,15 +643,15 @@ DoFile(const char *savedir, const char * printheader(info, &kdhl, device, bounds, status); fclose(info); - syslog(LOG_NOTICE, "writing %score to %s", - compress ? "compressed " : "", filename); + syslog(LOG_NOTICE, "writing %score to %s/%s", + compress ? "compressed " : "", savedir, corename); if (istextdump) { if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device, - filename, fp) < 0) + corename, fp) < 0) goto closeall; } else { - if (DoRegularFile(fd, dumpsize, buf, device, filename, fp) + if (DoRegularFile(fd, dumpsize, buf, device, corename, fp) < 0) goto closeall; } @@ -601,10 +659,11 @@ DoFile(const char *savedir, const char * printf("\n"); if (fclose(fp) < 0) { - syslog(LOG_ERR, "error on %s: %m", filename); + syslog(LOG_ERR, "error on %s: %m", corename); nerr++; goto closeall; } + nsaved++; if (verbose) @@ -637,8 +696,8 @@ usage(void) fprintf(stderr, "%s\n%s\n%s\n", "usage: savecore -c [-v] [device ...]", " savecore -C [-v] [device ...]", - " savecore [-fkvz] [directory [device ...]]"); - exit (1); + " savecore [-fkvz] [-m maxdumps] [directory [device ...]]"); + exit(1); } int @@ -654,7 +713,7 @@ main(int argc, char **argv) openlog("savecore", LOG_PERROR, LOG_DAEMON); signal(SIGINFO, infohandler); - while ((ch = getopt(argc, argv, "Ccfkvz")) != -1) + while ((ch = getopt(argc, argv, "Ccfkm:vz")) != -1) switch(ch) { case 'C': checkfor = 1; @@ -668,6 +727,13 @@ main(int argc, char **argv) case 'k': keep = 1; break; + case 'm': + maxdumps = atoi(optarg); + if (maxdumps <= 0) { + syslog(LOG_ERR, "Invalid maxdump value"); + exit(1); + } + break; case 'v': verbose++; break; @@ -682,6 +748,8 @@ main(int argc, char **argv) usage(); if (clear && (compress || keep)) usage(); + if (maxdumps > 0 && (checkfor || clear)) + usage(); argc -= optind; argv += optind; if (argc >= 1 && !checkfor && !clear) {