summaryrefslogtreecommitdiff
path: root/e2fsck
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2010-01-30 21:22:17 -0500
committerTheodore Ts'o <tytso@mit.edu>2010-01-31 18:49:08 -0500
commit2d07b3ad98bfe1db5fb1071f53a5338ab6c35522 (patch)
tree5569434a7e4a85b015c6ad0e3933ea09ae42f8a4 /e2fsck
parent2884320016e633d987203c0286a9dbf9e62a3fd4 (diff)
parentc70674387ee0c038bca16098f7869181beeabe0a (diff)
downloade2fsprogs-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.in13
-rw-r--r--e2fsck/pass1.c86
-rw-r--r--e2fsck/pass2.c30
-rw-r--r--e2fsck/problem.c11
-rw-r--r--e2fsck/rehash.c24
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.