Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 16 Dec 2012 23:06:12 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r244320 - head/sbin/savecore
Message-ID:  <201212162306.qBGN6CZR069280@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212162306.qBGN6CZR069280>