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 static void check_block_bitmaps(e2fsck_t ctx
);
25 static void check_inode_bitmaps(e2fsck_t ctx
);
26 static void check_inode_end(e2fsck_t ctx
);
27 static void check_block_end(e2fsck_t ctx
);
28 static void check_inode_bitmap_checksum(e2fsck_t ctx
);
29 static void check_block_bitmap_checksum(e2fsck_t ctx
);
31 void e2fsck_pass5(e2fsck_t ctx
)
34 struct resource_track rtrack
;
36 struct problem_context pctx
;
39 mtrace_print("Pass 5");
42 init_resource_track(&rtrack
, ctx
->fs
->io
);
43 clear_problem_context(&pctx
);
45 if (!(ctx
->options
& E2F_OPT_PREEN
))
46 fix_problem(ctx
, PR_5_PASS_HEADER
, &pctx
);
49 if ((ctx
->progress
)(ctx
, 5, 0, ctx
->fs
->group_desc_count
*2))
52 e2fsck_read_bitmaps(ctx
);
54 check_block_bitmaps(ctx
);
55 if (ctx
->flags
& E2F_FLAG_SIGNAL_MASK
)
57 check_inode_bitmaps(ctx
);
58 if (ctx
->flags
& E2F_FLAG_SIGNAL_MASK
)
61 if (ctx
->flags
& E2F_FLAG_SIGNAL_MASK
)
64 if (ctx
->flags
& E2F_FLAG_SIGNAL_MASK
)
67 check_inode_bitmap_checksum(ctx
);
68 check_block_bitmap_checksum(ctx
);
70 ext2fs_free_inode_bitmap(ctx
->inode_used_map
);
71 ctx
->inode_used_map
= 0;
72 ext2fs_free_inode_bitmap(ctx
->inode_dir_map
);
73 ctx
->inode_dir_map
= 0;
74 ext2fs_free_block_bitmap(ctx
->block_found_map
);
75 ctx
->block_found_map
= 0;
76 ext2fs_free_block_bitmap(ctx
->block_metadata_map
);
77 ctx
->block_metadata_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
;
91 if (!ext2fs_has_feature_metadata_csum(ctx
->fs
->super
))
94 /* If bitmap is dirty from being fixed, checksum will be corrected */
95 if (ext2fs_test_ib_dirty(ctx
->fs
))
98 nbytes
= (size_t)(EXT2_INODES_PER_GROUP(ctx
->fs
->super
) / 8);
99 retval
= ext2fs_get_mem(ctx
->fs
->blocksize
, &buf
);
101 com_err(ctx
->program_name
, 0, "%s",
102 _("check_inode_bitmap_checksum: Memory allocation error"));
106 clear_problem_context(&pctx
);
107 for (i
= 0; i
< ctx
->fs
->group_desc_count
; i
++) {
108 if (ext2fs_bg_flags_test(ctx
->fs
, i
, EXT2_BG_INODE_UNINIT
))
111 ino_itr
= 1 + (i
* (nbytes
<< 3));
112 retval
= ext2fs_get_inode_bitmap_range2(ctx
->fs
->inode_map
,
113 ino_itr
, nbytes
<< 3,
118 if (ext2fs_inode_bitmap_csum_verify(ctx
->fs
, i
, buf
, nbytes
))
121 if (!fix_problem(ctx
, PR_5_INODE_BITMAP_CSUM_INVALID
, &pctx
))
125 * Fixing one checksum will rewrite all of them. The bitmap
126 * will be checked against the one we made during pass1 for
127 * discrepancies, and fixed if need be.
129 ext2fs_mark_ib_dirty(ctx
->fs
);
133 ext2fs_free_mem(&buf
);
136 static void check_block_bitmap_checksum(e2fsck_t ctx
)
138 struct problem_context pctx
;
145 if (!ext2fs_has_feature_metadata_csum(ctx
->fs
->super
))
148 /* If bitmap is dirty from being fixed, checksum will be corrected */
149 if (ext2fs_test_bb_dirty(ctx
->fs
))
152 nbytes
= (size_t)(EXT2_CLUSTERS_PER_GROUP(ctx
->fs
->super
) / 8);
153 retval
= ext2fs_get_mem(ctx
->fs
->blocksize
, &buf
);
155 com_err(ctx
->program_name
, 0, "%s",
156 _("check_block_bitmap_checksum: Memory allocation error"));
160 clear_problem_context(&pctx
);
161 for (i
= 0; i
< ctx
->fs
->group_desc_count
; i
++) {
162 if (ext2fs_bg_flags_test(ctx
->fs
, i
, EXT2_BG_BLOCK_UNINIT
))
165 blk_itr
= EXT2FS_B2C(ctx
->fs
,
166 ctx
->fs
->super
->s_first_data_block
) +
167 ((blk64_t
) i
* (nbytes
<< 3));
168 retval
= ext2fs_get_block_bitmap_range2(ctx
->fs
->block_map
,
169 blk_itr
, nbytes
<< 3,
174 if (ext2fs_block_bitmap_csum_verify(ctx
->fs
, i
, buf
, nbytes
))
177 if (!fix_problem(ctx
, PR_5_BLOCK_BITMAP_CSUM_INVALID
, &pctx
))
181 * Fixing one checksum will rewrite all of them. The bitmap
182 * will be checked against the one we made during pass1 for
183 * discrepancies, and fixed if need be.
185 ext2fs_mark_bb_dirty(ctx
->fs
);
189 ext2fs_free_mem(&buf
);
192 static void e2fsck_discard_blocks(e2fsck_t ctx
, blk64_t start
,
195 ext2_filsys fs
= ctx
->fs
;
198 * If the filesystem has changed it means that there was an corruption
199 * which should be repaired, but in some cases just one e2fsck run is
200 * not enough to fix the problem, hence it is not safe to run discard
203 if (ext2fs_test_changed(fs
))
204 ctx
->options
&= ~E2F_OPT_DISCARD
;
206 if ((ctx
->options
& E2F_OPT_DISCARD
) &&
207 (io_channel_discard(fs
->io
, start
, count
)))
208 ctx
->options
&= ~E2F_OPT_DISCARD
;
212 * This will try to discard number 'count' inodes starting at
213 * inode number 'start' within the 'group'. Note that 'start'
214 * is 1-based, it means that we need to adjust it by -1 in this
215 * function to compute right offset in the particular inode table.
217 static void e2fsck_discard_inodes(e2fsck_t ctx
, dgrp_t group
,
218 ext2_ino_t start
, int count
)
220 ext2_filsys fs
= ctx
->fs
;
224 * Sanity check for 'start'
226 if ((start
< 1) || (start
> EXT2_INODES_PER_GROUP(fs
->super
))) {
227 printf("PROGRAMMING ERROR: Got start %d outside of group %d!"
228 " Disabling discard\n",
230 ctx
->options
&= ~E2F_OPT_DISCARD
;
234 * Do not attempt to discard if E2F_OPT_DISCARD is not set. And also
235 * skip the discard on this group if discard does not zero data.
236 * The reason is that if the inode table is not zeroed discard would
237 * no help us since we need to zero it anyway, or if the inode table
238 * is zeroed then the read after discard would not be deterministic
239 * anyway and we would not be able to assume that this inode table
240 * was zeroed anymore so we would have to zero it again, which does
241 * not really make sense.
243 if (!(ctx
->options
& E2F_OPT_DISCARD
) ||
244 !io_channel_discard_zeroes_data(fs
->io
))
248 * Start is inode number within the group which starts
249 * counting from 1, so we need to adjust it.
254 * We can discard only blocks containing only unused
255 * inodes in the table.
257 blk
= DIV_ROUND_UP(start
,
258 EXT2_INODES_PER_BLOCK(fs
->super
));
259 count
-= (blk
* EXT2_INODES_PER_BLOCK(fs
->super
) - start
);
260 blk
+= ext2fs_inode_table_loc(fs
, group
);
261 num
= count
/ EXT2_INODES_PER_BLOCK(fs
->super
);
264 e2fsck_discard_blocks(ctx
, blk
, num
);
267 #define NO_BLK ((blk64_t) -1)
269 static void print_bitmap_problem(e2fsck_t ctx
, problem_t problem
,
270 struct problem_context
*pctx
)
273 case PR_5_BLOCK_UNUSED
:
274 if (pctx
->blk
== pctx
->blk2
)
277 problem
= PR_5_BLOCK_RANGE_UNUSED
;
279 case PR_5_BLOCK_USED
:
280 if (pctx
->blk
== pctx
->blk2
)
283 problem
= PR_5_BLOCK_RANGE_USED
;
285 case PR_5_INODE_UNUSED
:
286 if (pctx
->ino
== pctx
->ino2
)
289 problem
= PR_5_INODE_RANGE_UNUSED
;
291 case PR_5_INODE_USED
:
292 if (pctx
->ino
== pctx
->ino2
)
295 problem
= PR_5_INODE_RANGE_USED
;
298 fix_problem(ctx
, problem
, pctx
);
299 pctx
->blk
= pctx
->blk2
= NO_BLK
;
300 pctx
->ino
= pctx
->ino2
= 0;
303 /* Just to be more succinct */
304 #define B2C(x) EXT2FS_B2C(fs, (x))
305 #define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
306 #define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
307 #define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
309 static void check_block_bitmaps(e2fsck_t ctx
)
311 ext2_filsys fs
= ctx
->fs
;
313 unsigned int *free_array
;
315 unsigned int blocks
= 0;
316 blk64_t free_blocks
= 0;
317 blk64_t first_free
= ext2fs_blocks_count(fs
->super
);
318 unsigned int group_free
= 0;
320 struct problem_context pctx
;
321 problem_t problem
, save_problem
;
322 int fixit
, had_problem
;
325 char *actual_buf
, *bitmap_buf
;
327 actual_buf
= (char *) e2fsck_allocate_memory(ctx
, fs
->blocksize
,
328 "actual bitmap buffer");
329 bitmap_buf
= (char *) e2fsck_allocate_memory(ctx
, fs
->blocksize
,
330 "bitmap block buffer");
332 clear_problem_context(&pctx
);
333 free_array
= (unsigned int *) e2fsck_allocate_memory(ctx
,
334 fs
->group_desc_count
* sizeof(unsigned int), "free block count array");
336 if ((B2C(fs
->super
->s_first_data_block
) <
337 ext2fs_get_block_bitmap_start2(ctx
->block_found_map
)) ||
338 (B2C(ext2fs_blocks_count(fs
->super
)-1) >
339 ext2fs_get_block_bitmap_end2(ctx
->block_found_map
))) {
341 pctx
.blk
= B2C(fs
->super
->s_first_data_block
);
342 pctx
.blk2
= B2C(ext2fs_blocks_count(fs
->super
) - 1);
343 pctx
.ino
= ext2fs_get_block_bitmap_start2(ctx
->block_found_map
);
344 pctx
.ino2
= ext2fs_get_block_bitmap_end2(ctx
->block_found_map
);
345 fix_problem(ctx
, PR_5_BMAP_ENDPOINTS
, &pctx
);
347 ctx
->flags
|= E2F_FLAG_ABORT
; /* fatal */
351 if ((B2C(fs
->super
->s_first_data_block
) <
352 ext2fs_get_block_bitmap_start2(fs
->block_map
)) ||
353 (B2C(ext2fs_blocks_count(fs
->super
)-1) >
354 ext2fs_get_block_bitmap_end2(fs
->block_map
))) {
356 pctx
.blk
= B2C(fs
->super
->s_first_data_block
);
357 pctx
.blk2
= B2C(ext2fs_blocks_count(fs
->super
) - 1);
358 pctx
.ino
= ext2fs_get_block_bitmap_start2(fs
->block_map
);
359 pctx
.ino2
= ext2fs_get_block_bitmap_end2(fs
->block_map
);
360 fix_problem(ctx
, PR_5_BMAP_ENDPOINTS
, &pctx
);
362 ctx
->flags
|= E2F_FLAG_ABORT
; /* fatal */
369 pctx
.blk
= pctx
.blk2
= NO_BLK
;
370 for (i
= B2C(fs
->super
->s_first_data_block
);
371 i
< ext2fs_blocks_count(fs
->super
);
372 i
+= EXT2FS_CLUSTER_RATIO(fs
)) {
373 int first_block_in_bg
= (B2C(i
) -
374 B2C(fs
->super
->s_first_data_block
)) %
375 fs
->super
->s_clusters_per_group
== 0;
376 int n
, nbytes
= fs
->super
->s_clusters_per_group
/ 8;
378 actual
= ext2fs_fast_test_block_bitmap2(ctx
->block_found_map
, i
);
381 * Try to optimize pass5 by extracting a bitmap block
382 * as expected from what we have on disk, and then
383 * comparing the two. If they are identical, then
384 * update the free block counts and go on to the next
385 * block group. This is much faster than doing the
386 * individual bit-by-bit comparison. The one downside
387 * is that this doesn't work if we are asking e2fsck
388 * to do a discard operation.
390 if (!first_block_in_bg
||
391 (group
== fs
->group_desc_count
- 1) ||
392 (ctx
->options
& E2F_OPT_DISCARD
))
395 retval
= ext2fs_get_block_bitmap_range2(ctx
->block_found_map
,
396 B2C(i
), fs
->super
->s_clusters_per_group
,
400 retval
= ext2fs_get_block_bitmap_range2(fs
->block_map
,
401 B2C(i
), fs
->super
->s_clusters_per_group
,
405 if (memcmp(actual_buf
, bitmap_buf
, nbytes
) != 0)
407 n
= ext2fs_bitcount(actual_buf
, nbytes
);
408 group_free
= fs
->super
->s_clusters_per_group
- n
;
409 free_blocks
+= group_free
;
410 i
+= EXT2FS_C2B(fs
, fs
->super
->s_clusters_per_group
- 1);
417 bitmap
= ext2fs_fast_test_block_bitmap2(fs
->block_map
, i
);
419 if (!actual
== !bitmap
)
422 if (!actual
&& bitmap
) {
424 * Block not used, but marked in use in the bitmap.
426 problem
= PR_5_BLOCK_UNUSED
;
429 * Block used, but not marked in use in the bitmap.
431 problem
= PR_5_BLOCK_USED
;
433 if (ext2fs_bg_flags_test(fs
, group
,
434 EXT2_BG_BLOCK_UNINIT
)) {
435 struct problem_context pctx2
;
438 if (fix_problem(ctx
, PR_5_BLOCK_UNINIT
,
440 ext2fs_bg_flags_clear(fs
, group
,
441 EXT2_BG_BLOCK_UNINIT
);
444 if (pctx
.blk
== NO_BLK
) {
445 pctx
.blk
= pctx
.blk2
= i
;
446 save_problem
= problem
;
448 if ((problem
== save_problem
) &&
449 (pctx
.blk2
== i
- EXT2FS_CLUSTER_RATIO(fs
)))
450 pctx
.blk2
+= EXT2FS_CLUSTER_RATIO(fs
);
452 print_bitmap_problem(ctx
, save_problem
, &pctx
);
453 pctx
.blk
= pctx
.blk2
= i
;
454 save_problem
= problem
;
457 ctx
->flags
|= E2F_FLAG_PROG_SUPPRESS
;
461 * If there a problem we should turn off the discard so we
462 * do not compromise the filesystem.
464 ctx
->options
&= ~E2F_OPT_DISCARD
;
472 } else if (i
> first_free
) {
473 e2fsck_discard_blocks(ctx
, first_free
,
475 first_free
= ext2fs_blocks_count(fs
->super
);
478 if ((blocks
== fs
->super
->s_clusters_per_group
) ||
479 (EXT2FS_B2C(fs
, i
) ==
480 EXT2FS_B2C(fs
, ext2fs_blocks_count(fs
->super
)-1))) {
482 * If the last block of this group is free, then we can
483 * discard it as well.
485 if (!bitmap
&& i
>= first_free
)
486 e2fsck_discard_blocks(ctx
, first_free
,
487 (i
- first_free
) + 1);
489 first_free
= ext2fs_blocks_count(fs
->super
);
491 free_array
[group
] = group_free
;
496 if ((ctx
->progress
)(ctx
, 5, group
,
497 fs
->group_desc_count
*2))
501 if (pctx
.blk
!= NO_BLK
)
502 print_bitmap_problem(ctx
, save_problem
, &pctx
);
504 fixit
= end_problem_latch(ctx
, PR_LATCH_BBITMAP
);
507 ctx
->flags
&= ~E2F_FLAG_PROG_SUPPRESS
;
510 ext2fs_free_block_bitmap(fs
->block_map
);
511 retval
= ext2fs_copy_bitmap(ctx
->block_found_map
,
514 clear_problem_context(&pctx
);
515 fix_problem(ctx
, PR_5_COPY_BBITMAP_ERROR
, &pctx
);
516 ctx
->flags
|= E2F_FLAG_ABORT
;
519 ext2fs_set_bitmap_padding(fs
->block_map
);
520 ext2fs_mark_bb_dirty(fs
);
522 /* Redo the counts */
523 blocks
= 0; free_blocks
= 0; group_free
= 0; group
= 0;
524 memset(free_array
, 0, fs
->group_desc_count
* sizeof(int));
527 } else if (fixit
== 0)
528 ext2fs_unmark_valid(fs
);
530 for (g
= 0; g
< fs
->group_desc_count
; g
++) {
531 if (free_array
[g
] != ext2fs_bg_free_blocks_count(fs
, g
)) {
533 pctx
.blk
= ext2fs_bg_free_blocks_count(fs
, g
);
534 pctx
.blk2
= free_array
[g
];
536 if (fix_problem(ctx
, PR_5_FREE_BLOCK_COUNT_GROUP
,
538 ext2fs_bg_free_blocks_count_set(fs
, g
, free_array
[g
]);
539 ext2fs_mark_super_dirty(fs
);
541 ext2fs_unmark_valid(fs
);
544 free_blocks
= EXT2FS_C2B(fs
, free_blocks
);
545 if (free_blocks
!= ext2fs_free_blocks_count(fs
->super
)) {
547 pctx
.blk
= ext2fs_free_blocks_count(fs
->super
);
548 pctx
.blk2
= free_blocks
;
550 if (fix_problem(ctx
, PR_5_FREE_BLOCK_COUNT
, &pctx
)) {
551 ext2fs_free_blocks_count_set(fs
->super
, free_blocks
);
552 ext2fs_mark_super_dirty(fs
);
556 ext2fs_free_mem(&free_array
);
557 ext2fs_free_mem(&actual_buf
);
558 ext2fs_free_mem(&bitmap_buf
);
561 static void check_inode_bitmaps(e2fsck_t ctx
)
563 ext2_filsys fs
= ctx
->fs
;
565 unsigned int free_inodes
= 0;
569 unsigned int inodes
= 0;
570 ext2_ino_t
*free_array
;
571 ext2_ino_t
*dir_array
;
574 struct problem_context pctx
;
575 problem_t problem
, save_problem
;
576 int fixit
, had_problem
;
580 ext2_ino_t first_free
= fs
->super
->s_inodes_per_group
+ 1;
582 clear_problem_context(&pctx
);
583 free_array
= (ext2_ino_t
*) e2fsck_allocate_memory(ctx
,
584 fs
->group_desc_count
* sizeof(ext2_ino_t
), "free inode count array");
586 dir_array
= (ext2_ino_t
*) e2fsck_allocate_memory(ctx
,
587 fs
->group_desc_count
* sizeof(ext2_ino_t
), "directory count array");
589 if ((1 < ext2fs_get_inode_bitmap_start2(ctx
->inode_used_map
)) ||
590 (fs
->super
->s_inodes_count
>
591 ext2fs_get_inode_bitmap_end2(ctx
->inode_used_map
))) {
594 pctx
.blk2
= fs
->super
->s_inodes_count
;
595 pctx
.ino
= ext2fs_get_inode_bitmap_start2(ctx
->inode_used_map
);
596 pctx
.ino2
= ext2fs_get_inode_bitmap_end2(ctx
->inode_used_map
);
597 fix_problem(ctx
, PR_5_BMAP_ENDPOINTS
, &pctx
);
599 ctx
->flags
|= E2F_FLAG_ABORT
; /* fatal */
602 if ((1 < ext2fs_get_inode_bitmap_start2(fs
->inode_map
)) ||
603 (fs
->super
->s_inodes_count
>
604 ext2fs_get_inode_bitmap_end2(fs
->inode_map
))) {
607 pctx
.blk2
= fs
->super
->s_inodes_count
;
608 pctx
.ino
= ext2fs_get_inode_bitmap_start2(fs
->inode_map
);
609 pctx
.ino2
= ext2fs_get_inode_bitmap_end2(fs
->inode_map
);
610 fix_problem(ctx
, PR_5_BMAP_ENDPOINTS
, &pctx
);
612 ctx
->flags
|= E2F_FLAG_ABORT
; /* fatal */
616 csum_flag
= ext2fs_has_group_desc_csum(fs
);
620 pctx
.ino
= pctx
.ino2
= 0;
622 (ext2fs_bg_flags_test(fs
, group
, EXT2_BG_INODE_UNINIT
)))
625 /* Protect loop from wrap-around if inodes_count is maxed */
626 for (i
= 1; i
<= fs
->super
->s_inodes_count
&& i
> 0; i
++) {
629 i
% fs
->super
->s_inodes_per_group
== 1) {
631 * Current inode is the first inode
632 * in the current block group.
634 if (ext2fs_test_inode_bitmap_range(
635 ctx
->inode_used_map
, i
,
636 fs
->super
->s_inodes_per_group
)) {
638 * When the compared inodes in inodes bitmap
639 * are 0, count the free inode,
640 * skip the current block group.
643 inodes
= fs
->super
->s_inodes_per_group
- 1;
645 free_inodes
+= inodes
;
652 actual
= ext2fs_fast_test_inode_bitmap2(ctx
->inode_used_map
, i
);
655 else if (!skip_group
)
656 bitmap
= ext2fs_fast_test_inode_bitmap2(fs
->inode_map
, i
);
657 if (!actual
== !bitmap
)
660 if (!actual
&& bitmap
) {
662 * Inode wasn't used, but marked in bitmap
664 problem
= PR_5_INODE_UNUSED
;
665 } else /* if (actual && !bitmap) */ {
667 * Inode used, but not in bitmap
669 problem
= PR_5_INODE_USED
;
671 /* We should never hit this, because it means that
672 * inodes were marked in use that weren't noticed
673 * in pass1 or pass 2. It is easier to fix the problem
674 * than to kill e2fsck and leave the user stuck. */
676 struct problem_context pctx2
;
679 if (fix_problem(ctx
, PR_5_INODE_UNINIT
,&pctx2
)){
680 ext2fs_bg_flags_clear(fs
, group
, EXT2_BG_INODE_UNINIT
);
686 pctx
.ino
= pctx
.ino2
= i
;
687 save_problem
= problem
;
689 if ((problem
== save_problem
) &&
693 print_bitmap_problem(ctx
, save_problem
, &pctx
);
694 pctx
.ino
= pctx
.ino2
= i
;
695 save_problem
= problem
;
698 ctx
->flags
|= E2F_FLAG_PROG_SUPPRESS
;
701 * If there a problem we should turn off the discard so we
702 * do not compromise the filesystem.
704 ctx
->options
&= ~E2F_OPT_DISCARD
;
709 if (ext2fs_test_inode_bitmap2(ctx
->inode_dir_map
, i
))
711 if (inodes
> first_free
) {
712 e2fsck_discard_inodes(ctx
, group
, first_free
,
713 inodes
- first_free
);
714 first_free
= fs
->super
->s_inodes_per_group
+ 1;
719 if (first_free
> inodes
)
723 if ((inodes
== fs
->super
->s_inodes_per_group
) ||
724 (i
== fs
->super
->s_inodes_count
)) {
726 * If the last inode is free, we can discard it as well.
728 if (!bitmap
&& inodes
>= first_free
)
729 e2fsck_discard_inodes(ctx
, group
, first_free
,
730 inodes
- first_free
+ 1);
732 * If discard zeroes data and the group inode table
733 * was not zeroed yet, set itable as zeroed
735 if ((ctx
->options
& E2F_OPT_DISCARD
) &&
736 io_channel_discard_zeroes_data(fs
->io
) &&
737 !(ext2fs_bg_flags_test(fs
, group
,
738 EXT2_BG_INODE_ZEROED
))) {
739 ext2fs_bg_flags_set(fs
, group
,
740 EXT2_BG_INODE_ZEROED
);
741 ext2fs_group_desc_csum_set(fs
, group
);
744 first_free
= fs
->super
->s_inodes_per_group
+ 1;
745 free_array
[group
] = group_free
;
746 dir_array
[group
] = dirs_count
;
753 if ((ctx
->progress
)(ctx
, 5,
754 group
+ fs
->group_desc_count
,
755 fs
->group_desc_count
*2))
758 (i
!= fs
->super
->s_inodes_count
) &&
759 (ext2fs_bg_flags_test(fs
, group
, EXT2_BG_INODE_UNINIT
)
765 print_bitmap_problem(ctx
, save_problem
, &pctx
);
768 fixit
= end_problem_latch(ctx
, PR_LATCH_IBITMAP
);
771 ctx
->flags
&= ~E2F_FLAG_PROG_SUPPRESS
;
774 ext2fs_free_inode_bitmap(fs
->inode_map
);
775 retval
= ext2fs_copy_bitmap(ctx
->inode_used_map
,
778 clear_problem_context(&pctx
);
779 fix_problem(ctx
, PR_5_COPY_IBITMAP_ERROR
, &pctx
);
780 ctx
->flags
|= E2F_FLAG_ABORT
;
783 ext2fs_set_bitmap_padding(fs
->inode_map
);
784 ext2fs_mark_ib_dirty(fs
);
787 inodes
= 0; free_inodes
= 0; group_free
= 0;
788 dirs_count
= 0; group
= 0;
789 memset(free_array
, 0, fs
->group_desc_count
* sizeof(int));
790 memset(dir_array
, 0, fs
->group_desc_count
* sizeof(int));
793 } else if (fixit
== 0)
794 ext2fs_unmark_valid(fs
);
796 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
797 if (free_array
[i
] != ext2fs_bg_free_inodes_count(fs
, i
)) {
799 pctx
.ino
= ext2fs_bg_free_inodes_count(fs
, i
);
800 pctx
.ino2
= free_array
[i
];
801 if (fix_problem(ctx
, PR_5_FREE_INODE_COUNT_GROUP
,
803 ext2fs_bg_free_inodes_count_set(fs
, i
, free_array
[i
]);
804 ext2fs_mark_super_dirty(fs
);
806 ext2fs_unmark_valid(fs
);
808 if (dir_array
[i
] != ext2fs_bg_used_dirs_count(fs
, i
)) {
810 pctx
.ino
= ext2fs_bg_used_dirs_count(fs
, i
);
811 pctx
.ino2
= dir_array
[i
];
813 if (fix_problem(ctx
, PR_5_FREE_DIR_COUNT_GROUP
,
815 ext2fs_bg_used_dirs_count_set(fs
, i
, dir_array
[i
]);
816 ext2fs_mark_super_dirty(fs
);
818 ext2fs_unmark_valid(fs
);
821 if (free_inodes
!= fs
->super
->s_free_inodes_count
) {
823 pctx
.ino
= fs
->super
->s_free_inodes_count
;
824 pctx
.ino2
= free_inodes
;
826 if (fix_problem(ctx
, PR_5_FREE_INODE_COUNT
, &pctx
)) {
827 fs
->super
->s_free_inodes_count
= free_inodes
;
828 ext2fs_mark_super_dirty(fs
);
832 ext2fs_free_mem(&free_array
);
833 ext2fs_free_mem(&dir_array
);
836 static void check_inode_end(e2fsck_t ctx
)
838 ext2_filsys fs
= ctx
->fs
;
839 ext2_ino_t end
, save_inodes_count
, i
;
840 struct problem_context pctx
;
842 clear_problem_context(&pctx
);
844 end
= EXT2_INODES_PER_GROUP(fs
->super
) * fs
->group_desc_count
;
845 pctx
.errcode
= ext2fs_fudge_inode_bitmap_end(fs
->inode_map
, end
,
849 fix_problem(ctx
, PR_5_FUDGE_BITMAP_ERROR
, &pctx
);
850 ctx
->flags
|= E2F_FLAG_ABORT
; /* fatal */
853 if (save_inodes_count
== end
)
856 /* protect loop from wrap-around if end is maxed */
857 for (i
= save_inodes_count
+ 1; i
<= end
&& i
> save_inodes_count
; i
++) {
858 if (!ext2fs_test_inode_bitmap(fs
->inode_map
, i
)) {
859 if (fix_problem(ctx
, PR_5_INODE_BMAP_PADDING
, &pctx
)) {
860 for (; i
<= end
; i
++)
861 ext2fs_mark_inode_bitmap(fs
->inode_map
,
863 ext2fs_mark_ib_dirty(fs
);
865 ext2fs_unmark_valid(fs
);
870 pctx
.errcode
= ext2fs_fudge_inode_bitmap_end(fs
->inode_map
,
871 save_inodes_count
, 0);
874 fix_problem(ctx
, PR_5_FUDGE_BITMAP_ERROR
, &pctx
);
875 ctx
->flags
|= E2F_FLAG_ABORT
; /* fatal */
880 static void check_block_end(e2fsck_t ctx
)
882 ext2_filsys fs
= ctx
->fs
;
883 blk64_t end
, save_blocks_count
, i
;
884 struct problem_context pctx
;
886 clear_problem_context(&pctx
);
888 end
= ext2fs_get_block_bitmap_start2(fs
->block_map
) +
889 EXT2_GROUPS_TO_CLUSTERS(fs
->super
, fs
->group_desc_count
) - 1;
890 pctx
.errcode
= ext2fs_fudge_block_bitmap_end2(fs
->block_map
, end
,
894 fix_problem(ctx
, PR_5_FUDGE_BITMAP_ERROR
, &pctx
);
895 ctx
->flags
|= E2F_FLAG_ABORT
; /* fatal */
898 if (save_blocks_count
== end
)
901 /* Protect loop from wrap-around if end is maxed */
902 for (i
= save_blocks_count
+ 1; i
<= end
&& i
> save_blocks_count
; i
++) {
903 if (!ext2fs_test_block_bitmap2(fs
->block_map
,
904 EXT2FS_C2B(fs
, i
))) {
905 if (fix_problem(ctx
, PR_5_BLOCK_BMAP_PADDING
, &pctx
)) {
906 for (; i
<= end
; i
++)
907 ext2fs_mark_block_bitmap2(fs
->block_map
,
909 ext2fs_mark_bb_dirty(fs
);
911 ext2fs_unmark_valid(fs
);
916 pctx
.errcode
= ext2fs_fudge_block_bitmap_end2(fs
->block_map
,
917 save_blocks_count
, 0);
920 fix_problem(ctx
, PR_5_FUDGE_BITMAP_ERROR
, &pctx
);
921 ctx
->flags
|= E2F_FLAG_ABORT
; /* fatal */