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
14 #include <sys/types.h>
16 #include <sys/ioctl.h>
23 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
25 static void check_block_bitmaps(e2fsck_t ctx);
26 static void check_inode_bitmaps(e2fsck_t ctx);
27 static void check_inode_end(e2fsck_t ctx);
28 static void check_block_end(e2fsck_t ctx);
30 void e2fsck_pass5(e2fsck_t ctx)
33 struct resource_track rtrack;
35 struct problem_context pctx;
38 mtrace_print("Pass 5");
41 init_resource_track(&rtrack, ctx->fs->io);
42 clear_problem_context(&pctx);
44 if (!(ctx->options & E2F_OPT_PREEN))
45 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
48 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
51 e2fsck_read_bitmaps(ctx);
53 check_block_bitmaps(ctx);
54 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
56 check_inode_bitmaps(ctx);
57 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
60 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
63 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
66 ext2fs_free_inode_bitmap(ctx->inode_used_map);
67 ctx->inode_used_map = 0;
68 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
69 ctx->inode_dir_map = 0;
70 ext2fs_free_block_bitmap(ctx->block_found_map);
71 ctx->block_found_map = 0;
73 print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
76 static void e2fsck_discard_blocks(e2fsck_t ctx, io_manager manager,
77 blk64_t start, blk64_t count)
79 ext2_filsys fs = ctx->fs;
83 * If the filesystem has changed it means that there was an corruption
84 * which should be repaired, but in some cases just one e2fsck run is
85 * not enough to fix the problem, hence it is not safe to run discard
88 if (ext2fs_test_changed(ctx->fs))
89 ctx->options &= ~E2F_OPT_DISCARD;
91 if ((ctx->options & E2F_OPT_DISCARD) &&
92 (io_channel_discard(fs->io, start, count)))
93 ctx->options &= ~E2F_OPT_DISCARD;
96 #define NO_BLK ((blk64_t) -1)
98 static void print_bitmap_problem(e2fsck_t ctx, int problem,
99 struct problem_context *pctx)
102 case PR_5_BLOCK_UNUSED:
103 if (pctx->blk == pctx->blk2)
106 problem = PR_5_BLOCK_RANGE_UNUSED;
108 case PR_5_BLOCK_USED:
109 if (pctx->blk == pctx->blk2)
112 problem = PR_5_BLOCK_RANGE_USED;
114 case PR_5_INODE_UNUSED:
115 if (pctx->ino == pctx->ino2)
118 problem = PR_5_INODE_RANGE_UNUSED;
120 case PR_5_INODE_USED:
121 if (pctx->ino == pctx->ino2)
124 problem = PR_5_INODE_RANGE_USED;
127 fix_problem(ctx, problem, pctx);
128 pctx->blk = pctx->blk2 = NO_BLK;
129 pctx->ino = pctx->ino2 = 0;
132 static void check_block_bitmaps(e2fsck_t ctx)
134 ext2_filsys fs = ctx->fs;
139 blk64_t free_blocks = 0;
140 blk64_t first_free = ext2fs_blocks_count(fs->super);
143 struct problem_context pctx;
144 int problem, save_problem, fixit, had_problem;
148 int old_desc_blocks = 0;
152 blk64_t super_blk, old_desc_blk, new_desc_blk;
153 io_manager manager = ctx->fs->io->manager;
155 clear_problem_context(&pctx);
156 free_array = (int *) e2fsck_allocate_memory(ctx,
157 fs->group_desc_count * sizeof(int), "free block count array");
159 if ((EXT2FS_B2C(fs, fs->super->s_first_data_block) <
160 ext2fs_get_block_bitmap_start2(ctx->block_found_map)) ||
161 (EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1) >
162 ext2fs_get_block_bitmap_end2(ctx->block_found_map))) {
164 pctx.blk = EXT2FS_B2C(fs, fs->super->s_first_data_block);
165 pctx.blk2 = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super) - 1);
166 pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map);
167 pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map);
168 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
170 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
174 if ((EXT2FS_B2C(fs, fs->super->s_first_data_block) <
175 ext2fs_get_block_bitmap_start2(fs->block_map)) ||
176 (EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1) >
177 ext2fs_get_block_bitmap_end2(fs->block_map))) {
179 pctx.blk = EXT2FS_B2C(fs, fs->super->s_first_data_block);
180 pctx.blk2 = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super) - 1);
181 pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map);
182 pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map);
183 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
185 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
189 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
190 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
194 pctx.blk = pctx.blk2 = NO_BLK;
196 (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
198 for (i = EXT2FS_B2C(fs, fs->super->s_first_data_block);
199 i < ext2fs_blocks_count(fs->super);
200 i += EXT2FS_CLUSTER_RATIO(fs)) {
201 actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i);
204 if ((i - fs->super->s_first_data_block) %
205 fs->super->s_blocks_per_group == 0) {
209 ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
210 &old_desc_blk, &new_desc_blk, 0);
212 if (fs->super->s_feature_incompat &
213 EXT2_FEATURE_INCOMPAT_META_BG)
215 fs->super->s_first_meta_bg;
217 old_desc_blocks = fs->desc_blocks +
218 fs->super->s_reserved_gdt_blocks;
221 cmp_block = fs->super->s_blocks_per_group;
222 if (group == (int)fs->group_desc_count - 1)
224 ext2fs_blocks_count(fs->super) %
225 fs->super->s_blocks_per_group;
229 if ((i == super_blk) ||
230 (old_desc_blk && old_desc_blocks &&
231 (i >= old_desc_blk) &&
232 (i < old_desc_blk + old_desc_blocks)) ||
233 (new_desc_blk && (i == new_desc_blk)) ||
234 (i == ext2fs_block_bitmap_loc(fs, group)) ||
235 (i == ext2fs_inode_bitmap_loc(fs, group)) ||
236 (i >= ext2fs_inode_table_loc(fs, group) &&
237 (i < ext2fs_inode_table_loc(fs, group) +
238 fs->inode_blocks_per_group))) {
240 actual = (actual != 0);
243 } else if ((i - count - fs->super->s_first_data_block) %
244 fs->super->s_blocks_per_group == 0) {
246 * When the compare data blocks in block bitmap
247 * are 0, count the free block,
248 * skip the current block group.
250 if (ext2fs_test_block_bitmap_range2(
251 ctx->block_found_map, i,
254 * -1 means to skip the current block
257 blocks = fs->super->s_blocks_per_group
259 group_free = cmp_block;
260 free_blocks += cmp_block;
262 * The current block group's last block
270 } else if (redo_flag)
273 bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
275 if (actual == bitmap)
278 if (!actual && bitmap) {
280 * Block not used, but marked in use in the bitmap.
282 problem = PR_5_BLOCK_UNUSED;
285 * Block used, but not marked in use in the bitmap.
287 problem = PR_5_BLOCK_USED;
290 struct problem_context pctx2;
293 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
294 ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
299 if (pctx.blk == NO_BLK) {
300 pctx.blk = pctx.blk2 = i;
301 save_problem = problem;
303 if ((problem == save_problem) &&
307 print_bitmap_problem(ctx, save_problem, &pctx);
308 pctx.blk = pctx.blk2 = i;
309 save_problem = problem;
312 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
316 * If there a problem we should turn off the discard so we
317 * do not compromise the filesystem.
319 ctx->options &= ~E2F_OPT_DISCARD;
322 if (!bitmap && (!skip_group || csum_flag)) {
328 if ((i > first_free) &&
329 (ctx->options & E2F_OPT_DISCARD)) {
330 e2fsck_discard_blocks(ctx, manager, first_free,
333 first_free = ext2fs_blocks_count(fs->super);
336 if ((blocks == fs->super->s_clusters_per_group) ||
337 (EXT2FS_B2C(fs, i) ==
338 EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) {
339 free_array[group] = group_free;
345 if ((ctx->progress)(ctx, 5, group,
346 fs->group_desc_count*2))
349 (i != ext2fs_blocks_count(fs->super)-1) &&
350 ext2fs_bg_flags_test(fs, group,
351 EXT2_BG_BLOCK_UNINIT))
355 if (pctx.blk != NO_BLK)
356 print_bitmap_problem(ctx, save_problem, &pctx);
358 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
361 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
364 ext2fs_free_block_bitmap(fs->block_map);
365 retval = ext2fs_copy_bitmap(ctx->block_found_map,
368 clear_problem_context(&pctx);
369 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
370 ctx->flags |= E2F_FLAG_ABORT;
373 ext2fs_set_bitmap_padding(fs->block_map);
374 ext2fs_mark_bb_dirty(fs);
376 /* Redo the counts */
377 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
378 memset(free_array, 0, fs->group_desc_count * sizeof(int));
381 } else if (fixit == 0)
382 ext2fs_unmark_valid(fs);
384 for (i = 0; i < fs->group_desc_count; i++) {
385 if (free_array[i] != ext2fs_bg_free_blocks_count(fs, i)) {
387 pctx.blk = ext2fs_bg_free_blocks_count(fs, i);
388 pctx.blk2 = free_array[i];
390 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
392 ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]);
393 ext2fs_mark_super_dirty(fs);
395 ext2fs_unmark_valid(fs);
398 if (free_blocks != ext2fs_free_blocks_count(fs->super)) {
400 pctx.blk = ext2fs_free_blocks_count(fs->super);
401 pctx.blk2 = free_blocks;
403 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
404 ext2fs_free_blocks_count_set(fs->super, free_blocks);
405 ext2fs_mark_super_dirty(fs);
407 ext2fs_unmark_valid(fs);
410 ext2fs_free_mem(&free_array);
413 static void check_inode_bitmaps(e2fsck_t ctx)
415 ext2_filsys fs = ctx->fs;
417 unsigned int free_inodes = 0;
421 unsigned int inodes = 0;
426 struct problem_context pctx;
427 int problem, save_problem, fixit, had_problem;
431 io_manager manager = ctx->fs->io->manager;
433 clear_problem_context(&pctx);
434 free_array = (int *) e2fsck_allocate_memory(ctx,
435 fs->group_desc_count * sizeof(int), "free inode count array");
437 dir_array = (int *) e2fsck_allocate_memory(ctx,
438 fs->group_desc_count * sizeof(int), "directory count array");
440 if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
441 (fs->super->s_inodes_count >
442 ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
445 pctx.blk2 = fs->super->s_inodes_count;
446 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
447 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
448 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
450 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
453 if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
454 (fs->super->s_inodes_count >
455 ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
458 pctx.blk2 = fs->super->s_inodes_count;
459 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
460 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
461 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
463 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
467 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
468 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
472 pctx.ino = pctx.ino2 = 0;
474 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
477 /* Protect loop from wrap-around if inodes_count is maxed */
478 for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
481 i % fs->super->s_inodes_per_group == 1) {
483 * Current inode is the first inode
484 * in the current block group.
486 if (ext2fs_test_inode_bitmap_range(
487 ctx->inode_used_map, i,
488 fs->super->s_inodes_per_group)) {
490 * When the compared inodes in inodes bitmap
491 * are 0, count the free inode,
492 * skip the current block group.
494 inodes = fs->super->s_inodes_per_group - 1;
496 free_inodes += inodes;
503 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
506 else if (!skip_group)
507 bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
508 if (actual == bitmap)
511 if (!actual && bitmap) {
513 * Inode wasn't used, but marked in bitmap
515 problem = PR_5_INODE_UNUSED;
516 } else /* if (actual && !bitmap) */ {
518 * Inode used, but not in bitmap
520 problem = PR_5_INODE_USED;
522 /* We should never hit this, because it means that
523 * inodes were marked in use that weren't noticed
524 * in pass1 or pass 2. It is easier to fix the problem
525 * than to kill e2fsck and leave the user stuck. */
527 struct problem_context pctx2;
530 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
531 ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
537 pctx.ino = pctx.ino2 = i;
538 save_problem = problem;
540 if ((problem == save_problem) &&
544 print_bitmap_problem(ctx, save_problem, &pctx);
545 pctx.ino = pctx.ino2 = i;
546 save_problem = problem;
549 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
552 * If there a problem we should turn off the discard so we
553 * do not compromise the filesystem.
555 ctx->options &= ~E2F_OPT_DISCARD;
559 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
561 } else if (!skip_group || csum_flag) {
567 if ((inodes == fs->super->s_inodes_per_group) ||
568 (i == fs->super->s_inodes_count)) {
570 free_array[group] = group_free;
571 dir_array[group] = dirs_count;
573 /* Discard inode table */
574 if (ctx->options & E2F_OPT_DISCARD) {
575 blk64_t used_blks, blk, num;
577 used_blks = DIV_ROUND_UP(
578 (EXT2_INODES_PER_GROUP(fs->super) -
580 EXT2_INODES_PER_BLOCK(fs->super));
582 blk = ext2fs_inode_table_loc(fs, group) +
584 num = fs->inode_blocks_per_group -
586 e2fsck_discard_blocks(ctx, manager, blk, num);
590 * If discard zeroes data and the group inode table
591 * was not zeroed yet, set itable as zeroed
593 if ((ctx->options & E2F_OPT_DISCARD) &&
594 (io_channel_discard_zeroes_data(fs->io)) &&
595 !(ext2fs_bg_flags_test(fs, group,
596 EXT2_BG_INODE_ZEROED))) {
597 ext2fs_bg_flags_set(fs, group,
598 EXT2_BG_INODE_ZEROED);
599 ext2fs_group_desc_csum_set(fs, group);
608 if ((ctx->progress)(ctx, 5,
609 group + fs->group_desc_count,
610 fs->group_desc_count*2))
613 (i != fs->super->s_inodes_count) &&
614 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)
620 print_bitmap_problem(ctx, save_problem, &pctx);
623 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
626 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
629 ext2fs_free_inode_bitmap(fs->inode_map);
630 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
633 clear_problem_context(&pctx);
634 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
635 ctx->flags |= E2F_FLAG_ABORT;
638 ext2fs_set_bitmap_padding(fs->inode_map);
639 ext2fs_mark_ib_dirty(fs);
642 inodes = 0; free_inodes = 0; group_free = 0;
643 dirs_count = 0; group = 0;
644 memset(free_array, 0, fs->group_desc_count * sizeof(int));
645 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
648 } else if (fixit == 0)
649 ext2fs_unmark_valid(fs);
651 for (i = 0; i < fs->group_desc_count; i++) {
652 if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) {
654 pctx.ino = ext2fs_bg_free_inodes_count(fs, i);
655 pctx.ino2 = free_array[i];
656 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
658 ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]);
659 ext2fs_mark_super_dirty(fs);
661 ext2fs_unmark_valid(fs);
663 if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) {
665 pctx.ino = ext2fs_bg_used_dirs_count(fs, i);
666 pctx.ino2 = dir_array[i];
668 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
670 ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]);
671 ext2fs_mark_super_dirty(fs);
673 ext2fs_unmark_valid(fs);
676 if (free_inodes != fs->super->s_free_inodes_count) {
678 pctx.ino = fs->super->s_free_inodes_count;
679 pctx.ino2 = free_inodes;
681 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
682 fs->super->s_free_inodes_count = free_inodes;
683 ext2fs_mark_super_dirty(fs);
685 ext2fs_unmark_valid(fs);
688 ext2fs_free_mem(&free_array);
689 ext2fs_free_mem(&dir_array);
692 static void check_inode_end(e2fsck_t ctx)
694 ext2_filsys fs = ctx->fs;
695 ext2_ino_t end, save_inodes_count, i;
696 struct problem_context pctx;
698 clear_problem_context(&pctx);
700 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
701 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
705 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
706 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
709 if (save_inodes_count == end)
712 /* protect loop from wrap-around if end is maxed */
713 for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
714 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
715 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
716 for (; i <= end; i++)
717 ext2fs_mark_inode_bitmap(fs->inode_map,
719 ext2fs_mark_ib_dirty(fs);
721 ext2fs_unmark_valid(fs);
726 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
727 save_inodes_count, 0);
730 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
731 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
736 static void check_block_end(e2fsck_t ctx)
738 ext2_filsys fs = ctx->fs;
739 blk64_t end, save_blocks_count, i;
740 struct problem_context pctx;
742 clear_problem_context(&pctx);
744 end = ext2fs_get_block_bitmap_start2(fs->block_map) +
745 ((blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
746 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
750 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
751 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
754 if (save_blocks_count == end)
757 /* Protect loop from wrap-around if end is maxed */
758 for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
759 if (!ext2fs_test_block_bitmap2(fs->block_map,
760 EXT2FS_C2B(fs, i))) {
761 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
762 for (; i <= end; i++)
763 ext2fs_mark_block_bitmap2(fs->block_map,
765 ext2fs_mark_bb_dirty(fs);
767 ext2fs_unmark_valid(fs);
772 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
773 save_blocks_count, 0);
776 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
777 ctx->flags |= E2F_FLAG_ABORT; /* fatal */