Whamcloud - gitweb
ChangeLog, bitops.h:
authorTheodore Ts'o <tytso@mit.edu>
Tue, 8 Feb 2000 19:14:02 +0000 (19:14 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 8 Feb 2000 19:14:02 +0000 (19:14 +0000)
  bitops.h (ext2fs_mark_generic_bitmap, ext2fs_unmark_generic_bitmap,
   ext2fs_mark_block_bitmap, ext2fs_unmark_block_bitmap,
   ext2fs_mark_inode_bitmap, ext2fs_unmark_inode_bitmap): Change to
   return the previous state of the bit that is being marked or unmarked.
   For speed optimization.
ChangeLog, pass3.c:
  pass3.c (check_directory): Only do the loop detection algorithm if
   we've searched over 2048 parent directories and haven't found the end
   yet.  This means that in the common case, we don't allocate or clear
   the inode_loop_detection bitmap, which for large systems, merely
   clearing the bitmap for each directory was turning out to be quite
   expensive.  Thanks to Jani Jaakkola (jjaakkol@cs.helsinki.fi) for
   identifying this problem.
ChangeLog, Makefile.in, e2fsck.h, unix.c:
  Makefile.in: Call sync after finishing building all in this directory.
  unix.c (PRS): sync the filesystem before trying to use BLKFLSBUF, to
   minimize the chance of causing dirty blocks to get dropped.
  e2fsck.h: Manually define BLKFLSBUF if not defined, and we're on a
   Linux/i386 system.

e2fsck/ChangeLog
e2fsck/Makefile.in
e2fsck/e2fsck.h
e2fsck/pass3.c
e2fsck/unix.c
lib/ext2fs/ChangeLog
lib/ext2fs/bitops.h

index 90ef434..abc0253 100644 (file)
@@ -1,3 +1,24 @@
+2000-02-08    <tytso@snap.thunk.org>
+
+       * Makefile.in: Call sync after finishing building all in this
+               directory. 
+       
+       * unix.c (PRS): sync the filesystem before trying to use
+               BLKFLSBUF, to minimize the chance of causing dirty blocks
+               to get dropped.
+
+       * e2fsck.h: Manually define BLKFLSBUF if not defined, and we're on
+               a Linux/i386 system.
+       
+       * pass3.c (check_directory): Only do the loop detection algorithm
+               if we've searched over 2048 parent directories and haven't
+               found the end yet.  This means that in the common case, we
+               don't allocate or clear the inode_loop_detection bitmap,
+               which for large systems, merely clearing the bitmap for
+               each directory was turning out to be quite expensive.
+               Thanks to Jani Jaakkola (jjaakkol@cs.helsinki.fi) for
+               identifying this problem.
+
 2000-02-06  Theodore Ts'o  <tytso@valinux.com>
 
        * badblocks.c, e2fsck.h, ehandler.c, emptydir.c, extend.c,
index 89c25ef..0cd5d43 100644 (file)
@@ -82,6 +82,7 @@ SRCS= $(srcdir)/e2fsck.c \
        $(MTRACE_SRC)
 
 all:: profiled $(PROGS) e2fsck.static e2fsck.shared $(MANPAGES)
+       @sync
 
 @PROFILE_CMT@all:: e2fsck.profiled
 
index cd648ab..e4a6837 100644 (file)
 #define N_(a) a
 #endif
 
+/* For Linux/i386, define BLKFLSBUF */
+#if (!defined(BLKFLSBUF) && defined(__i386__))
+#define BLKFLSBUF  0x1261      /* flush buffer cache */
+#endif
 
 /* Everything is STDC, these days */
 #define NOARGS void
index 2202d17..e3cd8d1 100644 (file)
@@ -42,8 +42,8 @@
 #include "problem.h"
 
 static void check_root(e2fsck_t ctx);
-static void check_directory(e2fsck_t ctx, struct dir_info *dir,
-                           struct problem_context *pctx);
+static int check_directory(e2fsck_t ctx, struct dir_info *dir,
+                          struct problem_context *pctx);
 static ino_t get_lost_and_found(e2fsck_t ctx);
 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ino_t parent);
 static errcode_t adjust_inode_count(e2fsck_t ctx, ino_t ino, int adj);
@@ -82,14 +82,6 @@ void e2fsck_pass3(e2fsck_t ctx)
        /*
         * Allocate some bitmaps to do loop detection.
         */
