diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index 5da29d9d..8e58a035 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,71 @@ +2002-08-17 Theodore Ts'o + + * e2fsck.h, e2fsck.c (e2fsck_allocate_context): Add new field to + the e2fsck context, ext_attr_ver, which specifies the EA + format version. + + * unix.c (usage, parse_extended_opts, PRS), e2fsck.8.in: Add new + option -E, which allows the users to specify extended + options. Added ea_ver extended option. + + * pass1.c (e2fsck_pass1_check_device_inode): Add ext2_filsys + argument to this function, so we can account for the + presence of extended attribute blocks attached to device + inodes. + (e2fsck_pass1_check_symlink, e2fsck_pass1): Take into + account the fact that symlinks can also have extended + attribute blocks. + (check_ext_attr): Don't be flexible about the EA format + version. Check against the version number in + ctx->ext_attr_ver. + (check_blocks): Check all inodes, so that we account for + extended attribute blocks belonging to special files. + Clean up i_size checks. + + * pass1b.c (pass1b): Check all inodes, so that we account for + extended attribute blocks belonging to special files. + (delete_file_block): Use ext2fs_alloc_block_stats() to + update the filesystem statistics. + (delete_file): Attempt to decrement the extended + attribute refcount, and free the EA block if the count + hits zero. + (clone_file): Fixed bugs in EA handling. Don't call + block_iterate on inodes that don't have a valid i_block[] + array. Reread the base inode since it may have been + changed by ext2fs_block_iterate. When updating inodes as + part of cloning an EA block, write out the correct inode + structure. + + * pass2.c (deallocate_inode_block, deallocate_inode): Use standard + ext2fs_alloc_*_stats functions to update the filesystem + statistics. + (deallocate_inode): Attempt to decrement the extended + attribute refcount, and free the EA block if the count + hits zero. + (e2fsck_process_bad_inode): Add extra argument to calls + to e2fsck_pass1_check_device_inode (). + + * pass3.c (e2fsck_get_lost_and_found): Use standard + ext2fs_alloc_*_stats functions to update the filesystem. + statistics when creating /lost+found. + (adjust_inode_count): Remove debugging code that can never + be triggered. + + * pass4.c (disconnect_inode): Add explanation about why we only + clear inodes that have no data blocks and no EA blocks. + Use ext2fs_inode_alloc_stats2 function to update the + filesystem statistics when clearing a zero-length inode. + + * problem.c, problem.h (PR_1B_ADJ_EA_REFCOUNT, + PR_2_ADJ_EA_REFCOUNT): Add new problem codes. + + * super.c (release_inode_block), (release_orphan_inodes): Use the + standard ext2fs_alloc_*_stats functions to update the + filesystem statistics. + (release_inode_blocks): Attempt to decrement the extended + attribute refcount, and free the EA block if the count + hits zero. + 2002-08-01 Theodore Ts'o * dict.c, dict.h: New file from kazlib 1.20 which implements a diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in index 8438a306..70596266 100644 --- a/e2fsck/e2fsck.8.in +++ b/e2fsck/e2fsck.8.in @@ -30,6 +30,10 @@ e2fsck \- check a Linux second extended file system @JDEV@.B \-j @JDEV@.I external-journal @JDEV@] +[ +.B \-E +.I extended_options +] .I device .SH DESCRIPTION .B e2fsck @@ -122,6 +126,18 @@ filesystem supports directory indexing, or by sorting and compressing directories for smaller directories, or for filesystems using traditional linear directories. .TP +.BI \-E " extended_options" +Set e2fsck extended options. Extended options are comma +separated, and may take an argument using the equals ('=') sign. The +following options are supported: +.RS 1.2i +.TP +.BI ea_ver= extended_attribute_version +Assume the format of the extended attribute blocks in the filesystem is +the specified version number. The version number may be 1 or 2. The +default extended attribute version format is 2. +.RE +.TP .B \-f Force checking even if the file system seems clean. .TP diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c index e9ccbb4c..4f49ec82 100644 --- a/e2fsck/e2fsck.c +++ b/e2fsck/e2fsck.c @@ -30,6 +30,7 @@ errcode_t e2fsck_allocate_context(e2fsck_t *ret) memset(context, 0, sizeof(struct e2fsck_struct)); context->process_inode_size = 256; + context->ext_attr_ver = 2; *ret = context; return 0; diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index c2dbc26c..6fcb1e79 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -308,6 +308,8 @@ struct e2fsck_struct { int fs_ext_attr_inodes; int fs_ext_attr_blocks; + int ext_attr_ver; + /* * For the use of callers of the e2fsck functions; not used by * e2fsck functions themselves. @@ -382,7 +384,8 @@ extern void e2fsck_move_ext3_journal(e2fsck_t ctx); /* pass1.c */ extern void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool); -extern int e2fsck_pass1_check_device_inode(struct ext2_inode *inode); +extern int e2fsck_pass1_check_device_inode(ext2_filsys fs, + struct ext2_inode *inode); extern int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf); diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index ce63792f..a0e39b71 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -125,7 +125,7 @@ static void unwind_pass1(ext2_filsys fs) * since they have the same requirement; the i_block fields should be * zero. */ -int e2fsck_pass1_check_device_inode(struct ext2_inode *inode) +int e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode) { int i; @@ -133,7 +133,8 @@ int e2fsck_pass1_check_device_inode(struct ext2_inode *inode) * If i_blocks is non-zero, or the index flag is set, then * this is a bogus device/fifo/socket */ - if (inode->i_blocks || (inode->i_flags & EXT2_INDEX_FL)) + if ((ext2fs_inode_data_blocks(fs, inode) != 0) || + (inode->i_flags & EXT2_INDEX_FL)) return 0; /* @@ -179,14 +180,16 @@ int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, { int len; int i; + blk_t blocks; if ((inode->i_size_high || inode->i_size == 0) || (inode->i_flags & EXT2_INDEX_FL)) return 0; - if (inode->i_blocks) { + blocks = ext2fs_inode_data_blocks(fs, inode); + if (blocks) { if ((inode->i_size >= fs->blocksize) || - (inode->i_blocks != fs->blocksize >> 9) || + (blocks != fs->blocksize >> 9) || (inode->i_block[0] < fs->super->s_first_data_block) || (inode->i_block[0] >= fs->super->s_blocks_count)) return 0; @@ -614,12 +617,12 @@ void e2fsck_pass1(e2fsck_t ctx) ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino); ctx->fs_regular_count++; } else if (LINUX_S_ISCHR (inode.i_mode) && - e2fsck_pass1_check_device_inode(&inode)) { + e2fsck_pass1_check_device_inode(fs, &inode)) { check_immutable(ctx, &pctx); check_size(ctx, &pctx); ctx->fs_chardev_count++; } else if (LINUX_S_ISBLK (inode.i_mode) && - e2fsck_pass1_check_device_inode(&inode)) { + e2fsck_pass1_check_device_inode(fs, &inode)) { check_immutable(ctx, &pctx); check_size(ctx, &pctx); ctx->fs_blockdev_count++; @@ -627,18 +630,19 @@ void e2fsck_pass1(e2fsck_t ctx) e2fsck_pass1_check_symlink(fs, &inode, block_buf)) { check_immutable(ctx, &pctx); ctx->fs_symlinks_count++; - if (!inode.i_blocks) { + if (ext2fs_inode_data_blocks(fs, &inode) == 0) { ctx->fs_fast_symlinks_count++; + check_blocks(ctx, &pctx, block_buf); goto next; } } else if (LINUX_S_ISFIFO (inode.i_mode) && - e2fsck_pass1_check_device_inode(&inode)) { + e2fsck_pass1_check_device_inode(fs, &inode)) { check_immutable(ctx, &pctx); check_size(ctx, &pctx); ctx->fs_fifo_count++; } else if ((LINUX_S_ISSOCK (inode.i_mode)) && - e2fsck_pass1_check_device_inode(&inode)) { + e2fsck_pass1_check_device_inode(fs, &inode)) { check_immutable(ctx, &pctx); check_size(ctx, &pctx); ctx->fs_sockets_count++; @@ -990,7 +994,6 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx, struct ext2_ext_attr_entry *entry; int count; region_t region; - int ext_attr_ver; blk = inode->i_file_acl; if (blk == 0) @@ -1068,12 +1071,13 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx, goto clear_extattr; header = (struct ext2_ext_attr_header *) block_buf; pctx->blk = inode->i_file_acl; - if (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1) - ext_attr_ver = 1; - if (header->h_magic != EXT2_EXT_ATTR_MAGIC) - ext_attr_ver = 2; - else if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx)) - goto clear_extattr; + if (((ctx->ext_attr_ver == 1) && + (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) || + ((ctx->ext_attr_ver == 2) && + (header->h_magic != EXT2_EXT_ATTR_MAGIC))) { + if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx)) + goto clear_extattr; + } if (header->h_blocks != 1) { if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx)) @@ -1099,9 +1103,9 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx, if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) goto clear_extattr; } - if ((ext_attr_ver == 1 && + if ((ctx->ext_attr_ver == 1 && (entry->e_name_len == 0 || entry->e_name_index != 0)) || - (ext_attr_ver == 2 && + (ctx->ext_attr_ver == 2 && entry->e_name_index == 0)) { if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx)) goto clear_extattr; @@ -1205,11 +1209,9 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, int dirty_inode = 0; __u64 size; - if (!ext2fs_inode_has_valid_blocks(inode)) - return; - pb.ino = ino; - pb.num_blocks = pb.last_block = 0; + pb.num_blocks = 0; + pb.last_block = -1; pb.num_illegal_blocks = 0; pb.suppress = 0; pb.clear = 0; pb.fragmented = 0; @@ -1222,6 +1224,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, pb.pctx = pctx; pb.ctx = ctx; pctx->ino = ino; + pctx->errcode = 0; if (inode->i_flags & EXT2_COMPRBLK_FL) { if (fs->super->s_feature_incompat & @@ -1235,13 +1238,14 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, } } - pctx->errcode = ext2fs_block_iterate2(fs, ino, + if (ext2fs_inode_has_valid_blocks(inode)) + pctx->errcode = ext2fs_block_iterate2(fs, ino, pb.is_dir ? BLOCK_FLAG_HOLE : 0, block_buf, process_block, &pb); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - goto out; end_problem_latch(ctx, PR_LATCH_BLOCK); end_problem_latch(ctx, PR_LATCH_TOOBIG); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + goto out; if (pctx->errcode) fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx); @@ -1280,15 +1284,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, ((inode->i_size / fs->blocksize) >= 3)) ext2fs_u32_list_add(ctx->dirs_to_hash, ino); - if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf)) - pb.num_blocks++; - - pb.num_blocks *= (fs->blocksize / 512); -#if 0 - printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n", - ino, inode->i_size, pb.last_block, inode->i_blocks, - pb.num_blocks); -#endif if (!pb.num_blocks && pb.is_dir) { if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) { inode->i_links_count = 0; @@ -1299,9 +1294,19 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino); ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); ctx->fs_directory_count--; - pb.is_dir = 0; + goto out; } } + + if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf)) + pb.num_blocks++; + + pb.num_blocks *= (fs->blocksize / 512); +#if 0 + printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n", + ino, inode->i_size, pb.last_block, inode->i_blocks, + pb.num_blocks); +#endif if (pb.is_dir) { int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super); if (nblock > (pb.last_block + 1)) @@ -1312,19 +1317,19 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, bad_size = 2; } } 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); - if ((size < pb.last_block * fs->blocksize)) + if ((pb.last_block >= 0) && + (size < pb.last_block * fs->blocksize)) bad_size = 3; else if (size > ext2_max_sizes[fs->super->s_log_block_size]) bad_size = 4; } - if (bad_size) { + /* i_size for symlinks is checked elsewhere */ + if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) { pctx->num = (pb.last_block+1) * fs->blocksize; if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) { inode->i_size = pctx->num; - if (LINUX_S_ISREG(inode->i_mode)) + if (!LINUX_S_ISDIR(inode->i_mode)) inode->i_size_high = pctx->num >> 32; dirty_inode++; } diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c index 8549a655..c370601e 100644 --- a/e2fsck/pass1b.c +++ b/e2fsck/pass1b.c @@ -259,15 +259,17 @@ static void pass1b(e2fsck_t ctx, char *block_buf) while (ino) { pctx.ino = ctx->stashed_ino = ino; if ((ino != EXT2_BAD_INO) && - (!ext2fs_test_inode_bitmap(ctx->inode_used_map, ino) || - !ext2fs_inode_has_valid_blocks(&inode))) + !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)) goto next; pb.ino = ino; pb.dup_blocks = 0; pb.inode = &inode; - pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, - process_pass1b_block, &pb); + + if (ext2fs_inode_has_valid_blocks(&inode) || + (ino == EXT2_BAD_INO)) + pctx.errcode = ext2fs_block_iterate2(fs, ino, + 0, block_buf, process_pass1b_block, &pb); if (inode.i_file_acl) process_pass1b_block(fs, &inode.i_file_acl, BLOCK_COUNT_EXTATTR, 0, 0, &pb); @@ -543,7 +545,7 @@ static int delete_file_block(ext2_filsys fs, *block_nr); } else { ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); - ext2fs_unmark_block_bitmap(fs->block_map, *block_nr); + ext2fs_block_alloc_stats(fs, *block_nr, -1); } return 0; @@ -556,6 +558,7 @@ static void delete_file(e2fsck_t ctx, ext2_ino_t ino, struct process_block_struct pb; struct ext2_inode inode; struct problem_context pctx; + unsigned int count; clear_problem_context(&pctx); pctx.ino = pb.ino = ino; @@ -563,23 +566,47 @@ static void delete_file(e2fsck_t ctx, ext2_ino_t ino, pb.ctx = ctx; pctx.str = "delete_file"; - pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, - delete_file_block, &pb); + e2fsck_read_inode(ctx, ino, &inode, "delete_file"); + if (ext2fs_inode_has_valid_blocks(&inode)) + pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, + delete_file_block, &pb); if (pctx.errcode) fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); if (ctx->inode_bad_map) ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); - ext2fs_unmark_inode_bitmap(fs->inode_map, ino); - ext2fs_mark_ib_dirty(fs); - ext2fs_mark_bb_dirty(fs); + ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); + + /* Inode may have changed by block_iterate, so reread it */ e2fsck_read_inode(ctx, ino, &inode, "delete_file"); inode.i_links_count = 0; inode.i_dtime = time(0); - if (inode.i_file_acl) - delete_file_block(fs, &inode.i_file_acl, - BLOCK_COUNT_EXTATTR, 0, 0, &pb); + if (inode.i_file_acl && + (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { + count = 1; + pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl, + block_buf, -1, &count); + if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { + pctx.errcode = 0; + count = 1; + } + if (pctx.errcode) { + pctx.blk = inode.i_file_acl; + fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx); + } + /* + * If the count is zero, then arrange to have the + * block deleted. If the block is in the block_dup_map, + * also call delete_file_block since it will take care + * of keeping the accounting straight. + */ + if ((count == 0) || + ext2fs_test_block_bitmap(ctx->block_dup_map, + inode.i_file_acl)) + delete_file_block(fs, &inode.i_file_acl, + BLOCK_COUNT_EXTATTR, 0, 0, &pb); + } e2fsck_write_inode(ctx, ino, &inode, "delete_file"); } @@ -683,8 +710,9 @@ static int clone_file(e2fsck_t ctx, ext2_ino_t ino, pctx.ino = ino; pctx.str = "clone_file"; - pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, - clone_file_block, &cs); + if (ext2fs_inode_has_valid_blocks(&dp->inode)) + pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, + clone_file_block, &cs); ext2fs_mark_bb_dirty(fs); if (pctx.errcode) { fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); @@ -697,6 +725,8 @@ static int clone_file(e2fsck_t ctx, ext2_ino_t ino, retval = cs.errcode; goto errout; } + /* The inode may have changed on disk, so we have to re-read it */ + e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA"); blk = dp->inode.i_file_acl; if (blk && (clone_file_block(fs, &dp->inode.i_file_acl, BLOCK_COUNT_EXTATTR, 0, 0, &cs) == @@ -717,7 +747,7 @@ static int clone_file(e2fsck_t ctx, ext2_ino_t ino, if (di->inode.i_file_acl == blk) { di->inode.i_file_acl = dp->inode.i_file_acl; e2fsck_write_inode(ctx, ino_el->inode, - &dp->inode, "clone file EA"); + &di->inode, "clone file EA"); decrement_badcount(ctx, blk, db); } } diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index 1f484f45..e61a6a27 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -886,7 +886,7 @@ static int deallocate_inode_block(ext2_filsys fs, if (HOLE_BLKADDR(*block_nr)) return 0; ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); - ext2fs_unmark_block_bitmap(fs->block_map, *block_nr); + ext2fs_block_alloc_stats(fs, *block_nr, -1); return 0; } @@ -898,6 +898,7 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) ext2_filsys fs = ctx->fs; struct ext2_inode inode; struct problem_context pctx; + __u32 count; ext2fs_icount_store(ctx->inode_link_info, ino, 0); e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); @@ -915,8 +916,29 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); if (ctx->inode_bad_map) ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); - ext2fs_unmark_inode_bitmap(fs->inode_map, ino); - ext2fs_mark_ib_dirty(fs); + ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); + + if (inode.i_file_acl && + (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { + pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl, + block_buf, -1, &count); + if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { + pctx.errcode = 0; + count = 1; + } + if (pctx.errcode) { + pctx.blk = inode.i_file_acl; + fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + if (count == 0) { + ext2fs_unmark_block_bitmap(ctx->block_found_map, + inode.i_file_acl); + ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1); + } + inode.i_file_acl = 0; + } if (!ext2fs_inode_has_valid_blocks(&inode)) return; @@ -925,13 +947,6 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) (inode.i_size_high || inode.i_size & 0x80000000UL)) ctx->large_files--; - if (inode.i_file_acl) { - ext2fs_unmark_block_bitmap(ctx->block_found_map, - inode.i_file_acl); - ext2fs_unmark_block_bitmap(fs->block_map, inode.i_file_acl); - } - - ext2fs_mark_bb_dirty(fs); pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, deallocate_inode_block, ctx); if (pctx.errcode) { @@ -947,7 +962,6 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) static void clear_htree(e2fsck_t ctx, ext2_ino_t ino) { struct ext2_inode inode; - struct problem_context pctx; e2fsck_read_inode(ctx, ino, &inode, "clear_htree"); inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL; @@ -980,16 +994,16 @@ extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, !(LINUX_S_ISSOCK(inode.i_mode))) problem = PR_2_BAD_MODE; else if (LINUX_S_ISCHR(inode.i_mode) - && !e2fsck_pass1_check_device_inode(&inode)) + && !e2fsck_pass1_check_device_inode(fs, &inode)) problem = PR_2_BAD_CHAR_DEV; else if (LINUX_S_ISBLK(inode.i_mode) - && !e2fsck_pass1_check_device_inode(&inode)) + && !e2fsck_pass1_check_device_inode(fs, &inode)) problem = PR_2_BAD_BLOCK_DEV; else if (LINUX_S_ISFIFO(inode.i_mode) - && !e2fsck_pass1_check_device_inode(&inode)) + && !e2fsck_pass1_check_device_inode(fs, &inode)) problem = PR_2_BAD_FIFO; else if (LINUX_S_ISSOCK(inode.i_mode) - && !e2fsck_pass1_check_device_inode(&inode)) + && !e2fsck_pass1_check_device_inode(fs, &inode)) problem = PR_2_BAD_SOCKET; else if (LINUX_S_ISLNK(inode.i_mode) && !e2fsck_pass1_check_symlink(fs, &inode, buf)) { diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c index 167add85..d4fea082 100644 --- a/e2fsck/pass3.c +++ b/e2fsck/pass3.c @@ -430,8 +430,7 @@ ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix) return 0; } ext2fs_mark_block_bitmap(ctx->block_found_map, blk); - ext2fs_mark_block_bitmap(fs->block_map, blk); - ext2fs_mark_bb_dirty(fs); + ext2fs_block_alloc_stats(fs, blk, +1); /* * Next find a free inode. @@ -445,8 +444,7 @@ ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix) } ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino); - ext2fs_mark_inode_bitmap(fs->inode_map, ino); - ext2fs_mark_ib_dirty(fs); + ext2fs_inode_alloc_stats2(fs, ino, +1, 1); /* * Now let's create the actual data block for the inode @@ -594,10 +592,6 @@ static errcode_t adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj) return 0; ext2fs_icount_decrement(ctx->inode_link_info, ino, 0); inode.i_links_count--; - } else { - /* Should never happen */ - fatal_error(ctx, _("Debug error in e2fsck adjust_inode_count, " - "should never happen.\n")); } retval = ext2fs_write_inode(fs, ino, &inode); diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c index 28c0996c..d1ffd82e 100644 --- a/e2fsck/pass4.c +++ b/e2fsck/pass4.c @@ -34,11 +34,14 @@ static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i) pctx.ino = i; pctx.inode = &inode; + /* + * Offer to delete any zero-length files that does not have + * blocks. If there is an EA block, it might have useful + * information, so we won't prompt to delete it, but let it be + * reconnected to lost+found. + */ if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) || LINUX_S_ISDIR(inode.i_mode))) { - /* - * This is a zero-length file; prompt to delete it... - */ if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) { ext2fs_icount_store(ctx->inode_link_info, i, 0); inode.i_links_count = 0; @@ -51,8 +54,8 @@ static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i) e2fsck_read_bitmaps(ctx); ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i); ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i); - ext2fs_unmark_inode_bitmap(fs->inode_map, i); - ext2fs_mark_ib_dirty(fs); + ext2fs_inode_alloc_stats2(fs, i, -1, + LINUX_S_ISDIR(inode.i_mode)); return 0; } } diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 07687cd6..0b3b557b 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -735,7 +735,13 @@ static const struct e2fsck_problem problem_table[] = { { PR_1B_BLOCK_ITERATE, N_("Error while iterating over @bs in @i %i (%s): %m\n"), PROMPT_NONE, 0 }, - + + /* Error adjusting EA refcount */ + { PR_1B_ADJ_EA_REFCOUNT, + N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"), + PROMPT_NONE, 0 }, + + /* Pass 1C: Scan directories for inodes with dup blocks. */ { PR_1C_PASS_HEADER, N_("Pass 1C: Scan directories for @is with dup @bs.\n"), @@ -1051,6 +1057,11 @@ static const struct e2fsck_problem problem_table[] = { N_("@p @h %d (%q): bad @b number %b.\n"), PROMPT_CLEAR_HTREE, 0 }, + /* Error adjusting EA refcount */ + { PR_2_ADJ_EA_REFCOUNT, + N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"), + PROMPT_NONE, PR_FATAL }, + /* Pass 3 errors */ /* Pass 3: Checking directory connectivity */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 05eba230..2196a33b 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -429,7 +429,10 @@ struct problem_context { /* Error while iterating over blocks */ #define PR_1B_BLOCK_ITERATE 0x0110006 - +/* Error adjusting EA refcount */ +#define PR_1B_ADJ_EA_REFCOUNT 0x0110007 + + /* Pass 1C: Scan directories for inodes with dup blocks. */ #define PR_1C_PASS_HEADER 0x012000 @@ -624,6 +627,9 @@ struct problem_context { /* Bad block in htree interior node */ #define PR_2_HTREE_BADBLK 0x02003A +/* Error adjusting EA refcount */ +#define PR_2_ADJ_EA_REFCOUNT 0x02003B + /* * Pass 3 errors */ diff --git a/e2fsck/super.c b/e2fsck/super.c index 227a0254..a8ea779d 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -152,10 +152,7 @@ static int release_inode_block(ext2_filsys fs, retval |= BLOCK_CHANGED; } - ext2fs_unmark_block_bitmap(fs->block_map, blk); - fs->group_desc[ext2fs_group_of_blk(fs, blk)].bg_free_blocks_count++; - fs->super->s_free_blocks_count++; - + ext2fs_block_alloc_stats(fs, blk, -1); return retval; } @@ -168,9 +165,10 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, struct ext2_inode *inode, char *block_buf, struct problem_context *pctx) { + struct process_block_struct pb; ext2_filsys fs = ctx->fs; errcode_t retval; - struct process_block_struct pb; + __u32 count; if (!ext2fs_inode_has_valid_blocks(inode)) return 0; @@ -211,7 +209,23 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, inode->i_blocks -= pb.truncated_blocks * (fs->blocksize / 512); - ext2fs_mark_bb_dirty(fs); + if (inode->i_file_acl) { + retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl, + block_buf, -1, &count); + if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) { + retval = 0; + count = 1; + } + if (retval) { + com_err("release_inode_blocks", retval, + _("while calling ext2fs_adjust_ea_refocunt for inode %d"), + ino); + return 1; + } + if (count == 0) + ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1); + inode->i_file_acl = 0; + } return 0; } @@ -222,7 +236,6 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, static int release_orphan_inodes(e2fsck_t ctx) { ext2_filsys fs = ctx->fs; - int group; ext2_ino_t ino, next_ino; struct ext2_inode inode; struct problem_context pctx; @@ -281,14 +294,8 @@ static int release_orphan_inodes(e2fsck_t ctx) goto return_abort; if (!inode.i_links_count) { - ext2fs_unmark_inode_bitmap(fs->inode_map, ino); - ext2fs_mark_ib_dirty(fs); - group = ext2fs_group_of_ino(fs, ino); - fs->group_desc[group].bg_free_inodes_count++; - fs->super->s_free_inodes_count++; - if (LINUX_S_ISDIR(inode.i_mode)) - fs->group_desc[group].bg_used_dirs_count--; - + ext2fs_inode_alloc_stats2(fs, ino, -1, + LINUX_S_ISDIR(inode.i_mode)); inode.i_dtime = time(0); } else { inode.i_dtime = 0; diff --git a/e2fsck/unix.c b/e2fsck/unix.c index fab82a25..156d25b1 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -61,7 +61,8 @@ static void usage(e2fsck_t ctx) fprintf(stderr, _("Usage: %s [-panyrcdfvstFSV] [-b superblock] [-B blocksize]\n" "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n" - "\t\t[-l|-L bad_blocks_file] [-C fd] [-j ext-journal] device\n"), + "\t\t[-l|-L bad_blocks_file] [-C fd] [-j ext-journal]\n" + "\t\t[-E extended-options] device\n"), ctx->program_name); fprintf(stderr, _("\nEmergency help:\n" @@ -448,6 +449,60 @@ static void signal_cancel(int sig) } #endif +static void parse_extended_opts(e2fsck_t ctx, const char *opts) +{ + char *buf, *token, *next, *p, *arg; + int len, ea_ver; + int extended_usage = 0; + + len = strlen(opts); + buf = malloc(len+1); + if (!buf) { + fprintf(stderr, _("Couldn't allocate memory to parse " + "extended options!\n")); + exit(1); + } + strcpy(buf, opts); + for (token = buf; token && *token; token = next) { + p = strchr(token, ','); + next = 0; + if (p) { + *p = 0; + next = p+1; + } + arg = strchr(token, '='); + if (arg) { + *arg = 0; + arg++; + } + if (strcmp(token, "ea_ver") == 0) { + if (!arg) { + extended_usage++; + continue; + } + ea_ver = strtoul(arg, &p, 0); + if (*p || + ((ea_ver != 1) && (ea_ver != 2))) { + fprintf(stderr, + _("Invalid EA version.\n")); + extended_usage++; + continue; + } + ctx->ext_attr_ver = ea_ver; + } else + extended_usage++; + } + if (extended_usage) { + fprintf(stderr, _("Extended options are separated by commas, " + "and may take an argument which\n" + "is set off by an equals ('=') sign. " + "Valid raid options are:\n" + "\tea_ver=program_name = *argv; else ctx->program_name = "e2fsck"; - while ((c = getopt (argc, argv, "panyrcC:B:dfvtFVM:b:I:j:P:l:L:N:SsD")) != EOF) + while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsD")) != EOF) switch (c) { case 'C': ctx->progress = e2fsck_update_progress; @@ -497,6 +553,9 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) case 'D': ctx->options |= E2F_OPT_COMPRESS_DIRS; break; + case 'E': + extended_opts = optarg; + break; case 'p': case 'a': ctx->options |= E2F_OPT_PREEN; @@ -602,6 +661,9 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS)) ctx->options |= E2F_OPT_READONLY; ctx->filesystem_name = argv[optind]; + if (extended_opts) + parse_extended_opts(ctx, extended_opts); + if (flush) { fd = open(ctx->filesystem_name, O_RDONLY, 0); if (fd < 0) { diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index 68d55249..bf0ae7b5 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,18 @@ +2002-08-16 Theodore Ts'o + + * ext2_err.et.in (EXT2_ET_BAD_EA_BLOCK_NUM): New error code + + * ext2fs.h (ext2fs_inode_data_blocks): New function which returns + the number of data blocks used by an inode exclusive of + the EA block. + + * ext_attr.c (ext2fs_adjust_ea_refcount): New function which + adjusts the reference count in an extended attribute block. + + * valid_blk.c (ext2fs_inode_has_valid_blocks): Add code to + correctly deal with extended attribute blocks in symbolic + links. + 2002-08-13 * Makefile.in: Move dupfs.o and test_io.o from the diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in index c22e5d86..b08f8635 100644 --- a/lib/ext2fs/ext2_err.et.in +++ b/lib/ext2fs/ext2_err.et.in @@ -278,5 +278,8 @@ ec EXT2_ET_NO_JOURNAL, ec EXT2_ET_DIRHASH_UNSUPP, "Directory hash unsupported" +ec EXT2_ET_BAD_EA_BLOCK_NUM, + "Illegal extended attribute block number" + end diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 60021930..507b1a3b 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -663,7 +663,12 @@ extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir); /* ext_attr.c */ void ext2fs_swap_ext_attr(ext2_filsys fs, char *to, char *from); extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf); -extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *buf); +extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, + void *buf); +extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, + char *block_buf, + int adjust, __u32 *newcount); + /* fileio.c */ extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, int flags, ext2_file_t *ret); @@ -873,6 +878,8 @@ extern int ext2fs_test_ib_dirty(ext2_filsys fs); extern int ext2fs_test_bb_dirty(ext2_filsys fs); extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk); extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino); +extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs, + struct ext2_inode *inode); /* * The actual inlined functions definitions themselves... @@ -1025,6 +1032,13 @@ _INLINE_ int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino) { return (ino - 1) / fs->super->s_inodes_per_group; } + +_INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs, + struct ext2_inode *inode) +{ + return inode->i_blocks - + (inode->i_file_acl ? fs->blocksize >> 9 : 0); +} #undef _INLINE_ #endif diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c index b5404390..5ebb22bb 100644 --- a/lib/ext2fs/ext_attr.c +++ b/lib/ext2fs/ext_attr.c @@ -1,7 +1,9 @@ /* * ext_attr.c --- extended attribute blocks * - * Copyright (C) Andreas Gruenbacher, + * Copyright (C) 2001 Andreas Gruenbacher, + * + * Copyright (C) 2002 Theodore Ts'o. * * %Begin-Header% * This file may be redistributed under the terms of the GNU Public @@ -96,3 +98,44 @@ errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf) ext2fs_mark_changed(fs); return retval; } + +/* + * This function adjusts the reference count of the EA block. + */ +errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, + char *block_buf, int adjust, + __u32 *newcount) +{ + errcode_t retval; + struct ext2_ext_attr_header *header; + char *buf = 0; + + if ((blk >= fs->super->s_blocks_count) || + (blk < fs->super->s_first_data_block)) + return EXT2_ET_BAD_EA_BLOCK_NUM; + + if (!block_buf) { + retval = ext2fs_get_mem(fs->blocksize, (void **) &buf); + if (retval) + return retval; + block_buf = buf; + } + + retval = ext2fs_read_ext_attr(fs, blk, block_buf); + if (retval) + goto errout; + + header = (struct ext2_ext_attr_header *) block_buf; + header->h_refcount += adjust; + if (newcount) + *newcount = header->h_refcount; + + retval = ext2fs_write_ext_attr(fs, blk, block_buf); + if (retval) + goto errout; + +errout: + if (buf) + ext2fs_free_mem((void **) &buf); + return retval; +} diff --git a/lib/ext2fs/valid_blk.c b/lib/ext2fs/valid_blk.c index 9e50ed5a..5236f1e3 100644 --- a/lib/ext2fs/valid_blk.c +++ b/lib/ext2fs/valid_blk.c @@ -38,8 +38,19 @@ int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode) * If the symbolic link is a "fast symlink", then the symlink * target is stored in the block entries. */ - if (LINUX_S_ISLNK (inode->i_mode) && inode->i_blocks == 0) - return 0; - + if (LINUX_S_ISLNK (inode->i_mode)) { + if (inode->i_file_acl == 0) { + /* With no EA block, we can rely on i_blocks */ + if (inode->i_blocks == 0) + return 0; + } else { + /* With an EA block, life gets more tricky */ + if (inode->i_size >= EXT2_N_BLOCKS*4) + return 1; /* definitely using i_block[] */ + if (inode->i_size > 3 && inode->i_block[1] != 0) + return 1; /* probably using i_block[] */ + return 0; /* Probably a fast symlink */ + } + } return 1; } diff --git a/tests/ChangeLog b/tests/ChangeLog index 98511519..3bf008bf 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,17 @@ +2002-08-17 Theodore Ts'o + + * f_badinode, f_badroot, f_badsymlinks, f_badtable, f_dupdot, + f_filetype, f_illitable, f_imagic, f_imagic_fs, f_lpf, + f_lpffile, f_mke2fs2b, f_noroot, f_recnect_bad: Update + expect files to deal with changes in the extended + attribute block processing, and in how e2fsck updates + filesystem statistics when deleting files and creating + /lost+found. + + * f_special_ea: New test which checks to make sure e2fsck + correctly handles special device files with extended + attribute blocks. + 2002-08-01 Theodore Ts'o * f_dup, f_dup2, f_dup3, f_bbfile, f_dupfsblks: Update expect diff --git a/tests/f_badinode/expect.1 b/tests/f_badinode/expect.1 index 6207042c..4601f1e3 100644 --- a/tests/f_badinode/expect.1 +++ b/tests/f_badinode/expect.1 @@ -1,6 +1,8 @@ Filesystem did not have a UUID; generating one. Pass 1: Checking inodes, blocks, and sizes +Inode 12, i_blocks is 2, should be 0. Fix? yes + Pass 2: Checking directory structure Inode 12 (/motd) has a bad mode (0110444). Clear? yes @@ -32,12 +34,6 @@ Fix? yes Free blocks count wrong (76, counted=77). Fix? yes -Free inodes count wrong for group #0 (16, counted=20). -Fix? yes - -Free inodes count wrong (16, counted=20). -Fix? yes - test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 12/32 files (0.0% non-contiguous), 23/100 blocks diff --git a/tests/f_badroot/expect.1 b/tests/f_badroot/expect.1 index 187c49a4..66ff32ee 100644 --- a/tests/f_badroot/expect.1 +++ b/tests/f_badroot/expect.1 @@ -23,21 +23,6 @@ Connect to /lost+found? yes Inode 12 ref count is 2, should be 1. Fix? yes Pass 5: Checking group summary information -Free blocks count wrong for group #0 (77, counted=76). -Fix? yes - -Free blocks count wrong (77, counted=76). -Fix? yes - -Free inodes count wrong for group #0 (20, counted=19). -Fix? yes - -Directories count wrong for group #0 (2, counted=3). -Fix? yes - -Free inodes count wrong (20, counted=19). -Fix? yes - test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 13/32 files (0.0% non-contiguous), 24/100 blocks diff --git a/tests/f_badsymlinks/expect.1 b/tests/f_badsymlinks/expect.1 index d8314b46..b28b57d6 100644 --- a/tests/f_badsymlinks/expect.1 +++ b/tests/f_badsymlinks/expect.1 @@ -1,6 +1,4 @@ Pass 1: Checking inodes, blocks, and sizes -Inode 16, i_size is 4294967358, should be 1024. Fix? yes - Special (device/socket/fifo/symlink) file (inode 18) has immutable or append-only flag set. Clear? yes @@ -51,16 +49,10 @@ Clear? yes Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -Free blocks count wrong for group #0 (995, counted=1001). +Free blocks count wrong for group #0 (1000, counted=1001). Fix? yes -Free blocks count wrong (995, counted=1001). -Fix? yes - -Free inodes count wrong for group #0 (9, counted=19). -Fix? yes - -Free inodes count wrong (9, counted=19). +Free blocks count wrong (1000, counted=1001). Fix? yes diff --git a/tests/f_badtable/expect.1 b/tests/f_badtable/expect.1 index 14a3a148..56881f1b 100644 --- a/tests/f_badtable/expect.1 +++ b/tests/f_badtable/expect.1 @@ -21,19 +21,22 @@ Pass 5: Checking group summary information Block bitmap differences: -(12--20) Fix? yes -Free blocks count wrong for group #0 (78, counted=87). +Free blocks count wrong for group #0 (77, counted=87). Fix? yes -Free blocks count wrong (78, counted=87). +Free blocks count wrong (77, counted=87). Fix? yes Inode bitmap differences: +(12--16) +(25--32) Fix? yes -Free inodes count wrong for group #0 (21, counted=7). +Free inodes count wrong for group #0 (20, counted=7). Fix? yes -Free inodes count wrong (21, counted=7). +Directories count wrong for group #0 (3, counted=2). +Fix? yes + +Free inodes count wrong (20, counted=7). Fix? yes diff --git a/tests/f_dupdot/expect.1 b/tests/f_dupdot/expect.1 index d630e032..611f8701 100644 --- a/tests/f_dupdot/expect.1 +++ b/tests/f_dupdot/expect.1 @@ -16,12 +16,6 @@ Inode 13 ref count is 2, should be 1. Fix? yes Unattached zero-length inode 14. Clear? yes Pass 5: Checking group summary information -Free inodes count wrong for group #0 (2, counted=3). -Fix? yes - -Free inodes count wrong (2, counted=3). -Fix? yes - test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 13/16 files (0.0% non-contiguous), 22/100 blocks diff --git a/tests/f_filetype/expect.1 b/tests/f_filetype/expect.1 index a94560e9..1624bfca 100644 --- a/tests/f_filetype/expect.1 +++ b/tests/f_filetype/expect.1 @@ -37,6 +37,12 @@ Setting filetype for entry '..' in /dir (13) to 2. Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information +Free inodes count wrong for group #0 (50, counted=47). +Fix? yes + +Free inodes count wrong (50, counted=47). +Fix? yes + test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 17/64 files (0.0% non-contiguous), 27/100 blocks diff --git a/tests/f_illitable/expect.1 b/tests/f_illitable/expect.1 index cc0ca345..3d7161a7 100644 --- a/tests/f_illitable/expect.1 +++ b/tests/f_illitable/expect.1 @@ -28,10 +28,19 @@ Pass 5: Checking group summary information Block bitmap differences: -(11--21) Fix? yes -Free blocks count wrong for group #0 (78, counted=89). +Free blocks count wrong for group #0 (77, counted=89). Fix? yes -Free blocks count wrong (78, counted=89). +Free blocks count wrong (77, counted=89). +Fix? yes + +Free inodes count wrong for group #0 (20, counted=21). +Fix? yes + +Directories count wrong for group #0 (3, counted=2). +Fix? yes + +Free inodes count wrong (20, counted=21). Fix? yes diff --git a/tests/f_imagic/expect.1 b/tests/f_imagic/expect.1 index 88e1f70e..ebee1926 100644 --- a/tests/f_imagic/expect.1 +++ b/tests/f_imagic/expect.1 @@ -26,10 +26,19 @@ Pass 5: Checking group summary information Block bitmap differences: -(9--19) Fix? yes -Free blocks count wrong for group #0 (76, counted=87). +Free blocks count wrong for group #0 (75, counted=87). Fix? yes -Free blocks count wrong (76, counted=87). +Free blocks count wrong (75, counted=87). +Fix? yes + +Free inodes count wrong for group #0 (1, counted=2). +Fix? yes + +Directories count wrong for group #0 (3, counted=2). +Fix? yes + +Free inodes count wrong (1, counted=2). Fix? yes diff --git a/tests/f_imagic_fs/expect.1 b/tests/f_imagic_fs/expect.1 index 13aa850e..b21fd358 100644 --- a/tests/f_imagic_fs/expect.1 +++ b/tests/f_imagic_fs/expect.1 @@ -10,10 +10,19 @@ Pass 5: Checking group summary information Block bitmap differences: -(9--19) Fix? yes -Free blocks count wrong for group #0 (76, counted=87). +Free blocks count wrong for group #0 (75, counted=87). Fix? yes -Free blocks count wrong (76, counted=87). +Free blocks count wrong (75, counted=87). +Fix? yes + +Free inodes count wrong for group #0 (1, counted=2). +Fix? yes + +Directories count wrong for group #0 (3, counted=2). +Fix? yes + +Free inodes count wrong (1, counted=2). Fix? yes diff --git a/tests/f_lpf/expect.1 b/tests/f_lpf/expect.1 index 767c3b54..4f2853c5 100644 --- a/tests/f_lpf/expect.1 +++ b/tests/f_lpf/expect.1 @@ -27,22 +27,19 @@ Pass 5: Checking group summary information Block bitmap differences: +(22--23) +49 +(57--58) Fix? yes -Free blocks count wrong for group #0 (25, counted=33). +Free blocks count wrong for group #0 (24, counted=33). Fix? yes -Free blocks count wrong (39, counted=33). +Free blocks count wrong (38, counted=33). Fix? yes Inode bitmap differences: +13 Fix? yes -Free inodes count wrong for group #0 (2, counted=0). +Free inodes count wrong for group #0 (1, counted=0). Fix? yes -Directories count wrong for group #0 (1, counted=2). -Fix? yes - -Free inodes count wrong (2, counted=0). +Free inodes count wrong (1, counted=0). Fix? yes diff --git a/tests/f_lpffile/expect.1 b/tests/f_lpffile/expect.1 index 909952e8..04cce4ce 100644 --- a/tests/f_lpffile/expect.1 +++ b/tests/f_lpffile/expect.1 @@ -26,21 +26,6 @@ Connect to /lost+found? yes Inode 14 ref count is 2, should be 1. Fix? yes Pass 5: Checking group summary information -Free blocks count wrong for group #0 (86, counted=85). -Fix? yes - -Free blocks count wrong (86, counted=85). -Fix? yes - -Free inodes count wrong for group #0 (18, counted=17). -Fix? yes - -Directories count wrong for group #0 (1, counted=2). -Fix? yes - -Free inodes count wrong (18, counted=17). -Fix? yes - test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 15/32 files (0.0% non-contiguous), 15/100 blocks diff --git a/tests/f_mke2fs2b/expect.1 b/tests/f_mke2fs2b/expect.1 index 87222470..5ffedcb9 100644 --- a/tests/f_mke2fs2b/expect.1 +++ b/tests/f_mke2fs2b/expect.1 @@ -13,6 +13,12 @@ Pass 4: Checking reference counts Unattached zero-length inode 15. Clear? yes Pass 5: Checking group summary information +Free inodes count wrong for group #0 (18, counted=17). +Fix? yes + +Free inodes count wrong (18, counted=17). +Fix? yes + test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 15/32 files (0.0% non-contiguous), 25/100 blocks diff --git a/tests/f_noroot/expect.1 b/tests/f_noroot/expect.1 index cc90d93a..7bdd7cba 100644 --- a/tests/f_noroot/expect.1 +++ b/tests/f_noroot/expect.1 @@ -27,18 +27,9 @@ Inode 12 ref count is 4, should be 3. Fix? yes Unattached zero-length inode 15. Clear? yes Pass 5: Checking group summary information -Free blocks count wrong for group #0 (75, counted=74). -Fix? yes - -Free blocks count wrong (75, counted=74). -Fix? yes - Free inodes count wrong for group #0 (17, counted=16). Fix? yes -Directories count wrong for group #0 (4, counted=5). -Fix? yes - Free inodes count wrong (17, counted=16). Fix? yes diff --git a/tests/f_recnect_bad/expect.1 b/tests/f_recnect_bad/expect.1 index 96fe9dbe..609a8fde 100644 --- a/tests/f_recnect_bad/expect.1 +++ b/tests/f_recnect_bad/expect.1 @@ -23,6 +23,12 @@ Inode 28 (...) has a bad mode (0177777). Clear? yes Pass 5: Checking group summary information +Free inodes count wrong for group #0 (18, counted=17). +Fix? yes + +Free inodes count wrong (18, counted=17). +Fix? yes + test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 15/32 files (0.0% non-contiguous), 26/100 blocks diff --git a/tests/f_special_ea/expect.1 b/tests/f_special_ea/expect.1 new file mode 100644 index 00000000..3c775d43 --- /dev/null +++ b/tests/f_special_ea/expect.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: 17/1024 files (0.0% non-contiguous), 1180/4096 blocks +Exit status is 1 diff --git a/tests/f_special_ea/image.gz b/tests/f_special_ea/image.gz new file mode 100644 index 00000000..c447cb73 Binary files /dev/null and b/tests/f_special_ea/image.gz differ diff --git a/tests/f_special_ea/name b/tests/f_special_ea/name new file mode 100644 index 00000000..8dfb2f4d --- /dev/null +++ b/tests/f_special_ea/name @@ -0,0 +1 @@ +Special files with extended attributes diff --git a/tests/f_special_ea/script b/tests/f_special_ea/script new file mode 100644 index 00000000..8ab2b9c6 --- /dev/null +++ b/tests/f_special_ea/script @@ -0,0 +1,2 @@ +ONE_PASS_ONLY="true" +. $cmd_dir/run_e2fsck