summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2002-12-03 18:21:09 +0000
committermckusick <mckusick@FreeBSD.org>2002-12-03 18:21:09 +0000
commitea268a7016db23d1e0fa7017ef98351925280ce7 (patch)
tree0655dd490c2c2d713a0dd9193ee574dfe7c3b405 /sbin
parent6822be5fe2bf90a5a45f1d01377d882248fde1f3 (diff)
downloadFreeBSD-src-ea268a7016db23d1e0fa7017ef98351925280ce7.zip
FreeBSD-src-ea268a7016db23d1e0fa7017ef98351925280ce7.tar.gz
Add the `L' option to dump to notify it that it is dumping a
live filesystem. To obtain a consistent dump image, dump takes a snapshot of the filesystem and then does a dump of the snapshot. The snapshot is removed when the dump is complete. Also add an operator warning that the `L' option should be used if dump is run on a live filesystem without the `L' option being specified. The alternative would be to silently use a snapshot any time that a live filesystem is dumped, but this change in dump semantics seemed too drastic at this time. Sponsored by: DARPA & NAI Labs. Approved by: re
Diffstat (limited to 'sbin')
-rw-r--r--sbin/dump/dump.811
-rw-r--r--sbin/dump/main.c95
2 files changed, 91 insertions, 15 deletions
diff --git a/sbin/dump/dump.8 b/sbin/dump/dump.8
index 7fdd2c0..82e55c6 100644
--- a/sbin/dump/dump.8
+++ b/sbin/dump/dump.8
@@ -42,7 +42,7 @@
.Nd file system backup
.Sh SYNOPSIS
.Nm
-.Op Fl 0123456789acknSu
+.Op Fl 0123456789ackLnSu
.Op Fl B Ar records
.Op Fl b Ar blocksize
.Op Fl D Ar dumpdates
@@ -194,6 +194,15 @@ Use Kerberos authentication to talk to remote tape servers. (Only
available if this option was enabled when
.Nm
was compiled.)
+.It Fl L
+This option is to notify
+.Nm
+that it is dumping a live filesystem.
+To obtain a consistent dump image,
+.Nm
+takes a snapshot of the filesystem and
+then does a dump of the snapshot.
+The snapshot is removed when the dump is complete.
.It Fl n
Whenever
.Nm
diff --git a/sbin/dump/main.c b/sbin/dump/main.c
index bc45eae..34223b1 100644
--- a/sbin/dump/main.c
+++ b/sbin/dump/main.c
@@ -48,15 +48,18 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/mount.h>
#include <sys/disklabel.h>
#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/ufsmount.h>
#include <ufs/ffs/fs.h>
#include <protocols/dumprestore.h>
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
#include <inttypes.h>
@@ -72,6 +75,7 @@ static const char rcsid[] =
#include "pathnames.h"
int notify = 0; /* notify operator flag */
+int snapdump = 0; /* dumping live filesystem, so use snapshot */
int blockswritten = 0; /* number of blocks written on current tape */
int tapeno = 0; /* current tape number */
int density = 0; /* density in bytes/0.1" " <- this is for hilit19 */
@@ -87,6 +91,7 @@ char *host = NULL; /* remote host (if any) */
*/
static int sblock_try[] = SBLOCKSEARCH;
+static char *getmntpt(char *, int *);
static long numarg(const char *, long, long);
static void obsolete(int *, char **[]);
static void usage(void) __dead2;
@@ -98,9 +103,9 @@ main(int argc, char *argv[])
ino_t ino;
int dirty;
union dinode *dp;
- struct fstab *dt;
- char *map;
- int ch, mode;
+ struct fstab *dt;
+ char *map, *mntpt;
+ int ch, mode, mntflags;
int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1;
int just_estimate = 0;
ino_t maxino;
@@ -122,9 +127,9 @@ main(int argc, char *argv[])
obsolete(&argc, &argv);
#ifdef KERBEROS
-#define optstring "0123456789aB:b:cd:f:h:kns:ST:uWwD:"
+#define optstring "0123456789aB:b:cd:f:h:kLns:ST:uWwD:"
#else
-#define optstring "0123456789aB:b:cd:f:h:ns:ST:uWwD:"
+#define optstring "0123456789aB:b:cd:f:h:Lns:ST:uWwD:"
#endif
while ((ch = getopt(argc, argv, optstring)) != -1)
#undef optstring
@@ -177,6 +182,10 @@ main(int argc, char *argv[])
break;
#endif
+ case 'L':
+ snapdump = 1;
+ break;
+
case 'n': /* notify operators */
notify = 1;
break;
@@ -309,12 +318,53 @@ main(int argc, char *argv[])
}
spcl.c_dev[NAMELEN-1]='\0';
spcl.c_filesys[NAMELEN-1]='\0';
+
+ if ((mntpt = getmntpt(disk, &mntflags)) != 0) {
+ if (snapdump == 0) {
+ msg("WARNING: %s\n",
+ "should use -L when dumping live filesystems!");
+ } else {
+ struct ufs_args args;
+ char snapname[BUFSIZ];
+
+ snprintf(snapname, sizeof snapname, "%s/.dump_snapshot",
+ mntpt);
+ args.fspec = snapname;
+ while (mount("ffs", mntpt,
+ mntflags | MNT_UPDATE | MNT_SNAPSHOT,
+ &args) < 0) {
+ if (errno == EEXIST && unlink(snapname) == 0)
+ continue;
+ errx(X_STARTUP, "Cannot create %s: %s\n",
+ snapname, strerror(errno));
+ }
+ if ((diskfd = open(snapname, O_RDONLY)) < 0) {
+ unlink(snapname);
+ errx(X_STARTUP, "Cannot open %s: %s\n",
+ snapname, strerror(errno));
+ }
+ unlink(snapname);
+ if (fstat(diskfd, &sb) != 0)
+ err(X_STARTUP, "%s: stat", snapname);
+ spcl.c_date = _time_to_time64(sb.st_mtime);
+ }
+ } else if (snapdump != 0) {
+ msg("WARNING: Cannot use -L on an unmounted filesystem.\n");
+ snapdump = 0;
+ }
+ if (snapdump == 0) {
+ if ((diskfd = open(disk, O_RDONLY)) < 0)
+ err(X_STARTUP, "Cannot open %s", disk);
+ if (fstat(diskfd, &sb) != 0)
+ err(X_STARTUP, "%s: stat", disk);
+ if (S_ISDIR(sb.st_mode))
+ errx(X_STARTUP, "%s: unknown file system", disk);
+ }
+
(void)strcpy(spcl.c_label, "none");
(void)gethostname(spcl.c_host, NAMELEN);
spcl.c_level = level - '0';
spcl.c_type = TS_TAPE;
- if (!Tflag)
- getdumptime(); /* /etc/dumpdates snarfed */
if (spcl.c_date == 0) {
tmsg = "the epoch\n";
@@ -323,6 +373,9 @@ main(int argc, char *argv[])
tmsg = ctime(&t);
}
msg("Date of this level %c dump: %s", level, tmsg);
+
+ if (!Tflag)
+ getdumptime(); /* /etc/dumpdates snarfed */
if (spcl.c_ddate == 0) {
tmsg = "the epoch\n";
} else {
@@ -330,7 +383,8 @@ main(int argc, char *argv[])
tmsg = ctime(&t);
}
msg("Date of last level %c dump: %s", lastlevel, tmsg);
- msg("Dumping %s ", disk);
+
+ msg("Dumping %s%s ", snapdump ? "snapshot of ": "", disk);
if (dt != NULL)
msgtail("(%s) ", dt->fs_file);
if (host)
@@ -338,12 +392,6 @@ main(int argc, char *argv[])
else
msgtail("to %s\n", tape);
- if ((diskfd = open(disk, O_RDONLY)) < 0)
- err(X_STARTUP, "Cannot open %s", disk);
- if (fstat(diskfd, &sb) != 0)
- err(X_STARTUP, "%s: stat", disk);
- if (S_ISDIR(sb.st_mode))
- errx(X_STARTUP, "%s: unknown file system", disk);
sync();
sblock = (struct fs *)sblock_buf;
for (i = 0; sblock_try[i] != -1; i++) {
@@ -531,6 +579,25 @@ usage(void)
}
/*
+ * Check to see if a disk is currently mounted.
+ */
+static char *
+getmntpt(char *name, int *mntflagsp)
+{
+ long mntsize, i;
+ struct statfs *mntbuf;
+
+ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+ for (i = 0; i < mntsize; i++) {
+ if (!strcmp(mntbuf[i].f_mntfromname, name)) {
+ *mntflagsp = mntbuf[i].f_flags;
+ return (mntbuf[i].f_mntonname);
+ }
+ }
+ return (0);
+}
+
+/*
* Pick up a numeric argument. It must be nonnegative and in the given
* range (except that a vmax of 0 means unlimited).
*/
OpenPOWER on IntegriCloud