Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sbin/fsck_ffs Do some basic checks of the WAPBL journal, to ...
details: https://anonhg.NetBSD.org/src/rev/b20a495295f6
branches: trunk
changeset: 747391:b20a495295f6
user: bouyer <bouyer%NetBSD.org@localhost>
date: Sun Sep 13 14:25:28 2009 +0000
description:
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.
diffstat:
sbin/fsck_ffs/extern.h | 3 +-
sbin/fsck_ffs/setup.c | 49 ++++++++-----
sbin/fsck_ffs/wapbl.c | 178 ++++++++++++++++++++++++++++++++++--------------
3 files changed, 156 insertions(+), 74 deletions(-)
diffs (293 lines):
diff -r 22faf1d212f9 -r b20a495295f6 sbin/fsck_ffs/extern.h
--- a/sbin/fsck_ffs/extern.h Sun Sep 13 14:13:23 2009 +0000
+++ b/sbin/fsck_ffs/extern.h Sun Sep 13 14:25:28 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.24 2008/08/30 10:46:16 bouyer Exp $ */
+/* $NetBSD: extern.h,v 1.25 2009/09/13 14:25:28 bouyer 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);
diff -r 22faf1d212f9 -r b20a495295f6 sbin/fsck_ffs/setup.c
--- a/sbin/fsck_ffs/setup.c Sun Sep 13 14:13:23 2009 +0000
+++ b/sbin/fsck_ffs/setup.c Sun Sep 13 14:25:28 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: setup.c,v 1.87 2009/04/07 05:50:11 mrg Exp $ */
+/* $NetBSD: setup.c,v 1.88 2009/09/13 14:25:28 bouyer 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.87 2009/04/07 05:50:11 mrg Exp $");
+__RCSID("$NetBSD: setup.c,v 1.88 2009/09/13 14:25:28 bouyer 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 && skipclean) {
- if (!quiet)
- pwarn("file system is journaled; not checking\n");
- return (-1);
+ /* 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 (!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 (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; "
+ "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);
diff -r 22faf1d212f9 -r b20a495295f6 sbin/fsck_ffs/wapbl.c
--- a/sbin/fsck_ffs/wapbl.c Sun Sep 13 14:13:23 2009 +0000
+++ b/sbin/fsck_ffs/wapbl.c Sun Sep 13 14:25:28 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wapbl.c,v 1.3 2008/11/10 20:12:13 joerg Exp $ */
+/* $NetBSD: wapbl.c,v 1.4 2009/09/13 14:25:28 bouyer Exp $ */
/*-
* Copyright (c) 2005,2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
#define WAPBL_INTERNAL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wapbl.c,v 1.3 2008/11/10 20:12:13 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wapbl.c,v 1.4 2009/09/13 14:25:28 bouyer Exp $");
#include <sys/stat.h>
#include <sys/time.h>
@@ -90,60 +90,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) {
@@ -201,3 +149,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;
+}
Home |
Main Index |
Thread Index |
Old Index