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 static void check_block_bitmaps(e2fsck_t ctx)
77 ext2_filsys fs = ctx->fs;
85 struct problem_context pctx;
86 int problem, fixit, had_problem;
89 clear_problem_context(&pctx);
90 free_array = (int *) e2fsck_allocate_memory(ctx,
91 fs->group_desc_count * sizeof(int), "free block count array");
93 if ((fs->super->s_first_data_block <
94 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
95 (fs->super->s_blocks_count-1 >
96 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
98 pctx.blk = fs->super->s_first_data_block;
99 pctx.blk2 = fs->super->s_blocks_count -1;
100 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
101 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
102 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
104 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
108 if ((fs->super->s_first_data_block <
109 ext2fs_get_block_bitmap_start(fs->block_map)) ||
110 (fs->super->s_blocks_count-1 >
111 ext2fs_get_block_bitmap_end(fs->block_map))) {
113 pctx.blk = fs->super->s_first_data_block;
114 pctx.blk2 = fs->super->s_blocks_count -1;
115 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
116 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
117 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
119 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
125 for (i = fs->super->s_first_data_block;
126 i < fs->super->s_blocks_count;
128 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
129 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
131 if (actual == bitmap)
134 if (!actual && bitmap) {
136 * Block not used, but marked in use in the bitmap.
138 problem = PR_5_UNUSED_BLOCK;
141 * Block used, but not marked in use in the bitmap.
143 problem = PR_5_BLOCK_USED;
146 fix_problem(ctx, problem, &pctx);
147 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
156 if ((blocks == fs->super->s_blocks_per_group) ||
157 (i == fs->super->s_blocks_count-1)) {
158 free_array[group] = group_free;
163 if ((ctx->progress)(ctx, 5, group,
164 fs->group_desc_count*2))
169 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
172 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
175 ext2fs_free_block_bitmap(fs->block_map);
176 retval = ext2fs_copy_bitmap(ctx->block_found_map,
179 clear_problem_context(&pctx);
180 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
181 ctx->flags |= E2F_FLAG_ABORT;
184 ext2fs_set_bitmap_padding(fs->block_map);
185 ext2fs_mark_bb_dirty(fs);
187 /* Redo the counts */
188 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
189 memset(free_array, 0, fs->group_desc_count * sizeof(int));
191 } else if (fixit == 0)
192 ext2fs_unmark_valid(fs);
194 for (i = 0; i < fs->group_desc_count; i++) {
195 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
197 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
198 pctx.blk2 = free_array[i];
200 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
202 fs->group_desc[i].bg_free_blocks_count =
204 ext2fs_mark_super_dirty(fs);
206 ext2fs_unmark_valid(fs);
209 if (free_blocks != fs->super->s_free_blocks_count) {
211 pctx.blk = fs->super->s_free_blocks_count;
212 pctx.blk2 = free_blocks;
214 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
215 fs->super->s_free_blocks_count = free_blocks;
216 ext2fs_mark_super_dirty(fs);
218 ext2fs_unmark_valid(fs);
220 ext2fs_free_mem((void **) &free_array);
223 static void check_inode_bitmaps(e2fsck_t ctx)
225 ext2_filsys fs = ctx->fs;
236 struct problem_context pctx;
237 int problem, fixit, had_problem;
239 clear_problem_context(&pctx);
240 free_array = (int *) e2fsck_allocate_memory(ctx,
241 fs->group_desc_count * sizeof(int), "free inode count array");
243 dir_array = (int *) e2fsck_allocate_memory(ctx,
244 fs->group_desc_count * sizeof(int), "directory count array");
246 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
247 (fs->super->s_inodes_count >
248 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
251 pctx.blk2 = fs->super->s_inodes_count;
252 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
253 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
254 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
256 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
259 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
260 (fs->super->s_inodes_count >
261 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
264 pctx.blk2 = fs->super->s_inodes_count;
265 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
266 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
267 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
269 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
275 for (i = 1; i <= fs->super->s_inodes_count; i++) {
276 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
277 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
279 if (actual == bitmap)
282 if (!actual && bitmap) {
284 * Inode wasn't used, but marked in bitmap
286 problem = PR_5_UNUSED_INODE;
287 } else /* if (actual && !bitmap) */ {
289 * Inode used, but not in bitmap
291 problem = PR_5_INODE_USED;
294 fix_problem(ctx, problem, &pctx);
295 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
303 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
307 if ((inodes == fs->super->s_inodes_per_group) ||
308 (i == fs->super->s_inodes_count)) {
309 free_array[group] = group_free;
310 dir_array[group] = dirs_count;
316 if ((ctx->progress)(ctx, 5,
317 group + fs->group_desc_count,
318 fs->group_desc_count*2))
323 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
326 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
329 ext2fs_free_inode_bitmap(fs->inode_map);
330 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
333 clear_problem_context(&pctx);
334 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
335 ctx->flags |= E2F_FLAG_ABORT;
338 ext2fs_set_bitmap_padding(fs->inode_map);
339 ext2fs_mark_ib_dirty(fs);
342 inodes = 0; free_inodes = 0; group_free = 0;
343 dirs_count = 0; group = 0;
344 memset(free_array, 0, fs->group_desc_count * sizeof(int));
345 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
347 } else if (fixit == 0)
348 ext2fs_unmark_valid(fs);
350 for (i = 0; i < fs->group_desc_count; i++) {
351 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
353 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
354 pctx.ino2 = free_array[i];
355 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
357 fs->group_desc[i].bg_free_inodes_count =
359 ext2fs_mark_super_dirty(fs);
361 ext2fs_unmark_valid(fs);
363 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
365 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
366 pctx.ino2 = dir_array[i];
368 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
370 fs->group_desc[i].bg_used_dirs_count =
372 ext2fs_mark_super_dirty(fs);
374 ext2fs_unmark_valid(fs);
377 if (free_inodes != fs->super->s_free_inodes_count) {
379 pctx.ino = fs->super->s_free_inodes_count;
380 pctx.ino2 = free_inodes;
382 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
383 fs->super->s_free_inodes_count = free_inodes;
384 ext2fs_mark_super_dirty(fs);
386 ext2fs_unmark_valid(fs);
388 ext2fs_free_mem((void **) &free_array);
389 ext2fs_free_mem((void **) &dir_array);
392 static void check_inode_end(e2fsck_t ctx)
394 ext2_filsys fs = ctx->fs;
395 ext2_ino_t end, save_inodes_count, i;
396 struct problem_context pctx;
398 clear_problem_context(&pctx);
400 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
401 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
405 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
406 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
409 if (save_inodes_count == end)
412 for (i = save_inodes_count + 1; i <= end; i++) {
413 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
414 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
415 for (i = save_inodes_count + 1; i <= end; i++)
416 ext2fs_mark_inode_bitmap(fs->inode_map,
418 ext2fs_mark_ib_dirty(fs);
420 ext2fs_unmark_valid(fs);
425 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
426 save_inodes_count, 0);
429 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
430 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
435 static void check_block_end(e2fsck_t ctx)
437 ext2_filsys fs = ctx->fs;
438 blk_t end, save_blocks_count, i;
439 struct problem_context pctx;
441 clear_problem_context(&pctx);
443 end = fs->block_map->start +
444 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
445 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
449 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
450 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
453 if (save_blocks_count == end)
456 for (i = save_blocks_count + 1; i <= end; i++) {
457 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
458 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
459 for (i = save_blocks_count + 1; i <= end; i++)
460 ext2fs_mark_block_bitmap(fs->block_map,
462 ext2fs_mark_bb_dirty(fs);
464 ext2fs_unmark_valid(fs);
469 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
470 save_blocks_count, 0);
473 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
474 ctx->flags |= E2F_FLAG_ABORT; /* fatal */