On Wed, Nov 17, 2010 at 12:19:14AM -0800, J.P. Larocque wrote:
> Hi Ted and Micah,
> 
> I ran into the problem in e2fsck that prints:
> 
> WARNING: PROGRAMMING BUG IN E2FSCK!
>         OR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.
> inode_link_info[X] is Y, inode.i_links_count is Z.  They should be the same!
> 
> I've sent a full transcript, e2image file with which the problem can
> be reproduced, and background information to 555...@bugs.debian.org,
> which you can access at
> <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=555456>.  (I'm
> sending this message separately to spare you both from the 2.1MiB
> attachment.)
> 
> Hope it helps.  Thanks!

Thanks for sending me the test case.  I've been able to find a fix for
this which will be going into e2fsprogs 1.41.13.

                                                        - Ted

commit 992016c5afde0f77a9ff10c4fc5be02f83eb055c
Author: Theodore Ts'o <ty...@mit.edu>
Date:   Fri Nov 26 19:09:43 2010 -0500

    e2fsck: Fix inode nlink accounting that could cause PROGRAMMING BUG errors
    
    This fixes two possible causes for the error message:
    
    WARNING: PROGRAMMING BUG IN E2FSCK!
            OR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.
    inode_link_info[X] is Y, inode.i_links_count is Z.  They should be the same!
    
    One cause which can trigger this message is when an inode has an
    illegal link count > 65500 --- for example, 65535.  This was the case
    in the Debian Bug report #555456.
    
    Another cause which could trigger this message is if an ext4 directory
    previously had more than 65000 subdirectories (thus causing
    i_link_count to be set to 1), but then some of the subdirectories were
    deleted, such that i_link_count should now be the actual number of
    subdirectories.
    
    Addresses-Debian-Bug: #555456
    
    Signed-off-by: "Theodore Ts'o" <ty...@mit.edu>

diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c
index d9706ce..515cb84 100644
--- a/e2fsck/pass4.c
+++ b/e2fsck/pass4.c
@@ -121,6 +121,8 @@ void e2fsck_pass4(e2fsck_t ctx)
 
        /* Protect loop from wrap-around if s_inodes_count maxed */
        for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
+               int isdir = ext2fs_test_inode_bitmap(ctx->inode_dir_map, i);
+
                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
                        goto errout;
                if ((i % fs->super->s_inodes_per_group) == 0) {
@@ -153,14 +155,14 @@ void e2fsck_pass4(e2fsck_t ctx)
                        ext2fs_icount_fetch(ctx->inode_count, i,
                                            &link_counted);
                }
-               if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i) &&
-                   (link_counted > EXT2_LINK_MAX))
+               if (isdir && (link_counted > EXT2_LINK_MAX))
                        link_counted = 1;
                if (link_counted != link_count) {
                        e2fsck_read_inode(ctx, i, inode, "pass4");
                        pctx.ino = i;
                        pctx.inode = inode;
-                       if (link_count != inode->i_links_count) {
+                       if ((link_count != inode->i_links_count) && !isdir &&
+                           (inode->i_links_count <= EXT2_LINK_MAX)) {
                                pctx.num = link_count;
                                fix_problem(ctx,
                                            PR_4_INCONSISTENT_COUNT, &pctx);
@@ -168,10 +170,10 @@ void e2fsck_pass4(e2fsck_t ctx)
                        pctx.num = link_counted;
                        /* i_link_count was previously exceeded, but no longer
                         * is, fix this but don't consider it an error */
-                       if ((LINUX_S_ISDIR(inode->i_mode) && link_counted > 1 &&
+                       if ((isdir && link_counted > 1 &&
                             (inode->i_flags & EXT2_INDEX_FL) &&
                             link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
-                            (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx))) {
+                           fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
                                inode->i_links_count = link_counted;
                                e2fsck_write_inode(ctx, i, inode, "pass4");
                        }



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to