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;
82 * If the filesystem has changed it means that there was an corruption
83 * which should be repaired, but in some cases just one e2fsck run is
84 * not enough to fix the problem, hence it is not safe to run discard
87 if (ext2fs_test_changed(ctx->fs))
88 ctx->options &= ~E2F_OPT_DISCARD;
90 if (!(ctx->options & E2F_OPT_NO) &&
91 (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 /* Just to be more succint */
133 #define B2C(x) EXT2FS_B2C(fs, (x))
134 #define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
135 #define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
136 #define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
138 static void check_block_bitmaps(e2fsck_t ctx)
140 ext2_filsys fs = ctx->fs;
145 blk64_t free_blocks = 0;
146 blk64_t first_free = ext2fs_blocks_count(fs->super);
149 struct problem_context pctx;
150 int problem, save_problem, fixit, had_problem;
154 int old_desc_blocks = 0;
158 blk64_t super_blk, old_desc_blk, new_desc_blk;
159 io_manager manager = ctx->fs->io->manager;
161 clear_problem_context(&pctx);
162 free_array = (int *) e2fsck_allocate_memory(ctx,
163 fs->group_desc_count * sizeof(int), "free block count array");
165 if ((B2C(fs->super->s_first_data_block) <
166 ext2fs_get_block_bitmap_start2(ctx->block_found_map)) ||
167 (B2C(ext2fs_blocks_count(fs->super)-1) >
168 ext2fs_get_block_bitmap_end2(ctx->block_found_map))) {
170 pctx.blk = B2C(fs->super->s_first_data_block);
171 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
172 pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map);
173 pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map);
174 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
176 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
180 if ((B2C(fs->super->s_first_data_block) <
181 ext2fs_get_block_bitmap_start2(fs->block_map)) ||
182 (B2C(ext2fs_blocks_count(fs->super)-1) >
183 ext2fs_get_block_bitmap_end2(fs->block_map))) {
185 pctx.blk = B2C(fs->super->s_first_data_block);
186 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
187 pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map);
188 pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map);
189 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
191 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
195 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
196 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
200 pctx.blk = pctx.blk2 = NO_BLK;
202 (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
204 for (i = B2C(fs->super->s_first_data_block);
205 i < ext2fs_blocks_count(fs->super);
206 i += EXT2FS_CLUSTER_RATIO(fs)) {
207 actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i);
210 if ((B2C(i) - B2C(fs->super->s_first_data_block)) %
211 fs->super->s_clusters_per_group == 0) {
215 ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
216 &old_desc_blk, &new_desc_blk, 0);
218 if (fs->super->s_feature_incompat &
219 EXT2_FEATURE_INCOMPAT_META_BG)
221 fs->super->s_first_meta_bg;
223 old_desc_blocks = fs->desc_blocks +
224 fs->super->s_reserved_gdt_blocks;
227 cmp_block = fs->super->s_clusters_per_group;
228 if (group == (int)fs->group_desc_count - 1)
231 ext2fs_blocks_count(fs->super) % fs->super->s_blocks_per_group);
235 if (EQ_CLSTR(i, super_blk) ||
236 (old_desc_blk && old_desc_blocks &&
237 GE_CLSTR(i, old_desc_blk) &&
238 LE_CLSTR(i, old_desc_blk + old_desc_blocks-1)) ||
239 (new_desc_blk && EQ_CLSTR(i, new_desc_blk)) ||
240 EQ_CLSTR(i, ext2fs_block_bitmap_loc(fs, group)) ||
241 EQ_CLSTR(i, ext2fs_inode_bitmap_loc(fs, group)) ||
242 (GE_CLSTR(i, ext2fs_inode_table_loc(fs, group)) &&
243 LE_CLSTR(i, (ext2fs_inode_table_loc(fs, group) +
244 fs->inode_blocks_per_group - 1)))) {
246 actual = (actual != 0);
249 } else if ((EXT2FS_B2C(fs, i) - count -
250 EXT2FS_B2C(fs, fs->super->s_first_data_block)) %
251 fs->super->s_clusters_per_group == 0) {
253 * When the compare data blocks in block bitmap
254 * are 0, count the free block,
255 * skip the current block group.
257 if (ext2fs_test_block_bitmap_range2(
258 ctx->block_found_map,
262 * -1 means to skip the current block
265 blocks = fs->super->s_clusters_per_group - 1;
266 group_free = cmp_block;
267 free_blocks += cmp_block;
269 * The current block group's last block
272 i += EXT2FS_C2B(fs, cmp_block - 1);
277 } else if (redo_flag)
280 bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
282 if (actual == bitmap)
285 if (!actual && bitmap) {
287 * Block not used, but marked in use in the bitmap.
289 problem = PR_5_BLOCK_UNUSED;
292 * Block used, but not marked in use in the bitmap.
294 problem = PR_5_BLOCK_USED;
297 struct problem_context pctx2;
300 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
301 ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
306 if (pctx.blk == NO_BLK) {
307 pctx.blk = pctx.blk2 = i;
308 save_problem = problem;
310 if ((problem == save_problem) &&
314 print_bitmap_problem(ctx, save_problem, &pctx);
315 pctx.blk = pctx.blk2 = i;
316 save_problem = problem;
319 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
323 * If there a problem we should turn off the discard so we
324 * do not compromise the filesystem.
326 ctx->options &= ~E2F_OPT_DISCARD;
329 if (!bitmap && (!skip_group || csum_flag)) {
336 e2fsck_discard_blocks(ctx, manager, first_free,
338 first_free = ext2fs_blocks_count(fs->super);
341 if ((blocks == fs->super->s_clusters_per_group) ||
342 (EXT2FS_B2C(fs, i) ==
343 EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) {
344 free_array[group] = group_free;
350 if ((ctx->progress)(ctx, 5, group,
351 fs->group_desc_count*2))
354 (i != ext2fs_blocks_count(fs->super)-1) &&
355 ext2fs_bg_flags_test(fs, group,
356 EXT2_BG_BLOCK_UNINIT))
360 if (pctx.blk != NO_BLK)
361 print_bitmap_problem(ctx, save_problem, &pctx);
363 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
366 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
369 ext2fs_free_block_bitmap(fs->block_map);
370 retval = ext2fs_copy_bitmap(ctx->block_found_map,
373 clear_problem_context(&pctx);
374 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
375 ctx->flags |= E2F_FLAG_ABORT;
378 ext2fs_set_bitmap_padding(fs->block_map);
379 ext2fs_mark_bb_dirty(fs);
381 /* Redo the counts */
382 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
383 memset(free_array, 0, fs->group_desc_count * sizeof(int));
386 } else if (fixit == 0)
387 ext2fs_unmark_valid(fs);
389 for (i = 0; i < fs->group_desc_count; i++) {
390 if (free_array[i] != ext2fs_bg_free_blocks_count(fs, i)) {
392 pctx.blk = ext2fs_bg_free_blocks_count(fs, i);
393 pctx.blk2 = free_array[i];
395 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
397 ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]);
398 ext2fs_mark_super_dirty(fs);
400 ext2fs_unmark_valid(fs);
403 free_blocks = EXT2FS_C2B(fs, free_blocks);
404 if (free_blocks != ext2fs_free_blocks_count(fs->super)) {
406 pctx.blk = ext2fs_free_blocks_count(fs->super);
407 pctx.blk2 = free_blocks;
409 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
410 ext2fs_free_blocks_count_set(fs->super, free_blocks);
411 ext2fs_mark_super_dirty(fs);
413 ext2fs_unmark_valid(fs);
416 ext2fs_free_mem(&free_array);
419 static void check_inode_bitmaps(e2fsck_t ctx)
421 ext2_filsys fs = ctx->fs;
423 unsigned int free_inodes = 0;
427 unsigned int inodes = 0;
432 struct problem_context pctx;
433 int problem, save_problem, fixit, had_problem;
437 io_manager manager = ctx->fs->io->manager;
439 clear_problem_context(&pctx);
440 free_array = (int *) e2fsck_allocate_memory(ctx,
441 fs->group_desc_count * sizeof(int), "free inode count array");
443 dir_array = (int *) e2fsck_allocate_memory(ctx,
444 fs->group_desc_count * sizeof(int), "directory count array");
446 if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
447 (fs->super->s_inodes_count >
448 ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
451 pctx.blk2 = fs->super->s_inodes_count;
452 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
453 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
454 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
456 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
459 if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
460 (fs->super->s_inodes_count >
461 ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
464 pctx.blk2 = fs->super->s_inodes_count;
465 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
466 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
467 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
469 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
473 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
474 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
478 pctx.ino = pctx.ino2 = 0;
480 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
483 /* Protect loop from wrap-around if inodes_count is maxed */
484 for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
487 i % fs->super->s_inodes_per_group == 1) {
489 * Current inode is the first inode
490 * in the current block group.
492 if (ext2fs_test_inode_bitmap_range(
493 ctx->inode_used_map, i,
494 fs->super->s_inodes_per_group)) {
496 * When the compared inodes in inodes bitmap
497 * are 0, count the free inode,
498 * skip the current block group.
500 inodes = fs->super->s_inodes_per_group - 1;
502 free_inodes += inodes;
509 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
512 else if (!skip_group)
513 bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
514 if (actual == bitmap)
517 if (!actual && bitmap) {
519 * Inode wasn't used, but marked in bitmap
521 problem = PR_5_INODE_UNUSED;
522 } else /* if (actual && !bitmap) */ {
524 * Inode used, but not in bitmap
526 problem = PR_5_INODE_USED;
528 /* We should never hit this, because it means that
529 * inodes were marked in use that weren't noticed
530 * in pass1 or pass 2. It is easier to fix the problem
531 * than to kill e2fsck and leave the user stuck. */
533 struct problem_context pctx2;
536 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
537 ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
543 pctx.ino = pctx.ino2 = i;
544 save_problem = problem;
546 if ((problem == save_problem) &&
550 print_bitmap_problem(ctx, save_problem, &pctx);
551 pctx.ino = pctx.ino2 = i;
552 save_problem = problem;
555 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
558 * If there a problem we should turn off the discard so we
559 * do not compromise the filesystem.
561 ctx->options &= ~E2F_OPT_DISCARD;
565 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
567 } else if (!skip_group || csum_flag) {
573 if ((inodes == fs->super->s_inodes_per_group) ||
574 (i == fs->super->s_inodes_count)) {
576 free_array[group] = group_free;
577 dir_array[group] = dirs_count;
579 /* Discard inode table */
580 if (ctx->options & E2F_OPT_DISCARD) {
581 blk64_t used_blks, blk, num;
583 used_blks = DIV_ROUND_UP(
584 (EXT2_INODES_PER_GROUP(fs->super) -
586 EXT2_INODES_PER_BLOCK(fs->super));
588 blk = ext2fs_inode_table_loc(fs, group) +
590 num = fs->inode_blocks_per_group -
592 e2fsck_discard_blocks(ctx, manager, blk, num);
596 * If discard zeroes data and the group inode table
597 * was not zeroed yet, set itable as zeroed
599 if ((ctx->options & E2F_OPT_DISCARD) &&
600 (io_channel_discard_zeroes_data(fs->io)) &&
601 !(ext2fs_bg_flags_test(fs, group,
602 EXT2_BG_INODE_ZEROED))) {
603 ext2fs_bg_flags_set(fs, group,
604 EXT2_BG_INODE_ZEROED);
605 ext2fs_group_desc_csum_set(fs, group);
614 if ((ctx->progress)(ctx, 5,
615 group + fs->group_desc_count,
616 fs->group_desc_count*2))
619 (i != fs->super->s_inodes_count) &&
620 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)
626 print_bitmap_problem(ctx, save_problem, &pctx);
629 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
632 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
635 ext2fs_free_inode_bitmap(fs->inode_map);
636 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
639 clear_problem_context(&pctx);
640 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
641 ctx->flags |= E2F_FLAG_ABORT;
644 ext2fs_set_bitmap_padding(fs->inode_map);
645 ext2fs_mark_ib_dirty(fs);
648 inodes = 0; free_inodes = 0; group_free = 0;
649 dirs_count = 0; group = 0;
650 memset(free_array, 0, fs->group_desc_count * sizeof(int));
651 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
654 } else if (fixit == 0)
655 ext2fs_unmark_valid(fs);
657 for (i = 0; i < fs->group_desc_count; i++) {
658 if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) {
660 pctx.ino = ext2fs_bg_free_inodes_count(fs, i);
661 pctx.ino2 = free_array[i];
662 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
664 ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]);
665 ext2fs_mark_super_dirty(fs);
667 ext2fs_unmark_valid(fs);
669 if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) {
671 pctx.ino = ext2fs_bg_used_dirs_count(fs, i);
672 pctx.ino2 = dir_array[i];
674 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
676 ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]);
677 ext2fs_mark_super_dirty(fs);
679 ext2fs_unmark_valid(fs);
682 if (free_inodes != fs->super->s_free_inodes_count) {
684 pctx.ino = fs->super->s_free_inodes_count;
685 pctx.ino2 = free_inodes;
687 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
688 fs->super->s_free_inodes_count = free_inodes;
689 ext2fs_mark_super_dirty(fs);
691 ext2fs_unmark_valid(fs);
694 ext2fs_free_mem(&free_array);
695 ext2fs_free_mem(&dir_array);
698 static void check_inode_end(e2fsck_t ctx)
700 ext2_filsys fs = ctx->fs;
701 ext2_ino_t end, save_inodes_count, i;
702 struct problem_context pctx;
704 clear_problem_context(&pctx);
706 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
707 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
711 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
712 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
715 if (save_inodes_count == end)
718 /* protect loop from wrap-around if end is maxed */
719 for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
720 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
721 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
722 for (; i <= end; i++)
723 ext2fs_mark_inode_bitmap(fs->inode_map,
725 ext2fs_mark_ib_dirty(fs);
727 ext2fs_unmark_valid(fs);
732 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
733 save_inodes_count, 0);
736 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
737 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
742 static void check_block_end(e2fsck_t ctx)
744 ext2_filsys fs = ctx->fs;
745 blk64_t end, save_blocks_count, i;
746 struct problem_context pctx;
748 clear_problem_context(&pctx);
750 end = ext2fs_get_block_bitmap_start2(fs->block_map) +
751 ((blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
752 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
756 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
757 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
760 if (save_blocks_count == end)
763 /* Protect loop from wrap-around if end is maxed */
764 for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
765 if (!ext2fs_test_block_bitmap2(fs->block_map,
766 EXT2FS_C2B(fs, i))) {
767 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
768 for (; i <= end; i++)
769 ext2fs_mark_block_bitmap2(fs->block_map,
771 ext2fs_mark_bb_dirty(fs);
773 ext2fs_unmark_valid(fs);
778 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
779 save_blocks_count, 0);
782 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
783 ctx->flags |= E2F_FLAG_ABORT; /* fatal */