Re: Weird ext4 bug: 256P used?

Felipe Contreras
2009-10-13T11:13:17Z

On Tue, Oct 13, 2009 at 5:11 AM, Theodore Tso <tytso@mit.edu> wrote:
> Here's a patch to e2fsprogs which will cause e2fsck to find and fix
> the filesystem corruption.  I'm not sure how i_blocks_hi was set to
> the incorect value in the first place, but this should fix the
> filesystem for you (largely a cosmetic issue).
>
>                                        - Ted
>
> commit 8a8f36540bbf5d4397cf476e216e9a720b5c1d8e
> Author: Theodore Ts'o <tytso@mit.edu>
> Date:   Mon Oct 12 21:59:37 2009 -0400
>
>    e2fsck: Fix handling of non-zero i_blocks_high field
>
>    E2fsck was not properly printing the i_blocks field in filesystem
>    corruption messages, and it was not properly checking i_blocks_hi and
>    i_blocks_lo, either.  This commit fixes this.
>
>    Thanks to Felipe Conteras for pointing this out.
>
>    Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

This patch fixes my problem.
Tested-by: Felipe Contreras <felipe.contreras@gmail.com>

However, I had one problem compiling:

> diff --git a/e2fsck/message.c b/e2fsck/message.c
> index 5e28812..9aaedc5 100644
> --- a/e2fsck/message.c
> +++ b/e2fsck/message.c
> @@ -258,7 +258,7 @@ static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch,
>  /*
>  * This function expands '%IX' expressions
>  */
> -static _INLINE_ void expand_inode_expression(char ch,
> +static _INLINE_ void expand_inode_expression(ext2_filsys fs, char ch,
>                                             struct problem_context *ctx)
>  {
>        struct ext2_inode       *inode;
> @@ -292,7 +292,8 @@ static _INLINE_ void expand_inode_expression(char ch,
>                printf("%u", large_inode->i_extra_isize);
>                break;
>        case 'b':
> -               if (inode->i_flags & EXT4_HUGE_FILE_FL)
> +               if (fs->super->s_feature_ro_compat &
> +                   EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
>                        printf("%llu", inode->i_blocks +
>                               (((long long) inode->osd2.linux2.l_i_blocks_hi)
>                                << 32));
> @@ -528,7 +529,7 @@ void print_e2fsck_message(e2fsck_t ctx, const char *msg,
>                        expand_at_expression(ctx, *cp, pctx, &first, recurse);
>                } else if (cp[0] == '%' && cp[1] == 'I') {
>                        cp += 2;
> -                       expand_inode_expression(*cp, pctx);
> +                       expand_inode_expression(fs, *cp, pctx);
>                } else if (cp[0] == '%' && cp[1] == 'D') {
>                        cp += 2;
>                        expand_dirent_expression(fs, *cp, pctx);
> diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
> index 9b12005..2531e57 100644
> --- a/e2fsck/pass1.c
> +++ b/e2fsck/pass1.c
> @@ -1792,6 +1792,15 @@ static void check_blocks_extents(e2fsck_t ctx, struct problem_context *pctx,
>        ext2fs_extent_free(ehandle);
>  }
>
> +static blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
> +                                    struct ext2_inode *inode)

My compiler fails because this function is already defined at
'lib/ext2fs/ext2fs.h' as non static.

> +{
> +       return (inode->i_blocks |
> +               (fs->super->s_feature_ro_compat &
> +                EXT4_FEATURE_RO_COMPAT_HUGE_FILE ?
> +                (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0));
> +}
> +
>  /*
>  * This subroutine is called on each inode to account for all of the
>  * blocks used by that inode.
> @@ -1972,7 +1981,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
>        if (LINUX_S_ISREG(inode->i_mode) &&
>            (inode->i_size_high || inode->i_size & 0x80000000UL))
>                ctx->large_files++;
> -       if ((pb.num_blocks != inode->i_blocks) ||
> +       if ((pb.num_blocks != ext2fs_inode_i_blocks(fs, inode)) ||
>            ((fs->super->s_feature_ro_compat &
>              EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
>             (inode->i_flags & EXT4_HUGE_FILE_FL) &&