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