mirror of https://github.com/vitalif/e2fsprogs
Check for inodes which are too big (either too many blocks, or
would cause i_size to be too big), and offer to truncate the inode. Remove old bogus i_size checks. Add test case which tests e2fsck's handling of large sparse files. Older e2fsck with the old(er) bogus i_size checks didn't handle this correctly.bitmap-optimize
parent
bcf9c5d401
commit
da307041e7
|
@ -1,3 +1,15 @@
|
||||||
|
2002-05-21 Theodore Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
|
* pass1.c (process_block): If an inode has too many blocks or
|
||||||
|
is too big, then offer to truncate the inode.
|
||||||
|
(check_blocks): Don't bother checking the size to see if
|
||||||
|
it's too big, since that's just a symptom, not the disease
|
||||||
|
(which we're now appropriately checking in process_block).
|
||||||
|
|
||||||
|
* problem.c, problem.h: Add new problem codes PR_1_INODE_TOOBIG,
|
||||||
|
PR_1_TOOBIG_DIR, PR_1_TOOBIG_REG, PR_1_TOOBIG_SYMLINK, and
|
||||||
|
add the latch code PR_LATCH_TOOBIG.
|
||||||
|
|
||||||
2002-05-20 Theodore Ts'o <tytso@mit.edu>
|
2002-05-20 Theodore Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
* e2fsck.h, pass1.c (e2fsck_pass1_check_symlink), pass2.c
|
* e2fsck.h, pass1.c (e2fsck_pass1_check_symlink), pass2.c
|
||||||
|
|
|
@ -76,9 +76,10 @@ static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
|
||||||
|
|
||||||
struct process_block_struct {
|
struct process_block_struct {
|
||||||
ext2_ino_t ino;
|
ext2_ino_t ino;
|
||||||
int is_dir:1, clear:1, suppress:1,
|
int is_dir:1, is_reg:1, clear:1, suppress:1,
|
||||||
fragmented:1, compressed:1;
|
fragmented:1, compressed:1;
|
||||||
blk_t num_blocks;
|
blk_t num_blocks;
|
||||||
|
blk_t max_blocks;
|
||||||
e2_blkcnt_t last_block;
|
e2_blkcnt_t last_block;
|
||||||
int num_illegal_blocks;
|
int num_illegal_blocks;
|
||||||
blk_t previous_block;
|
blk_t previous_block;
|
||||||
|
@ -410,7 +411,7 @@ void e2fsck_pass1(e2fsck_t ctx)
|
||||||
pb.num_blocks = pb.last_block = 0;
|
pb.num_blocks = pb.last_block = 0;
|
||||||
pb.num_illegal_blocks = 0;
|
pb.num_illegal_blocks = 0;
|
||||||
pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
|
pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
|
||||||
pb.fragmented = 0;
|
pb.is_reg = 0; pb.fragmented = 0;
|
||||||
pb.inode = &inode;
|
pb.inode = &inode;
|
||||||
pb.pctx = &pctx;
|
pb.pctx = &pctx;
|
||||||
pb.ctx = ctx;
|
pb.ctx = ctx;
|
||||||
|
@ -1150,6 +1151,8 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
|
||||||
pb.compressed = 0;
|
pb.compressed = 0;
|
||||||
pb.previous_block = 0;
|
pb.previous_block = 0;
|
||||||
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
|
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
|
||||||
|
pb.is_reg = LINUX_S_ISREG(inode->i_mode);
|
||||||
|
pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
|
||||||
pb.inode = inode;
|
pb.inode = inode;
|
||||||
pb.pctx = pctx;
|
pb.pctx = pctx;
|
||||||
pb.ctx = ctx;
|
pb.ctx = ctx;
|
||||||
|
@ -1174,6 +1177,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
|
||||||
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
|
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
|
||||||
return;
|
return;
|
||||||
end_problem_latch(ctx, PR_LATCH_BLOCK);
|
end_problem_latch(ctx, PR_LATCH_BLOCK);
|
||||||
|
end_problem_latch(ctx, PR_LATCH_TOOBIG);
|
||||||
if (pctx->errcode)
|
if (pctx->errcode)
|
||||||
fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
|
fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
|
||||||
|
|
||||||
|
@ -1221,25 +1225,21 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
|
||||||
}
|
}
|
||||||
if (pb.is_dir) {
|
if (pb.is_dir) {
|
||||||
int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
|
int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
|
||||||
/* We don't let a directory become larger than 2GB */
|
if (nblock > (pb.last_block + 1))
|
||||||
if (nblock > (pb.last_block + 1) ||
|
|
||||||
(inode->i_size & ((fs->blocksize-1) | 0x80000000UL)) != 0)
|
|
||||||
bad_size = 1;
|
bad_size = 1;
|
||||||
else if (nblock < (pb.last_block + 1)) {
|
else if (nblock < (pb.last_block + 1)) {
|
||||||
if (((pb.last_block + 1) - nblock) >
|
if (((pb.last_block + 1) - nblock) >
|
||||||
fs->super->s_prealloc_dir_blocks)
|
fs->super->s_prealloc_dir_blocks)
|
||||||
bad_size = 2;
|
bad_size = 2;
|
||||||
}
|
}
|
||||||
} else if (!LINUX_S_ISREG(inode->i_mode)) {
|
|
||||||
if (inode->i_size_high)
|
|
||||||
bad_size = 5;
|
|
||||||
} else {
|
} else {
|
||||||
|
if (!LINUX_S_ISREG(inode->i_mode) && inode->i_size_high)
|
||||||
|
bad_size = 5;
|
||||||
size = inode->i_size | ((__u64) inode->i_size_high << 32);
|
size = inode->i_size | ((__u64) inode->i_size_high << 32);
|
||||||
if ((size < pb.last_block * fs->blocksize))
|
if ((size < pb.last_block * fs->blocksize))
|
||||||
bad_size = 3;
|
bad_size = 3;
|
||||||
else if (size > ext2_max_sizes[fs->super->s_log_block_size])
|
else if (size > ext2_max_sizes[fs->super->s_log_block_size])
|
||||||
bad_size = 4;
|
bad_size = 4;
|
||||||
/* FIXME: need to ensure pb.num_blocks < 2^32 */
|
|
||||||
}
|
}
|
||||||
if (bad_size) {
|
if (bad_size) {
|
||||||
pctx->num = (pb.last_block+1) * fs->blocksize;
|
pctx->num = (pb.last_block+1) * fs->blocksize;
|
||||||
|
@ -1400,6 +1400,13 @@ static int process_block(ext2_filsys fs,
|
||||||
}
|
}
|
||||||
p->previous_block = blk;
|
p->previous_block = blk;
|
||||||
|
|
||||||
|
if (p->is_dir && blockcnt > 2*1024*1024/fs->blocksize)
|
||||||
|
problem = PR_1_TOOBIG_DIR;
|
||||||
|
if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
|
||||||
|
problem = PR_1_TOOBIG_REG;
|
||||||
|
if (!p->is_dir && !p->is_reg && blockcnt > 0)
|
||||||
|
problem = PR_1_TOOBIG_SYMLINK;
|
||||||
|
|
||||||
if (blk < fs->super->s_first_data_block ||
|
if (blk < fs->super->s_first_data_block ||
|
||||||
blk >= fs->super->s_blocks_count)
|
blk >= fs->super->s_blocks_count)
|
||||||
problem = PR_1_ILLEGAL_BLOCK_NUM;
|
problem = PR_1_ILLEGAL_BLOCK_NUM;
|
||||||
|
|
|
@ -89,6 +89,7 @@ static const char *preen_msg[] = {
|
||||||
N_("FILE DELETED"), /* 15 */
|
N_("FILE DELETED"), /* 15 */
|
||||||
N_("SUPPRESSED"), /* 16 */
|
N_("SUPPRESSED"), /* 16 */
|
||||||
N_("UNLINKED"), /* 17 */
|
N_("UNLINKED"), /* 17 */
|
||||||
|
"", /* 18 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct e2fsck_problem problem_table[] = {
|
static const struct e2fsck_problem problem_table[] = {
|
||||||
|
@ -645,6 +646,25 @@ static const struct e2fsck_problem problem_table[] = {
|
||||||
N_("@a @b %b is corrupt (invalid value). "),
|
N_("@a @b %b is corrupt (invalid value). "),
|
||||||
PROMPT_CLEAR, 0},
|
PROMPT_CLEAR, 0},
|
||||||
|
|
||||||
|
/* Inode too big (latch question) */
|
||||||
|
{ PR_1_INODE_TOOBIG,
|
||||||
|
N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 },
|
||||||
|
|
||||||
|
/* Directory too big */
|
||||||
|
{ PR_1_TOOBIG_DIR,
|
||||||
|
N_("@b #%B (%b) causes @d to be too big. "),
|
||||||
|
PROMPT_CLEAR, PR_LATCH_TOOBIG },
|
||||||
|
|
||||||
|
/* Regular file too big */
|
||||||
|
{ PR_1_TOOBIG_REG,
|
||||||
|
N_("@b #%B (%b) causes file to be too big. "),
|
||||||
|
PROMPT_CLEAR, PR_LATCH_TOOBIG },
|
||||||
|
|
||||||
|
/* Symlink too big */
|
||||||
|
{ PR_1_TOOBIG_SYMLINK,
|
||||||
|
N_("@b #%B (%b) causes symlink to be too big. "),
|
||||||
|
PROMPT_CLEAR, PR_LATCH_TOOBIG },
|
||||||
|
|
||||||
/* Pass 1b errors */
|
/* Pass 1b errors */
|
||||||
|
|
||||||
/* Pass 1B: Rescan for duplicate/bad blocks */
|
/* Pass 1B: Rescan for duplicate/bad blocks */
|
||||||
|
@ -1255,6 +1275,7 @@ static struct latch_descr pr_latch_info[] = {
|
||||||
{ PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
|
{ PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
|
||||||
{ PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
|
{ PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
|
||||||
{ PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
|
{ PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
|
||||||
|
{ PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
|
||||||
{ -1, 0, 0 },
|
{ -1, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct problem_context {
|
||||||
#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
|
#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
|
||||||
#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
|
#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
|
||||||
#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
|
#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
|
||||||
|
#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
|
||||||
|
|
||||||
#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
|
#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
|
||||||
|
|
||||||
|
@ -372,6 +373,18 @@ struct problem_context {
|
||||||
/* Bad extended attribute value */
|
/* Bad extended attribute value */
|
||||||
#define PR_1_EA_BAD_VALUE 0x010042
|
#define PR_1_EA_BAD_VALUE 0x010042
|
||||||
|
|
||||||
|
/* Inode too big (latch question) */
|
||||||
|
#define PR_1_INODE_TOOBIG 0x010043
|
||||||
|
|
||||||
|
/* Directory too big */
|
||||||
|
#define PR_1_TOOBIG_DIR 0x010044
|
||||||
|
|
||||||
|
/* Regular file too big */
|
||||||
|
#define PR_1_TOOBIG_REG 0x010045
|
||||||
|
|
||||||
|
/* Symlink too big */
|
||||||
|
#define PR_1_TOOBIG_SYMLINK 0x010046
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pass 1b errors
|
* Pass 1b errors
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
2002-05-21 Theodore Ts'o <tytso@mit.edu>
|
2002-05-21 Theodore Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
|
* f_badsymlinks: Check for symlink too big error message.
|
||||||
|
|
||||||
|
* f_lotsbad: Check for directory too big error message.
|
||||||
|
|
||||||
|
* f_big_sparse: New test case which e2fsck's response to a large,
|
||||||
|
sparse file, and tests the code which adds the LARGE_FILE
|
||||||
|
feature to a filesystem.
|
||||||
|
|
||||||
* f_badsymlinks, f_filetype: Revert expected text since we're no
|
* f_badsymlinks, f_filetype: Revert expected text since we're no
|
||||||
longer checking for EXT2_INDEX_FL along with the other
|
longer checking for EXT2_INDEX_FL along with the other
|
||||||
immutable flags.
|
immutable flags.
|
||||||
|
|
|
@ -12,6 +12,11 @@ Inode 19, i_blocks is 2, should be 0. Fix? yes
|
||||||
Special (device/socket/fifo/symlink) file (inode 20) has immutable
|
Special (device/socket/fifo/symlink) file (inode 20) has immutable
|
||||||
or append-only flag set. Clear? yes
|
or append-only flag set. Clear? yes
|
||||||
|
|
||||||
|
Inode 21 is too big. Truncate? yes
|
||||||
|
|
||||||
|
Block #1 (22) causes symlink to be too big. CLEARED.
|
||||||
|
Inode 21, i_blocks is 4, should be 2. Fix? yes
|
||||||
|
|
||||||
Pass 2: Checking directory structure
|
Pass 2: Checking directory structure
|
||||||
Symlink /empty_link (inode #17) is invalid.
|
Symlink /empty_link (inode #17) is invalid.
|
||||||
Clear? yes
|
Clear? yes
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Inode 12, i_size is 61440, should be 4398050758656. Fix? yes
|
||||||
|
|
||||||
|
Pass 2: Checking directory structure
|
||||||
|
Filesystem contains large files, but lacks LARGE_FILE flag in superblock.
|
||||||
|
Fix? yes
|
||||||
|
|
||||||
|
Filesystem has feature flag(s) set, but is a revision 0 filesystem. Fix? yes
|
||||||
|
|
||||||
|
Pass 3: Checking directory connectivity
|
||||||
|
Pass 4: Checking reference counts
|
||||||
|
Pass 5: Checking group summary information
|
||||||
|
|
||||||
|
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
|
||||||
|
test_filesys: 12/64 files (0.0% non-contiguous), 27/100 blocks
|
||||||
|
Exit status is 1
|
|
@ -0,0 +1,7 @@
|
||||||
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Pass 2: Checking directory structure
|
||||||
|
Pass 3: Checking directory connectivity
|
||||||
|
Pass 4: Checking reference counts
|
||||||
|
Pass 5: Checking group summary information
|
||||||
|
test_filesys: 12/64 files (0.0% non-contiguous), 27/100 blocks
|
||||||
|
Exit status is 0
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
big sparse file
|
|
@ -1,6 +1,13 @@
|
||||||
Filesystem did not have a UUID; generating one.
|
Filesystem did not have a UUID; generating one.
|
||||||
|
|
||||||
Pass 1: Checking inodes, blocks, and sizes
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Inode 13 is too big. Truncate? yes
|
||||||
|
|
||||||
|
Block #16580876 (74) causes directory to be too big. CLEARED.
|
||||||
|
Inode 13, i_size is 15360, should be 12288. Fix? yes
|
||||||
|
|
||||||
|
Inode 13, i_blocks is 32, should be 30. Fix? yes
|
||||||
|
|
||||||
Inode 12 has illegal block(s). Clear? yes
|
Inode 12 has illegal block(s). Clear? yes
|
||||||
|
|
||||||
Illegal block #12 (778398818) in inode 12. CLEARED.
|
Illegal block #12 (778398818) in inode 12. CLEARED.
|
||||||
|
@ -24,26 +31,31 @@ Entry 'termcap' in / (2) has deleted/unused inode 12. Clear? yes
|
||||||
|
|
||||||
Pass 3: Checking directory connectivity
|
Pass 3: Checking directory connectivity
|
||||||
Pass 4: Checking reference counts
|
Pass 4: Checking reference counts
|
||||||
|
Inode 2 ref count is 5, should be 4. Fix? yes
|
||||||
|
|
||||||
Pass 5: Checking group summary information
|
Pass 5: Checking group summary information
|
||||||
Block bitmap differences: -(27--41) -(44--45)
|
Block bitmap differences: -(27--41) -(44--45) -(74--90)
|
||||||
Fix? yes
|
Fix? yes
|
||||||
|
|
||||||
Free blocks count wrong for group #0 (41, counted=58).
|
Free blocks count wrong for group #0 (9, counted=43).
|
||||||
Fix? yes
|
Fix? yes
|
||||||
|
|
||||||
Free blocks count wrong (41, counted=58).
|
Free blocks count wrong (9, counted=43).
|
||||||
Fix? yes
|
Fix? yes
|
||||||
|
|
||||||
Inode bitmap differences: -12
|
Inode bitmap differences: -12 -14
|
||||||
Fix? yes
|
Fix? yes
|
||||||
|
|
||||||
Free inodes count wrong for group #0 (20, counted=21).
|
Free inodes count wrong for group #0 (18, counted=20).
|
||||||
Fix? yes
|
Fix? yes
|
||||||
|
|
||||||
Free inodes count wrong (20, counted=21).
|
Directories count wrong for group #0 (4, counted=3).
|
||||||
|
Fix? yes
|
||||||
|
|
||||||
|
Free inodes count wrong (18, counted=20).
|
||||||
Fix? yes
|
Fix? yes
|
||||||
|
|
||||||
|
|
||||||
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
|
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
|
||||||
test_filesys: 11/32 files (0.0% non-contiguous), 42/100 blocks
|
test_filesys: 12/32 files (0.0% non-contiguous), 57/100 blocks
|
||||||
Exit status is 1
|
Exit status is 1
|
||||||
|
|
|
@ -3,5 +3,5 @@ Pass 2: Checking directory structure
|
||||||
Pass 3: Checking directory connectivity
|
Pass 3: Checking directory connectivity
|
||||||
Pass 4: Checking reference counts
|
Pass 4: Checking reference counts
|
||||||
Pass 5: Checking group summary information
|
Pass 5: Checking group summary information
|
||||||
test_filesys: 11/32 files (0.0% non-contiguous), 42/100 blocks
|
test_filesys: 12/32 files (0.0% non-contiguous), 57/100 blocks
|
||||||
Exit status is 0
|
Exit status is 0
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue