summaryrefslogtreecommitdiff
path: root/e2fsck/super.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2005-01-25 03:09:24 -0500
committerTheodore Ts'o <tytso@mit.edu>2005-01-25 03:09:24 -0500
commit550a4afa24be35976edffe578555de30e06c456a (patch)
treeb8636bd9ad24334a2d1608ad5f3247a74e2a6236 /e2fsck/super.c
parentfbc3514623262e695679d08557ad270fd9df6eeb (diff)
downloade2fsprogs-550a4afa24be35976edffe578555de30e06c456a.tar.gz
E2fsck will now check the individual block group inode and block free counts,
as well as the filesystem-wide inode and block free counts. If any of the free counts is too large, force a full filesystem check. (Addresses Debian Bug #291571)
Diffstat (limited to 'e2fsck/super.c')
-rw-r--r--e2fsck/super.c92
1 files changed, 54 insertions, 38 deletions
diff --git a/e2fsck/super.c b/e2fsck/super.c
index 2e9e6a8c..9a662f0a 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -431,6 +431,7 @@ void check_super_block(e2fsck_t ctx)
ext2_filsys fs = ctx->fs;
blk_t first_block, last_block;
struct ext2_super_block *sb = fs->super;
+ struct ext2_group_desc *gd;
blk_t blocks_per_group = fs->super->s_blocks_per_group;
blk_t bpg_max;
int inodes_per_block;
@@ -542,56 +543,86 @@ void check_super_block(e2fsck_t ctx)
/*
* Verify the group descriptors....
*/
- first_block = fs->super->s_first_data_block;
+ first_block = sb->s_first_data_block;
last_block = first_block + blocks_per_group;
- for (i = 0; i < fs->group_desc_count; i++) {
+ for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
pctx.group = i;
if (i == fs->group_desc_count - 1)
- last_block = fs->super->s_blocks_count;
- if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
- (fs->group_desc[i].bg_block_bitmap >= last_block)) {
- pctx.blk = fs->group_desc[i].bg_block_bitmap;
+ last_block = sb->s_blocks_count;
+ if ((gd->bg_block_bitmap < first_block) ||
+ (gd->bg_block_bitmap >= last_block)) {
+ pctx.blk = gd->bg_block_bitmap;
if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
- fs->group_desc[i].bg_block_bitmap = 0;
+ gd->bg_block_bitmap = 0;
}
- if (fs->group_desc[i].bg_block_bitmap == 0) {
+ if (gd->bg_block_bitmap == 0) {
ctx->invalid_block_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
- if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
- (fs->group_desc[i].bg_inode_bitmap >= last_block)) {
- pctx.blk = fs->group_desc[i].bg_inode_bitmap;
+ if ((gd->bg_inode_bitmap < first_block) ||
+ (gd->bg_inode_bitmap >= last_block)) {
+ pctx.blk = gd->bg_inode_bitmap;
if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
- fs->group_desc[i].bg_inode_bitmap = 0;
+ gd->bg_inode_bitmap = 0;
}
- if (fs->group_desc[i].bg_inode_bitmap == 0) {
+ if (gd->bg_inode_bitmap == 0) {
ctx->invalid_inode_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
- if ((fs->group_desc[i].bg_inode_table < first_block) ||
- ((fs->group_desc[i].bg_inode_table +
+ if ((gd->bg_inode_table < first_block) ||
+ ((gd->bg_inode_table +
fs->inode_blocks_per_group - 1) >= last_block)) {
- pctx.blk = fs->group_desc[i].bg_inode_table;
+ pctx.blk = gd->bg_inode_table;
if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
- fs->group_desc[i].bg_inode_table = 0;
+ gd->bg_inode_table = 0;
}
- if (fs->group_desc[i].bg_inode_table == 0) {
+ if (gd->bg_inode_table == 0) {
ctx->invalid_inode_table_flag[i]++;
ctx->invalid_bitmaps++;
}
- free_blocks += fs->group_desc[i].bg_free_blocks_count;
- free_inodes += fs->group_desc[i].bg_free_inodes_count;
- first_block += fs->super->s_blocks_per_group;
- last_block += fs->super->s_blocks_per_group;
+ free_blocks += gd->bg_free_blocks_count;
+ free_inodes += gd->bg_free_inodes_count;
+ first_block += sb->s_blocks_per_group;
+ last_block += sb->s_blocks_per_group;
+
+ if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
+ (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
+ (gd->bg_used_dirs_count > sb->s_inodes_per_group))
+ ext2fs_unmark_valid(fs);
+
+ }
+
+ /*
+ * Update the global counts from the block group counts. This
+ * is needed for an experimental patch which eliminates
+ * locking the entire filesystem when allocating blocks or
+ * inodes; if the filesystem is not unmounted cleanly, the
+ * global counts may not be accurate.
+ */
+ if ((free_blocks != sb->s_free_blocks_count) ||
+ (free_inodes != sb->s_free_inodes_count)) {
+ if (ctx->options & E2F_OPT_READONLY)
+ ext2fs_unmark_valid(fs);
+ else {
+ sb->s_free_blocks_count = free_blocks;
+ sb->s_free_inodes_count = free_inodes;
+ ext2fs_mark_super_dirty(fs);
+ }
}
+
+ if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
+ (sb->s_free_inodes_count > sb->s_inodes_count))
+ ext2fs_unmark_valid(fs);
+
+
/*
* If we have invalid bitmaps, set the error state of the
* filesystem.
*/
if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
- fs->super->s_state &= ~EXT2_VALID_FS;
+ sb->s_state &= ~EXT2_VALID_FS;
ext2fs_mark_super_dirty(fs);
}
@@ -611,21 +642,6 @@ void check_super_block(e2fsck_t ctx)
#endif
/*
- * Update the global counts from the block group counts. This
- * is needed for an experimental patch which eliminates
- * locking the entire filesystem when allocating blocks or
- * inodes; if the filesystem is not unmounted cleanly, the
- * global counts may not be accurate.
- */
- if (!(ctx->options & E2F_OPT_READONLY) &&
- ((free_blocks != fs->super->s_free_blocks_count) ||
- (free_inodes != fs->super->s_free_inodes_count))) {
- fs->super->s_free_blocks_count = free_blocks;
- fs->super->s_free_inodes_count = free_inodes;
- ext2fs_mark_super_dirty(fs);
- }
-
- /*
* For the Hurd, check to see if the filetype option is set,
* since it doesn't support it.
*/