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, 3))
45 e2fsck_read_bitmaps(ctx);
48 if ((ctx->progress)(ctx, 5, 2, 3))
51 check_block_bitmaps(ctx);
52 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
54 check_inode_bitmaps(ctx);
55 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
58 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
61 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
65 if ((ctx->progress)(ctx, 5, 3, 3))
68 ext2fs_free_inode_bitmap(ctx->inode_used_map);
69 ctx->inode_used_map = 0;
70 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
71 ctx->inode_dir_map = 0;
72 ext2fs_free_block_bitmap(ctx->block_found_map);
73 ctx->block_found_map = 0;
76 if (ctx->options & E2F_OPT_TIME2)
77 print_resource_track("Pass 5", &rtrack);
81 static void check_block_bitmaps(e2fsck_t ctx)
83 ext2_filsys fs = ctx->fs;
91 struct problem_context pctx;
92 int problem, fixit, had_problem;
95 clear_problem_context(&pctx);
96 free_array = (int *) e2fsck_allocate_memory(ctx,
97 fs->group_desc_count * sizeof(int), "free block count array");
99 if ((fs->super->s_first_data_block <
100 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
101 (fs->super->s_blocks_count-1 >
102 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
104 pctx.blk = fs->super->s_first_data_block;
105 pctx.blk2 = fs->super->s_blocks_count -1;
106 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
107 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
108 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
110 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
114 if ((fs->super->s_first_data_block <
115 ext2fs_get_block_bitmap_start(fs->block_map)) ||
116 (fs->super->s_blocks_count-1 >
117 ext2fs_get_block_bitmap_end(fs->block_map))) {
119 pctx.blk = fs->super->s_first_data_block;
120 pctx.blk2 = fs->super->s_blocks_count -1;
121 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
122 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
123 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
125 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
131 for (i = fs->super->s_first_data_block;
132 i < fs->super->s_blocks_count;
134 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
135 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
137 if (actual == bitmap)
140 if (!actual && bitmap) {
142 * Block not used, but marked in use in the bitmap.
144 problem = PR_5_UNUSED_BLOCK;
147 * Block used, but not marked in use in the bitmap.
149 problem = PR_5_BLOCK_USED;
152 fix_problem(ctx, problem, &pctx);
161 if ((blocks == fs->super->s_blocks_per_group) ||
162 (i == fs->super->s_blocks_count-1)) {
163 free_array[group] = group_free;
170 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
174 ext2fs_free_block_bitmap(fs->block_map);
175 retval = ext2fs_copy_bitmap(ctx->block_found_map,
177 /* XXX check retval --- should never fail! */
178 ext2fs_set_bitmap_padding(fs->block_map);
179 ext2fs_mark_bb_dirty(fs);
181 /* Redo the counts */
182 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
183 memset(free_array, 0, fs->group_desc_count * sizeof(int));
185 } else if (fixit == 0)
186 ext2fs_unmark_valid(fs);
188 for (i = 0; i < fs->group_desc_count; i++) {
189 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
191 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
192 pctx.blk2 = free_array[i];
194 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
196 fs->group_desc[i].bg_free_blocks_count =
198 ext2fs_mark_super_dirty(fs);
200 ext2fs_unmark_valid(fs);
203 if (free_blocks != fs->super->s_free_blocks_count) {
205 pctx.blk = fs->super->s_free_blocks_count;
206 pctx.blk2 = free_blocks;
208 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
209 fs->super->s_free_blocks_count = free_blocks;
210 ext2fs_mark_super_dirty(fs);
212 ext2fs_unmark_valid(fs);
214 ext2fs_free_mem((void **) &free_array);
217 static void check_inode_bitmaps(e2fsck_t ctx)
219 ext2_filsys fs = ctx->fs;
230 struct problem_context pctx;
231 int problem, fixit, had_problem;
233 clear_problem_context(&pctx);
234 free_array = (int *) e2fsck_allocate_memory(ctx,
235 fs->group_desc_count * sizeof(int), "free inode count array");
237 dir_array = (int *) e2fsck_allocate_memory(ctx,
238 fs->group_desc_count * sizeof(int), "directory count array");
240 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
241 (fs->super->s_inodes_count >
242 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
245 pctx.blk2 = fs->super->s_inodes_count;
246 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
247 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
248 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
250 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
253 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
254 (fs->super->s_inodes_count >
255 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
258 pctx.blk2 = fs->super->s_inodes_count;
259 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
260 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
261 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
263 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
269 for (i = 1; i <= fs->super->s_inodes_count; i++) {
270 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
271 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
273 if (actual == bitmap)
276 if (!actual && bitmap) {
278 * Inode wasn't used, but marked in bitmap
280 problem = PR_5_UNUSED_INODE;
281 } else /* if (actual && !bitmap) */ {
283 * Inode used, but not in bitmap
285 problem = PR_5_INODE_USED;
288 fix_problem(ctx, problem, &pctx);
296 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
300 if ((inodes == fs->super->s_inodes_per_group) ||
301 (i == fs->super->s_inodes_count)) {
302 free_array[group] = group_free;
303 dir_array[group] = dirs_count;
311 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
315 ext2fs_free_inode_bitmap(fs->inode_map);
316 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
318 /* XXX check retval --- should never fail! */
319 ext2fs_set_bitmap_padding(fs->inode_map);
320 ext2fs_mark_ib_dirty(fs);
323 inodes = 0; free_inodes = 0; group_free = 0;
324 dirs_count = 0; group = 0;
325 memset(free_array, 0, fs->group_desc_count * sizeof(int));
326 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
328 } else if (fixit == 0)
329 ext2fs_unmark_valid(fs);
331 for (i = 0; i < fs->group_desc_count; i++) {
332 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
334 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
335 pctx.ino2 = free_array[i];
336 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
338 fs->group_desc[i].bg_free_inodes_count =
340 ext2fs_mark_super_dirty(fs);
342 ext2fs_unmark_valid(fs);
344 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
346 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
347 pctx.ino2 = dir_array[i];
349 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
351 fs->group_desc[i].bg_used_dirs_count =
353 ext2fs_mark_super_dirty(fs);
355 ext2fs_unmark_valid(fs);
358 if (free_inodes != fs->super->s_free_inodes_count) {
360 pctx.ino = fs->super->s_free_inodes_count;
361 pctx.ino2 = free_inodes;
363 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
364 fs->super->s_free_inodes_count = free_inodes;
365 ext2fs_mark_super_dirty(fs);
367 ext2fs_unmark_valid(fs);
369 ext2fs_free_mem((void **) &free_array);
370 ext2fs_free_mem((void **) &dir_array);
373 static void check_inode_end(e2fsck_t ctx)
375 ext2_filsys fs = ctx->fs;
376 ino_t end, save_inodes_count, i;
377 struct problem_context pctx;
379 clear_problem_context(&pctx);
381 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
382 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
386 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
387 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
390 if (save_inodes_count == end)
393 for (i = save_inodes_count + 1; i <= end; i++) {
394 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
395 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
396 for (i = save_inodes_count + 1; i <= end; i++)
397 ext2fs_mark_inode_bitmap(fs->inode_map,
399 ext2fs_mark_ib_dirty(fs);
401 ext2fs_unmark_valid(fs);
406 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
407 save_inodes_count, 0);
410 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
411 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
416 static void check_block_end(e2fsck_t ctx)
418 ext2_filsys fs = ctx->fs;
419 blk_t end, save_blocks_count, i;
420 struct problem_context pctx;
422 clear_problem_context(&pctx);
424 end = fs->block_map->start +
425 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
426 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
430 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
431 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
434 if (save_blocks_count == end)
437 for (i = save_blocks_count + 1; i <= end; i++) {
438 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
439 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
440 for (i = save_blocks_count + 1; i < end; i++)
441 ext2fs_mark_block_bitmap(fs->block_map,
443 ext2fs_mark_bb_dirty(fs);
445 ext2fs_unmark_valid(fs);
450 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
451 save_blocks_count, 0);
454 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
455 ctx->flags |= E2F_FLAG_ABORT; /* fatal */