diff options
author | Theodore Ts'o <tytso@mit.edu> | 2010-01-30 21:22:17 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-01-31 18:49:08 -0500 |
commit | 2d07b3ad98bfe1db5fb1071f53a5338ab6c35522 (patch) | |
tree | 5569434a7e4a85b015c6ad0e3933ea09ae42f8a4 /e2fsck | |
parent | 2884320016e633d987203c0286a9dbf9e62a3fd4 (diff) | |
parent | c70674387ee0c038bca16098f7869181beeabe0a (diff) | |
download | e2fsprogs-2d07b3ad98bfe1db5fb1071f53a5338ab6c35522.tar.gz |
Merge branch 'maint' into next
Conflicts:
configure
lib/ext2fs/alloc_tables.c
misc/mke2fs.c
Diffstat (limited to 'e2fsck')
-rw-r--r-- | e2fsck/e2fsck.conf.5.in | 13 | ||||
-rw-r--r-- | e2fsck/pass1.c | 86 | ||||
-rw-r--r-- | e2fsck/pass2.c | 30 | ||||
-rw-r--r-- | e2fsck/problem.c | 11 | ||||
-rw-r--r-- | e2fsck/rehash.c | 24 |
5 files changed, 81 insertions, 83 deletions
diff --git a/e2fsck/e2fsck.conf.5.in b/e2fsck/e2fsck.conf.5.in index a5021bd1..64aafd70 100644 --- a/e2fsck/e2fsck.conf.5.in +++ b/e2fsck/e2fsck.conf.5.in @@ -109,6 +109,19 @@ This can be disabled by setting to the boolean value of false. This setting defaults to true. .TP +.I broken_system_clock +The +.BR e2fsck (8) +program has some hueristics that assume that the system clock is +correct. In addition, many system programs make similar assumptions. +For example, the UUID library depends on time not going backwards in +order for it to be able to make its guarantees about issuing universally +unique ID's. Systems with broken system clocks, are well, broken. +However, broken system clocks, particularly in embedded systems, do +exist. If true, e2fsck will not abort a preen check if it detects a +last mounted or last write time in the superblock in the future. This +setting defaults to false. +.TP .I clear_test_fs_flag This boolean relation controls whether or not .BR e2fsck (8) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 1578aa17..ed03af30 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -83,6 +83,7 @@ struct process_block_struct { blk_t num_blocks; blk_t max_blocks; e2_blkcnt_t last_block; + e2_blkcnt_t last_db_block; int num_illegal_blocks; blk_t previous_block; struct ext2_inode *inode; @@ -767,6 +768,7 @@ void e2fsck_pass1(e2fsck_t ctx) } pb.ino = EXT2_BAD_INO; pb.num_blocks = pb.last_block = 0; + pb.last_db_block = -1; pb.num_illegal_blocks = 0; pb.suppress = 0; pb.clear = 0; pb.is_dir = 0; pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0; @@ -1724,6 +1726,16 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, } pb->fragmented = 1; } + while (is_dir && ++pb->last_db_block < extent.e_lblk) { + pctx->errcode = ext2fs_add_dir_block(ctx->fs->dblist, + pb->ino, 0, + pb->last_db_block); + if (pctx->errcode) { + pctx->blk = 0; + pctx->num = pb->last_db_block; + goto failed_add_dir_block; + } + } for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0; i < extent.e_len; blk++, blockcnt++, i++) { @@ -1734,6 +1746,7 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, if (pctx->errcode) { pctx->blk = blk; pctx->num = blockcnt; + failed_add_dir_block: fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); /* Should never get here */ ctx->flags |= E2F_FLAG_ABORT; @@ -1741,6 +1754,8 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, } } } + if (is_dir && extent.e_len > 0) + pb->last_db_block = blockcnt - 1; pb->num_blocks += extent.e_len; pb->previous_block = extent.e_pblk + extent.e_len - 1; start_block = extent.e_lblk + extent.e_len - 1; @@ -1812,6 +1827,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, pb.ino = ino; pb.num_blocks = 0; pb.last_block = -1; + pb.last_db_block = -1; pb.num_illegal_blocks = 0; pb.suppress = 0; pb.clear = 0; pb.fragmented = 0; @@ -1876,26 +1892,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, return; } - if (pb.is_dir) { - while (1) { - struct ext2_db_entry *entry; - - if (ext2fs_dblist_get_last(fs->dblist, &entry) || - (entry->ino != ino) || - (entry->blk != 0) || - (entry->blockcnt == 0)) - break; - /* printf("Dropping ino %lu blk %lu blockcnt %d\n", - entry->ino, entry->blk, entry->blockcnt); */ - ext2fs_dblist_drop_last(fs->dblist); - if (ext2fs_dblist_get_last(fs->dblist, &entry) || - (entry->ino != ino)) - pb.last_block--; - else - pb.last_block = entry->blockcnt; - } - } - if (inode->i_flags & EXT2_INDEX_FL) { if (handle_htree(ctx, pctx, ino, inode, block_buf)) { inode->i_flags &= ~EXT2_INDEX_FL; @@ -1906,10 +1902,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, #endif } } - if (ctx->dirs_to_hash && pb.is_dir && - !(inode->i_flags & EXT2_INDEX_FL) && - ((inode->i_size / fs->blocksize) >= 3)) - ext2fs_u32_list_add(ctx->dirs_to_hash, ino); if (!pb.num_blocks && pb.is_dir) { if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) { @@ -1987,6 +1979,12 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, } pctx->num = 0; } + + if (ctx->dirs_to_hash && pb.is_dir && + !(inode->i_flags & EXT2_INDEX_FL) && + ((inode->i_size / fs->blocksize) >= 3)) + ext2fs_u32_list_add(ctx->dirs_to_hash, ino); + out: if (dirty_inode) e2fsck_write_inode(ctx, ino, inode, "check_blocks"); @@ -2087,31 +2085,8 @@ static int process_block(ext2_filsys fs, return 0; } - if (blk == 0) { - if (p->is_dir == 0) { - /* - * Should never happen, since only directories - * get called with BLOCK_FLAG_HOLE - */ -#if DEBUG_E2FSCK - printf("process_block() called with blk == 0, " - "blockcnt=%d, inode %lu???\n", - blockcnt, p->ino); -#endif - return 0; - } - if (blockcnt < 0) - return 0; - if (blockcnt * fs->blocksize < p->inode->i_size) { -#if 0 - printf("Missing block (#%d) in directory inode %lu!\n", - blockcnt, p->ino); -#endif - p->last_block = blockcnt; - goto mark_dir; - } + if (blk == 0) return 0; - } #if 0 printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk, @@ -2196,11 +2171,22 @@ static int process_block(ext2_filsys fs, p->last_block = blockcnt; mark_dir: if (p->is_dir && (blockcnt >= 0)) { + while (++p->last_db_block < blockcnt) { + pctx->errcode = ext2fs_add_dir_block(fs->dblist, + p->ino, 0, + p->last_db_block); + if (pctx->errcode) { + pctx->blk = 0; + pctx->num = p->last_db_block; + goto failed_add_dir_block; + } + } pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino, blk, blockcnt); if (pctx->errcode) { pctx->blk = blk; pctx->num = blockcnt; + failed_add_dir_block: fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); /* Should never get here */ ctx->flags |= E2F_FLAG_ABORT; @@ -2642,6 +2628,10 @@ static errcode_t e2fsck_get_alloc_block(ext2_filsys fs, blk64_t goal, &new_block); if (retval) return retval; + if (fs->block_map) { + ext2fs_mark_block_bitmap2(fs->block_map, new_block); + ext2fs_mark_bb_dirty(fs); + } } else { if (!fs->block_map) { retval = ext2fs_read_block_bitmap(fs); diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index 1e91e6d0..29a0174a 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -66,12 +66,6 @@ static int check_dir_block(ext2_filsys fs, static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info, char *buf, struct problem_context *pctx); -static int update_dir_block(ext2_filsys fs, - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block, - int ref_offset, - void *priv_data); static void clear_htree(e2fsck_t ctx, ext2_ino_t ino); static int htree_depth(struct dx_dir_info *dx_dir, struct dx_dirblock_info *dx_db); @@ -1465,8 +1459,8 @@ static int allocate_dir_block(e2fsck_t ctx, * Finally, update the block pointers for the inode */ db->blk = blk; - pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE, - 0, update_dir_block, db); + pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET, + db->blockcnt, 0, &blk); if (pctx->errcode) { pctx->str = "ext2fs_block_iterate"; fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); @@ -1475,23 +1469,3 @@ static int allocate_dir_block(e2fsck_t ctx, return 0; } - -/* - * This is a helper function for allocate_dir_block(). - */ -static int update_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)), - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct ext2_db_entry *db; - - db = (struct ext2_db_entry *) priv_data; - if (db->blockcnt == (int) blockcnt) { - *block_nr = db->blk; - return BLOCK_CHANGED; - } - return 0; -} diff --git a/e2fsck/problem.c b/e2fsck/problem.c index a713f1b2..9043281d 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1741,7 +1741,7 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx) struct e2fsck_problem *ptr; struct latch_descr *ldesc = 0; const char *message; - int def_yn, answer, ans; + int def_yn, answer, ans, broken_system_clock; int print_answer = 0; int suppress = 0; @@ -1753,6 +1753,15 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx) if (!(ptr->flags & PR_CONFIG)) { char key[9], *new_desc; + if ((code == PR_0_FUTURE_SB_LAST_MOUNT) || + (code == PR_0_FUTURE_SB_LAST_WRITE)) { + profile_get_boolean(ctx->profile, "options", + "broken_system_clock", 0, 0, + &broken_system_clock); + if (broken_system_clock) + ptr->flags |= PR_PREEN_OK; + } + sprintf(key, "0x%06x", code); profile_get_string(ctx->profile, "problems", key, diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c index bf033a90..6f00d5aa 100644 --- a/e2fsck/rehash.c +++ b/e2fsck/rehash.c @@ -736,6 +736,7 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino) fd.compress = 1; fd.parent = 0; +retry_nohash: /* Read in the entire directory into memory */ retval = ext2fs_block_iterate2(fs, ino, 0, 0, fill_dir_block, &fd); @@ -744,6 +745,17 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino) goto errout; } + /* + * If the entries read are less than a block, then don't index + * the directory + */ + if (!fd.compress && (fd.dir_size < (fs->blocksize - 24))) { + fd.compress = 1; + fd.dir_size = 0; + fd.num_array = 0; + goto retry_nohash; + } + #if 0 printf("%d entries (%d bytes) found in inode %d\n", fd.num_array, fd.dir_size, ino); @@ -751,12 +763,7 @@ errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino) /* Sort the list */ resort: - if (fd.compress) - qsort(fd.harray+2, fd.num_array-2, - sizeof(struct hash_entry), ino_cmp); - else - qsort(fd.harray, fd.num_array, - sizeof(struct hash_entry), hash_cmp); + qsort(fd.harray, fd.num_array, sizeof(struct hash_entry), hash_cmp); /* * Look for duplicates @@ -769,6 +776,11 @@ resort: goto errout; } + /* Sort non-hashed directories by inode number */ + if (fd.compress) + qsort(fd.harray+2, fd.num_array-2, + sizeof(struct hash_entry), ino_cmp); + /* * Copy the directory entries. In a htree directory these * will become the leaf nodes. |