Module Name:    src
Committed By:   snj
Date:           Sat Oct  3 22:49:43 UTC 2009

Modified Files:
        src/sbin/fsck_ffs [netbsd-5]: extern.h setup.c wapbl.c
        src/sbin/tunefs [netbsd-5]: tunefs.c
        src/sys/ufs/ffs [netbsd-5]: ffs_vfsops.c ffs_wapbl.c

Log Message:
Pull up following revision(s) (requested by bouyer in ticket #1036):
        sbin/fsck_ffs/extern.h: revision 1.25 via patch
        sbin/fsck_ffs/setup.c: revision 1.88 via patch
        sbin/fsck_ffs/wapbl.c: revision 1.4 via patch
        sbin/tunefs/tunefs.c: revision 1.41 via patch
        sys/ufs/ffs/ffs_vfsops.c: revision 1.252 via patch
        sys/ufs/ffs/ffs_wapbl.c: revision 1.13 via patch
Allow tunefs to clear any type of WAPBL log, not only in-filesystem
ones. Discussed in
http://mail-index.netbsd.org/tech-kern/2009/08/17/msg005896.html
and followups.
--
Do some basic checks of the WAPBL journal, to abort the boot before the
kernel refuse to mount a filesystem read-write (booting a system
multiuser with critical filesystems read-only is bad):
Add a check_wapbl() which will check some WAPBL values in the superblock,
and try to read the journal via wapbl_replay_start() if there is one.
pfatal() if one of these fail (abort boot if in preen mode,
as "CONTINUE" otherwise). In non-preen mode the bogus journal will
be cleared.
check_wapbl() is always called if the superblock supports WAPBL.
Even if FS_DOWAPBL is not there, there could be flags asking the
kernel to clear or create a log with bogus values which would cause the
kernel refuse to mount the filesystem.
Discussed in
http://mail-index.netbsd.org/tech-kern/2009/08/17/msg005896.html
and followups.
--
If the WAPBL journal can't be read (ffs_wapbl_replay_start() fails),
mount the filesystem anyway if MNT_FORCE is present.
This allows to still boot single-user a system with a corrupted
WAPBL on /, and so get a chance to run fsck to fix it.
http://mail-index.netbsd.org/tech-kern/2009/08/17/msg005896.html
and followups.


To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.24.2.1 src/sbin/fsck_ffs/extern.h
cvs rdiff -u -r1.84 -r1.84.2.1 src/sbin/fsck_ffs/setup.c
cvs rdiff -u -r1.2 -r1.2.6.1 src/sbin/fsck_ffs/wapbl.c
cvs rdiff -u -r1.37.2.1 -r1.37.2.2 src/sbin/tunefs/tunefs.c
cvs rdiff -u -r1.239.2.3 -r1.239.2.4 src/sys/ufs/ffs/ffs_vfsops.c
cvs rdiff -u -r1.6 -r1.6.8.1 src/sys/ufs/ffs/ffs_wapbl.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/fsck_ffs/extern.h
diff -u src/sbin/fsck_ffs/extern.h:1.24 src/sbin/fsck_ffs/extern.h:1.24.2.1
--- src/sbin/fsck_ffs/extern.h:1.24	Sat Aug 30 10:46:16 2008
+++ src/sbin/fsck_ffs/extern.h	Sat Oct  3 22:49:42 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.24 2008/08/30 10:46:16 bouyer Exp $	*/
+/*	$NetBSD: extern.h,v 1.24.2.1 2009/10/03 22:49:42 snj Exp $	*/
 
 /*
  * Copyright (c) 1994 James A. Jegers
@@ -82,6 +82,7 @@
 int		setup(const char *, const char *);
 void		voidquit(int);
 
+int		check_wapbl(void);
 void		replay_wapbl(void);
 void		cleanup_wapbl(void);
 int		read_wapbl(char *, long, daddr_t);

Index: src/sbin/fsck_ffs/setup.c
diff -u src/sbin/fsck_ffs/setup.c:1.84 src/sbin/fsck_ffs/setup.c:1.84.2.1
--- src/sbin/fsck_ffs/setup.c:1.84	Sat Aug 30 10:46:16 2008
+++ src/sbin/fsck_ffs/setup.c	Sat Oct  3 22:49:42 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: setup.c,v 1.84 2008/08/30 10:46:16 bouyer Exp $	*/
+/*	$NetBSD: setup.c,v 1.84.2.1 2009/10/03 22:49:42 snj Exp $	*/
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)setup.c	8.10 (Berkeley) 5/9/95";
 #else
