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
This commit is contained in:
Kirk McKusick 2002-12-03 18:21:09 +00:00
parent 0cb652d925
commit 194a666749
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=107559
2 changed files with 91 additions and 15 deletions

View File

@ -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

View File

@ -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++) {
@ -530,6 +578,25 @@ usage(void)
exit(X_STARTUP);
}
/*
* 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).