]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - e2fsck/pass5.c
libext2fs: Convert ext2fs_bg_flag_test() to ext2fs_bg_flags_test()
[thirdparty/e2fsprogs.git] / e2fsck / pass5.c
CommitLineData
3839e657
TT
1/*
2 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
efc6f628 3 *
21c84b71
TT
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
efc6f628 10 *
3839e657
TT
11 */
12
3839e657 13#include "e2fsck.h"
1b6bf175 14#include "problem.h"
3839e657 15
1b6bf175
TT
16static void check_block_bitmaps(e2fsck_t ctx);
17static void check_inode_bitmaps(e2fsck_t ctx);
18static void check_inode_end(e2fsck_t ctx);
19static void check_block_end(e2fsck_t ctx);
3839e657 20
08b21301 21void e2fsck_pass5(e2fsck_t ctx)
3839e657 22{
8bf191e8 23#ifdef RESOURCE_TRACK
3839e657 24 struct resource_track rtrack;
8bf191e8 25#endif
1b6bf175 26 struct problem_context pctx;
efc6f628 27
3839e657
TT
28#ifdef MTRACE
29 mtrace_print("Pass 5");
30#endif
31
6d96b00d 32 init_resource_track(&rtrack, ctx->fs->io);
1b6bf175 33 clear_problem_context(&pctx);
3839e657 34
1b6bf175
TT
35 if (!(ctx->options & E2F_OPT_PREEN))
36 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
3839e657 37
f8188fff 38 if (ctx->progress)
efac9a1b 39 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
a02ce9df 40 return;
f8188fff
TT
41
42 e2fsck_read_bitmaps(ctx);
43
1b6bf175 44 check_block_bitmaps(ctx);
a02ce9df 45 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
08b21301 46 return;
1b6bf175 47 check_inode_bitmaps(ctx);
a02ce9df 48 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
08b21301 49 return;
1b6bf175 50 check_inode_end(ctx);
a02ce9df 51 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
08b21301 52 return;
1b6bf175 53 check_block_end(ctx);
a02ce9df 54 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
08b21301 55 return;
3839e657 56
1b6bf175
TT
57 ext2fs_free_inode_bitmap(ctx->inode_used_map);
58 ctx->inode_used_map = 0;
59 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
60 ctx->inode_dir_map = 0;
61 ext2fs_free_block_bitmap(ctx->block_found_map);
62 ctx->block_found_map = 0;
63
9facd076 64 print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
3839e657
TT
65}
66
f122632e
TT
67#define NO_BLK ((blk_t) -1)
68
546a1ff1 69static void print_bitmap_problem(e2fsck_t ctx, int problem,
f122632e
TT
70 struct problem_context *pctx)
71{
72 switch (problem) {
73 case PR_5_BLOCK_UNUSED:
74 if (pctx->blk == pctx->blk2)
75 pctx->blk2 = 0;
76 else
77 problem = PR_5_BLOCK_RANGE_UNUSED;
78 break;
79 case PR_5_BLOCK_USED:
80 if (pctx->blk == pctx->blk2)
81 pctx->blk2 = 0;
82 else
83 problem = PR_5_BLOCK_RANGE_USED;
84 break;
85 case PR_5_INODE_UNUSED:
86 if (pctx->ino == pctx->ino2)
87 pctx->ino2 = 0;
88 else
89 problem = PR_5_INODE_RANGE_UNUSED;
90 break;
91 case PR_5_INODE_USED:
92 if (pctx->ino == pctx->ino2)
93 pctx->ino2 = 0;
94 else
95 problem = PR_5_INODE_RANGE_USED;
96 break;
97 }
98 fix_problem(ctx, problem, pctx);
99 pctx->blk = pctx->blk2 = NO_BLK;
100 pctx->ino = pctx->ino2 = 0;
101}
49e2df29 102
1b6bf175 103static void check_block_bitmaps(e2fsck_t ctx)
3839e657 104{
1b6bf175 105 ext2_filsys fs = ctx->fs;
20f2ccb3 106 blk64_t i;
3839e657
TT
107 int *free_array;
108 int group = 0;
5d38ef1d
VC
109 blk_t blocks = 0;
110 blk_t free_blocks = 0;
3839e657
TT
111 int group_free = 0;
112 int actual, bitmap;
1b6bf175 113 struct problem_context pctx;
f122632e 114 int problem, save_problem, fixit, had_problem;
1b6bf175 115 errcode_t retval;
16b851cd 116 int csum_flag;
f5fa2007 117 int skip_group = 0;
479463aa
KM
118 int old_desc_blocks = 0;
119 int count = 0;
120 int cmp_block = 0;
121 int redo_flag = 0;
20f2ccb3 122 blk64_t super_blk, old_desc_blk, new_desc_blk;
49e2df29 123
1b6bf175 124 clear_problem_context(&pctx);
54dc7ca2 125 free_array = (int *) e2fsck_allocate_memory(ctx,
f8188fff 126 fs->group_desc_count * sizeof(int), "free block count array");
50e1e10f
TT
127
128 if ((fs->super->s_first_data_block <
c5d2f50d 129 ext2fs_get_block_bitmap_start2(ctx->block_found_map)) ||
4efbac6f 130 (ext2fs_blocks_count(fs->super)-1 >
c5d2f50d 131 ext2fs_get_block_bitmap_end2(ctx->block_found_map))) {
1b6bf175
TT
132 pctx.num = 1;
133 pctx.blk = fs->super->s_first_data_block;
4efbac6f 134 pctx.blk2 = ext2fs_blocks_count(fs->super) -1;
c5d2f50d
VAH
135 pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map);
136 pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map);
1b6bf175 137 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
08b21301
TT
138
139 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
49e2df29 140 goto errout;
50e1e10f 141 }
49e2df29 142
50e1e10f 143 if ((fs->super->s_first_data_block <
c5d2f50d 144 ext2fs_get_block_bitmap_start2(fs->block_map)) ||
4efbac6f 145 (ext2fs_blocks_count(fs->super)-1 >
c5d2f50d 146 ext2fs_get_block_bitmap_end2(fs->block_map))) {
1b6bf175
TT
147 pctx.num = 2;
148 pctx.blk = fs->super->s_first_data_block;
4efbac6f 149 pctx.blk2 = ext2fs_blocks_count(fs->super) -1;
c5d2f50d
VAH
150 pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map);
151 pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map);
1b6bf175 152 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
08b21301
TT
153
154 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
49e2df29 155 goto errout;
50e1e10f 156 }
49e2df29 157
49a7360b
JS
158 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
159 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
63c4969c
TT
160redo_counts:
161 had_problem = 0;
f122632e
TT
162 save_problem = 0;
163 pctx.blk = pctx.blk2 = NO_BLK;
16b851cd 164 if (csum_flag &&
cd65a24e 165 (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
f5fa2007 166 skip_group++;
3839e657 167 for (i = fs->super->s_first_data_block;
4efbac6f 168 i < ext2fs_blocks_count(fs->super);
3839e657 169 i++) {
c5d2f50d 170 actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i);
f5fa2007
TT
171
172 if (skip_group) {
479463aa
KM
173 if ((i - fs->super->s_first_data_block) %
174 fs->super->s_blocks_per_group == 0) {
175 super_blk = 0;
176 old_desc_blk = 0;
177 new_desc_blk = 0;
20f2ccb3 178 ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
4a2924ea
TT
179 &old_desc_blk, &new_desc_blk, 0);
180
479463aa
KM
181 if (fs->super->s_feature_incompat &
182 EXT2_FEATURE_INCOMPAT_META_BG)
183 old_desc_blocks =
184 fs->super->s_first_meta_bg;
185 else
186 old_desc_blocks = fs->desc_blocks +
4a2924ea
TT
187 fs->super->s_reserved_gdt_blocks;
188
479463aa
KM
189 count = 0;
190 cmp_block = fs->super->s_blocks_per_group;
191 if (group == (int)fs->group_desc_count - 1)
192 cmp_block =
4efbac6f 193 ext2fs_blocks_count(fs->super) %
479463aa
KM
194 fs->super->s_blocks_per_group;
195 }
196
4a2924ea 197 bitmap = 0;
479463aa
KM
198 if ((i == super_blk) ||
199 (old_desc_blk && old_desc_blocks &&
200 (i >= old_desc_blk) &&
201 (i < old_desc_blk + old_desc_blocks)) ||
202 (new_desc_blk && (i == new_desc_blk)) ||
203 (i == fs->group_desc[group].bg_block_bitmap) ||
204 (i == fs->group_desc[group].bg_inode_bitmap) ||
205 (i >= fs->group_desc[group].bg_inode_table &&
206 (i < fs->group_desc[group].bg_inode_table +
207 fs->inode_blocks_per_group))) {
4a2924ea 208 bitmap = 1;
479463aa
KM
209 actual = (actual != 0);
210 count++;
211 cmp_block--;
212 } else if ((i - count - fs->super->s_first_data_block) %
213 fs->super->s_blocks_per_group == 0) {
214 /*
215 * When the compare data blocks in block bitmap
216 * are 0, count the free block,
217 * skip the current block group.
218 */
c5d2f50d 219 if (ext2fs_test_block_bitmap_range2(
479463aa
KM
220 ctx->block_found_map, i,
221 cmp_block)) {
222 /*
223 * -1 means to skip the current block
224 * group.
225 */
226 blocks = fs->super->s_blocks_per_group
227 - 1;
228 group_free = cmp_block;
229 free_blocks += cmp_block;
230 /*
231 * The current block group's last block
232 * is set to i.
233 */
234 i += cmp_block - 1;
235 bitmap = 1;
236 goto do_counts;
237 }
238 }
239 } else if (redo_flag)
240 bitmap = actual;
241 else
c5d2f50d 242 bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
49e2df29 243
3839e657
TT
244 if (actual == bitmap)
245 goto do_counts;
f5fa2007 246
3839e657
TT
247 if (!actual && bitmap) {
248 /*
249 * Block not used, but marked in use in the bitmap.
250 */
f122632e 251 problem = PR_5_BLOCK_UNUSED;
3839e657
TT
252 } else {
253 /*
254 * Block used, but not marked in use in the bitmap.
255 */
1b6bf175 256 problem = PR_5_BLOCK_USED;
49a7360b
JS
257
258 if (skip_group) {
259 struct problem_context pctx2;
260 pctx2.blk = i;
261 pctx2.group = group;
262 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
e633b58a 263 ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
49a7360b
JS
264 skip_group = 0;
265 }
266 }
3839e657 267 }
f122632e
TT
268 if (pctx.blk == NO_BLK) {
269 pctx.blk = pctx.blk2 = i;
270 save_problem = problem;
271 } else {
272 if ((problem == save_problem) &&
273 (pctx.blk2 == i-1))
274 pctx.blk2++;
275 else {
276 print_bitmap_problem(ctx, save_problem, &pctx);
277 pctx.blk = pctx.blk2 = i;
278 save_problem = problem;
279 }
280 }
5596defa 281 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
63c4969c 282 had_problem++;
49e2df29 283
3839e657 284 do_counts:
49a7360b 285 if (!bitmap && (!skip_group || csum_flag)) {
3839e657
TT
286 group_free++;
287 free_blocks++;
288 }
289 blocks ++;
290 if ((blocks == fs->super->s_blocks_per_group) ||
4efbac6f 291 (i == ext2fs_blocks_count(fs->super)-1)) {
3839e657
TT
292 free_array[group] = group_free;
293 group ++;
294 blocks = 0;
295 group_free = 0;
f5fa2007 296 skip_group = 0;
efac9a1b
TT
297 if (ctx->progress)
298 if ((ctx->progress)(ctx, 5, group,
299 fs->group_desc_count*2))
49e2df29 300 goto errout;
16b851cd 301 if (csum_flag &&
4efbac6f 302 (i != ext2fs_blocks_count(fs->super)-1) &&
cd65a24e 303 ext2fs_bg_flags_test(fs, group,
732c8cd5 304 EXT2_BG_BLOCK_UNINIT))
f5fa2007 305 skip_group++;
3839e657
TT
306 }
307 }
f122632e
TT
308 if (pctx.blk != NO_BLK)
309 print_bitmap_problem(ctx, save_problem, &pctx);
63c4969c 310 if (had_problem)
f122632e 311 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
63c4969c
TT
312 else
313 fixit = -1;
5596defa 314 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
49e2df29 315
1b6bf175
TT
316 if (fixit == 1) {
317 ext2fs_free_block_bitmap(fs->block_map);
318 retval = ext2fs_copy_bitmap(ctx->block_found_map,
319 &fs->block_map);
bbd47d76
TT
320 if (retval) {
321 clear_problem_context(&pctx);
322 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
323 ctx->flags |= E2F_FLAG_ABORT;
49e2df29 324 goto errout;
bbd47d76 325 }
1b6bf175
TT
326 ext2fs_set_bitmap_padding(fs->block_map);
327 ext2fs_mark_bb_dirty(fs);
49e2df29 328
1b6bf175
TT
329 /* Redo the counts */
330 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
331 memset(free_array, 0, fs->group_desc_count * sizeof(int));
479463aa 332 redo_flag++;
1b6bf175
TT
333 goto redo_counts;
334 } else if (fixit == 0)
335 ext2fs_unmark_valid(fs);
336
3839e657
TT
337 for (i = 0; i < fs->group_desc_count; i++) {
338 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
1b6bf175
TT
339 pctx.group = i;
340 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
341 pctx.blk2 = free_array[i];
342
343 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
344 &pctx)) {
e633b58a 345 ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]);
3839e657
TT
346 ext2fs_mark_super_dirty(fs);
347 } else
348 ext2fs_unmark_valid(fs);
349 }
350 }
4efbac6f 351 if (free_blocks != ext2fs_free_blocks_count(fs->super)) {
1b6bf175 352 pctx.group = 0;
4efbac6f 353 pctx.blk = ext2fs_free_blocks_count(fs->super);
1b6bf175
TT
354 pctx.blk2 = free_blocks;
355
356 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
4efbac6f 357 ext2fs_free_blocks_count_set(fs->super, free_blocks);
3839e657
TT
358 ext2fs_mark_super_dirty(fs);
359 } else
360 ext2fs_unmark_valid(fs);
361 }
49e2df29 362errout:
c4e3d3f3 363 ext2fs_free_mem(&free_array);
3839e657 364}
49e2df29 365
1b6bf175 366static void check_inode_bitmaps(e2fsck_t ctx)
3839e657 367{
1b6bf175 368 ext2_filsys fs = ctx->fs;
86c627ec 369 ext2_ino_t i;
54434927
TT
370 unsigned int free_inodes = 0;
371 int group_free = 0;
372 int dirs_count = 0;
373 int group = 0;
374 unsigned int inodes = 0;
375 int *free_array;
376 int *dir_array;
377 int actual, bitmap;
1b6bf175
TT
378 errcode_t retval;
379 struct problem_context pctx;
54434927 380 int problem, save_problem, fixit, had_problem;
16b851cd 381 int csum_flag;
f5fa2007 382 int skip_group = 0;
479463aa 383 int redo_flag = 0;
49e2df29 384
1b6bf175 385 clear_problem_context(&pctx);
54dc7ca2 386 free_array = (int *) e2fsck_allocate_memory(ctx,
f8188fff 387 fs->group_desc_count * sizeof(int), "free inode count array");
49e2df29 388
54dc7ca2 389 dir_array = (int *) e2fsck_allocate_memory(ctx,
f8188fff 390 fs->group_desc_count * sizeof(int), "directory count array");
49e2df29 391
c5d2f50d 392 if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
49e2df29 393 (fs->super->s_inodes_count >
c5d2f50d 394 ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
1b6bf175
TT
395 pctx.num = 3;
396 pctx.blk = 1;
397 pctx.blk2 = fs->super->s_inodes_count;
c5d2f50d
VAH
398 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
399 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
1b6bf175 400 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
08b21301
TT
401
402 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
49e2df29 403 goto errout;
50e1e10f 404 }
c5d2f50d 405 if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
49e2df29 406 (fs->super->s_inodes_count >
c5d2f50d 407 ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
1b6bf175
TT
408 pctx.num = 4;
409 pctx.blk = 1;
410 pctx.blk2 = fs->super->s_inodes_count;
c5d2f50d
VAH
411 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
412 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
1b6bf175 413 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
08b21301
TT
414
415 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
49e2df29 416 goto errout;
50e1e10f
TT
417 }
418
49a7360b
JS
419 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
420 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
1b6bf175 421redo_counts:
63c4969c 422 had_problem = 0;
f122632e
TT
423 save_problem = 0;
424 pctx.ino = pctx.ino2 = 0;
16b851cd 425 if (csum_flag &&
cd65a24e 426 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
f5fa2007
TT
427 skip_group++;
428
5830d6be
ES
429 /* Protect loop from wrap-around if inodes_count is maxed */
430 for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
479463aa
KM
431 bitmap = 0;
432 if (skip_group &&
433 i % fs->super->s_inodes_per_group == 1) {
434 /*
435 * Current inode is the first inode
436 * in the current block group.
437 */
438 if (ext2fs_test_inode_bitmap_range(
439 ctx->inode_used_map, i,
440 fs->super->s_inodes_per_group)) {
441 /*
442 * When the compared inodes in inodes bitmap
443 * are 0, count the free inode,
444 * skip the current block group.
445 */
446 inodes = fs->super->s_inodes_per_group - 1;
447 group_free = inodes;
448 free_inodes += inodes;
449 i += inodes;
450 skip_group = 0;
451 goto do_counts;
452 }
453 }
454
c5d2f50d 455 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
479463aa
KM
456 if (redo_flag)
457 bitmap = actual;
458 else if (!skip_group)
c5d2f50d 459 bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
3839e657
TT
460 if (actual == bitmap)
461 goto do_counts;
49e2df29 462
3839e657
TT
463 if (!actual && bitmap) {
464 /*
465 * Inode wasn't used, but marked in bitmap
466 */
f122632e 467 problem = PR_5_INODE_UNUSED;
1b6bf175 468 } else /* if (actual && !bitmap) */ {
3839e657
TT
469 /*
470 * Inode used, but not in bitmap
471 */
1b6bf175 472 problem = PR_5_INODE_USED;
49a7360b
JS
473
474 /* We should never hit this, because it means that
475 * inodes were marked in use that weren't noticed
476 * in pass1 or pass 2. It is easier to fix the problem
477 * than to kill e2fsck and leave the user stuck. */
478 if (skip_group) {
479 struct problem_context pctx2;
480 pctx2.blk = i;
481 pctx2.group = group;
482 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
e633b58a 483 ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
49a7360b
JS
484 skip_group = 0;
485 }
486 }
3839e657 487 }
f122632e
TT
488 if (pctx.ino == 0) {
489 pctx.ino = pctx.ino2 = i;
490 save_problem = problem;
491 } else {
492 if ((problem == save_problem) &&
493 (pctx.ino2 == i-1))
494 pctx.ino2++;
495 else {
496 print_bitmap_problem(ctx, save_problem, &pctx);
497 pctx.ino = pctx.ino2 = i;
498 save_problem = problem;
499 }
500 }
5596defa 501 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
63c4969c 502 had_problem++;
49e2df29 503
3839e657 504do_counts:
f5fa2007 505 if (bitmap) {
c5d2f50d 506 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
3839e657 507 dirs_count++;
49a7360b 508 } else if (!skip_group || csum_flag) {
f5fa2007
TT
509 group_free++;
510 free_inodes++;
3839e657
TT
511 }
512 inodes++;
513 if ((inodes == fs->super->s_inodes_per_group) ||
514 (i == fs->super->s_inodes_count)) {
515 free_array[group] = group_free;
516 dir_array[group] = dirs_count;
517 group ++;
518 inodes = 0;
f5fa2007 519 skip_group = 0;
3839e657
TT
520 group_free = 0;
521 dirs_count = 0;
efac9a1b
TT
522 if (ctx->progress)
523 if ((ctx->progress)(ctx, 5,
524 group + fs->group_desc_count,
525 fs->group_desc_count*2))
49e2df29 526 goto errout;
16b851cd 527 if (csum_flag &&
f5fa2007 528 (i != fs->super->s_inodes_count) &&
cd65a24e 529 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)
732c8cd5 530 ))
f5fa2007 531 skip_group++;
3839e657
TT
532 }
533 }
f122632e
TT
534 if (pctx.ino)
535 print_bitmap_problem(ctx, save_problem, &pctx);
49e2df29 536
63c4969c
TT
537 if (had_problem)
538 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
539 else
540 fixit = -1;
5596defa 541 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
49e2df29 542
1b6bf175
TT
543 if (fixit == 1) {
544 ext2fs_free_inode_bitmap(fs->inode_map);
545 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
546 &fs->inode_map);
bbd47d76
TT
547 if (retval) {
548 clear_problem_context(&pctx);
549 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
550 ctx->flags |= E2F_FLAG_ABORT;
49e2df29 551 goto errout;
bbd47d76 552 }
1b6bf175
TT
553 ext2fs_set_bitmap_padding(fs->inode_map);
554 ext2fs_mark_ib_dirty(fs);
555
556 /* redo counts */
557 inodes = 0; free_inodes = 0; group_free = 0;
558 dirs_count = 0; group = 0;
559 memset(free_array, 0, fs->group_desc_count * sizeof(int));
560 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
479463aa 561 redo_flag++;
1b6bf175
TT
562 goto redo_counts;
563 } else if (fixit == 0)
564 ext2fs_unmark_valid(fs);
49e2df29 565
3839e657
TT
566 for (i = 0; i < fs->group_desc_count; i++) {
567 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
1b6bf175
TT
568 pctx.group = i;
569 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
570 pctx.ino2 = free_array[i];
571 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
572 &pctx)) {
3839e657
TT
573 fs->group_desc[i].bg_free_inodes_count =
574 free_array[i];
575 ext2fs_mark_super_dirty(fs);
576 } else
577 ext2fs_unmark_valid(fs);
578 }
579 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
1b6bf175
TT
580 pctx.group = i;
581 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
582 pctx.ino2 = dir_array[i];
583
584 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
585 &pctx)) {
3839e657
TT
586 fs->group_desc[i].bg_used_dirs_count =
587 dir_array[i];
588 ext2fs_mark_super_dirty(fs);
589 } else
590 ext2fs_unmark_valid(fs);
591 }
592 }
593 if (free_inodes != fs->super->s_free_inodes_count) {
1b6bf175
TT
594 pctx.group = -1;
595 pctx.ino = fs->super->s_free_inodes_count;
596 pctx.ino2 = free_inodes;
597
598 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
3839e657
TT
599 fs->super->s_free_inodes_count = free_inodes;
600 ext2fs_mark_super_dirty(fs);
601 } else
602 ext2fs_unmark_valid(fs);
603 }
49e2df29 604errout:
c4e3d3f3
TT
605 ext2fs_free_mem(&free_array);
606 ext2fs_free_mem(&dir_array);
3839e657
TT
607}
608
1b6bf175 609static void check_inode_end(e2fsck_t ctx)
3839e657 610{
1b6bf175 611 ext2_filsys fs = ctx->fs;
86c627ec 612 ext2_ino_t end, save_inodes_count, i;
1b6bf175
TT
613 struct problem_context pctx;
614
615 clear_problem_context(&pctx);
3839e657
TT
616
617 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
1b6bf175
TT
618 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
619 &save_inodes_count);
620 if (pctx.errcode) {
621 pctx.num = 1;
622 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
08b21301
TT
623 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
624 return;
f3db3566 625 }
3839e657
TT
626 if (save_inodes_count == end)
627 return;
5830d6be 628
efc6f628 629 /* protect loop from wrap-around if end is maxed */
5830d6be 630 for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
f3db3566 631 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
1b6bf175 632 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
01ec1268 633 for (; i <= end; i++)
f3db3566 634 ext2fs_mark_inode_bitmap(fs->inode_map,
3839e657
TT
635 i);
636 ext2fs_mark_ib_dirty(fs);
637 } else
638 ext2fs_unmark_valid(fs);
639 break;
640 }
641 }
642
1b6bf175
TT
643 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
644 save_inodes_count, 0);
645 if (pctx.errcode) {
646 pctx.num = 2;
647 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
08b21301
TT
648 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
649 return;
f3db3566 650 }
3839e657
TT
651}
652
1b6bf175 653static void check_block_end(e2fsck_t ctx)
3839e657 654{
1b6bf175 655 ext2_filsys fs = ctx->fs;
c5d2f50d 656 blk64_t end, save_blocks_count, i;
1b6bf175
TT
657 struct problem_context pctx;
658
659 clear_problem_context(&pctx);
3839e657 660
c5d2f50d 661 end = ext2fs_get_block_bitmap_start2(fs->block_map) +
c5b7b6ba 662 ((blk64_t)EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
c5d2f50d 663 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
1b6bf175
TT
664 &save_blocks_count);
665 if (pctx.errcode) {
666 pctx.num = 3;
667 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
08b21301
TT
668 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
669 return;
f3db3566 670 }
3839e657
TT
671 if (save_blocks_count == end)
672 return;
5830d6be 673
efc6f628 674 /* Protect loop from wrap-around if end is maxed */
5830d6be 675 for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
c5d2f50d 676 if (!ext2fs_test_block_bitmap2(fs->block_map, i)) {
1b6bf175 677 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
01ec1268 678 for (; i <= end; i++)
c5d2f50d
VAH
679 ext2fs_mark_block_bitmap2(fs->block_map,
680 i);
3839e657
TT
681 ext2fs_mark_bb_dirty(fs);
682 } else
683 ext2fs_unmark_valid(fs);
684 break;
685 }
686 }
687
c5d2f50d 688 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
1b6bf175
TT
689 save_blocks_count, 0);
690 if (pctx.errcode) {
691 pctx.num = 4;
692 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
08b21301
TT
693 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
694 return;
f3db3566 695 }
3839e657
TT
696}
697
1b6bf175
TT
698
699