-__RCSID("$NetBSD: setup.c,v 1.84 2008/08/30 10:46:16 bouyer Exp $");
+__RCSID("$NetBSD: setup.c,v 1.84.2.1 2009/10/03 22:49:42 snj Exp $");
 #endif
 #endif /* not lint */
 
@@ -173,24 +173,35 @@
 		doskipclean = 0;
 		pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
 	}
-	if (sblock->fs_flags & FS_DOWAPBL) {
-		if (preen) {
+	/* ffs_superblock_layout() == 2 */
+	if (sblock->fs_magic != FS_UFS1_MAGIC ||
+	    (sblock->fs_old_flags & FS_FLAGS_UPDATED) != 0) {
+		/* can have WAPBL */
+		if (check_wapbl() != 0) {
+			doskipclean = 0;
+		}
+		if (sblock->fs_flags & FS_DOWAPBL) {
+			if (preen) {
+				if (!quiet)
+					pwarn("file system is journaled; "
+					    "not checking\n");
+				return (-1);
+			}
 			if (!quiet)
-				pwarn("file system is journaled; not checking\n");
-			return (-1);
+				pwarn("** File system is journaled; "
+				    "replaying journal\n");
+			replay_wapbl();
+			doskipclean = 0;
+			sblock->fs_flags &= ~FS_DOWAPBL;
+			sbdirty();
+			/* Although we may have updated the superblock from
+			 * the journal, we are still going to do a full check,
+			 * so we don't bother to re-read the superblock from
+			 * the journal.
+			 * XXX, instead we could re-read the superblock and
+			 * then not force doskipclean = 0 
+			 */
 		}
-		if (!quiet)
-			pwarn("** File system is journaled; replaying journal\n");
-		replay_wapbl();
-		doskipclean = 0;
-		sblock->fs_flags &= ~FS_DOWAPBL;
-		sbdirty();
-		/* Although we may have updated the superblock from the
-		 * journal, we are still going to do a full check, so we
-		 * don't bother to re-read the superblock from the journal.
-		 * XXX, instead we could re-read the superblock and then not
-		 * force doskipclean = 0 
-		 */
 	}
 	if (debug)
 		printf("clean = %d\n", sblock->fs_clean);

Index: src/sbin/fsck_ffs/wapbl.c
diff -u src/sbin/fsck_ffs/wapbl.c:1.2 src/sbin/fsck_ffs/wapbl.c:1.2.6.1
--- src/sbin/fsck_ffs/wapbl.c:1.2	Thu Jul 31 05:38:04 2008
+++ src/sbin/fsck_ffs/wapbl.c	Sat Oct  3 22:49:42 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: wapbl.c,v 1.2 2008/07/31 05:38:04 simonb Exp $	*/
+/*	$NetBSD: wapbl.c,v 1.2.6.1 2009/10/03 22:49:42 snj Exp $	*/
 
 /*-
  * Copyright (c) 2005,2008 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wapbl.c,v 1.2 2008/07/31 05:38:04 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wapbl.c,v 1.2.6.1 2009/10/03 22:49:42 snj Exp $");
 
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -89,60 +89,8 @@
 void
 replay_wapbl(void)
 {
-	uint64_t addr, count, blksize;
 	int error;
 
-	if (debug)
-		wapbl_debug_print = WAPBL_PRINT_ERROR | WAPBL_PRINT_REPLAY;
-	if (debug > 1)
-		wapbl_debug_print |= WAPBL_PRINT_IO;
-
-	if (sblock->fs_journal_version != UFS_WAPBL_VERSION) {
-		pfatal("INVALID JOURNAL VERSION %d",
-		    sblock->fs_journal_version);
-		if (reply("CONTINUE") == 0) {
-			exit(FSCK_EXIT_CHECK_FAILED);
-		}
-		return;
-	}
-
-	switch (sblock->fs_journal_location) {
-	case UFS_WAPBL_JOURNALLOC_NONE:
-		pfatal("INVALID JOURNAL LOCATION 'NONE'");
-		if (reply("CONTINUE") == 0) {
-			exit(FSCK_EXIT_CHECK_FAILED);
-		}
-		return;
-
-	case UFS_WAPBL_JOURNALLOC_END_PARTITION:
-		addr = sblock->fs_journallocs[UFS_WAPBL_EPART_ADDR];
-		count = sblock->fs_journallocs[UFS_WAPBL_EPART_COUNT];
-		blksize = sblock->fs_journallocs[UFS_WAPBL_EPART_BLKSZ];
-		break;
-
-	case UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM:
-		addr = sblock->fs_journallocs[UFS_WAPBL_INFS_ADDR];
-		count = sblock->fs_journallocs[UFS_WAPBL_INFS_COUNT];
-		blksize = sblock->fs_journallocs[UFS_WAPBL_INFS_BLKSZ];
-		break;
-
-	default:
-		pfatal("INVALID JOURNAL LOCATION %d",
-		    sblock->fs_journal_location);
-		if (reply("CONTINUE") == 0) {
-			exit(FSCK_EXIT_CHECK_FAILED);
-		}
-		return;
-	}
-
-	error = wapbl_replay_start(&wapbl_replay, 0, addr, count, blksize);
-	if (error) {
-		pfatal("UNABLE TO READ JOURNAL FOR REPLAY");
-		if (reply("CONTINUE") == 0) {
-			exit(FSCK_EXIT_CHECK_FAILED);
-		}
-		return;
-	}
 	if (!nflag) {
 		error = wapbl_replay_write(wapbl_replay, 0);
 		if (error) {
@@ -200,3 +148,125 @@
 
 	return 0;
 }
+
+int
+check_wapbl(void)
+{
+	uint64_t addr = 0, count = 0, blksize = 0;
+	int error;
+	int ret = 0;
+	if (debug)
+		wapbl_debug_print = WAPBL_PRINT_ERROR | WAPBL_PRINT_REPLAY;
+	if (debug > 1)
+		wapbl_debug_print |= WAPBL_PRINT_IO;
+
+	if (sblock->fs_flags & FS_DOWAPBL) {
+		if (sblock->fs_journal_version != UFS_WAPBL_VERSION) {
+			pfatal("INVALID JOURNAL VERSION %d",
+			    sblock->fs_journal_version);
+			if (reply("CONTINUE") == 0) {
+				exit(FSCK_EXIT_CHECK_FAILED);
+			}
+			pwarn("CLEARING EXISTING JOURNAL\n");
+			sblock->fs_flags &= ~FS_DOWAPBL;
+			sbdirty();
+			ret = FSCK_EXIT_CHECK_FAILED;
+		} else {
+			switch(sblock->fs_journal_location) {
+			case UFS_WAPBL_JOURNALLOC_END_PARTITION:
+				addr =
+				  sblock->fs_journallocs[UFS_WAPBL_EPART_ADDR];
+				count =
+				  sblock->fs_journallocs[UFS_WAPBL_EPART_COUNT];
+				blksize =
+				  sblock->fs_journallocs[UFS_WAPBL_EPART_BLKSZ];
+				break;
+			case UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM:
+				addr =
+				  sblock->fs_journallocs[UFS_WAPBL_INFS_ADDR];
+				count =
+				  sblock->fs_journallocs[UFS_WAPBL_INFS_COUNT];
+				blksize =
+				  sblock->fs_journallocs[UFS_WAPBL_INFS_BLKSZ];
+				break;
+			default:
+				pfatal("INVALID JOURNAL LOCATION %d",
+				    sblock->fs_journal_location);
+				if (reply("CONTINUE") == 0) {
+					exit(FSCK_EXIT_CHECK_FAILED);
+				}
+				pwarn("CLEARING EXISTING JOURNAL\n");
+				sblock->fs_flags &= ~FS_DOWAPBL;
+				sblock->fs_journal_location =
+				    UFS_WAPBL_JOURNALLOC_NONE;
+				sbdirty();
+				ret = FSCK_EXIT_CHECK_FAILED;
+				break;
+			}
+			if (sblock->fs_flags & FS_DOWAPBL) {
+				error = wapbl_replay_start(
+				    &wapbl_replay, 0, addr, count, blksize);
+				if (error) {
+					pfatal(
+					   "UNABLE TO READ JOURNAL FOR REPLAY");
+					if (reply("CONTINUE") == 0) {
+						exit(FSCK_EXIT_CHECK_FAILED);
+					}
+					pwarn("CLEARING EXISTING JOURNAL\n");
+					sblock->fs_flags &= ~FS_DOWAPBL;
+					sbdirty();
+					ret = FSCK_EXIT_CHECK_FAILED;
+				}
+			}
+		}
+	}
+	/*
+	 * at this time fs_journal_flags can only be 0,
+	 * UFS_WAPBL_FLAGS_CREATE_LOG or UFS_WAPBL_FLAGS_CLEAR_LOG.
+	 * We can't have both flags at the same time.
+	 */
+	switch (sblock->fs_journal_flags) {
+	case 0:
+		break;
+	case UFS_WAPBL_FLAGS_CREATE_LOG:
+	case UFS_WAPBL_FLAGS_CLEAR_LOG:
+		switch(sblock->fs_journal_location) {
+		case UFS_WAPBL_JOURNALLOC_END_PARTITION:
+		case UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM:
+			break;
+		case UFS_WAPBL_JOURNALLOC_NONE:
+			if (sblock->fs_journal_flags ==
+			    UFS_WAPBL_FLAGS_CLEAR_LOG)
+				break;
+			/* FALLTHROUGH */
+		default:
+			pfatal("INVALID JOURNAL LOCATION %d",
+			    sblock->fs_journal_location);
+			if (reply("CONTINUE") == 0) {
+				exit(FSCK_EXIT_CHECK_FAILED);
+			}
+			pwarn("CLEARING JOURNAL FLAGS\n");
+			sblock->fs_journal_flags = 0;
+			sblock->fs_journal_location =
+			    UFS_WAPBL_JOURNALLOC_NONE;
+			sbdirty();
+			ret = FSCK_EXIT_CHECK_FAILED;
+			break;
+		}
+		break;
+	default:
+		pfatal("INVALID JOURNAL FLAGS %d",
+		    sblock->fs_journal_flags);
+		if (reply("CONTINUE") == 0) {
+			exit(FSCK_EXIT_CHECK_FAILED);
+		}
+		pwarn("CLEARING JOURNAL FLAGS\n");
+		sblock->fs_journal_flags = 0;
+		sblock->fs_journal_location =
+		    UFS_WAPBL_JOURNALLOC_NONE;
+		sbdirty();
+		ret = FSCK_EXIT_CHECK_FAILED;
+		break;
+	}
+	return ret;
+}

Index: src/sbin/tunefs/tunefs.c
diff -u src/sbin/tunefs/tunefs.c:1.37.2.1 src/sbin/tunefs/tunefs.c:1.37.2.2
--- src/sbin/tunefs/tunefs.c:1.37.2.1	Tue Aug 25 18:32:33 2009
+++ src/sbin/tunefs/tunefs.c	Sat Oct  3 22:49:42 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: tunefs.c,v 1.37.2.1 2009/08/25 18:32:33 snj Exp $	*/
+/*	$NetBSD: tunefs.c,v 1.37.2.2 2009/10/03 22:49:42 snj Exp $	*/
 
 /*
  * Copyright (c) 1983, 1993
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)tunefs.c	8.3 (Berkeley) 5/3/95";
 #else
-__RCSID("$NetBSD: tunefs.c,v 1.37.2.1 2009/08/25 18:32:33 snj Exp $");
+__RCSID("$NetBSD: tunefs.c,v 1.37.2.2 2009/10/03 22:49:42 snj Exp $");
 #endif
 #endif /* not lint */
 
@@ -389,15 +389,6 @@
 		break;
 	}
 
