mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-04 09:09:56 +00:00
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:
parent
0cb652d925
commit
194a666749
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=107559
@ -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
|
||||
|
@ -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).
|
||||
|
Loading…
Reference in New Issue
Block a user