2 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
7 * This file may be redistributed under the terms of the GNU Public
16 static void check_block_bitmaps(e2fsck_t ctx);
17 static void check_inode_bitmaps(e2fsck_t ctx);
18 static void check_inode_end(e2fsck_t ctx);
19 static void check_block_end(e2fsck_t ctx);
21 void e2fsck_pass5(e2fsck_t ctx)
24 struct resource_track rtrack;
26 struct problem_context pctx;
29 mtrace_print("Pass 5");
33 init_resource_track(&rtrack, ctx->fs->io);
36 clear_problem_context(&pctx);
38 if (!(ctx->options & E2F_OPT_PREEN))
39 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
42 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
45 e2fsck_read_bitmaps(ctx);
47 check_block_bitmaps(ctx);
48 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
50 check_inode_bitmaps(ctx);
51 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
54 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
57 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
60 ext2fs_free_inode_bitmap(ctx->inode_used_map);
61 ctx->inode_used_map = 0;
62 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
63 ctx->inode_dir_map = 0;
64 ext2fs_free_block_bitmap(ctx->block_found_map);
65 ctx->block_found_map = 0;
68 if (ctx->options & E2F_OPT_TIME2) {
69 e2fsck_clear_progbar(ctx);
70 print_resource_track(_("Pass 5"), &rtrack, ctx->fs->io);
75 #define NO_BLK ((blk_t) -1)
77 static void print_bitmap_problem(e2fsck_t ctx, int problem,
78 struct problem_context *pctx)
81 case PR_5_BLOCK_UNUSED:
82 if (pctx->blk == pctx->blk2)
85 problem = PR_5_BLOCK_RANGE_UNUSED;
88 if (pctx->blk == pctx->blk2)
91 problem = PR_5_BLOCK_RANGE_USED;
93 case PR_5_INODE_UNUSED:
94 if (pctx->ino == pctx->ino2)
97 problem = PR_5_INODE_RANGE_UNUSED;
100 if (pctx->ino == pctx->ino2)
103 problem = PR_5_INODE_RANGE_USED;
106 fix_problem(ctx, problem, pctx);
107 pctx->blk = pctx->blk2 = NO_BLK;
108 pctx->ino = pctx->ino2 = 0;
111 static void check_block_bitmaps(e2fsck_t ctx)
113 ext2_filsys fs = ctx->fs;
118 blk_t free_blocks = 0;
121 struct problem_context pctx;
122 int problem, save_problem, fixit, had_problem;
124 int lazy_flag, csum_flag;
127 clear_problem_context(&pctx);
128 free_array = (int *) e2fsck_allocate_memory(ctx,
129 fs->group_desc_count * sizeof(int), "free block count array");
131 if ((fs->super->s_first_data_block <
132 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
133 (fs->super->s_blocks_count-1 >
134 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
136 pctx.blk = fs->super->s_first_data_block;
137 pctx.blk2 = fs->super->s_blocks_count -1;
138 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
139 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
140 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
142 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
146 if ((fs->super->s_first_data_block <
147 ext2fs_get_block_bitmap_start(fs->block_map)) ||
148 (fs->super->s_blocks_count-1 >
149 ext2fs_get_block_bitmap_end(fs->block_map))) {
151 pctx.blk = fs->super->s_first_data_block;
152 pctx.blk2 = fs->super->s_blocks_count -1;
153 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
154 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
155 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
157 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
161 lazy_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
162 EXT2_FEATURE_COMPAT_LAZY_BG);
163 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
164 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
168 pctx.blk = pctx.blk2 = NO_BLK;
169 if ((lazy_flag || csum_flag) &&
170 (fs->group_desc[group].bg_flags & EXT2_BG_BLOCK_UNINIT))
172 super = fs->super->s_first_data_block;
173 for (i = fs->super->s_first_data_block;
174 i < fs->super->s_blocks_count;
176 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
180 (i <= super + fs->desc_blocks) &&
181 ext2fs_bg_has_super(fs, group))
183 else if (i == fs->group_desc[group].bg_block_bitmap)
185 else if (i == fs->group_desc[group].bg_inode_bitmap)
187 else if (i >= fs->group_desc[group].bg_inode_table &&
188 (i < fs->group_desc[group].bg_inode_table
189 + fs->inode_blocks_per_group))
193 actual = (actual != 0);
195 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
197 if (actual == bitmap)
200 if (!actual && bitmap) {
202 * Block not used, but marked in use in the bitmap.
204 problem = PR_5_BLOCK_UNUSED;
207 * Block used, but not marked in use in the bitmap.
209 problem = PR_5_BLOCK_USED;
212 struct problem_context pctx2;
215 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
216 fs->group_desc[group].bg_flags &=
217 ~EXT2_BG_BLOCK_UNINIT;
222 if (pctx.blk == NO_BLK) {
223 pctx.blk = pctx.blk2 = i;
224 save_problem = problem;
226 if ((problem == save_problem) &&
230 print_bitmap_problem(ctx, save_problem, &pctx);
231 pctx.blk = pctx.blk2 = i;
232 save_problem = problem;
235 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
239 if (!bitmap && (!skip_group || csum_flag)) {
244 if ((blocks == fs->super->s_blocks_per_group) ||
245 (i == fs->super->s_blocks_count-1)) {
246 free_array[group] = group_free;
251 super += fs->super->s_blocks_per_group;
253 if ((ctx->progress)(ctx, 5, group,
254 fs->group_desc_count*2))
256 if ((lazy_flag || csum_flag) &&
257 (i != fs->super->s_blocks_count-1) &&
258 (fs->group_desc[group].bg_flags &
259 EXT2_BG_BLOCK_UNINIT))
263 if (pctx.blk != NO_BLK)
264 print_bitmap_problem(ctx, save_problem, &pctx);
266 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
269 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
272 ext2fs_free_block_bitmap(fs->block_map);
273 retval = ext2fs_copy_bitmap(ctx->block_found_map,
276 clear_problem_context(&pctx);
277 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
278 ctx->flags |= E2F_FLAG_ABORT;
281 ext2fs_set_bitmap_padding(fs->block_map);
282 ext2fs_mark_bb_dirty(fs);
284 /* Redo the counts */
285 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
286 memset(free_array, 0, fs->group_desc_count * sizeof(int));
288 } else if (fixit == 0)
289 ext2fs_unmark_valid(fs);
291 for (i = 0; i < fs->group_desc_count; i++) {
292 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
294 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
295 pctx.blk2 = free_array[i];
297 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
299 fs->group_desc[i].bg_free_blocks_count =
301 ext2fs_mark_super_dirty(fs);
303 ext2fs_unmark_valid(fs);
306 if (free_blocks != fs->super->s_free_blocks_count) {
308 pctx.blk = fs->super->s_free_blocks_count;
309 pctx.blk2 = free_blocks;
311 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
312 fs->super->s_free_blocks_count = free_blocks;
313 ext2fs_mark_super_dirty(fs);
315 ext2fs_unmark_valid(fs);
318 ext2fs_free_mem(&free_array);
321 static void check_inode_bitmaps(e2fsck_t ctx)
323 ext2_filsys fs = ctx->fs;
325 unsigned int free_inodes = 0;
329 unsigned int inodes = 0;
334 struct problem_context pctx;
335 int problem, save_problem, fixit, had_problem;
336 int lazy_flag, csum_flag;
339 clear_problem_context(&pctx);
340 free_array = (int *) e2fsck_allocate_memory(ctx,
341 fs->group_desc_count * sizeof(int), "free inode count array");
343 dir_array = (int *) e2fsck_allocate_memory(ctx,
344 fs->group_desc_count * sizeof(int), "directory count array");
346 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
347 (fs->super->s_inodes_count >
348 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
351 pctx.blk2 = fs->super->s_inodes_count;
352 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
353 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
354 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
356 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
359 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
360 (fs->super->s_inodes_count >
361 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
364 pctx.blk2 = fs->super->s_inodes_count;
365 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
366 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
367 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
369 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
373 lazy_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
374 EXT2_FEATURE_COMPAT_LAZY_BG);
375 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
376 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
380 pctx.ino = pctx.ino2 = 0;
381 if ((lazy_flag || csum_flag) &&
382 (fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT))
385 /* Protect loop from wrap-around if inodes_count is maxed */
386 for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
387 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
391 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
392 if (actual == bitmap)
395 if (!actual && bitmap) {
397 * Inode wasn't used, but marked in bitmap
399 problem = PR_5_INODE_UNUSED;
400 } else /* if (actual && !bitmap) */ {
402 * Inode used, but not in bitmap
404 problem = PR_5_INODE_USED;
406 /* We should never hit this, because it means that
407 * inodes were marked in use that weren't noticed
408 * in pass1 or pass 2. It is easier to fix the problem
409 * than to kill e2fsck and leave the user stuck. */
411 struct problem_context pctx2;
414 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
415 fs->group_desc[group].bg_flags &=
416 ~EXT2_BG_INODE_UNINIT;
422 pctx.ino = pctx.ino2 = i;
423 save_problem = problem;
425 if ((problem == save_problem) &&
429 print_bitmap_problem(ctx, save_problem, &pctx);
430 pctx.ino = pctx.ino2 = i;
431 save_problem = problem;
434 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
439 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
441 } else if (!skip_group || csum_flag) {
446 if ((inodes == fs->super->s_inodes_per_group) ||
447 (i == fs->super->s_inodes_count)) {
448 free_array[group] = group_free;
449 dir_array[group] = dirs_count;
456 if ((ctx->progress)(ctx, 5,
457 group + fs->group_desc_count,
458 fs->group_desc_count*2))
460 if ((lazy_flag || csum_flag) &&
461 (i != fs->super->s_inodes_count) &&
462 (fs->group_desc[group].bg_flags &
463 EXT2_BG_INODE_UNINIT))
468 print_bitmap_problem(ctx, save_problem, &pctx);
471 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
474 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
477 ext2fs_free_inode_bitmap(fs->inode_map);
478 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
481 clear_problem_context(&pctx);
482 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
483 ctx->flags |= E2F_FLAG_ABORT;
486 ext2fs_set_bitmap_padding(fs->inode_map);
487 ext2fs_mark_ib_dirty(fs);
490 inodes = 0; free_inodes = 0; group_free = 0;
491 dirs_count = 0; group = 0;
492 memset(free_array, 0, fs->group_desc_count * sizeof(int));
493 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
495 } else if (fixit == 0)
496 ext2fs_unmark_valid(fs);
498 for (i = 0; i < fs->group_desc_count; i++) {
499 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
501 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
502 pctx.ino2 = free_array[i];
503 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
505 fs->group_desc[i].bg_free_inodes_count =
507 ext2fs_mark_super_dirty(fs);
509 ext2fs_unmark_valid(fs);
511 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
513 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
514 pctx.ino2 = dir_array[i];
516 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
518 fs->group_desc[i].bg_used_dirs_count =
520 ext2fs_mark_super_dirty(fs);
522 ext2fs_unmark_valid(fs);
525 if (free_inodes != fs->super->s_free_inodes_count) {
527 pctx.ino = fs->super->s_free_inodes_count;
528 pctx.ino2 = free_inodes;
530 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
531 fs->super->s_free_inodes_count = free_inodes;
532 ext2fs_mark_super_dirty(fs);
534 ext2fs_unmark_valid(fs);
537 ext2fs_free_mem(&free_array);
538 ext2fs_free_mem(&dir_array);
541 static void check_inode_end(e2fsck_t ctx)
543 ext2_filsys fs = ctx->fs;
544 ext2_ino_t end, save_inodes_count, i;
545 struct problem_context pctx;
547 clear_problem_context(&pctx);
549 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
550 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
554 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
555 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
558 if (save_inodes_count == end)
561 /* protect loop from wrap-around if end is maxed */
562 for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
563 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
564 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
565 for (i = save_inodes_count + 1; i <= end; i++)
566 ext2fs_mark_inode_bitmap(fs->inode_map,
568 ext2fs_mark_ib_dirty(fs);
570 ext2fs_unmark_valid(fs);
575 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
576 save_inodes_count, 0);
579 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
580 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
585 static void check_block_end(e2fsck_t ctx)
587 ext2_filsys fs = ctx->fs;
588 blk_t end, save_blocks_count, i;
589 struct problem_context pctx;
591 clear_problem_context(&pctx);
593 end = ext2fs_get_block_bitmap_start(fs->block_map) +
594 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
595 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
599 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
600 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
603 if (save_blocks_count == end)
606 /* Protect loop from wrap-around if end is maxed */
607 for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
608 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
609 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
610 for (i = save_blocks_count + 1; i <= end; i++)
611 ext2fs_mark_block_bitmap(fs->block_map,
613 ext2fs_mark_bb_dirty(fs);
615 ext2fs_unmark_valid(fs);
620 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
621 save_blocks_count, 0);
624 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
625 ctx->flags |= E2F_FLAG_ABORT; /* fatal */