-	if (!in_fs_log)
-		errx(1, "Can't change size of non-in-filesystem log");
-
-	if (old_size == logfilesize && logfilesize > 0) {
-		/* no action */
-		warnx("log file size remains unchanged at %lld", logfilesize);
-		return;
-	}
-
 	if (logfilesize == 0) {
 		/*
 		 * Don't clear out the locators - the kernel might need
@@ -410,6 +401,15 @@
 		return;
 	}
 
+	if (!in_fs_log && logfilesize > 0 && old_size > 0)
+		errx(1, "Can't change size of non-in-filesystem log");
+
+	if (old_size == logfilesize && logfilesize > 0) {
+		/* no action */
+		warnx("log file size remains unchanged at %lld", logfilesize);
+		return;
+	}
+
 	if (old_size == 0) {
 		/* create new log of desired size next mount */
 		sblock.fs_journal_location = UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM;

Index: src/sys/ufs/ffs/ffs_vfsops.c
diff -u src/sys/ufs/ffs/ffs_vfsops.c:1.239.2.3 src/sys/ufs/ffs/ffs_vfsops.c:1.239.2.4
--- src/sys/ufs/ffs/ffs_vfsops.c:1.239.2.3	Sat Apr  4 17:38:30 2009
+++ src/sys/ufs/ffs/ffs_vfsops.c	Sat Oct  3 22:49:43 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ffs_vfsops.c,v 1.239.2.3 2009/04/04 17:38:30 snj Exp $	*/
+/*	$NetBSD: ffs_vfsops.c,v 1.239.2.4 2009/10/03 22:49:43 snj Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.239.2.3 2009/04/04 17:38:30 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.239.2.4 2009/10/03 22:49:43 snj Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -1055,28 +1055,32 @@
 #ifdef WAPBL
 	if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
 		error = ffs_wapbl_replay_start(mp, fs, devvp);
-		if (error)
+		if (error && (mp->mnt_flag & MNT_FORCE) == 0)
 			goto out;
+		if (!error) {
+			if (!ronly) {
+				/* XXX fsmnt may be stale. */
+				printf("%s: replaying log to disk\n",
+				    fs->fs_fsmnt);
+				error = wapbl_replay_write(mp->mnt_wapbl_replay,
+				    devvp);
+				if (error)
+					goto out;
+				wapbl_replay_stop(mp->mnt_wapbl_replay);
+				fs->fs_clean = FS_WASCLEAN;
+			} else {
+				/* XXX fsmnt may be stale */
+				printf("%s: replaying log to memory\n",
+				    fs->fs_fsmnt);
+			}
 