-       pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
-                   _("inode loop detection bitmap"), &inode_loop_detect);
-       if (pctx.errcode) {
-               pctx.num = 1;
-               fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
-               ctx->flags |= E2F_FLAG_ABORT;
-               goto abort_exit;
-       }
        pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
                                                    &inode_done_map);
        if (pctx.errcode) {
@@ -123,7 +115,8 @@ void e2fsck_pass3(e2fsck_t ctx)
                        if ((ctx->progress)(ctx, 3, count++, maxdirs))
                                goto abort_exit;
                if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
-                       check_directory(ctx, dir, &pctx);
+                       if (check_directory(ctx, dir, &pctx))
+                               goto abort_exit;
        }
 
        /*
@@ -134,10 +127,14 @@ void e2fsck_pass3(e2fsck_t ctx)
 
 abort_exit:
        e2fsck_free_dir_info(ctx);
-       if (inode_loop_detect)
+       if (inode_loop_detect) {
                ext2fs_free_inode_bitmap(inode_loop_detect);
-       if (inode_done_map)
+               inode_loop_detect = 0;
+       }
+       if (inode_done_map) {
                ext2fs_free_inode_bitmap(inode_done_map);
+               inode_done_map = 0;
+       }
 #ifdef RESOURCE_TRACK
        if (ctx->options & E2F_OPT_TIME2) {
                e2fsck_clear_progbar(ctx);
@@ -259,34 +256,38 @@ static void check_root(e2fsck_t ctx)
  * the lost+found.  We have to do loop detection; if we ever discover
  * a loop, we treat that as a disconnected directory and offer to
  * reparent it to lost+found.
+ * 
+ * However, loop detection is expensive, because for very large
+ * filesystems, the inode_loop_detect bitmap is huge, and clearing it
+ * is non-trivial.  Loops in filesystems are also a rare error case,
+ * and we shouldn't optimize for error cases.  So we try two passes of
+ * the algorithm.  The first time, we ignore loop detection and merely
+ * increment a counter; if the counter exceeds some extreme threshold,
+ * then we try again with the loop detection bitmap enabled.
  */
