]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - e2fsck/pass5.c
Convert to use io_channel_read_blk64() and io_channel_write_blk64()
[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)) ||
50e1e10f 130 (fs->super->s_blocks_count-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;
134 pctx.blk2 = fs->super->s_blocks_count -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)) ||
50e1e10f 145 (fs->super->s_blocks_count-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;
149 pctx.blk2 = fs->super->s_blocks_count -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 &&
49a7360b 165 (fs->group_desc[group].bg_flags & EXT2_BG_BLOCK_UNINIT))
f5fa2007 166 skip_group++;
3839e657
TT
167 for (i = fs->super->s_first_data_block;
168 i < fs->super->s_blocks_count;
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 =
193 fs->super->s_blocks_count %
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)){
263 fs->group_desc[group].bg_flags &=
264 ~EXT2_BG_BLOCK_UNINIT;
265 skip_group = 0;
266 }
267 }
3839e657 268 }
f122632e
TT
269 if (pctx.blk == NO_BLK) {
270 pctx.blk = pctx.blk2 = i;
271 save_problem = problem;
272 } else {
273 if ((problem == save_problem) &&
274 (pctx.blk2 == i-1))
275 pctx.blk2++;
276 else {
277 print_bitmap_problem(ctx, save_problem, &pctx);
278 pctx.blk = pctx.blk2 = i;
279 save_problem = problem;
280 }
281 }
5596defa 282 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
63c4969c 283 had_problem++;
49e2df29 284
3839e657 285 do_counts:
49a7360b 286 if (!bitmap && (!skip_group || csum_flag)) {
3839e657
TT
287 group_free++;
288 free_blocks++;
289 }
290 blocks ++;
291 if ((blocks == fs->super->s_blocks_per_group) ||
292 (i == fs->super->s_blocks_count-1)) {
293 free_array[group] = group_free;
294 group ++;
295 blocks = 0;
296 group_free = 0;
f5fa2007 297 skip_group = 0;
efac9a1b
TT
298 if (ctx->progress)
299 if ((ctx->progress)(ctx, 5, group,
300 fs->group_desc_count*2))
49e2df29 301 goto errout;
16b851cd 302 if (csum_flag &&
f5fa2007
TT
303 (i != fs->super->s_blocks_count-1) &&
304 (fs->group_desc[group].bg_flags &
305 EXT2_BG_BLOCK_UNINIT))
306 skip_group++;
3839e657
TT
307 }
308 }
f122632e
TT
309 if (pctx.blk != NO_BLK)
310 print_bitmap_problem(ctx, save_problem, &pctx);
63c4969c 311 if (had_problem)
f122632e 312 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
63c4969c
TT
313 else
314 fixit = -1;
5596defa 315 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
49e2df29 316
1b6bf175
TT
317 if (fixit == 1) {
318 ext2fs_free_block_bitmap(fs->block_map);
319 retval = ext2fs_copy_bitmap(ctx->block_found_map,
320 &fs->block_map);
bbd47d76
TT
321 if (retval) {
322 clear_problem_context(&pctx);
323 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
324 ctx->flags |= E2F_FLAG_ABORT;
49e2df29 325 goto errout;
bbd47d76 326 }
1b6bf175
TT
327 ext2fs_set_bitmap_padding(fs->block_map);
328 ext2fs_mark_bb_dirty(fs);
49e2df29 329
1b6bf175
TT
330 /* Redo the counts */
331 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
332 memset(free_array, 0, fs->group_desc_count * sizeof(int));
479463aa 333 redo_flag++;
1b6bf175
TT
334 goto redo_counts;
335 } else if (fixit == 0)
336 ext2fs_unmark_valid(fs);
337
3839e657
TT
338 for (i = 0; i < fs->group_desc_count; i++) {
339 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
1b6bf175
TT
340 pctx.group = i;
341 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
342 pctx.blk2 = free_array[i];
343
344 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
345 &pctx)) {
3839e657
TT
346 fs->group_desc[i].bg_free_blocks_count =
347 free_array[i];
348 ext2fs_mark_super_dirty(fs);
349 } else
350 ext2fs_unmark_valid(fs);
351 }
352 }
353 if (free_blocks != fs->super->s_free_blocks_count) {
1b6bf175
TT
354 pctx.group = 0;
355 pctx.blk = fs->super->s_free_blocks_count;
356 pctx.blk2 = free_blocks;
357
358 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
3839e657
TT
359 fs->super->s_free_blocks_count = free_blocks;
360 ext2fs_mark_super_dirty(fs);
361 } else
362 ext2fs_unmark_valid(fs);
363 }
49e2df29 364errout:
c4e3d3f3 365 ext2fs_free_mem(&free_array);
3839e657 366}
49e2df29 367
1b6bf175 368static void check_inode_bitmaps(e2fsck_t ctx)
3839e657 369{
1b6bf175 370 ext2_filsys fs = ctx->fs;
86c627ec 371 ext2_ino_t i;
54434927
TT
372 unsigned int free_inodes = 0;
373 int group_free = 0;
374 int dirs_count = 0;
375 int group = 0;
376 unsigned int inodes = 0;
377 int *free_array;
378 int *dir_array;
379 int actual, bitmap;
1b6bf175
TT
380 errcode_t retval;
381 struct problem_context pctx;
54434927 382 int problem, save_problem, fixit, had_problem;
16b851cd 383 int csum_flag;
f5fa2007 384 int skip_group = 0;
479463aa 385 int redo_flag = 0;
49e2df29 386
1b6bf175 387 clear_problem_context(&pctx);
54dc7ca2 388 free_array = (int *) e2fsck_allocate_memory(ctx,
f8188fff 389 fs->group_desc_count * sizeof(int), "free inode count array");
49e2df29 390
54dc7ca2 391 dir_array = (int *) e2fsck_allocate_memory(ctx,
f8188fff 392 fs->group_desc_count * sizeof(int), "directory count array");
49e2df29 393
c5d2f50d 394 if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
49e2df29 395 (fs->super->s_inodes_count >
c5d2f50d 396 ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
1b6bf175
TT
397 pctx.num = 3;
398 pctx.blk = 1;
399 pctx.blk2 = fs->super->s_inodes_count;
c5d2f50d
VAH
400 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
401 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
1b6bf175 402 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
08b21301
TT
403
404 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
49e2df29 405 goto errout;
50e1e10f 406 }
c5d2f50d 407 if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
49e2df29 408 (fs->super->s_inodes_count >
c5d2f50d 409 ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
1b6bf175
TT
410 pctx.num = 4;
411 pctx.blk = 1;
412 pctx.blk2 = fs->super->s_inodes_count;
c5d2f50d
VAH
413 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
414 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
1b6bf175 415 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
08b21301
TT
416
417 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
49e2df29 418 goto errout;
50e1e10f
TT
419 }
420
49a7360b
JS
421 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
422 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
1b6bf175 423redo_counts:
63c4969c 424 had_problem = 0;
f122632e
TT
425 save_problem = 0;
426 pctx.ino = pctx.ino2 = 0;
16b851cd 427 if (csum_flag &&
49a7360b 428 (fs->group_desc[group].bg_flags & EXT2_BG_INODE_UNINIT))
f5fa2007
TT
429 skip_group++;
430
5830d6be
ES
431 /* Protect loop from wrap-around if inodes_count is maxed */
432 for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
479463aa
KM
433 bitmap = 0;
434 if (skip_group &&
435 i % fs->super->s_inodes_per_group == 1) {
436 /*
437 * Current inode is the first inode
438 * in the current block group.
439 */
440 if (ext2fs_test_inode_bitmap_range(
441 ctx->inode_used_map, i,
442 fs->super->s_inodes_per_group)) {
443 /*
444 * When the compared inodes in inodes bitmap
445 * are 0, count the free inode,
446 * skip the current block group.
447 */
448 inodes = fs->super->s_inodes_per_group - 1;
449 group_free = inodes;
450 free_inodes += inodes;
451 i += inodes;
452 skip_group = 0;
453 goto do_counts;
454 }
455 }
456
c5d2f50d 457 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
479463aa
KM
458 if (redo_flag)
459 bitmap = actual;
460 else if (!skip_group)
c5d2f50d 461 bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
3839e657
TT
462 if (actual == bitmap)
463 goto do_counts;
49e2df29 464
3839e657
TT
465 if (!actual && bitmap) {
466 /*
467 * Inode wasn't used, but marked in bitmap
468 */
f122632e 469 problem = PR_5_INODE_UNUSED;
1b6bf175 470 } else /* if (actual && !bitmap) */ {
3839e657
TT
471 /*
472 * Inode used, but not in bitmap
473 */
1b6bf175 474 problem = PR_5_INODE_USED;
49a7360b
JS
475
476 /* We should never hit this, because it means that
477 * inodes were marked in use that weren't noticed
478 * in pass1 or pass 2. It is easier to fix the problem
479 * than to kill e2fsck and leave the user stuck. */
480 if (skip_group) {
481 struct problem_context pctx2;
482 pctx2.blk = i;
483 pctx2.group = group;
484 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
485 fs->group_desc[group].bg_flags &=
486 ~EXT2_BG_INODE_UNINIT;
487 skip_group = 0;
488 }
489 }
3839e657 490 }
f122632e
TT
491 if (pctx.ino == 0) {
492 pctx.ino = pctx.ino2 = i;
493 save_problem = problem;
494 } else {
495 if ((problem == save_problem) &&
496 (pctx.ino2 == i-1))
497 pctx.ino2++;
498 else {
499 print_bitmap_problem(ctx, save_problem, &pctx);
500 pctx.ino = pctx.ino2 = i;
501 save_problem = problem;
502 }
503 }
5596defa 504 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
63c4969c 505 had_problem++;
49e2df29 506
3839e657 507do_counts:
f5fa2007 508 if (bitmap) {
c5d2f50d 509 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
3839e657 510 dirs_count++;
49a7360b 511 } else if (!skip_group || csum_flag) {
f5fa2007
TT
512 group_free++;
513 free_inodes++;
3839e657
TT
514 }
515 inodes++;
516 if ((inodes == fs->super->s_inodes_per_group) ||
517 (i == fs->super->s_inodes_count)) {
518 free_array[group] = group_free;
519 dir_array[group] = dirs_count;
520 group ++;
521 inodes = 0;
f5fa2007 522 skip_group = 0;
3839e657
TT
523 group_free = 0;
524 dirs_count = 0;
efac9a1b
TT
525 if (ctx->progress)
526 if ((ctx->progress)(ctx, 5,
527 group + fs->group_desc_count,
528 fs->group_desc_count*2))
49e2df29 529 goto errout;
16b851cd 530 if (csum_flag &&
f5fa2007
TT
531 (i != fs->super->s_inodes_count) &&
532 (fs->group_desc[group].bg_flags &
533 EXT2_BG_INODE_UNINIT))
534 skip_group++;
3839e657
TT
535 }
536 }
f122632e
TT
537 if (pctx.ino)
538 print_bitmap_problem(ctx, save_problem, &pctx);
49e2df29 539
63c4969c
TT
540 if (had_problem)
541 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
542 else
543 fixit = -1;
5596defa 544 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
49e2df29 545
1b6bf175
TT
546 if (fixit == 1) {
547 ext2fs_free_inode_bitmap(fs->inode_map);
548 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
549 &fs->inode_map);
bbd47d76
TT
550 if (retval) {
551 clear_problem_context(&pctx);
552 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
553 ctx->flags |= E2F_FLAG_ABORT;
49e2df29 554 goto errout;
bbd47d76 555 }
1b6bf175
TT
556 ext2fs_set_bitmap_padding(fs->inode_map);
557 ext2fs_mark_ib_dirty(fs);
558
559 /* redo counts */
560 inodes = 0; free_inodes = 0; group_free = 0;
561 dirs_count = 0; group = 0;
562 memset(free_array, 0, fs->group_desc_count * sizeof(int));
563 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
479463aa 564 redo_flag++;
1b6bf175
TT
565 goto redo_counts;
566 } else if (fixit == 0)
567 ext2fs_unmark_valid(fs);
49e2df29 568
3839e657
TT
569 for (i = 0; i < fs->group_desc_count; i++) {
570 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
1b6bf175
TT
571 pctx.group = i;
572 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
573 pctx.ino2 = free_array[i];
574 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
575 &pctx)) {
3839e657
TT
576 fs->group_desc[i].bg_free_inodes_count =
577 free_array[i];
578 ext2fs_mark_super_dirty(fs);
579 } else
580 ext2fs_unmark_valid(fs);
581 }
582 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
1b6bf175
TT
583 pctx.group = i;
584 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
585 pctx.ino2 = dir_array[i];
586
587 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
588 &pctx)) {
3839e657
TT
589 fs->group_desc[i].bg_used_dirs_count =
590 dir_array[i];
591 ext2fs_mark_super_dirty(fs);
592 } else
593 ext2fs_unmark_valid(fs);
594 }
595 }
596 if (free_inodes != fs->super->s_free_inodes_count) {
1b6bf175
TT
597 pctx.group = -1;
598 pctx.ino = fs->super->s_free_inodes_count;
599 pctx.ino2 = free_inodes;
600
601 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
3839e657
TT
602 fs->super->s_free_inodes_count = free_inodes;
603 ext2fs_mark_super_dirty(fs);
604 } else
605 ext2fs_unmark_valid(fs);
606 }
49e2df29 607errout:
c4e3d3f3
TT
608 ext2fs_free_mem(&free_array);
609 ext2fs_free_mem(&dir_array);
3839e657
TT
610}
611
1b6bf175 612static void check_inode_end(e2fsck_t ctx)
3839e657 613{
1b6bf175 614 ext2_filsys fs = ctx->fs;
86c627ec 615 ext2_ino_t end, save_inodes_count, i;
1b6bf175
TT
616 struct problem_context pctx;
617
618 clear_problem_context(&pctx);
3839e657
TT
619
620 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
1b6bf175
TT
621 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
622 &save_inodes_count);
623 if (pctx.errcode) {
624 pctx.num = 1;
625 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
08b21301
TT
626 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
627 return;
f3db3566 628 }
3839e657
TT
629 if (save_inodes_count == end)
630 return;
5830d6be 631
efc6f628 632 /* protect loop from wrap-around if end is maxed */
5830d6be 633 for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
f3db3566 634 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
1b6bf175 635 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
01ec1268 636 for (; i <= end; i++)
f3db3566 637 ext2fs_mark_inode_bitmap(fs->inode_map,
3839e657
TT
638 i);
639 ext2fs_mark_ib_dirty(fs);
640 } else
641 ext2fs_unmark_valid(fs);
642 break;
643 }
644 }
645
1b6bf175
TT
646 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
647 save_inodes_count, 0);
648 if (pctx.errcode) {
649 pctx.num = 2;
650 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
08b21301
TT
651 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
652 return;
f3db3566 653 }
3839e657
TT
654}
655
1b6bf175 656static void check_block_end(e2fsck_t ctx)
3839e657 657{
1b6bf175 658 ext2_filsys fs = ctx->fs;
c5d2f50d 659 blk64_t end, save_blocks_count, i;
1b6bf175
TT
660 struct problem_context pctx;
661
662 clear_problem_context(&pctx);
3839e657 663
c5d2f50d 664 end = ext2fs_get_block_bitmap_start2(fs->block_map) +
f3db3566 665 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
c5d2f50d 666 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
1b6bf175
TT
667 &save_blocks_count);
668 if (pctx.errcode) {
669 pctx.num = 3;
670 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
08b21301
TT
671 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
672 return;
f3db3566 673 }
3839e657
TT
674 if (save_blocks_count == end)
675 return;
5830d6be 676
efc6f628 677 /* Protect loop from wrap-around if end is maxed */
5830d6be 678 for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
c5d2f50d 679 if (!ext2fs_test_block_bitmap2(fs->block_map, i)) {
1b6bf175 680 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
01ec1268 681 for (; i <= end; i++)
c5d2f50d
VAH
682 ext2fs_mark_block_bitmap2(fs->block_map,
683 i);
3839e657
TT
684 ext2fs_mark_bb_dirty(fs);
685 } else
686 ext2fs_unmark_valid(fs);
687 break;
688 }
689 }
690
c5d2f50d 691 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
1b6bf175
TT
692 save_blocks_count, 0);
693 if (pctx.errcode) {
694 pctx.num = 4;
695 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
08b21301
TT
696 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
697 return;
f3db3566 698 }
3839e657
TT
699}
700
1b6bf175
TT
701
702