Commit c3ffaf83 authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

Add support to detect corrupted resize_inode's to e2fsck.

parent 9213a93b
master brillo-m10-dev brillo-m10-release brillo-m7-dev brillo-m7-mr-dev brillo-m7-release brillo-m8-dev brillo-m8-release brillo-m9-dev brillo-m9-release halo-rk312x-5.1.0_r5 idea133-weekly-release l-preview lollipop-cts-release lollipop-dev lollipop-mr1-cts-release lollipop-mr1-dev lollipop-mr1-fi-release lollipop-mr1-release lollipop-mr1-wfc-release lollipop-release lollipop-wear-release m-preview marshmallow-cts-release marshmallow-dev marshmallow-dr-arc-dev marshmallow-dr-arc-m53 marshmallow-dr-arc-m54 marshmallow-dr-dev marshmallow-dr-dragon-release marshmallow-dr-lego-release marshmallow-dr-release marshmallow-dr1.5-dev marshmallow-dr1.5-release marshmallow-dr1.6-release marshmallow-mr1-dev marshmallow-mr1-release marshmallow-mr2-release marshmallow-mr3-release marshmallow-release master-soong n-mr1-preview-1 n-preview-1 n-preview-2 nougat-cts-release nougat-dev nougat-dr1-release nougat-mr0.5-release nougat-mr1-cts-release nougat-mr1-dev nougat-mr1-release nougat-mr1.1-release nougat-mr1.2-release nougat-release rockchip-5.1.0_r5 rockchip-6.0.1_r55 sdk-release upstream-mirror-e2fsprogs android-wear-n-preview-2 android-wear-n-preview-1 android-wear-5.1.1_r1 android-wear-5.1.0_r1 android-wear-5.0.0_r1 android-n-preview-5 android-n-preview-4 android-n-preview-3 android-n-preview-2 android-n-preview-1 android-n-mr1-preview-2 android-n-mr1-preview-1 android-m-preview android-m-preview-2 android-m-preview-1 android-lego-6.0.1_r2 android-lego-6.0.1_r1 android-l-preview_r2 android-cts-7.1_r1 android-cts-7.0_r5 android-cts-7.0_r4 android-cts-7.0_r3 android-cts-7.0_r2 android-cts-7.0_r1 android-cts-6.0_r14 android-cts-6.0_r13 android-cts-6.0_r12 android-cts-6.0_r9 android-cts-6.0_r8 android-cts-6.0_r7 android-cts-6.0_r6 android-cts-6.0_r5 android-cts-6.0_r4 android-cts-6.0_r3 android-cts-6.0_r2 android-cts-6.0_r1 android-cts-5.1_r15 android-cts-5.1_r14 android-cts-5.1_r13 android-cts-5.1_r10 android-cts-5.1_r9 android-cts-5.1_r8 android-cts-5.1_r7 android-cts-5.1_r6 android-cts-5.1_r5 android-cts-5.1_r4 android-cts-5.1_r3 android-cts-5.1_r2 android-cts-5.1_r1 android-cts-5.0_r9 android-cts-5.0_r8 android-cts-5.0_r7 android-cts-5.0_r6 android-cts-5.0_r5 android-cts-5.0_r4 android-cts-5.0_r3 android-7.1.1_r13 android-7.1.1_r12 android-7.1.1_r11 android-7.1.1_r10 android-7.1.1_r9 android-7.1.1_r8 android-7.1.1_r7 android-7.1.1_r6 android-7.1.1_r4 android-7.1.1_r3 android-7.1.1_r2 android-7.1.1_r1 android-7.1.0_r7 android-7.1.0_r6 android-7.1.0_r5 android-7.1.0_r4 android-7.1.0_r3 android-7.1.0_r2 android-7.1.0_r1 android-7.0.0_r27 android-7.0.0_r24 android-7.0.0_r21 android-7.0.0_r19 android-7.0.0_r17 android-7.0.0_r15 android-7.0.0_r14 android-7.0.0_r13 android-7.0.0_r12 android-7.0.0_r7 android-7.0.0_r6 android-7.0.0_r5 android-7.0.0_r4 android-7.0.0_r3 android-7.0.0_r1 android-6.0.1_r78 android-6.0.1_r77 android-6.0.1_r74 android-6.0.1_r73 android-6.0.1_r72 android-6.0.1_r70 android-6.0.1_r69 android-6.0.1_r68 android-6.0.1_r67 android-6.0.1_r66 android-6.0.1_r65 android-6.0.1_r63 android-6.0.1_r62 android-6.0.1_r61 android-6.0.1_r60 android-6.0.1_r59 android-6.0.1_r58 android-6.0.1_r57 android-6.0.1_r56 android-6.0.1_r55 android-6.0.1_r54 android-6.0.1_r53 android-6.0.1_r52 android-6.0.1_r51 android-6.0.1_r50 android-6.0.1_r49 android-6.0.1_r48 android-6.0.1_r47 android-6.0.1_r46 android-6.0.1_r45 android-6.0.1_r43 android-6.0.1_r42 android-6.0.1_r41 android-6.0.1_r40 android-6.0.1_r33 android-6.0.1_r32 android-6.0.1_r31 android-6.0.1_r30 android-6.0.1_r28 android-6.0.1_r27 android-6.0.1_r26 android-6.0.1_r25 android-6.0.1_r24 android-6.0.1_r22 android-6.0.1_r21 android-6.0.1_r20 android-6.0.1_r18 android-6.0.1_r17 android-6.0.1_r16 android-6.0.1_r13 android-6.0.1_r12 android-6.0.1_r11 android-6.0.1_r10 android-6.0.1_r9 android-6.0.1_r8 android-6.0.1_r7 android-6.0.1_r5 android-6.0.1_r4 android-6.0.1_r3 android-6.0.1_r1 android-6.0.0_r41 android-6.0.0_r26 android-6.0.0_r25 android-6.0.0_r24 android-6.0.0_r23 android-6.0.0_r13 android-6.0.0_r12 android-6.0.0_r11 android-6.0.0_r7 android-6.0.0_r6 android-6.0.0_r5 android-6.0.0_r4 android-6.0.0_r3 android-6.0.0_r2 android-6.0.0_r1 android-5.1.1_r38 android-5.1.1_r37 android-5.1.1_r36 android-5.1.1_r35 android-5.1.1_r34 android-5.1.1_r33 android-5.1.1_r30 android-5.1.1_r29 android-5.1.1_r28 android-5.1.1_r26 android-5.1.1_r25 android-5.1.1_r24 android-5.1.1_r23 android-5.1.1_r22 android-5.1.1_r20 android-5.1.1_r19 android-5.1.1_r18 android-5.1.1_r17 android-5.1.1_r16 android-5.1.1_r15 android-5.1.1_r14 android-5.1.1_r13 android-5.1.1_r12 android-5.1.1_r10 android-5.1.1_r9 android-5.1.1_r8 android-5.1.1_r7 android-5.1.1_r6 android-5.1.1_r5 android-5.1.1_r4 android-5.1.1_r3 android-5.1.1_r2 android-5.1.1_r1 android-5.1.0_r5 android-5.1.0_r4 android-5.1.0_r3 android-5.1.0_r1 android-5.0.2_r3 android-5.0.2_r1 android-5.0.1_r1 android-5.0.0_r7 android-5.0.0_r6 android-5.0.0_r5.1 android-5.0.0_r5 android-5.0.0_r4 android-5.0.0_r3 android-5.0.0_r2 android-5.0.0_r1
No related merge requests found
2004-12-24 Theodore Ts'o <tytso@mit.edu>
* pass1.c (e2fsck_pass1): At the end of the pass 1 processing, if
we have been signalled to do so, recreate the resize inode.
* super.c (check_resize_inode): New function which checks to make
sure the resize inode is valid. It is called by
check_super_block(). If it is invalid, it will signal to
pass1.c that the resize inode needs to recreate.
* e2fsck.h (E2F_FLAG_RESIZE_INODE): New flag
* problem.c, problem.h (PR_0_RESIZE_INODE_INVALID,
PR_1_RESIZE_INODE_CREATE): Add new problem codes.
2004-12-23 Theodore Ts'o <tytso@mit.edu>
* swapfs.c (swap_inodes): Since swap_inodes bypasses the inode
......
......@@ -163,6 +163,7 @@ struct resource_track {
#define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly
* specified by the user */
#define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */
#define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */
/*
* Defines for indicating the e2fsck pass number
......
......@@ -721,6 +721,24 @@ void e2fsck_pass1(e2fsck_t ctx)
ctx->block_ea_map = 0;
}
if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
ext2fs_block_bitmap save_bmap;
errcode_t retval;
save_bmap = fs->block_map;
fs->block_map = ctx->block_found_map;
clear_problem_context(&pctx);
pctx.errcode = ext2fs_create_resize_inode(fs);
if (pctx.errcode) {
fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
/* Should never get here */
ctx->flags |= E2F_FLAG_ABORT;
return;
}
fs->block_map = save_bmap;
ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
}
if (ctx->flags & E2F_FLAG_RESTART) {
/*
* Only the master copy of the superblock and block
......@@ -1526,14 +1544,14 @@ static int process_block(ext2_filsys fs,
}
if (p->ino == EXT2_RESIZE_INO) {
if (blockcnt >= 0) {
/* Check that the block is in the correct place
* in the appropriate backup reserved gdt area */
} else if (blockcnt == BLOCK_COUNT_IND) {
/* Check that the block is in the correct place
* in the primary reserved gdt area */
} else /* The resize inode's DIND block should be
* allocated as a normal block. */
/*
* The resize inode has already be sanity checked
* during pass #0 (the superblock checks). All we
* have to do is mark the double indirect block as
* being in use; all of the other blocks are handled
* by mark_table_blocks()).
*/
if (blockcnt == BLOCK_COUNT_DIND)
mark_block_used(ctx, blk);
} else
mark_block_used(ctx, blk);
......
......@@ -39,7 +39,8 @@
#define PROMPT_SUPPRESS 16
#define PROMPT_UNLINK 17
#define PROMPT_CLEAR_HTREE 18
#define PROMPT_NULL 19
#define PROMPT_RECREATE 19
#define PROMPT_NULL 20
/*
* These are the prompts which are used to ask the user if they want
......@@ -65,7 +66,8 @@ static const char *prompt[] = {
N_("Suppress messages"),/* 16 */
N_("Unlink"), /* 17 */
N_("Clear HTree index"),/* 18 */
"", /* 19 */
N_("Recreate"), /* 19 */
"", /* 29 */
};
/*
......@@ -92,7 +94,8 @@ static const char *preen_msg[] = {
N_("SUPPRESSED"), /* 16 */
N_("UNLINKED"), /* 17 */
N_("HTREE INDEX CLEARED"),/* 18 */
"", /* 19 */
N_("WILL RECREATE"), /* 19 */
"", /* 20 */
};
static const struct e2fsck_problem problem_table[] = {
......@@ -325,6 +328,11 @@ static const struct e2fsck_problem problem_table[] = {
N_("Resize_@i not enabled, but the resize inode is non-zero. "),
PROMPT_CLEAR, 0 },
/* Resize inode invalid */
{ PR_0_RESIZE_INODE_INVALID,
N_("Resize @i not valid. "),
PROMPT_RECREATE, 0 },
/* Pass 1 errors */
/* Pass 1: Checking inodes, blocks, and sizes */
......@@ -718,7 +726,12 @@ static const struct e2fsck_problem problem_table[] = {
N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
"@f metadata. "),
PROMPT_CLEAR, PR_LATCH_BBLOCK },
/* Resize inode failed */
{ PR_1_RESIZE_INODE_CREATE,
N_("Resize @i (re)creation failed: %m."),
PROMPT_ABORT, 0 },
/* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */
......
......@@ -181,6 +181,9 @@ struct problem_context {
/* Resize_inode not enabled, but resize inode is non-zero */
#define PR_0_CLEAR_RESIZE_INODE 0x00002F
/* Resize inode invalid */
#define PR_0_RESIZE_INODE_INVALID 0x000030
/*
* Pass 1 errors
*/
......@@ -416,6 +419,9 @@ struct problem_context {
/* Bad block has indirect block that conflicts with filesystem block */
#define PR_1_BB_FS_BLOCK 0x01004D
/* Resize inode failed */
#define PR_1_RESIZE_INODE_CREATE 0x01004E
/*
* Pass 1b errors
*/
......
......@@ -312,6 +312,116 @@ return_abort:
return 1;
}
/*
* Check the resize inode to make sure it is sane. We check both for
* the case where on-line resizing is not enabled (in which case the
* resize inode should be cleared) as well as the case where on-line
* resizing is enabled.
*/
void check_resize_inode(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
struct ext2_inode inode;
struct problem_context pctx;
int i, j, gdt_off, ind_off;
blk_t blk, pblk, expect;
__u32 *dind_buf = 0, *ind_buf;
errcode_t retval;
clear_problem_context(&pctx);
pctx.ino = EXT2_RESIZE_INO;
retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
if (retval) {
ctx->flags |= E2F_FLAG_RESIZE_INODE;
return;
}
/*
* If the resize inode feature isn't set, then
* s_reserved_gdt_blocks must be zero, and the resize inode
* must be cleared.
*/
if (!(fs->super->s_feature_compat &
EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
if (fs->super->s_reserved_gdt_blocks) {
pctx.num = fs->super->s_reserved_gdt_blocks;
if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
&pctx)) {
fs->super->s_reserved_gdt_blocks = 0;
ext2fs_mark_super_dirty(fs);
}
}
for (i=0; i < EXT2_N_BLOCKS; i++) {
if (inode.i_block[i])
break;
}
if ((i < EXT2_N_BLOCKS) &&
fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
memset(&inode, 0, sizeof(inode));
e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
"clear_resize");
}
return;
}
/*
* The resize inode feature is enabled; check to make sure the
* only block in use is the double indirect block
*/
blk = inode.i_block[EXT2_DIND_BLOCK];
for (i=0; i < EXT2_N_BLOCKS; i++) {
if (i != EXT2_DIND_BLOCK && inode.i_block[i])
break;
}
if ((i < EXT2_N_BLOCKS) || !blk ||
(blk < fs->super->s_first_data_block ||
blk >= fs->super->s_blocks_count)) {
resize_inode_invalid:
if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
memset(&inode, 0, sizeof(inode));
e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
"clear_resize");
ctx->flags |= E2F_FLAG_RESIZE_INODE;
}
if (!(ctx->options & E2F_OPT_READONLY)) {
fs->super->s_state &= ~EXT2_VALID_FS;
ext2fs_mark_super_dirty(fs);
}
goto cleanup;
}
dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
"resize dind buffer");
ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
retval = io_channel_read_blk(fs->io, blk, 1, dind_buf);
if (retval)
goto resize_inode_invalid;
gdt_off = fs->desc_blocks;
pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
i++, gdt_off++, pblk++) {
gdt_off %= fs->blocksize/4;
if (dind_buf[gdt_off] != pblk)
goto resize_inode_invalid;
retval = io_channel_read_blk(fs->io, pblk, 1, ind_buf);
if (retval)
goto resize_inode_invalid;
ind_off = 0;
for (j = 1; j < fs->group_desc_count; j++) {
if (!ext2fs_bg_has_super(fs, j))
continue;
expect = pblk + (j * fs->super->s_blocks_per_group);
if (ind_buf[ind_off] != expect)
goto resize_inode_invalid;
ind_off++;
}
}
cleanup:
if (dind_buf)
ext2fs_free_mem(&dind_buf);
}
void check_super_block(e2fsck_t ctx)
{
......@@ -325,7 +435,6 @@ void check_super_block(e2fsck_t ctx)
dgrp_t i;
blk_t should_be;
struct problem_context pctx;
struct ext2_inode inode;
__u32 free_blocks = 0, free_inodes = 0;
inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
......@@ -368,6 +477,9 @@ void check_super_block(e2fsck_t ctx)
MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
MAX_CHECK, 0, sb->s_blocks_count / 4);
check_super_value(ctx, "reserved_gdt_blocks",
sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
fs->blocksize/4);
if (!ctx->num_blocks) {
pctx.errcode = e2fsck_get_device_size(ctx);
......@@ -542,38 +654,7 @@ void check_super_block(e2fsck_t ctx)
ext2fs_mark_super_dirty(fs);
}
/*
* If the resize inode feature isn't set, then
* s_reserved_gdt_blocks must be zero, and the resize inode
* must be cleared.
*/
if (!(fs->super->s_feature_compat &
EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
if (fs->super->s_reserved_gdt_blocks) {
pctx.num = fs->super->s_reserved_gdt_blocks;
if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
&pctx)) {
fs->super->s_reserved_gdt_blocks = 0;
ext2fs_mark_super_dirty(fs);
}
}
e2fsck_read_inode(ctx, EXT2_RESIZE_INO, &inode,
"check_resize");
for (i=0; i < EXT2_N_BLOCKS; i++) {
if (inode.i_block[i])
break;
}
pctx.ino = EXT2_RESIZE_INO;
if ((i < EXT2_N_BLOCKS) &&
fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
for (i=0; i < EXT2_N_BLOCKS; i++) {
inode.i_block[i] = 0;
}
inode.i_blocks = 0;
e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
"clear_resize");
}
}
check_resize_inode(ctx);
/*
* Clean up any orphan inodes, if present.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment