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
15 #include <sys/types.h>
17 #include <sys/ioctl.h>
24 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
26 static void check_block_bitmaps(e2fsck_t ctx);
27 static void check_inode_bitmaps(e2fsck_t ctx);
28 static void check_inode_end(e2fsck_t ctx);
29 static void check_block_end(e2fsck_t ctx);
30 static void check_inode_bitmap_checksum(e2fsck_t ctx);
31 static void check_block_bitmap_checksum(e2fsck_t ctx);
33 void e2fsck_pass5(e2fsck_t ctx)
36 struct resource_track rtrack;
38 struct problem_context pctx;
41 mtrace_print("Pass 5");
44 init_resource_track(&rtrack, ctx->fs->io);
45 clear_problem_context(&pctx);
47 if (!(ctx->options & E2F_OPT_PREEN))
48 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
51 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
54 e2fsck_read_bitmaps(ctx);
56 check_block_bitmaps(ctx);
57 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
59 check_inode_bitmaps(ctx);
60 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
63 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
66 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
69 check_inode_bitmap_checksum(ctx);
70 check_block_bitmap_checksum(ctx);
72 ext2fs_free_inode_bitmap(ctx->inode_used_map);
73 ctx->inode_used_map = 0;
74 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
75 ctx->inode_dir_map = 0;
76 ext2fs_free_block_bitmap(ctx->block_found_map);
77 ctx->block_found_map = 0;
79 print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
82 static void check_inode_bitmap_checksum(e2fsck_t ctx)
84 struct problem_context pctx;
85 struct ext4_group_desc *gdp;
92 if (!EXT2_HAS_RO_COMPAT_FEATURE(ctx->fs->super,
93 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
96 /* If bitmap is dirty from being fixed, checksum will be corrected */
97 if (ext2fs_test_ib_dirty(ctx->fs))
100 nbytes = (size_t)(EXT2_INODES_PER_GROUP(ctx->fs->super) / 8);
101 retval = ext2fs_get_memalign(ctx->fs->blocksize, ctx->fs->blocksize,
104 com_err(ctx->program_name, 0,
105 _("check_inode_bitmap_checksum: Memory allocation error"));
109 clear_problem_context(&pctx);
110 for (i = 0; i < ctx->fs->group_desc_count; i++) {
111 if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_INODE_UNINIT))
114 ino_itr = 1 + (i * (nbytes << 3));
115 gdp = (struct ext4_group_desc *)ext2fs_group_desc(ctx->fs,
116 ctx->fs->group_desc, i);
117 retval = ext2fs_get_inode_bitmap_range2(ctx->fs->inode_map,
118 ino_itr, nbytes << 3,
123 if (ext2fs_inode_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
126 if (!fix_problem(ctx, PR_5_INODE_BITMAP_CSUM_INVALID, &pctx))
130 * Fixing one checksum will rewrite all of them. The bitmap
131 * will be checked against the one we made during pass1 for
132 * discrepancies, and fixed if need be.
134 ext2fs_mark_ib_dirty(ctx->fs);
138 ext2fs_free_mem(&buf);
141 static void check_block_bitmap_checksum(e2fsck_t ctx)
143 struct problem_context pctx;
144 struct ext4_group_desc *gdp;
151 if (!EXT2_HAS_RO_COMPAT_FEATURE(ctx->fs->super,
152 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
155 /* If bitmap is dirty from being fixed, checksum will be corrected */
156 if (ext2fs_test_bb_dirty(ctx->fs))
159 nbytes = (size_t)(EXT2_CLUSTERS_PER_GROUP(ctx->fs->super) / 8);
160 retval = ext2fs_get_memalign(ctx->fs->blocksize, ctx->fs->blocksize,
163 com_err(ctx->program_name, 0,
164 _("check_block_bitmap_checksum: Memory allocation error"));
168 clear_problem_context(&pctx);
169 for (i = 0; i < ctx->fs->group_desc_count; i++) {
170 if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_BLOCK_UNINIT))
173 blk_itr = EXT2FS_B2C(ctx->fs,
174 ctx->fs->super->s_first_data_block) +
176 gdp = (struct ext4_group_desc *)ext2fs_group_desc(ctx->fs,
177 ctx->fs->group_desc, i);
178 retval = ext2fs_get_block_bitmap_range2(ctx->fs->block_map,
179 blk_itr, nbytes << 3,
184 if (ext2fs_block_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
187 if (!fix_problem(ctx, PR_5_BLOCK_BITMAP_CSUM_INVALID, &pctx))
191 * Fixing one checksum will rewrite all of them. The bitmap
192 * will be checked against the one we made during pass1 for
193 * discrepancies, and fixed if need be.
195 ext2fs_mark_bb_dirty(ctx->fs);
199 ext2fs_free_mem(&buf);
202 static void e2fsck_discard_blocks(e2fsck_t ctx, blk64_t start,
205 ext2_filsys fs = ctx->fs;
208 * If the filesystem has changed it means that there was an corruption
209 * which should be repaired, but in some cases just one e2fsck run is
210 * not enough to fix the problem, hence it is not safe to run discard
213 if (ext2fs_test_changed(fs))
214 ctx->options &= ~E2F_OPT_DISCARD;
216 if ((ctx->options & E2F_OPT_DISCARD) &&
217 (io_channel_discard(fs->io, start, count)))
218 ctx->options &= ~E2F_OPT_DISCARD;
222 * This will try to discard number 'count' inodes starting at
223 * inode number 'start' within the 'group'. Note that 'start'
224 * is 1-based, it means that we need to adjust it by -1 in this
225 * function to compute right offset in the particular inode table.
227 static void e2fsck_discard_inodes(e2fsck_t ctx, dgrp_t group,
228 ext2_ino_t start, int count)
230 ext2_filsys fs = ctx->fs;
234 * Sanity check for 'start'
236 if ((start < 1) || (start > EXT2_INODES_PER_GROUP(fs->super))) {
237 printf("PROGRAMMING ERROR: Got start %d outside of group %d!"
238 " Disabling discard\n",
240 ctx->options &= ~E2F_OPT_DISCARD;
244 * Do not attempt to discard if E2F_OPT_DISCARD is not set. And also
245 * skip the discard on this group if discard does not zero data.
246 * The reason is that if the inode table is not zeroed discard would
247 * no help us since we need to zero it anyway, or if the inode table
248 * is zeroed then the read after discard would not be deterministic
249 * anyway and we would not be able to assume that this inode table
250 * was zeroed anymore so we would have to zero it again, which does
251 * not really make sense.
253 if (!(ctx->options & E2F_OPT_DISCARD) ||
254 !io_channel_discard_zeroes_data(fs->io))
258 * Start is inode number within the group which starts
259 * counting from 1, so we need to adjust it.
264 * We can discard only blocks containing only unused
265 * inodes in the table.
267 blk = DIV_ROUND_UP(start,
268 EXT2_INODES_PER_BLOCK(fs->super));
269 count -= (blk * EXT2_INODES_PER_BLOCK(fs->super) - start);
270 blk += ext2fs_inode_table_loc(fs, group);
271 num = count / EXT2_INODES_PER_BLOCK(fs->super);
274 e2fsck_discard_blocks(ctx, blk, num);
277 #define NO_BLK ((blk64_t) -1)
279 static void print_bitmap_problem(e2fsck_t ctx, int problem,
280 struct problem_context *pctx)
283 case PR_5_BLOCK_UNUSED:
284 if (pctx->blk == pctx->blk2)
287 problem = PR_5_BLOCK_RANGE_UNUSED;
289 case PR_5_BLOCK_USED:
290 if (pctx->blk == pctx->blk2)
293 problem = PR_5_BLOCK_RANGE_USED;
295 case PR_5_INODE_UNUSED:
296 if (pctx->ino == pctx->ino2)
299 problem = PR_5_INODE_RANGE_UNUSED;
301 case PR_5_INODE_USED:
302 if (pctx->ino == pctx->ino2)
305 problem = PR_5_INODE_RANGE_USED;
308 fix_problem(ctx, problem, pctx);
309 pctx->blk = pctx->blk2 = NO_BLK;
310 pctx->ino = pctx->ino2 = 0;
313 /* Just to be more succint */
314 #define B2C(x) EXT2FS_B2C(fs, (x))
315 #define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
316 #define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
317 #define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
319 static void check_block_bitmaps(e2fsck_t ctx)
321 ext2_filsys fs = ctx->fs;
323 unsigned int *free_array;
325 unsigned int blocks = 0;
326 blk64_t free_blocks = 0;
327 blk64_t first_free = ext2fs_blocks_count(fs->super);
328 unsigned int group_free = 0;
330 struct problem_context pctx;
331 int problem, save_problem, fixit, had_problem;
335 int old_desc_blocks = 0;
339 blk64_t super_blk, old_desc_blk, new_desc_blk;
341 clear_problem_context(&pctx);
342 free_array = (unsigned int *) e2fsck_allocate_memory(ctx,
343 fs->group_desc_count * sizeof(unsigned int), "free block count array");
345 if ((B2C(fs->super->s_first_data_block) <
346 ext2fs_get_block_bitmap_start2(ctx->block_found_map)) ||
347 (B2C(ext2fs_blocks_count(fs->super)-1) >
348 ext2fs_get_block_bitmap_end2(ctx->block_found_map))) {
350 pctx.blk = B2C(fs->super->s_first_data_block);
351 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
352 pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map);
353 pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map);
354 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
356 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
360 if ((B2C(fs->super->s_first_data_block) <
361 ext2fs_get_block_bitmap_start2(fs->block_map)) ||
362 (B2C(ext2fs_blocks_count(fs->super)-1) >
363 ext2fs_get_block_bitmap_end2(fs->block_map))) {
365 pctx.blk = B2C(fs->super->s_first_data_block);
366 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
367 pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map);
368 pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map);
369 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
371 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
375 csum_flag = ext2fs_has_group_desc_csum(fs);
379 pctx.blk = pctx.blk2 = NO_BLK;
381 (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
383 for (i = B2C(fs->super->s_first_data_block);
384 i < ext2fs_blocks_count(fs->super);
385 i += EXT2FS_CLUSTER_RATIO(fs)) {
386 actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i);
389 if ((B2C(i) - B2C(fs->super->s_first_data_block)) %
390 fs->super->s_clusters_per_group == 0) {
394 ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
395 &old_desc_blk, &new_desc_blk, 0);
397 if (fs->super->s_feature_incompat &
398 EXT2_FEATURE_INCOMPAT_META_BG)
400 fs->super->s_first_meta_bg;
402 old_desc_blocks = fs->desc_blocks +
403 fs->super->s_reserved_gdt_blocks;
406 cmp_block = fs->super->s_clusters_per_group;
407 if (group == (int)fs->group_desc_count - 1)
408 cmp_block = EXT2FS_NUM_B2C(fs,
409 ext2fs_group_blocks_count(fs, group));
413 if (EQ_CLSTR(i, super_blk) ||
414 (old_desc_blk && old_desc_blocks &&
415 GE_CLSTR(i, old_desc_blk) &&
416 LE_CLSTR(i, old_desc_blk + old_desc_blocks-1)) ||
417 (new_desc_blk && EQ_CLSTR(i, new_desc_blk)) ||
418 EQ_CLSTR(i, ext2fs_block_bitmap_loc(fs, group)) ||
419 EQ_CLSTR(i, ext2fs_inode_bitmap_loc(fs, group)) ||
420 (GE_CLSTR(i, ext2fs_inode_table_loc(fs, group)) &&
421 LE_CLSTR(i, (ext2fs_inode_table_loc(fs, group) +
422 fs->inode_blocks_per_group - 1)))) {
424 actual = (actual != 0);
427 } else if ((EXT2FS_B2C(fs, i) - count -
428 EXT2FS_B2C(fs, fs->super->s_first_data_block)) %
429 fs->super->s_clusters_per_group == 0) {
431 * When the compare data blocks in block bitmap
432 * are 0, count the free block,
433 * skip the current block group.
435 if (ext2fs_test_block_bitmap_range2(
436 ctx->block_found_map,
440 * -1 means to skip the current block
443 blocks = fs->super->s_clusters_per_group - 1;
444 group_free = cmp_block;
445 free_blocks += cmp_block;
447 * The current block group's last block
450 i += EXT2FS_C2B(fs, cmp_block - 1);
455 } else if (redo_flag)
458 bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
460 if (!actual == !bitmap)
463 if (!actual && bitmap) {
465 * Block not used, but marked in use in the bitmap.
467 problem = PR_5_BLOCK_UNUSED;
470 * Block used, but not marked in use in the bitmap.
472 problem = PR_5_BLOCK_USED;
475 struct problem_context pctx2;
478 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
479 ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
484 if (pctx.blk == NO_BLK) {
485 pctx.blk = pctx.blk2 = i;
486 save_problem = problem;
488 if ((problem == save_problem) &&
492 print_bitmap_problem(ctx, save_problem, &pctx);
493 pctx.blk = pctx.blk2 = i;
494 save_problem = problem;
497 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
501 * If there a problem we should turn off the discard so we
502 * do not compromise the filesystem.
504 ctx->options &= ~E2F_OPT_DISCARD;
512 } else if (i > first_free) {
513 e2fsck_discard_blocks(ctx, first_free,
515 first_free = ext2fs_blocks_count(fs->super);
518 if ((blocks == fs->super->s_clusters_per_group) ||
519 (EXT2FS_B2C(fs, i) ==
520 EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) {
522 * If the last block of this group is free, then we can
523 * discard it as well.
525 if (!bitmap && i >= first_free)
526 e2fsck_discard_blocks(ctx, first_free,
527 (i - first_free) + 1);
528 first_free = ext2fs_blocks_count(fs->super);
530 free_array[group] = group_free;
536 if ((ctx->progress)(ctx, 5, group,
537 fs->group_desc_count*2))
540 (i != ext2fs_blocks_count(fs->super)-1) &&
541 ext2fs_bg_flags_test(fs, group,
542 EXT2_BG_BLOCK_UNINIT))
546 if (pctx.blk != NO_BLK)
547 print_bitmap_problem(ctx, save_problem, &pctx);
549 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
552 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
555 ext2fs_free_block_bitmap(fs->block_map);
556 retval = ext2fs_copy_bitmap(ctx->block_found_map,
559 clear_problem_context(&pctx);
560 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
561 ctx->flags |= E2F_FLAG_ABORT;
564 ext2fs_set_bitmap_padding(fs->block_map);
565 ext2fs_mark_bb_dirty(fs);
567 /* Redo the counts */
568 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
569 memset(free_array, 0, fs->group_desc_count * sizeof(int));
572 } else if (fixit == 0)
573 ext2fs_unmark_valid(fs);
575 for (i = 0; i < fs->group_desc_count; i++) {
576 if (free_array[i] != ext2fs_bg_free_blocks_count(fs, i)) {
578 pctx.blk = ext2fs_bg_free_blocks_count(fs, i);
579 pctx.blk2 = free_array[i];
581 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
583 ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]);
584 ext2fs_mark_super_dirty(fs);
586 ext2fs_unmark_valid(fs);
589 free_blocks = EXT2FS_C2B(fs, free_blocks);
590 if (free_blocks != ext2fs_free_blocks_count(fs->super)) {
592 pctx.blk = ext2fs_free_blocks_count(fs->super);
593 pctx.blk2 = free_blocks;
595 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
596 ext2fs_free_blocks_count_set(fs->super, free_blocks);
597 ext2fs_mark_super_dirty(fs);
601 ext2fs_free_mem(&free_array);
604 static void check_inode_bitmaps(e2fsck_t ctx)
606 ext2_filsys fs = ctx->fs;
608 unsigned int free_inodes = 0;
612 unsigned int inodes = 0;
613 ext2_ino_t *free_array;
614 ext2_ino_t *dir_array;
617 struct problem_context pctx;
618 int problem, save_problem, fixit, had_problem;
622 ext2_ino_t first_free = fs->super->s_inodes_per_group + 1;
624 clear_problem_context(&pctx);
625 free_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
626 fs->group_desc_count * sizeof(ext2_ino_t), "free inode count array");
628 dir_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
629 fs->group_desc_count * sizeof(ext2_ino_t), "directory count array");
631 if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
632 (fs->super->s_inodes_count >
633 ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
636 pctx.blk2 = fs->super->s_inodes_count;
637 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
638 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
639 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
641 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
644 if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
645 (fs->super->s_inodes_count >
646 ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
649 pctx.blk2 = fs->super->s_inodes_count;
650 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
651 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
652 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
654 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
658 csum_flag = ext2fs_has_group_desc_csum(fs);
662 pctx.ino = pctx.ino2 = 0;
664 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
667 /* Protect loop from wrap-around if inodes_count is maxed */
668 for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
671 i % fs->super->s_inodes_per_group == 1) {
673 * Current inode is the first inode
674 * in the current block group.
676 if (ext2fs_test_inode_bitmap_range(
677 ctx->inode_used_map, i,
678 fs->super->s_inodes_per_group)) {
680 * When the compared inodes in inodes bitmap
681 * are 0, count the free inode,
682 * skip the current block group.
685 inodes = fs->super->s_inodes_per_group - 1;
687 free_inodes += inodes;
694 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
697 else if (!skip_group)
698 bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
699 if (!actual == !bitmap)
702 if (!actual && bitmap) {
704 * Inode wasn't used, but marked in bitmap
706 problem = PR_5_INODE_UNUSED;
707 } else /* if (actual && !bitmap) */ {
709 * Inode used, but not in bitmap
711 problem = PR_5_INODE_USED;
713 /* We should never hit this, because it means that
714 * inodes were marked in use that weren't noticed
715 * in pass1 or pass 2. It is easier to fix the problem
716 * than to kill e2fsck and leave the user stuck. */
718 struct problem_context pctx2;
721 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
722 ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
728 pctx.ino = pctx.ino2 = i;
729 save_problem = problem;
731 if ((problem == save_problem) &&
735 print_bitmap_problem(ctx, save_problem, &pctx);
736 pctx.ino = pctx.ino2 = i;
737 save_problem = problem;
740 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
743 * If there a problem we should turn off the discard so we
744 * do not compromise the filesystem.
746 ctx->options &= ~E2F_OPT_DISCARD;
751 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
753 if (inodes > first_free) {
754 e2fsck_discard_inodes(ctx, group, first_free,
755 inodes - first_free);
756 first_free = fs->super->s_inodes_per_group + 1;
761 if (first_free > inodes)
765 if ((inodes == fs->super->s_inodes_per_group) ||
766 (i == fs->super->s_inodes_count)) {
768 * If the last inode is free, we can discard it as well.
770 if (!bitmap && inodes >= first_free)
771 e2fsck_discard_inodes(ctx, group, first_free,
772 inodes - first_free + 1);
774 * If discard zeroes data and the group inode table
775 * was not zeroed yet, set itable as zeroed
777 if ((ctx->options & E2F_OPT_DISCARD) &&
778 io_channel_discard_zeroes_data(fs->io) &&
779 !(ext2fs_bg_flags_test(fs, group,
780 EXT2_BG_INODE_ZEROED))) {
781 ext2fs_bg_flags_set(fs, group,
782 EXT2_BG_INODE_ZEROED);
783 ext2fs_group_desc_csum_set(fs, group);
786 first_free = fs->super->s_inodes_per_group + 1;
787 free_array[group] = group_free;
788 dir_array[group] = dirs_count;
795 if ((ctx->progress)(ctx, 5,
796 group + fs->group_desc_count,
797 fs->group_desc_count*2))
800 (i != fs->super->s_inodes_count) &&
801 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)
807 print_bitmap_problem(ctx, save_problem, &pctx);
810 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
813 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
816 ext2fs_free_inode_bitmap(fs->inode_map);
817 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
820 clear_problem_context(&pctx);
821 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
822 ctx->flags |= E2F_FLAG_ABORT;
825 ext2fs_set_bitmap_padding(fs->inode_map);
826 ext2fs_mark_ib_dirty(fs);
829 inodes = 0; free_inodes = 0; group_free = 0;
830 dirs_count = 0; group = 0;
831 memset(free_array, 0, fs->group_desc_count * sizeof(int));
832 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
835 } else if (fixit == 0)
836 ext2fs_unmark_valid(fs);
838 for (i = 0; i < fs->group_desc_count; i++) {
839 if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) {
841 pctx.ino = ext2fs_bg_free_inodes_count(fs, i);
842 pctx.ino2 = free_array[i];
843 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
845 ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]);
846 ext2fs_mark_super_dirty(fs);
848 ext2fs_unmark_valid(fs);
850 if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) {
852 pctx.ino = ext2fs_bg_used_dirs_count(fs, i);
853 pctx.ino2 = dir_array[i];
855 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
857 ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]);
858 ext2fs_mark_super_dirty(fs);
860 ext2fs_unmark_valid(fs);
863 if (free_inodes != fs->super->s_free_inodes_count) {
865 pctx.ino = fs->super->s_free_inodes_count;
866 pctx.ino2 = free_inodes;
868 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
869 fs->super->s_free_inodes_count = free_inodes;
870 ext2fs_mark_super_dirty(fs);
874 ext2fs_free_mem(&free_array);
875 ext2fs_free_mem(&dir_array);
878 static void check_inode_end(e2fsck_t ctx)
880 ext2_filsys fs = ctx->fs;
881 ext2_ino_t end, save_inodes_count, i;
882 struct problem_context pctx;
884 clear_problem_context(&pctx);
886 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
887 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
891 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
892 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
895 if (save_inodes_count == end)
898 /* protect loop from wrap-around if end is maxed */
899 for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
900 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
901 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
902 for (; i <= end; i++)
903 ext2fs_mark_inode_bitmap(fs->inode_map,
905 ext2fs_mark_ib_dirty(fs);
907 ext2fs_unmark_valid(fs);
912 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
913 save_inodes_count, 0);
916 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
917 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
922 static void check_block_end(e2fsck_t ctx)
924 ext2_filsys fs = ctx->fs;
925 blk64_t end, save_blocks_count, i;
926 struct problem_context pctx;
928 clear_problem_context(&pctx);
930 end = ext2fs_get_block_bitmap_start2(fs->block_map) +
931 ((blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
932 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
936 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
937 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
940 if (save_blocks_count == end)
943 /* Protect loop from wrap-around if end is maxed */
944 for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
945 if (!ext2fs_test_block_bitmap2(fs->block_map,
946 EXT2FS_C2B(fs, i))) {
947 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
948 for (; i <= end; i++)
949 ext2fs_mark_block_bitmap2(fs->block_map,
951 ext2fs_mark_bb_dirty(fs);
953 ext2fs_unmark_valid(fs);
958 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
959 save_blocks_count, 0);
962 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
963 ctx->flags |= E2F_FLAG_ABORT; /* fatal */