tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
snapshot support for fsck_ffs
Hi,
the attached diff adds snapshot support for fsck_ffs (via -x or -X options,
like dump(8)). The point is to have fsck_ffs optionally take a snapshot
of a R/W mounted filesystem before checking it, to avoid errors related
to the filesystem being live. Obviously this will only work with -n, the
code enforce this.
The goal is to be able to use
fsck -fn -Tffs:-X
in /etc/daily (via a daily.conf variable of course). The daily fsck check is
often highly noisy on busy filesystems (like, say, /var/spool/mqueue on
a busy sendmail server), making it hard to differenciate between trancient
errors, and errors related to real filesystem corruption. When a snapshot
is used, a filesystem should always show clean, unless it's really corrupted.
I've tested this by running 'fsck -fn -Tffs:-X' in a loop on a system,
while at the same time doing a tar xf of the NetBSD src tree followed
by rm -rf src; also in a loop. The fsck -fn -Tffs:-X always did come
clean; while any run of fsck -fn done in parallel did show lots of
errors.
comments ?
--
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
NetBSD: 26 ans d'experience feront toujours la difference
--
Index: sbin/fsck_ffs/Makefile
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/Makefile,v
retrieving revision 1.36
diff -u -r1.36 Makefile
--- sbin/fsck_ffs/Makefile 31 Jul 2008 05:38:04 -0000 1.36
+++ sbin/fsck_ffs/Makefile 24 Aug 2008 15:44:00 -0000
@@ -7,17 +7,18 @@
MAN= fsck_ffs.8
SRCS= dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \
pass5.c fsutil.c setup.c utilities.c ffs_bswap.c ffs_subr.c \
- ffs_tables.c ffs_appleufs.c partutil.c
+ ffs_tables.c ffs_appleufs.c partutil.c snapshot.c
FSCK= ${NETBSDSRCDIR}/sbin/fsck
-CPPFLAGS+=-I${FSCK}
+DUMP= ${NETBSDSRCDIR}/sbin/dump
+CPPFLAGS+=-I${FSCK} -I${DUMP}
.ifndef SMALLPROG
CPPFLAGS+=-DPROGRESS
.endif
SRCS+= progress.c
.PATH: ${FSCK}
-.PATH: ${NETBSDSRCDIR}/sys/ufs/ffs ${FSCK}
+.PATH: ${NETBSDSRCDIR}/sys/ufs/ffs ${FSCK} ${DUMP}
SRCS+= vfs_wapbl.c wapbl.c
.PATH: ${NETBSDSRCDIR}/sys/kern
Index: sbin/fsck_ffs/extern.h
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/extern.h,v
retrieving revision 1.23
diff -u -r1.23 extern.h
--- sbin/fsck_ffs/extern.h 31 Jul 2008 05:38:04 -0000 1.23
+++ sbin/fsck_ffs/extern.h 24 Aug 2008 15:44:00 -0000
@@ -79,7 +79,7 @@
void propagate(ino_t);
int reply(const char *);
void setinodebuf(ino_t);
-int setup(const char *);
+int setup(const char *, const char *);
void voidquit(int);
void replay_wapbl(void);
Index: sbin/fsck_ffs/fsck_ffs.8
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/fsck_ffs.8,v
retrieving revision 1.41
diff -u -r1.41 fsck_ffs.8
--- sbin/fsck_ffs/fsck_ffs.8 31 Jul 2008 05:38:04 -0000 1.41
+++ sbin/fsck_ffs/fsck_ffs.8 24 Aug 2008 15:44:01 -0000
@@ -29,7 +29,7 @@
.\"
.\" @(#)fsck.8 8.3 (Berkeley) 11/29/94
.\"
-.Dd January 13, 2004
+.Dd August 24, 2008
.Dt FSCK_FFS 8
.Os
.Sh NAME
@@ -37,11 +37,12 @@
.Nd Fast File System consistency check and interactive repair
.Sh SYNOPSIS
.Nm
-.Op Fl adFfPpq
+.Op Fl adFfPpqX
.Op Fl B Ar byteorder
.Op Fl b Ar block
.Op Fl c Ar level
.Op Fl m Ar mode
+.Op Fl x Ar snap-backup
.Op Fl y | n
.Ar filesystem ...
.Sh DESCRIPTION
@@ -248,8 +249,18 @@
Specify
.Dq preen
mode, described above.
-.It Fl q
-Quiet mode, do not output any messages for clean filesystems.
+.It Fl x Ar snap-backup
+Use a snapshot with
+.Ar snap-backup
+as backup to check a read-write mounted filesystem. Must be used with
+.Fl n .
+See
+.Xr fss 4
+for more details.
+.It Fl X
+Similar to
+.Fl x
+but uses a file system internal snapshot on the file system to be checked.
.It Fl y
Assume a yes response to all questions asked by
.Nm ;
@@ -321,6 +332,7 @@
.%T "Fsck \- The UNIX File System Check Program"
.Re
.Sh SEE ALSO
+.Xr fss 4 ,
.Xr fs 5 ,
.Xr fstab 5 ,
.Xr fsck 8 ,
Index: sbin/fsck_ffs/main.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/main.c,v
retrieving revision 1.68
diff -u -r1.68 main.c
--- sbin/fsck_ffs/main.c 20 Jul 2008 01:20:22 -0000 1.68
+++ sbin/fsck_ffs/main.c 24 Aug 2008 15:44:01 -0000
@@ -67,13 +67,15 @@
#include "extern.h"
#include "fsutil.h"
#include "exitvalues.h"
+#include "snapshot.h"
int progress = 0;
int returntosingle = 0;
static int argtoi(int, const char *, const char *, int);
-static int checkfilesys(const char *, char *, long, int);
+static int checkfilesys(const char *, const char *, int);
static void usage(void);
+static char *get_snap_device(char *);
int
main(int argc, char *argv[])
@@ -81,6 +83,8 @@
struct rlimit r;
int ch;
int ret = FSCK_EXIT_OK;
+ char *snap_backup = NULL;
+ int snap_internal = 0;
if (getrlimit(RLIMIT_DATA, &r) == 0) {
r.rlim_cur = r.rlim_max;
@@ -92,7 +96,7 @@
forceimage = 0;
endian = 0;
isappleufs = 0;
- while ((ch = getopt(argc, argv, "aB:b:c:dFfm:npPqy")) != -1) {
+ while ((ch = getopt(argc, argv, "aB:b:c:dFfm:npPqyx:X")) != -1) {
switch (ch) {
case 'a':
isappleufs = 1;
@@ -163,12 +167,27 @@
yflag++;
nflag = 0;
break;
+ case 'x':
+ snap_backup = optarg;
+ break;
+ case 'X':
+ snap_internal = 1;
+ break;
default:
usage();
}
}
+ if (snap_backup || snap_internal) {
+ if (!nflag || yflag) {
+ warnx("Cannot use -x or -X without -n\n");
+ snap_backup = NULL;
+ snap_internal = 0;
+ }
+ }
+
+
argc -= optind;
argv += optind;
@@ -191,15 +210,38 @@
signal(SIGINFO, infohandler);
while (argc-- > 0) {
- const char *path = blockcheck(*argv);
+ int nret;
+ char *path = strdup(blockcheck(*argv));
if (path == NULL)
pfatal("Can't check %s\n", *argv);
- else {
- int nret = checkfilesys(blockcheck(*argv), 0, 0L, 0);
+
+ if (snap_backup || snap_internal) {
+ char *mpt;
+ char *snap_dev;
+ int snapfd;
+
+ mpt = get_snap_device(*argv);
+ if (mpt == NULL)
+ goto next;
+ snapfd = snap_open(mpt, snap_backup, NULL, &snap_dev);
+ if (snapfd < 0) {
+ warn("can't take snapshot of %s", mpt);
+ free(mpt);
+ goto next;
+ }
+ nret = checkfilesys(blockcheck(snap_dev), path, 0);
+ if (ret < nret)
+ ret = nret;
+ free(mpt);
+ close(snapfd);
+ } else {
+ nret = checkfilesys(path, path, 0);
if (ret < nret)
ret = nret;
- }
+ }
+next:
+ free(path);
argv++;
}
@@ -224,7 +266,7 @@
*/
/* ARGSUSED */
static int
-checkfilesys(const char *filesys, char *mntpt, long auxdata, int child)
+checkfilesys(const char *filesys, const char *origfs, int child)
{
daddr_t n_ffree, n_bfree;
struct dups *dp;
@@ -255,7 +297,7 @@
setcdevname(filesys, preen);
if (debug && preen)
pwarn("starting\n");
- switch (setup(filesys)) {
+ switch (setup(filesys, origfs)) {
case 0:
if (preen)
pfatal("CAN'T CHECK FILE SYSTEM.");
@@ -458,9 +500,62 @@
{
(void) fprintf(stderr,
- "usage: %s [-adFfnPpqy] [-B be|le] [-b block] [-c level] [-m mode]"
- " filesystem ...\n",
+ "usage: %s [-adFfnPpqyX] [-B be|le] [-b block] [-c level] [-m mode]"
+ " [-x snap-backup] filesystem ...\n",
getprogname());
exit(FSCK_EXIT_USAGE);
}
+static
+char *get_snap_device(char *file)
+{
+ char *mountpoint = NULL;
+ struct statvfs *mntbuf, *fs, fsbuf;
+ struct stat sb;
+
+ /* find the mount point */
+ if (lstat(file, &sb) == -1) {
+ warn("can't stat %s", file);
+ return NULL;
+ }
+ if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ int mntbufc, i;
+ if ((mntbufc = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
+ pfatal("can't get mount list: %s\n", strerror(errno));
+ for (fs = mntbuf, i = 0;
+ i < mntbufc; i++, fs++) {
+ if (strcmp(fs->f_fstypename, "ufs") != 0 &&
+ strcmp(fs->f_fstypename, "ffs") != 0)
+ continue;
+ if (fs->f_flag & ST_RDONLY) {
+ warnx("Cannot use -x or -X "
+ "on read-only filesystem");
+ free(mntbuf);
+ return NULL;
+ }
+ if (strcmp(fs->f_mntfromname, unrawname(file)) == 0) {
+ mountpoint = strdup(fs->f_mntonname);
+ free(mntbuf);
+ return mountpoint;
+ }
+ }
+ warnx("Cannot use -x or -X on unmounted device");
+ free(mntbuf);
+ return NULL;
+ }
+ if (S_ISDIR(sb.st_mode)) {
+ if (statvfs(file, &fsbuf) == -1)
+ pfatal("can't statvfs %s: %s\n", file, strerror(errno));
+ if (strcmp(fsbuf.f_mntonname, file))
+ pfatal("%s is not a mount point\n", file);
+ if (fsbuf.f_flag & ST_RDONLY) {
+ warnx("Cannot use -x or -X "
+ "on read-only filesystem");
+ return NULL;
+ }
+ mountpoint = strdup(file);
+ return mountpoint;
+ }
+ pfatal("%s is not a mount point\n", file);
+ return NULL;
+}
Index: sbin/fsck_ffs/setup.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/setup.c,v
retrieving revision 1.83
diff -u -r1.83 setup.c
--- sbin/fsck_ffs/setup.c 31 Jul 2008 05:38:04 -0000 1.83
+++ sbin/fsck_ffs/setup.c 24 Aug 2008 15:44:01 -0000
@@ -79,7 +79,7 @@
* is already clean (preen mode only).
*/
int
-setup(const char *dev)
+setup(const char *dev, const char *origdev)
{
long cg, size, asked, i, j;
long bmapsize;
@@ -91,6 +91,7 @@
int doskipclean;
u_int64_t maxfilesize;
struct csum *ccsp;
+ int fd;
havesb = 0;
fswritefd = -1;
@@ -128,7 +129,20 @@
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL ||
sblock == NULL || altsblock == NULL)
errexit("Cannot allocate space for superblock");
- if (!forceimage && getdiskinfo(dev, fsreadfd, NULL, &geo, &dkw) != -1)
+ if (strcmp(dev, origdev) && !forceimage) {
+ /*
+ * dev isn't the original fs (for example it's a snapshot)
+ * do getdiskinfo on the original device
+ */
+ fd = open(origdev, O_RDONLY);
+ if (fd < 0) {
+ warn("Can't open %s", origdev);
+ return (0);
+ }
+ } else {
+ fd = fsreadfd;
+ }
+ if (!forceimage && getdiskinfo(origdev, fd, NULL, &geo, &dkw) != -1)
dev_bsize = secsize = geo.dg_secsize;
else
dev_bsize = secsize = DEV_BSIZE;
Index: sbin/fsdb/fsdb.c
===================================================================
RCS file: /cvsroot/src/sbin/fsdb/fsdb.c,v
retrieving revision 1.37
diff -u -r1.37 fsdb.c
--- sbin/fsdb/fsdb.c 28 Apr 2008 20:23:08 -0000 1.37
+++ sbin/fsdb/fsdb.c 24 Aug 2008 15:44:01 -0000
@@ -130,7 +130,7 @@
if (fsys == NULL)
usage();
endian = 0;
- if (setup(fsys) <= 0)
+ if (setup(fsys, fsys) <= 0)
errx(1, "cannot set up file system `%s'", fsys);
printf("Editing file system `%s'\nLast Mounted on %s\n", fsys,
sblock->fs_fsmnt);
Home |
Main Index |
Thread Index |
Old Index