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;
}