~vcs-imports/e2fsprogs/trunk

« back to all changes in this revision

Viewing changes to e2fsck/pass1.c

  • Committer: Theodore Ts'o
  • Author(s): Darrick J. Wong
  • Date: 2014-08-10 22:44:07 UTC
  • Revision ID: git-v1:ef9c58d572de36f1786d32c93196a679294e3bc7
e2fsck: do a better job of fixing i_size of inline directories

If we encounter a directory whose i_size != the inline data size, just
set i_size to the size of the inline data.  The pb.last_block
calculation is wrong since pb.last_block == -1, which results in
i_size being set to zero, which corrupts the directory.

Clear the inline_data inode flag if we actually /are/ setting i_size
to zero.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>

Show diffs side-by-side

added added

removed removed

Lines of Context:
2856
2856
                if (inode->i_flags & EXT4_INLINE_DATA_FL) {
2857
2857
                        int flags;
2858
2858
                        size_t size;
 
2859
                        errcode_t err;
2859
2860
 
 
2861
                        size = 0;
2860
2862
                        flags = ctx->fs->flags;
2861
2863
                        ctx->fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
2862
 
                        if (ext2fs_inline_data_size(ctx->fs, pctx->ino, &size))
2863
 
                                bad_size = 5;
 
2864
                        err = ext2fs_inline_data_size(ctx->fs, pctx->ino,
 
2865
                                                      &size);
2864
2866
                        ctx->fs->flags = (flags &
2865
2867
                                          EXT2_FLAG_IGNORE_CSUM_ERRORS) |
2866
2868
                                         (ctx->fs->flags &
2867
2869
                                          ~EXT2_FLAG_IGNORE_CSUM_ERRORS);
2868
 
                        if (size != inode->i_size)
2869
 
                                bad_size = 5;
 
2870
                        if (err || size != inode->i_size) {
 
2871
                                bad_size = 7;
 
2872
                                pctx->num = size;
 
2873
                        }
2870
2874
                } else if (inode->i_size & (fs->blocksize - 1))
2871
2875
                        bad_size = 5;
2872
2876
                else if (nblock > (pb.last_block + 1))
2899
2903
        }
2900
2904
        /* i_size for symlinks is checked elsewhere */
2901
2905
        if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
2902
 
                pctx->num = (pb.last_block+1) * fs->blocksize;
 
2906
                /* Did inline_data set pctx->num earlier? */
 
2907
                if (bad_size != 7)
 
2908
                        pctx->num = (pb.last_block + 1) * fs->blocksize;
2903
2909
                pctx->group = bad_size;
2904
2910
                if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
2905
2911
                        if (LINUX_S_ISDIR(inode->i_mode))
2906
2912
                                pctx->num &= 0xFFFFFFFFULL;
2907
2913
                        ext2fs_inode_size_set(fs, inode, pctx->num);
 
2914
                        if (EXT2_I_SIZE(inode) == 0 &&
 
2915
                            (inode->i_flags & EXT4_INLINE_DATA_FL)) {
 
2916
                                memset(inode->i_block, 0,
 
2917
                                       sizeof(inode->i_block));
 
2918
                                inode->i_flags &= ~EXT4_INLINE_DATA_FL;
 
2919
                        }
2908
2920
                        dirty_inode++;
2909
2921
                }
2910
2922
                pctx->num = 0;