From: Robin Dong <sanbai@xxxxxxxxxx> Signed-off-by: Robin Dong <sanbai@xxxxxxxxxx> --- e2fsck/pass1.c | 63 +++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 44 insertions(+), 19 deletions(-) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 532e132..70d26df 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -1741,6 +1741,8 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, { struct ext2fs_extent extent; blk64_t blk; + blk64_t elblk; + __u32 elen; e2_blkcnt_t blockcnt; unsigned int i; int is_dir, is_leaf; @@ -1753,6 +1755,8 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_FIRST_SIB, &extent); + elblk = extent.e_lblk << ctx->fs->cluster_ratio_bits; + elen = extent.e_len << ctx->fs->cluster_ratio_bits; while (!pctx->errcode && info.num_entries-- > 0) { is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF; is_dir = LINUX_S_ISDIR(pctx->inode->i_mode); @@ -1762,18 +1766,18 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, extent.e_pblk < ctx->fs->super->s_first_data_block || extent.e_pblk >= ext2fs_blocks_count(ctx->fs->super)) problem = PR_1_EXTENT_BAD_START_BLK; - else if (extent.e_lblk < start_block) + else if (elblk < start_block) problem = PR_1_OUT_OF_ORDER_EXTENTS; else if (is_leaf && - (extent.e_pblk + extent.e_len) > + (extent.e_pblk + elen) > ext2fs_blocks_count(ctx->fs->super)) problem = PR_1_EXTENT_ENDS_BEYOND; if (problem) { report_problem: pctx->blk = extent.e_pblk; - pctx->blk2 = extent.e_lblk; - pctx->num = extent.e_len; + pctx->blk2 = elblk; + pctx->num = elen; if (fix_problem(ctx, problem, pctx)) { e2fsck_read_bitmaps(ctx); pctx->errcode = @@ -1785,6 +1789,10 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_CURRENT, &extent); + elblk = extent.e_lblk << + ctx->fs->cluster_ratio_bits; + elen = extent.e_len << + ctx->fs->cluster_ratio_bits; if (pctx->errcode == EXT2_ET_NO_CURRENT_NODE) { pctx->errcode = 0; break; @@ -1805,11 +1813,13 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, goto report_problem; return; } - scan_extent_node(ctx, pctx, pb, extent.e_lblk, ehandle); + scan_extent_node(ctx, pctx, pb, elblk, ehandle); if (pctx->errcode) return; pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_UP, &extent); + elblk = extent.e_lblk << ctx->fs->cluster_ratio_bits; + elen = extent.e_len << ctx->fs->cluster_ratio_bits; if (pctx->errcode) { pctx->str = "EXT2_EXTENT_UP"; return; @@ -1835,12 +1845,12 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, (unsigned long) pctx->ino, type, (unsigned long) pb->previous_block+1, (unsigned long) extent.e_pblk, - (unsigned long) extent.e_lblk, - (unsigned long) extent.e_len); + (unsigned long) elblk, + (unsigned long) elen); } pb->fragmented = 1; } - while (is_dir && ++pb->last_db_block < extent.e_lblk) { + while (is_dir && ++pb->last_db_block < elblk) { pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, pb->ino, 0, pb->last_db_block); @@ -1850,8 +1860,7 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, goto failed_add_dir_block; } } - for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0; - i < extent.e_len; + for (blk = extent.e_pblk, blockcnt = elblk, i = 0; i < elen; blk++, blockcnt++, i++) { if (!(ctx->fs->cluster_ratio_bits && pb->previous_block && @@ -1865,7 +1874,8 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, pb->previous_block = blk; - if (is_dir) { + if (is_dir && i < (pctx->inode->i_size / + ctx->fs->blocksize)) { pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, pctx->ino, blk, blockcnt); if (pctx->errcode) { pctx->blk = blk; @@ -1878,14 +1888,16 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, } } } - if (is_dir && extent.e_len > 0) + if (is_dir && elen > 0) pb->last_db_block = blockcnt - 1; - pb->previous_block = extent.e_pblk + extent.e_len - 1; - start_block = pb->last_block = extent.e_lblk + extent.e_len - 1; + pb->previous_block = extent.e_pblk + elen - 1; + start_block = pb->last_block = elblk + elen - 1; next: pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_NEXT_SIB, &extent); + elblk = extent.e_lblk << ctx->fs->cluster_ratio_bits; + elen = extent.e_len << ctx->fs->cluster_ratio_bits; } if (pctx->errcode == EXT2_ET_EXTENT_NO_NEXT) pctx->errcode = 0; @@ -1944,6 +1956,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, int dirty_inode = 0; int extent_fs; __u64 size; + __u32 last_cluster; pb.ino = ino; pb.num_blocks = 0; @@ -2055,9 +2068,15 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, else if (nblock > (pb.last_block + 1)) bad_size = 1; else if (nblock < (pb.last_block + 1)) { - if (((pb.last_block + 1) - nblock) > - fs->super->s_prealloc_dir_blocks) - bad_size = 2; + if (fs->cluster_ratio_bits > 0) { + if ((EXT2FS_B2C(fs, pb.last_block) - + EXT2FS_B2C(fs, nblock)) > 1) + bad_size = 2; + } else { + if (((pb.last_block + 1) - nblock) > + fs->super->s_prealloc_dir_blocks) + bad_size = 2; + } } } else { e2_blkcnt_t blkpg = ctx->blocks_per_page; @@ -2068,8 +2087,14 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, (size < (__u64)pb.last_block * fs->blocksize) && (pb.last_block / blkpg * blkpg != pb.last_block || size < (__u64)(pb.last_block & ~(blkpg-1)) *fs->blocksize) && - !(inode->i_flags & EXT4_EOFBLOCKS_FL)) - bad_size = 3; + !(inode->i_flags & EXT4_EOFBLOCKS_FL)) { + last_cluster = EXT2FS_NUM_B2C(fs, (size + fs->blocksize + - 1) / fs->blocksize); + if (fs->cluster_ratio_bits <= 0 || + last_cluster < ((pb.last_block + 1) >> + fs->cluster_ratio_bits)) + bad_size = 3; + } else if (!(extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) && size > ext2_max_sizes[fs->super->s_log_block_size]) /* too big for a direct/indirect-mapped file */ -- 1.7.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html