-static void check_directory(e2fsck_t ctx, struct dir_info *dir,
-                           struct problem_context *pctx)
+static int check_directory(e2fsck_t ctx, struct dir_info *dir,
+                          struct problem_context *pctx)
 {
-       ext2_filsys fs = ctx->fs;
+       ext2_filsys     fs = ctx->fs;
        struct dir_info *p = dir;
+       int             loop_pass = 0, parent_count = 0;
 
        if (!p)
-               return;
-
-       ext2fs_clear_inode_bitmap(inode_loop_detect);
+               return 0;
 
-       /*
-        * Keep going until we find a parent which we've already
-        * checked.  We know it's either already connected to the
-        * directory tree, or it isn't but the user has already told
-        * us he doesn't want us to reconnect the disconnected
-        * subtree.
-        */
-       while (!ext2fs_test_inode_bitmap(inode_done_map, p->ino)) {
+       while (1) {
                /*
                 * Mark this inode as being "done"; by the time we
                 * return from this function, the inode we either be
                 * verified as being connected to the directory tree,
                 * or we will have offered to reconnect this to
                 * lost+found.
+                *
+                * If it was marked done already, then we've reached a
+                * parent we've already checked.
                 */
-               ext2fs_mark_inode_bitmap(inode_done_map, p->ino);
+               if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
+                       break;
 
                /*
                 * If this directory doesn't have a parent, or we've
@@ -294,8 +295,9 @@ static void check_directory(e2fsck_t ctx, struct dir_info *dir,
                 * reparent it to lost+found
                 */
                if (!p->parent ||
-                   (ext2fs_test_inode_bitmap(inode_loop_detect,
-                                             p->parent))) {
+                   (loop_pass && 
+                    (ext2fs_test_inode_bitmap(inode_loop_detect,
+                                             p->parent)))) {
                        pctx->ino = p->ino;
                        if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
                                if (e2fsck_reconnect_file(ctx, p->ino))
@@ -307,13 +309,35 @@ static void check_directory(e2fsck_t ctx, struct dir_info *dir,
                        }
                        break;
                }
-               ext2fs_mark_inode_bitmap(inode_loop_detect,
-                                        p->parent);
-               pctx->ino = p->parent;
                p = e2fsck_get_dir_info(ctx, p->parent);
                if (!p) {
                        fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
-                       return;
+                       return 0;
+               }
+               if (loop_pass) {
+                       ext2fs_mark_inode_bitmap(inode_loop_detect,
+                                                p->ino);
+               } else if (parent_count++ > 2048) {
+                       /*
+                        * If we've run into a path depth that's
+                        * greater than 2048, try again with the inode
+                        * loop bitmap turned on and start from the
+                        * top.
+                        */
+                       loop_pass = 1;
+                       if (inode_loop_detect)
+                               ext2fs_clear_inode_bitmap(inode_loop_detect);
+                       else {
+                               pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
+                               if (pctx->errcode) {
+                                       pctx->num = 1;
+                                       fix_problem(ctx, 
+                                   PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
+                                       ctx->flags |= E2F_FLAG_ABORT;
+                                       return -1;
+                               }
+                       }
+                       p = dir;
                }
        }
 
@@ -328,6 +352,7 @@ static void check_directory(e2fsck_t ctx, struct dir_info *dir,
                if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
                        fix_dotdot(ctx, dir, dir->parent);
        }
+       return 0;
 }      
 
 /*
index 882e580..fbe5980 100644 (file)
@@ -547,8 +547,8 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
            !cflag && !swapfs)
                ctx->options |= E2F_OPT_READONLY;
        ctx->filesystem_name = argv[optind];
-       if (flush) {
 #ifdef BLKFLSBUF
+       if (flush) {
                int     fd = open(ctx->filesystem_name, O_RDONLY, 0);
 
                if (fd < 0) {
@@ -557,6 +557,12 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                                ctx->filesystem_name);
                        exit(FSCK_ERROR);
                }
+               if (fsync(fd) < 0) {
+                       com_err("fsync", errno,
+                               _("while trying to flush %s"),
+                               ctx->filesystem_name);
+                       exit(FSCK_ERROR);
+               }
                if (ioctl(fd, BLKFLSBUF, 0) < 0) {
                        com_err("BLKFLSBUF", errno,
                                _("while trying to flush %s"),
@@ -564,10 +570,8 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                        exit(FSCK_ERROR);
                }
                close(fd);
-#else
-               fatal_error(ctx, _("BLKFLSBUF not supported"));
-#endif /* BLKFLSBUF */
        }
+#endif /* BLKFLSBUF */
        if (swapfs) {
                if (cflag || bad_blocks_file) {
                        fprintf(stderr, _("Incompatible options not "
index 6be53a5..214ec0d 100644 (file)
@@ -1,3 +1,11 @@
+2000-02-08    <tytso@snap.thunk.org>
+
+       * bitops.h (ext2fs_mark_generic_bitmap, ext2fs_unmark_generic_bitmap,
+               ext2fs_mark_block_bitmap, ext2fs_unmark_block_bitmap,
+               ext2fs_mark_inode_bitmap, ext2fs_unmark_inode_bitmap):
+               Change to return the previous state of the bit that is
+               being marked or unmarked.  For speed optimization.
+       
 2000-02-02  Theodore Ts'o  <tytso@valinux.com>
 
        * getsize.c, ismounted.c: Remove unneeded include of linux/fs.h
index 0361d9b..7e049d1 100644 (file)
@@ -35,13 +35,13 @@ extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
 extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
                                int code, unsigned long arg);
 
-extern void ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
-extern void ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
+extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
                                       blk_t block);
 extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
 
-extern void ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode);
-extern void ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode);
+extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
                                       ino_t inode);
 extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode);
 
@@ -329,31 +329,31 @@ _INLINE_ __u32 ext2fs_swab32(__u32 val)
 
 #endif /* !_EXT2_HAVE_ASM_SWAB */
 
-_INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+_INLINE_ int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
                                         __u32 bitno);
-_INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+_INLINE_ int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
                                           blk_t bitno);
 _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
                                        blk_t bitno);
 
-_INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+_INLINE_ int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
                                         __u32 bitno)
 {
        if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
                ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
-               return;
+               return 0;
        }
-       ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
+       return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
 }
 
-_INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+_INLINE_ int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
                                           blk_t bitno)
 {
        if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
                ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
-               return;
+               return 0;
        }
-       ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
+       return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
 }
 
 _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
@@ -366,16 +366,19 @@ _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
        return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
 }
 
-_INLINE_ void ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
+_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
                                       blk_t block)
 {
-       ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
+       return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
+                                      bitmap,
+                                         block);
 }
 
-_INLINE_ void ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
+_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
                                         blk_t block)
 {
-       ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
+       return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, 
+                                           block);
 }
 
 _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
@@ -385,16 +388,18 @@ _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
                                          block);
 }
 
-_INLINE_ void ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
                                       ino_t inode)
 {
-       ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
+       return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, 
+                                         inode);
 }
 
-_INLINE_ void ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
                                         ino_t inode)
 {
-       ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
+       return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, 
+                                    inode);
 }
 
 _INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,