-		if (!ronly) {
-			/* XXX fsmnt may be stale. */
-			printf("%s: replaying log to disk\n", fs->fs_fsmnt);
-			error = wapbl_replay_write(mp->mnt_wapbl_replay, devvp);
-			if (error)
-				goto out;
-			wapbl_replay_stop(mp->mnt_wapbl_replay);
-			fs->fs_clean = FS_WASCLEAN;
-		} else {
-			/* XXX fsmnt may be stale */
-			printf("%s: replaying log to memory\n", fs->fs_fsmnt);
+			/* Force a re-read of the superblock */
+			brelse(bp, BC_INVAL);
+			bp = NULL;
+			free(fs, M_UFSMNT);
+			fs = NULL;
+			goto sbagain;
 		}
-
-		/* Force a re-read of the superblock */
-		brelse(bp, BC_INVAL);
-		bp = NULL;
-		free(fs, M_UFSMNT);
-		fs = NULL;
-		goto sbagain;
 	}
 #else /* !WAPBL */
 	if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) {

Index: src/sys/ufs/ffs/ffs_wapbl.c
diff -u src/sys/ufs/ffs/ffs_wapbl.c:1.6 src/sys/ufs/ffs/ffs_wapbl.c:1.6.8.1
--- src/sys/ufs/ffs/ffs_wapbl.c:1.6	Mon Sep  8 03:16:43 2008
+++ src/sys/ufs/ffs/ffs_wapbl.c	Sat Oct  3 22:49:43 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ffs_wapbl.c,v 1.6 2008/09/08 03:16:43 joerg Exp $	*/
+/*	$NetBSD: ffs_wapbl.c,v 1.6.8.1 2009/10/03 22:49:43 snj Exp $	*/
 
 /*-
  * Copyright (c) 2003,2006,2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_wapbl.c,v 1.6 2008/09/08 03:16:43 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_wapbl.c,v 1.6.8.1 2009/10/03 22:49:43 snj Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -286,7 +286,7 @@
 	default:
 		printf("ffs_wapbl: unknown journal type %d\n",
 		    fs->fs_journal_location);
-		return EINVAL;
+		break;
 	}
 
 

Reply via email to