Merge branch 'maint' into next

debian
Theodore Ts'o 2015-11-30 18:16:36 -05:00
commit 94676ef2b3
24 changed files with 258 additions and 82 deletions

View File

@ -209,8 +209,6 @@ static pass_t e2fsck_passes[] = {
e2fsck_pass1, e2fsck_pass1e, e2fsck_pass2, e2fsck_pass3, e2fsck_pass1, e2fsck_pass1e, e2fsck_pass2, e2fsck_pass3,
e2fsck_pass4, e2fsck_pass5, 0 }; e2fsck_pass4, e2fsck_pass5, 0 };
#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
int e2fsck_run(e2fsck_t ctx) int e2fsck_run(e2fsck_t ctx)
{ {
int i; int i;

View File

@ -175,10 +175,10 @@ struct resource_track {
*/ */
#define E2F_FLAG_ABORT 0x0001 /* Abort signaled */ #define E2F_FLAG_ABORT 0x0001 /* Abort signaled */
#define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */ #define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */
#define E2F_FLAG_SIGNAL_MASK 0x0003 #define E2F_FLAG_SIGNAL_MASK (E2F_FLAG_ABORT | E2F_FLAG_CANCEL)
#define E2F_FLAG_RESTART 0x0004 /* Restart signaled */ #define E2F_FLAG_RESTART 0x0004 /* Restart signaled */
#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK | E2F_FLAG_RESTART)
#define E2F_FLAG_RESTART_LATER 0x0008 /* Restart after all iterations done */ #define E2F_FLAG_RESTART_LATER 0x0008 /* Restart after all iterations done */
#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */ #define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
#define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */ #define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */

View File

@ -482,6 +482,10 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
return; return;
} }
/* check if there is no place for an EA header */
if (inode->i_extra_isize >= max - sizeof(__u32))
return;
eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
inode->i_extra_isize); inode->i_extra_isize);
if (*eamagic == EXT2_EXT_ATTR_MAGIC) { if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
@ -1166,7 +1170,7 @@ void e2fsck_pass1(e2fsck_t ctx)
pass1_readahead(ctx, &ra_group, &ino_threshold); pass1_readahead(ctx, &ra_group, &ino_threshold);
ehandler_operation(old_op); ehandler_operation(old_op);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK) if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return; goto endit;
if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) { if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
/* /*
* If badblocks says badblocks is bad, offer to clear * If badblocks says badblocks is bad, offer to clear
@ -1847,6 +1851,8 @@ endit:
if ((ctx->flags & E2F_FLAG_SIGNAL_MASK) == 0) if ((ctx->flags & E2F_FLAG_SIGNAL_MASK) == 0)
print_resource_track(ctx, _("Pass 1"), &rtrack, ctx->fs->io); print_resource_track(ctx, _("Pass 1"), &rtrack, ctx->fs->io);
else
ctx->invalid_bitmaps++;
} }
#undef FINISH_INODE_LOOP #undef FINISH_INODE_LOOP
@ -2820,7 +2826,20 @@ static void check_blocks_extents(e2fsck_t ctx, struct problem_context *pctx,
ext2_ino_t ino = pctx->ino; ext2_ino_t ino = pctx->ino;
errcode_t retval; errcode_t retval;
blk64_t eof_lblk; blk64_t eof_lblk;
struct ext3_extent_header *eh;
/* Check for a proper extent header... */
eh = (struct ext3_extent_header *) &inode->i_block[0];
retval = ext2fs_extent_header_verify(eh, sizeof(inode->i_block));
if (retval) {
if (fix_problem(ctx, PR_1_MISSING_EXTENT_HEADER, pctx))
e2fsck_clear_inode(ctx, ino, inode, 0,
"check_blocks_extents");
pctx->errcode = 0;
return;
}
/* ...since this function doesn't fail if i_block is zeroed. */
pctx->errcode = ext2fs_extent_open2(fs, ino, inode, &ehandle); pctx->errcode = ext2fs_extent_open2(fs, ino, inode, &ehandle);
if (pctx->errcode) { if (pctx->errcode) {
if (fix_problem(ctx, PR_1_READ_EXTENT, pctx)) if (fix_problem(ctx, PR_1_READ_EXTENT, pctx))

View File

@ -161,14 +161,14 @@ void e2fsck_pass2(e2fsck_t ctx)
check_dir_func = cd.ra_entries ? check_dir_block2 : check_dir_block; check_dir_func = cd.ra_entries ? check_dir_block2 : check_dir_block;
cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_func, cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_func,
&cd); &cd);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
return;
if (ctx->flags & E2F_FLAG_RESTART_LATER) { if (ctx->flags & E2F_FLAG_RESTART_LATER) {
ctx->flags |= E2F_FLAG_RESTART; ctx->flags |= E2F_FLAG_RESTART;
return; ctx->flags &= ~E2F_FLAG_RESTART_LATER;
} }
if (ctx->flags & E2F_FLAG_RUN_RETURN)
return;
if (cd.pctx.errcode) { if (cd.pctx.errcode) {
fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx); fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
ctx->flags |= E2F_FLAG_ABORT; ctx->flags |= E2F_FLAG_ABORT;
@ -922,7 +922,7 @@ static int check_dir_block(ext2_filsys fs,
ibuf = buf = cd->buf; ibuf = buf = cd->buf;
ctx = cd->ctx; ctx = cd->ctx;
if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) if (ctx->flags & E2F_FLAG_RUN_RETURN)
return DIRENT_ABORT; return DIRENT_ABORT;
if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max)) if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))

