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