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 */