View File

@ -1114,6 +1114,11 @@ static struct e2fsck_problem problem_table[] = {
N_("@i %i on bigalloc @f cannot be @b mapped. "), N_("@i %i on bigalloc @f cannot be @b mapped. "),
PROMPT_FIX, 0 }, PROMPT_FIX, 0 },
/* Inode has corrupt extent header */
{ PR_1_MISSING_EXTENT_HEADER,
N_("@i %i has corrupt @x header. "),
PROMPT_CLEAR_INODE, 0 },
/* Pass 1b errors */ /* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */ /* Pass 1B: Rescan for duplicate/bad blocks */

View File

@ -651,6 +651,9 @@ struct problem_context {
/* bigalloc fs cannot have blockmap files */ /* bigalloc fs cannot have blockmap files */
#define PR_1_NO_BIGALLOC_BLOCKMAP_FILES 0x010080 #define PR_1_NO_BIGALLOC_BLOCKMAP_FILES 0x010080
/* Missing extent header */
#define PR_1_MISSING_EXTENT_HEADER 0x010081
/* /*
* Pass 1b errors * Pass 1b errors
*/ */

View File

@ -71,6 +71,8 @@ int e2fsck_dir_will_be_rehashed(e2fsck_t ctx, ext2_ino_t ino)
return ext2fs_u32_list_test(ctx->dirs_to_hash, ino); return ext2fs_u32_list_test(ctx->dirs_to_hash, ino);
} }
#undef REHASH_DEBUG
struct fill_dir_struct { struct fill_dir_struct {
char *buf; char *buf;
struct ext2_inode *inode; struct ext2_inode *inode;
@ -684,8 +686,8 @@ static errcode_t calculate_tree(ext2_filsys fs,
struct write_dir_struct { struct write_dir_struct {
struct out_dir *outdir; struct out_dir *outdir;
errcode_t err; errcode_t err;
ext2_ino_t ino;
e2fsck_t ctx; e2fsck_t ctx;
blk64_t cleared;
ext2_ino_t dir; ext2_ino_t dir;
}; };
@ -703,10 +705,15 @@ static int write_dir_block(ext2_filsys fs,
blk64_t blk; blk64_t blk;
char *dir, *buf = 0; char *dir, *buf = 0;
if (*block_nr == 0) #ifdef REHASH_DEBUG
return 0; printf("%u: write_dir_block %lld:%lld", wd->ino, blockcnt, *block_nr);
if (blockcnt < 0) #endif
if ((*block_nr == 0) || (blockcnt < 0)) {
#ifdef REHASH_DEBUG
printf(" - skip\n");
#endif
return 0; return 0;
}
if (blockcnt < wd->outdir->num) if (blockcnt < wd->outdir->num)
dir = wd->outdir->buf + (blockcnt * fs->blocksize); dir = wd->outdir->buf + (blockcnt * fs->blocksize);
else if (wd->ctx->lost_and_found == wd->dir) { else if (wd->ctx->lost_and_found == wd->dir) {
@ -717,26 +724,20 @@ static int write_dir_block(ext2_filsys fs,
dir = buf; dir = buf;
wd->outdir->num++; wd->outdir->num++;
} else { } else {
/* We don't need this block, so release it */ /* Don't free blocks at the end of the directory, they
e2fsck_read_bitmaps(wd->ctx); * will be truncated by the caller. */
blk = *block_nr; #ifdef REHASH_DEBUG
/* printf(" - not freed\n");
* In theory, we only release blocks from the end of the #endif
* directory file, so it's fine to clobber a whole cluster at return 0;
* once.
*/
if (blk % EXT2FS_CLUSTER_RATIO(fs) == 0) {
ext2fs_block_alloc_stats2(fs, blk, -1);
wd->cleared++;
}
*block_nr = 0;
return BLOCK_CHANGED;
} }
wd->err = ext2fs_write_dir_block4(fs, *block_nr, dir, 0, wd->dir); wd->err = ext2fs_write_dir_block4(fs, *block_nr, dir, 0, wd->dir);
if (buf) if (buf)
ext2fs_free_mem(&buf); ext2fs_free_mem(&buf);
#ifdef REHASH_DEBUG
printf(" - write (%d)\n", wd->err);
#endif
if (wd->err) if (wd->err)
return BLOCK_ABORT; return BLOCK_ABORT;
return 0; return 0;
@ -756,11 +757,11 @@ static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
wd.outdir = outdir; wd.outdir = outdir;
wd.err = 0; wd.err = 0;
wd.ino = ino;
wd.ctx = ctx; wd.ctx = ctx;
wd.cleared = 0;
wd.dir = ino; wd.dir = ino;
retval = ext2fs_block_iterate3(fs, ino, 0, 0, retval = ext2fs_block_iterate3(fs, ino, 0, NULL,
write_dir_block, &wd); write_dir_block, &wd);
if (retval) if (retval)
return retval; return retval;
@ -772,14 +773,17 @@ static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
inode->i_flags &= ~EXT2_INDEX_FL; inode->i_flags &= ~EXT2_INDEX_FL;
else else
inode->i_flags |= EXT2_INDEX_FL; inode->i_flags |= EXT2_INDEX_FL;
retval = ext2fs_inode_size_set(fs, inode, #ifdef REHASH_DEBUG
outdir->num * fs->blocksize); printf("%u: set inode size to %u blocks = %u bytes\n",
ino, outdir->num, outdir->num * fs->blocksize);
#endif
retval = ext2fs_inode_size_set(fs, inode, (ext2_off64_t)outdir->num *
fs->blocksize);
if (retval) if (retval)
return retval; return retval;
ext2fs_iblk_sub_blocks(fs, inode, wd.cleared);
e2fsck_write_inode(ctx, ino, inode, "rehash_dir");
return 0; /* ext2fs_punch() calls ext2fs_write_inode() which writes the size */
return ext2fs_punch(fs, ino, inode, NULL, outdir->num, ~0ULL);
} }
errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino, errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
@ -789,12 +793,9 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
errcode_t retval; errcode_t retval;
struct ext2_inode inode; struct ext2_inode inode;
char *dir_buf = 0; char *dir_buf = 0;
struct fill_dir_struct fd; struct fill_dir_struct fd = { NULL };
struct out_dir outdir; struct out_dir outdir = { 0 };
outdir.max = outdir.num = 0;
outdir.buf = 0;
outdir.hashes = 0;
e2fsck_read_inode(ctx, ino, &inode, "rehash_dir"); e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
if (ext2fs_has_feature_inline_data(fs->super) && if (ext2fs_has_feature_inline_data(fs->super) &&
@ -802,24 +803,19 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino,
return 0; return 0;
retval = ENOMEM; retval = ENOMEM;
fd.harray = 0;
dir_buf = malloc(inode.i_size); dir_buf = malloc(inode.i_size);
if (!dir_buf) if (!dir_buf)
goto errout; goto errout;
fd.max_array = inode.i_size / 32; fd.max_array = inode.i_size / 32;
fd.num_array = 0;
fd.harray = malloc(fd.max_array * sizeof(struct hash_entry)); fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
if (!fd.harray) if (!fd.harray)
goto errout; goto errout;
fd.ino = ino;
fd.ctx = ctx; fd.ctx = ctx;
fd.buf = dir_buf; fd.buf = dir_buf;
fd.inode = &inode; fd.inode = &inode;
fd.ino = ino;
fd.err = 0;
fd.dir_size = 0;
fd.compress = 0;
fd.dir = ino; fd.dir = ino;
if (!ext2fs_has_feature_dir_index(fs->super) || if (!ext2fs_has_feature_dir_index(fs->super) ||
(inode.i_size / fs->blocksize) < 2) (inode.i_size / fs->blocksize) < 2)

View File

@ -1819,8 +1819,15 @@ print_unsupp_features:
} }
no_journal: no_journal:
if (ctx->qctx) { if (run_result & E2F_FLAG_ABORT) {
fatal_error(ctx, _("aborted"));
} else if (run_result & E2F_FLAG_CANCEL) {
log_out(ctx, _("%s: e2fsck canceled.\n"), ctx->device_name ?
ctx->device_name : ctx->filesystem_name);
exit_value |= FSCK_CANCELED;
} else if (ctx->qctx && !ctx->invalid_bitmaps) {
int i, needs_writeout; int i, needs_writeout;
for (i = 0; i < MAXQUOTAS; i++) { for (i = 0; i < MAXQUOTAS; i++) {
if (qtype != -1 && qtype != i) if (qtype != -1 && qtype != i)
continue; continue;
@ -1847,18 +1854,13 @@ no_journal:
ext2fs_close_free(&ctx->fs); ext2fs_close_free(&ctx->fs);
goto restart; goto restart;
} }
if (run_result & E2F_FLAG_ABORT)
fatal_error(ctx, _("aborted"));
#ifdef MTRACE #ifdef MTRACE
mtrace_print("Cleanup"); mtrace_print("Cleanup");
#endif #endif
was_changed = ext2fs_test_changed(fs); was_changed = ext2fs_test_changed(fs);
if (run_result & E2F_FLAG_CANCEL) { if (!(ctx->flags & E2F_FLAG_RUN_RETURN) &&
log_out(ctx, _("%s: e2fsck canceled.\n"), ctx->device_name ? !(ctx->options & E2F_OPT_READONLY)) {
ctx->device_name : ctx->filesystem_name);
exit_value |= FSCK_CANCELED;
} else if (!(ctx->options & E2F_OPT_READONLY)) {
if (ext2fs_test_valid(fs)) { if (ext2fs_test_valid(fs)) {
if (!(sb->s_state & EXT2_VALID_FS)) if (!(sb->s_state & EXT2_VALID_FS))
exit_value |= FSCK_NONDESTRUCT; exit_value |= FSCK_NONDESTRUCT;

View File

@ -48,7 +48,7 @@ static int check_zero_block(char *buf, int blocksize)
*/ */
static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode, static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode,
char *block_buf, blk_t *p, int level, char *block_buf, blk_t *p, int level,
blk_t start, blk_t count, int max) blk64_t start, blk64_t count, int max)
{ {
errcode_t retval; errcode_t retval;
blk_t b; blk_t b;
@ -57,11 +57,11 @@ static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode,
int freed = 0; int freed = 0;
#ifdef PUNCH_DEBUG #ifdef PUNCH_DEBUG
printf("Entering ind_punch, level %d, start %u, count %u, " printf("Entering ind_punch, level %d, start %llu, count %llu, "
"max %d\n", level, start, count, max); "max %d\n", level, start, count, max);
#endif #endif
incr = 1ULL << ((EXT2_BLOCK_SIZE_BITS(fs->super)-2)*level); incr = 1ULL << ((EXT2_BLOCK_SIZE_BITS(fs->super) - 2) * level);
for (i=0, offset=0; i < max; i++, p++, offset += incr) { for (i = 0, offset = 0; i < max; i++, p++, offset += incr) {
if (offset >= start + count) if (offset >= start + count)
break; break;
if (*p == 0 || (offset+incr) <= start) if (*p == 0 || (offset+incr) <= start)
@ -101,8 +101,9 @@ static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode,
return ext2fs_iblk_sub_blocks(fs, inode, freed); return ext2fs_iblk_sub_blocks(fs, inode, freed);
} }
#define BLK_T_MAX ((blk_t)~0ULL)
static errcode_t ext2fs_punch_ind(ext2_filsys fs, struct ext2_inode *inode, static errcode_t ext2fs_punch_ind(ext2_filsys fs, struct ext2_inode *inode,
char *block_buf, blk_t start, blk_t count) char *block_buf, blk64_t start, blk64_t end)
{ {
errcode_t retval; errcode_t retval;
char *buf = 0; char *buf = 0;
@ -111,6 +112,15 @@ static errcode_t ext2fs_punch_ind(ext2_filsys fs, struct ext2_inode *inode,
blk_t *bp = inode->i_block; blk_t *bp = inode->i_block;
blk_t addr_per_block; blk_t addr_per_block;
blk64_t max = EXT2_NDIR_BLOCKS; blk64_t max = EXT2_NDIR_BLOCKS;
blk_t count;
/* Check start/end don't overflow the 2^32-1 indirect block limit */
if (start > BLK_T_MAX)
return 0;
if (end >= BLK_T_MAX || end - start + 1 >= BLK_T_MAX)
count = BLK_T_MAX - start;
else
count = end - start + 1;
if (!block_buf) { if (!block_buf) {
retval = ext2fs_get_array(3, fs->blocksize, &buf); retval = ext2fs_get_array(3, fs->blocksize, &buf);
@ -119,11 +129,11 @@ static errcode_t ext2fs_punch_ind(ext2_filsys fs, struct ext2_inode *inode,
block_buf = buf; block_buf = buf;
} }
addr_per_block = (blk_t) fs->blocksize >> 2; addr_per_block = (blk_t)fs->blocksize >> 2;
for (level = 0; level < 4; level++, max *= (blk64_t)addr_per_block) { for (level = 0; level < 4; level++, max *= (blk64_t)addr_per_block) {
#ifdef PUNCH_DEBUG #ifdef PUNCH_DEBUG
printf("Main loop level %d, start %u count %u " printf("Main loop level %d, start %llu count %u "
"max %llu num %d\n", level, start, count, max, num); "max %llu num %d\n", level, start, count, max, num);
#endif #endif
if (start < max) { if (start < max) {
@ -150,6 +160,7 @@ errout:
ext2fs_free_mem(&buf); ext2fs_free_mem(&buf);
return retval; return retval;
} }
#undef BLK_T_MAX
#ifdef PUNCH_DEBUG #ifdef PUNCH_DEBUG
@ -460,8 +471,8 @@ static errcode_t ext2fs_punch_inline_data(ext2_filsys fs, ext2_ino_t ino,
} }
/* /*
* Deallocate all logical blocks starting at start to end, inclusive. * Deallocate all logical _blocks_ starting at start to end, inclusive.
* If end is ~0, then this is effectively truncate. * If end is ~0ULL, then this is effectively truncate.
*/ */
errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino, errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode, struct ext2_inode *inode,
@ -485,19 +496,14 @@ errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino,
return ext2fs_punch_inline_data(fs, ino, inode, start, end); return ext2fs_punch_inline_data(fs, ino, inode, start, end);
else if (inode->i_flags & EXT4_EXTENTS_FL) else if (inode->i_flags & EXT4_EXTENTS_FL)
retval = ext2fs_punch_extent(fs, ino, inode, start, end); retval = ext2fs_punch_extent(fs, ino, inode, start, end);
else { else
blk_t count; retval = ext2fs_punch_ind(fs, inode, block_buf, start, end);
if (start > ~0U)
return 0;
if (end > ~0U)
end = ~0U;
count = ((end - start + 1) < ~0U) ? (end - start + 1) : ~0U;
retval = ext2fs_punch_ind(fs, inode, block_buf,
(blk_t) start, count);
}
if (retval) if (retval)
return retval; return retval;
#ifdef PUNCH_DEBUG
printf("%u: write inode size now %u blocks %u\n",
ino, inode->i_size, inode->i_blocks);
#endif
return ext2fs_write_inode(fs, ino, inode); return ext2fs_write_inode(fs, ino, inode);
} }

View File

@ -30,11 +30,11 @@
#define DEL_BLK 0x0002 #define DEL_BLK 0x0002
blk_t test1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 }; blk_t test1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
blk_t test2[] = { 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 1 }; blk_t test2[] = { 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 1, 0 };
blk_t test3[] = { 3, 1, 4, 5, 9, 2, 7, 10, 5, 6, 10, 8, 0 }; blk_t test3[] = { 3, 1, 4, 5, 9, 2, 7, 10, 5, 6, 10, 8, 0 };
blk_t test4[] = { 20, 50, 12, 17, 13, 2, 66, 23, 56, 0 }; blk_t test4[] = { 20, 50, 12, 17, 13, 2, 66, 23, 56, 0 };
blk_t test4a[] = { blk_t test4a[] = {
20, 1, 20, 1,
50, 1, 50, 1,
3, 0, 3, 0,
17, 1, 17, 1,

View File

@ -93,7 +93,7 @@ set on new or empty files. If it is set on a file which already has
data blocks, it is undefined when the blocks assigned to the file will data blocks, it is undefined when the blocks assigned to the file will
be fully stable. If the 'C' flag is set on a directory, it will have no be fully stable. If the 'C' flag is set on a directory, it will have no
effect on the directory, but new files created in that directory will effect on the directory, but new files created in that directory will
the No_COW attribute.) have the No_COW attribute set.)
.PP .PP
A file with the 'd' attribute set is not candidate for backup when the A file with the 'd' attribute set is not candidate for backup when the
.BR dump (8) .BR dump (8)

View File

@ -3070,6 +3070,18 @@ retry_open:
ext_mount_opts); ext_mount_opts);
free(ext_mount_opts); free(ext_mount_opts);
} }
/* Warn if file system needs recovery and it is opened for writing. */
if ((open_flag & EXT2_FLAG_RW) && !(mount_flags & EXT2_MF_MOUNTED) &&
(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER)) {
fprintf(stderr,
_("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
"\te2fsck -E journal_only %s\n\n"
"then rerun this command. Otherwise, any changes made may be overwritten\n"
"by journal recovery.\n"), device_name);
}
free(device_name); free(device_name);
remove_error_table(&et_ext2_error_table); remove_error_table(&et_ext2_error_table);

View File

@ -0,0 +1,29 @@
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 3A: Optimizing directories
Pass 4: Checking reference counts
Pass 5: Checking group summary information
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
352 inodes used (41.12%, out of 856)
0 non-contiguous files (0.0%)
1 non-contiguous directory (0.3%)
# of inodes with ind/dind/tind blocks: 0/0/0
Extent depth histogram: 342/1
586 blocks used (68.94%, out of 850)
0 bad blocks
0 large files
340 regular files
3 directories
0 character device files
0 block device files
0 fifos
0 links
0 symbolic links (0 fast symbolic links)
0 sockets
------------
343 files
Exit status is 1

View File

@ -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: 352/856 files (0.3% non-contiguous), 586/850 blocks
Exit status is 0

Binary file not shown.

View File

@ -0,0 +1 @@
htree extent compression

View File

@ -0,0 +1,69 @@
#!/bin/bash
FSCK_OPT="-fyvD"
. $cmd_dir/run_e2fsck
exit $?
# This script depends on "mke2fs -d", which is only in master and not maint,
# to populate the file directory tree poorly (namely that there are no
# contiguous blocks in the directory leaf and the extent tree is large).
# Once the "mke2fs -d" option is available on the "maint" branch, the
# above few lines should be deleted, along with the "image.gz" file.
TMPDIR=${TMPDIR:-"/tmp"}
OUT=$test_name.log
FSCK_OPT="-fyvD"
SKIP_GUNZIP="true"
NAMELEN=250
SRC=$TMPDIR/$test_name.tmp
SUB=subdir
BASE=$SRC/$SUB/$(yes | tr -d '\n' | dd bs=$NAMELEN count=1 2> /dev/null)
TMPFILE=${TMPFILE:-"$TMPDIR/image"}
BSIZE=1024
> $OUT
mkdir -p $SRC/$SUB
# calculate the number of files needed to create the directory extent tree
# deep enough to exceed the in-inode index and spill into an index block.
#
# dirents per block * extents per block * (index blocks > i_blocks)
NUM=$(((BSIZE / (NAMELEN + 8)) * (BSIZE / 12) * 2))
# Create source files. Unfortunately hard links will be copied as links,
# and blocks with only NULs will be turned into holes.
if [ ! -f $BASE.1 ]; then
for N in $(seq $NUM); do
echo "foo" > $BASE.$N
done >> $OUT
fi
# make filesystem with enough inodes and blocks to hold all the test files
> $TMPFILE
NUM=$((NUM * 5 / 3))
echo "mke2fs -b $BSIZE -O dir_index,extent -d$SRC -N$NUM $TMPFILE $NUM" >> $OUT
$MKE2FS -b $BSIZE -O dir_index,extent -d$SRC -N$NUM $TMPFILE $NUM >> $OUT 2>&1
rm -r $SRC
# Run e2fsck to convert dir to htree before deleting the files, as mke2fs
# doesn't do this. Run second e2fsck to verify there is no corruption yet.
(
EXP1=$test_dir/expect.pre.1
EXP2=$test_dir/expect.pre.2
OUT1=$test_name.pre.1.log
OUT2=$test_name.pre.2.log
DESCRIPTION="$(cat $test_dir/name) setup"
. $cmd_dir/run_e2fsck
)
# generate a list of filenames for debugfs to delete, one from each leaf block
DELETE_LIST=$TMPDIR/delete.$$
$DEBUGFS -c -R "htree subdir" $TMPFILE 2>> $OUT |
grep -A2 "Reading directory block" |
awk '/yyyyy/ { print "rm '$SUB'/"$4 }' > $DELETE_LIST
$DEBUGFS -w -f $DELETE_LIST $TMPFILE >> $OUT 2>&1
rm $DELETE_LIST
cp $TMPFILE $TMPFILE.sav
. $cmd_dir/run_e2fsck

View File

@ -27,8 +27,7 @@ Inode 17 extent tree (at level 1) could be shorter. Fix? yes
Inode 17, i_blocks is 32, should be 0. Fix? yes Inode 17, i_blocks is 32, should be 0. Fix? yes
Error while reading over extent tree in inode 18: Corrupt extent header Inode 18 has corrupt extent header. Clear inode? yes
Clear inode? yes
Inode 18, i_blocks is 2, should be 0. Fix? yes Inode 18, i_blocks is 2, should be 0. Fix? yes

View File

@ -14,5 +14,5 @@ Pass 4: Checking reference counts
Pass 5: Checking group summary information Pass 5: Checking group summary information
test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 47730/100192 files (0.0% non-contiguous), 13551/31745 blocks test_filesys: 47730/100192 files (0.0% non-contiguous), 13550/31745 blocks
Exit status is 1 Exit status is 1

View File

@ -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: 47730/100192 files (0.0% non-contiguous), 13551/31745 blocks test_filesys: 47730/100192 files (0.0% non-contiguous), 13550/31745 blocks
Exit status is 0 Exit status is 0

View File

@ -0,0 +1,22 @@
Pass 1: Checking inodes, blocks, and sizes
Inode 12 has corrupt extent header. Clear inode? yes
Pass 2: Checking directory structure
Entry 'testa' in / (2) has deleted/unused inode 12. Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Inode bitmap differences: -12
Fix? yes
Free inodes count wrong for group #0 (115, counted=116).
Fix? yes
Free inodes count wrong (115, counted=116).
Fix? yes
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/128 files (0.0% non-contiguous), 15/256 blocks
Exit status is 1

View File

@ -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/128 files (0.0% non-contiguous), 15/256 blocks
Exit status is 0

Binary file not shown.

View File

@ -0,0 +1 @@
zap inode with zeroed extent header