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);
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);
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;
121 struct problem_context pctx;
122 int problem, save_problem, fixit, had_problem;
125 clear_problem_context(&pctx);
126 free_array = (int *) e2fsck_allocate_memory(ctx,
127 fs->group_desc_count * sizeof(int), "free block count array");
129 if ((fs->super->s_first_data_block <
130 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
131 (fs->super->s_blocks_count-1 >
132 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
134 pctx.blk = fs->super->s_first_data_block;
135 pctx.blk2 = fs->super->s_blocks_count -1;
136 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
137 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
138 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
140 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
144 if ((fs->super->s_first_data_block <
145 ext2fs_get_block_bitmap_start(fs->block_map)) ||
146 (fs->super->s_blocks_count-1 >
147 ext2fs_get_block_bitmap_end(fs->block_map))) {
149 pctx.blk = fs->super->s_first_data_block;
150 pctx.blk2 = fs->super->s_blocks_count -1;
151 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
152 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
153 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
155 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
162 pctx.blk = pctx.blk2 = NO_BLK;
163 for (i = fs->super->s_first_data_block;
164 i < fs->super->s_blocks_count;
166 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
167 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
169 if (actual == bitmap)
172 if (!actual && bitmap) {
174 * Block not used, but marked in use in the bitmap.
176 problem = PR_5_BLOCK_UNUSED;
179 * Block used, but not marked in use in the bitmap.
181 problem = PR_5_BLOCK_USED;
183 if (pctx.blk == NO_BLK) {
184 pctx.blk = pctx.blk2 = i;
185 save_problem = problem;
187 if ((problem == save_problem) &&
191 print_bitmap_problem(ctx, save_problem, &pctx);
192 pctx.blk = pctx.blk2 = i;
193 save_problem = problem;
196 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
205 if ((blocks == fs->super->s_blocks_per_group) ||
206 (i == fs->super->s_blocks_count-1)) {
207 free_array[group] = group_free;
212 if ((ctx->progress)(ctx, 5, group,
213 fs->group_desc_count*2))
217 if (pctx.blk != NO_BLK)
218 print_bitmap_problem(ctx, save_problem, &pctx);
220 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
223 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
226 ext2fs_free_block_bitmap(fs->block_map);
227 retval = ext2fs_copy_bitmap(ctx->block_found_map,
230 clear_problem_context(&pctx);
231 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
232 ctx->flags |= E2F_FLAG_ABORT;
235 ext2fs_set_bitmap_padding(fs->block_map);
236 ext2fs_mark_bb_dirty(fs);
238 /* Redo the counts */
239 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
240 memset(free_array, 0, fs->group_desc_count * sizeof(int));
242 } else if (fixit == 0)
243 ext2fs_unmark_valid(fs);
245 for (i = 0; i < fs->group_desc_count; i++) {
246 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
248 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
249 pctx.blk2 = free_array[i];
251 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
253 fs->group_desc[i].bg_free_blocks_count =
255 ext2fs_mark_super_dirty(fs);
257 ext2fs_unmark_valid(fs);
260 if (free_blocks != fs->super->s_free_blocks_count) {
262 pctx.blk = fs->super->s_free_blocks_count;
263 pctx.blk2 = free_blocks;
265 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
266 fs->super->s_free_blocks_count = free_blocks;
267 ext2fs_mark_super_dirty(fs);
269 ext2fs_unmark_valid(fs);
271 ext2fs_free_mem((void **) &free_array);
274 static void check_inode_bitmaps(e2fsck_t ctx)
276 ext2_filsys fs = ctx->fs;
287 struct problem_context pctx;
288 int problem, save_problem, fixit, had_problem;
290 clear_problem_context(&pctx);
291 free_array = (int *) e2fsck_allocate_memory(ctx,
292 fs->group_desc_count * sizeof(int), "free inode count array");
294 dir_array = (int *) e2fsck_allocate_memory(ctx,
295 fs->group_desc_count * sizeof(int), "directory count array");
297 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
298 (fs->super->s_inodes_count >
299 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
302 pctx.blk2 = fs->super->s_inodes_count;
303 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
304 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
305 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
307 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
310 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
311 (fs->super->s_inodes_count >
312 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
315 pctx.blk2 = fs->super->s_inodes_count;
316 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
317 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
318 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
320 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
327 pctx.ino = pctx.ino2 = 0;
328 for (i = 1; i <= fs->super->s_inodes_count; i++) {
329 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
330 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
332 if (actual == bitmap)
335 if (!actual && bitmap) {
337 * Inode wasn't used, but marked in bitmap
339 problem = PR_5_INODE_UNUSED;
340 } else /* if (actual && !bitmap) */ {
342 * Inode used, but not in bitmap
344 problem = PR_5_INODE_USED;
347 pctx.ino = pctx.ino2 = i;
348 save_problem = problem;
350 if ((problem == save_problem) &&
354 print_bitmap_problem(ctx, save_problem, &pctx);
355 pctx.ino = pctx.ino2 = i;
356 save_problem = problem;
359 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
367 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
371 if ((inodes == fs->super->s_inodes_per_group) ||
372 (i == fs->super->s_inodes_count)) {
373 free_array[group] = group_free;
374 dir_array[group] = dirs_count;
380 if ((ctx->progress)(ctx, 5,
381 group + fs->group_desc_count,
382 fs->group_desc_count*2))
387 print_bitmap_problem(ctx, save_problem, &pctx);
390 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
393 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
396 ext2fs_free_inode_bitmap(fs->inode_map);
397 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
400 clear_problem_context(&pctx);
401 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
402 ctx->flags |= E2F_FLAG_ABORT;
405 ext2fs_set_bitmap_padding(fs->inode_map);
406 ext2fs_mark_ib_dirty(fs);
409 inodes = 0; free_inodes = 0; group_free = 0;
410 dirs_count = 0; group = 0;
411 memset(free_array, 0, fs->group_desc_count * sizeof(int));
412 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
414 } else if (fixit == 0)
415 ext2fs_unmark_valid(fs);
417 for (i = 0; i < fs->group_desc_count; i++) {
418 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
420 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
421 pctx.ino2 = free_array[i];
422 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
424 fs->group_desc[i].bg_free_inodes_count =
426 ext2fs_mark_super_dirty(fs);
428 ext2fs_unmark_valid(fs);
430 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
432 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
433 pctx.ino2 = dir_array[i];
435 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
437 fs->group_desc[i].bg_used_dirs_count =
439 ext2fs_mark_super_dirty(fs);
441 ext2fs_unmark_valid(fs);
444 if (free_inodes != fs->super->s_free_inodes_count) {
446 pctx.ino = fs->super->s_free_inodes_count;
447 pctx.ino2 = free_inodes;
449 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
450 fs->super->s_free_inodes_count = free_inodes;
451 ext2fs_mark_super_dirty(fs);
453 ext2fs_unmark_valid(fs);
455 ext2fs_free_mem((void **) &free_array);
456 ext2fs_free_mem((void **) &dir_array);
459 static void check_inode_end(e2fsck_t ctx)
461 ext2_filsys fs = ctx->fs;
462 ext2_ino_t end, save_inodes_count, i;
463 struct problem_context pctx;
465 clear_problem_context(&pctx);
467 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
468 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
472 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
473 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
476 if (save_inodes_count == end)
479 for (i = save_inodes_count + 1; i <= end; i++) {
480 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
481 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
482 for (i = save_inodes_count + 1; i <= end; i++)
483 ext2fs_mark_inode_bitmap(fs->inode_map,
485 ext2fs_mark_ib_dirty(fs);
487 ext2fs_unmark_valid(fs);
492 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
493 save_inodes_count, 0);
496 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
497 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
502 static void check_block_end(e2fsck_t ctx)
504 ext2_filsys fs = ctx->fs;
505 blk_t end, save_blocks_count, i;
506 struct problem_context pctx;
508 clear_problem_context(&pctx);
510 end = fs->block_map->start +
511 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
512 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
516 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
517 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
520 if (save_blocks_count == end)
523 for (i = save_blocks_count + 1; i <= end; i++) {
524 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
525 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
526 for (i = save_blocks_count + 1; i <= end; i++)
527 ext2fs_mark_block_bitmap(fs->block_map,
529 ext2fs_mark_bb_dirty(fs);
531 ext2fs_unmark_valid(fs);
536 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
537 save_blocks_count, 0);
540 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
541 ctx->flags |= E2F_FLAG_ABORT; /* fatal */