pass5.c revision 2788cc879bbe667d28277e1d660b7e56514e5b30
1/* 2 * pass5.c --- check block and inode bitmaps against on-disk bitmaps 3 * 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% 10 * 11 */ 12 13#include "config.h" 14#include <stdint.h> 15#include <sys/types.h> 16#include <sys/stat.h> 17#include <sys/ioctl.h> 18#include <fcntl.h> 19#include <errno.h> 20 21#include "e2fsck.h" 22#include "problem.h" 23 24#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 25 26static void check_block_bitmaps(e2fsck_t ctx); 27static void check_inode_bitmaps(e2fsck_t ctx); 28static void check_inode_end(e2fsck_t ctx); 29static void check_block_end(e2fsck_t ctx); 30 31void e2fsck_pass5(e2fsck_t ctx) 32{ 33#ifdef RESOURCE_TRACK 34 struct resource_track rtrack; 35#endif 36 struct problem_context pctx; 37 38#ifdef MTRACE 39 mtrace_print("Pass 5"); 40#endif 41 42 init_resource_track(&rtrack, ctx->fs->io); 43 clear_problem_context(&pctx); 44 45 if (!(ctx->options & E2F_OPT_PREEN)) 46 fix_problem(ctx, PR_5_PASS_HEADER, &pctx); 47 48 if (ctx->progress) 49 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2)) 50 return; 51 52 e2fsck_read_bitmaps(ctx); 53 54 check_block_bitmaps(ctx); 55 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 56 return; 57 check_inode_bitmaps(ctx); 58 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 59 return; 60 check_inode_end(ctx); 61 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 62 return; 63 check_block_end(ctx); 64 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 65 return; 66 67 ext2fs_free_inode_bitmap(ctx->inode_used_map); 68 ctx->inode_used_map = 0; 69 ext2fs_free_inode_bitmap(ctx->inode_dir_map); 70 ctx->inode_dir_map = 0; 71 ext2fs_free_block_bitmap(ctx->block_found_map); 72 ctx->block_found_map = 0; 73 74 print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io); 75} 76 77static void e2fsck_discard_blocks(e2fsck_t ctx, blk64_t start, 78 blk64_t count) 79{ 80 ext2_filsys fs = ctx->fs; 81 82 /* 83 * If the filesystem has changed it means that there was an corruption 84 * which should be repaired, but in some cases just one e2fsck run is 85 * not enough to fix the problem, hence it is not safe to run discard 86 * in this case. 87 */ 88 if (ext2fs_test_changed(fs)) 89 ctx->options &= ~E2F_OPT_DISCARD; 90 91 if ((ctx->options & E2F_OPT_DISCARD) && 92 (io_channel_discard(fs->io, start, count))) 93 ctx->options &= ~E2F_OPT_DISCARD; 94} 95 96/* 97 * This will try to discard number 'count' inodes starting at 98 * inode number 'start' within the 'group'. Note that 'start' 99 * is 1-based, it means that we need to adjust it by -1 in this 100 * function to compute right offset in the particular inode table. 101 */ 102static void e2fsck_discard_inodes(e2fsck_t ctx, dgrp_t group, 103 ext2_ino_t start, int count) 104{ 105 ext2_filsys fs = ctx->fs; 106 blk64_t blk, num; 107 108 /* 109 * Sanity check for 'start' 110 */ 111 if ((start < 1) || (start > EXT2_INODES_PER_GROUP(fs->super))) { 112 printf("PROGRAMMING ERROR: Got start %d outside of group %d!" 113 " Disabling discard\n", 114 start, group); 115 ctx->options &= ~E2F_OPT_DISCARD; 116 } 117 118 /* 119 * Do not attempt to discard if E2F_OPT_DISCARD is not set. And also 120 * skip the discard on this group if discard does not zero data. 121 * The reason is that if the inode table is not zeroed discard would 122 * no help us since we need to zero it anyway, or if the inode table 123 * is zeroed then the read after discard would not be deterministic 124 * anyway and we would not be able to assume that this inode table 125 * was zeroed anymore so we would have to zero it again, which does 126 * not really make sense. 127 */ 128 if (!(ctx->options & E2F_OPT_DISCARD) || 129 !io_channel_discard_zeroes_data(fs->io)) 130 return; 131 132 /* 133 * Start is inode number within the group which starts 134 * counting from 1, so we need to adjust it. 135 */ 136 start -= 1; 137 138 /* 139 * We can discard only blocks containing only unused 140 * inodes in the table. 141 */ 142 blk = DIV_ROUND_UP(start, 143 EXT2_INODES_PER_BLOCK(fs->super)); 144 count -= (blk * EXT2_INODES_PER_BLOCK(fs->super) - start); 145 blk += ext2fs_inode_table_loc(fs, group); 146 num = count / EXT2_INODES_PER_BLOCK(fs->super); 147 148 if (num > 0) 149 e2fsck_discard_blocks(ctx, blk, num); 150} 151 152#define NO_BLK ((blk64_t) -1) 153 154static void print_bitmap_problem(e2fsck_t ctx, int problem, 155 struct problem_context *pctx) 156{ 157 switch (problem) { 158 case PR_5_BLOCK_UNUSED: 159 if (pctx->blk == pctx->blk2) 160 pctx->blk2 = 0; 161 else 162 problem = PR_5_BLOCK_RANGE_UNUSED; 163 break; 164 case PR_5_BLOCK_USED: 165 if (pctx->blk == pctx->blk2) 166 pctx->blk2 = 0; 167 else 168 problem = PR_5_BLOCK_RANGE_USED; 169 break; 170 case PR_5_INODE_UNUSED: 171 if (pctx->ino == pctx->ino2) 172 pctx->ino2 = 0; 173 else 174 problem = PR_5_INODE_RANGE_UNUSED; 175 break; 176 case PR_5_INODE_USED: 177 if (pctx->ino == pctx->ino2) 178 pctx->ino2 = 0; 179 else 180 problem = PR_5_INODE_RANGE_USED; 181 break; 182 } 183 fix_problem(ctx, problem, pctx); 184 pctx->blk = pctx->blk2 = NO_BLK; 185 pctx->ino = pctx->ino2 = 0; 186} 187 188/* Just to be more succint */ 189#define B2C(x) EXT2FS_B2C(fs, (x)) 190#define EQ_CLSTR(x, y) (B2C(x) == B2C(y)) 191#define LE_CLSTR(x, y) (B2C(x) <= B2C(y)) 192#define GE_CLSTR(x, y) (B2C(x) >= B2C(y)) 193 194static void check_block_bitmaps(e2fsck_t ctx) 195{ 196 ext2_filsys fs = ctx->fs; 197 blk64_t i; 198 unsigned int *free_array; 199 int group = 0; 200 unsigned int blocks = 0; 201 blk64_t free_blocks = 0; 202 blk64_t first_free = ext2fs_blocks_count(fs->super); 203 unsigned int group_free = 0; 204 int actual, bitmap; 205 struct problem_context pctx; 206 int problem, save_problem, fixit, had_problem; 207 errcode_t retval; 208 int csum_flag; 209 int skip_group = 0; 210 int old_desc_blocks = 0; 211 int count = 0; 212 int cmp_block = 0; 213 int redo_flag = 0; 214 blk64_t super_blk, old_desc_blk, new_desc_blk; 215 216 clear_problem_context(&pctx); 217 free_array = (unsigned int *) e2fsck_allocate_memory(ctx, 218 fs->group_desc_count * sizeof(unsigned int), "free block count array"); 219 220 if ((B2C(fs->super->s_first_data_block) < 221 ext2fs_get_block_bitmap_start2(ctx->block_found_map)) || 222 (B2C(ext2fs_blocks_count(fs->super)-1) > 223 ext2fs_get_block_bitmap_end2(ctx->block_found_map))) { 224 pctx.num = 1; 225 pctx.blk = B2C(fs->super->s_first_data_block); 226 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1); 227 pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map); 228 pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map); 229 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); 230 231 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 232 goto errout; 233 } 234 235 if ((B2C(fs->super->s_first_data_block) < 236 ext2fs_get_block_bitmap_start2(fs->block_map)) || 237 (B2C(ext2fs_blocks_count(fs->super)-1) > 238 ext2fs_get_block_bitmap_end2(fs->block_map))) { 239 pctx.num = 2; 240 pctx.blk = B2C(fs->super->s_first_data_block); 241 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1); 242 pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map); 243 pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map); 244 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); 245 246 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 247 goto errout; 248 } 249 250 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 251 EXT4_FEATURE_RO_COMPAT_GDT_CSUM); 252redo_counts: 253 had_problem = 0; 254 save_problem = 0; 255 pctx.blk = pctx.blk2 = NO_BLK; 256 if (csum_flag && 257 (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) 258 skip_group++; 259 for (i = B2C(fs->super->s_first_data_block); 260 i < ext2fs_blocks_count(fs->super); 261 i += EXT2FS_CLUSTER_RATIO(fs)) { 262 actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i); 263 264 if (skip_group) { 265 if ((B2C(i) - B2C(fs->super->s_first_data_block)) % 266 fs->super->s_clusters_per_group == 0) { 267 super_blk = 0; 268 old_desc_blk = 0; 269 new_desc_blk = 0; 270 ext2fs_super_and_bgd_loc2(fs, group, &super_blk, 271 &old_desc_blk, &new_desc_blk, 0); 272 273 if (fs->super->s_feature_incompat & 274 EXT2_FEATURE_INCOMPAT_META_BG) 275 old_desc_blocks = 276 fs->super->s_first_meta_bg; 277 else 278 old_desc_blocks = fs->desc_blocks + 279 fs->super->s_reserved_gdt_blocks; 280 281 count = 0; 282 cmp_block = fs->super->s_clusters_per_group; 283 if (group == (int)fs->group_desc_count - 1) 284 cmp_block = EXT2FS_NUM_B2C(fs, 285 ext2fs_group_blocks_count(fs, group)); 286 } 287 288 bitmap = 0; 289 if (EQ_CLSTR(i, super_blk) || 290 (old_desc_blk && old_desc_blocks && 291 GE_CLSTR(i, old_desc_blk) && 292 LE_CLSTR(i, old_desc_blk + old_desc_blocks-1)) || 293 (new_desc_blk && EQ_CLSTR(i, new_desc_blk)) || 294 EQ_CLSTR(i, ext2fs_block_bitmap_loc(fs, group)) || 295 EQ_CLSTR(i, ext2fs_inode_bitmap_loc(fs, group)) || 296 (GE_CLSTR(i, ext2fs_inode_table_loc(fs, group)) && 297 LE_CLSTR(i, (ext2fs_inode_table_loc(fs, group) + 298 fs->inode_blocks_per_group - 1)))) { 299 bitmap = 1; 300 actual = (actual != 0); 301 count++; 302 cmp_block--; 303 } else if ((EXT2FS_B2C(fs, i) - count - 304 EXT2FS_B2C(fs, fs->super->s_first_data_block)) % 305 fs->super->s_clusters_per_group == 0) { 306 /* 307 * When the compare data blocks in block bitmap 308 * are 0, count the free block, 309 * skip the current block group. 310 */ 311 if (ext2fs_test_block_bitmap_range2( 312 ctx->block_found_map, 313 EXT2FS_B2C(fs, i), 314 cmp_block)) { 315 /* 316 * -1 means to skip the current block 317 * group. 318 */ 319 blocks = fs->super->s_clusters_per_group - 1; 320 group_free = cmp_block; 321 free_blocks += cmp_block; 322 /* 323 * The current block group's last block 324 * is set to i. 325 */ 326 i += EXT2FS_C2B(fs, cmp_block - 1); 327 bitmap = 1; 328 goto do_counts; 329 } 330 } 331 } else if (redo_flag) 332 bitmap = actual; 333 else 334 bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i); 335 336 if (!actual == !bitmap) 337 goto do_counts; 338 339 if (!actual && bitmap) { 340 /* 341 * Block not used, but marked in use in the bitmap. 342 */ 343 problem = PR_5_BLOCK_UNUSED; 344 } else { 345 /* 346 * Block used, but not marked in use in the bitmap. 347 */ 348 problem = PR_5_BLOCK_USED; 349 350 if (skip_group) { 351 struct problem_context pctx2; 352 pctx2.blk = i; 353 pctx2.group = group; 354 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){ 355 ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); 356 skip_group = 0; 357 } 358 } 359 } 360 if (pctx.blk == NO_BLK) { 361 pctx.blk = pctx.blk2 = i; 362 save_problem = problem; 363 } else { 364 if ((problem == save_problem) && 365 (pctx.blk2 == i-1)) 366 pctx.blk2++; 367 else { 368 print_bitmap_problem(ctx, save_problem, &pctx); 369 pctx.blk = pctx.blk2 = i; 370 save_problem = problem; 371 } 372 } 373 ctx->flags |= E2F_FLAG_PROG_SUPPRESS; 374 had_problem++; 375 376 /* 377 * If there a problem we should turn off the discard so we 378 * do not compromise the filesystem. 379 */ 380 ctx->options &= ~E2F_OPT_DISCARD; 381 382 do_counts: 383 if (!bitmap) { 384 group_free++; 385 free_blocks++; 386 if (first_free > i) 387 first_free = i; 388 } else if (i > first_free) { 389 e2fsck_discard_blocks(ctx, first_free, 390 (i - first_free)); 391 first_free = ext2fs_blocks_count(fs->super); 392 } 393 blocks ++; 394 if ((blocks == fs->super->s_clusters_per_group) || 395 (EXT2FS_B2C(fs, i) == 396 EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) { 397 /* 398 * If the last block of this group is free, then we can 399 * discard it as well. 400 */ 401 if (!bitmap && i >= first_free) 402 e2fsck_discard_blocks(ctx, first_free, 403 (i - first_free) + 1); 404 first_free = ext2fs_blocks_count(fs->super); 405 406 free_array[group] = group_free; 407 group ++; 408 blocks = 0; 409 group_free = 0; 410 skip_group = 0; 411 if (ctx->progress) 412 if ((ctx->progress)(ctx, 5, group, 413 fs->group_desc_count*2)) 414 goto errout; 415 if (csum_flag && 416 (i != ext2fs_blocks_count(fs->super)-1) && 417 ext2fs_bg_flags_test(fs, group, 418 EXT2_BG_BLOCK_UNINIT)) 419 skip_group++; 420 } 421 } 422 if (pctx.blk != NO_BLK) 423 print_bitmap_problem(ctx, save_problem, &pctx); 424 if (had_problem) 425 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP); 426 else 427 fixit = -1; 428 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; 429 430 if (fixit == 1) { 431 ext2fs_free_block_bitmap(fs->block_map); 432 retval = ext2fs_copy_bitmap(ctx->block_found_map, 433 &fs->block_map); 434 if (retval) { 435 clear_problem_context(&pctx); 436 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx); 437 ctx->flags |= E2F_FLAG_ABORT; 438 goto errout; 439 } 440 ext2fs_set_bitmap_padding(fs->block_map); 441 ext2fs_mark_bb_dirty(fs); 442 443 /* Redo the counts */ 444 blocks = 0; free_blocks = 0; group_free = 0; group = 0; 445 memset(free_array, 0, fs->group_desc_count * sizeof(int)); 446 redo_flag++; 447 goto redo_counts; 448 } else if (fixit == 0) 449 ext2fs_unmark_valid(fs); 450 451 for (i = 0; i < fs->group_desc_count; i++) { 452 if (free_array[i] != ext2fs_bg_free_blocks_count(fs, i)) { 453 pctx.group = i; 454 pctx.blk = ext2fs_bg_free_blocks_count(fs, i); 455 pctx.blk2 = free_array[i]; 456 457 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP, 458 &pctx)) { 459 ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]); 460 ext2fs_mark_super_dirty(fs); 461 } else 462 ext2fs_unmark_valid(fs); 463 } 464 } 465 free_blocks = EXT2FS_C2B(fs, free_blocks); 466 if (free_blocks != ext2fs_free_blocks_count(fs->super)) { 467 pctx.group = 0; 468 pctx.blk = ext2fs_free_blocks_count(fs->super); 469 pctx.blk2 = free_blocks; 470 471 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) { 472 ext2fs_free_blocks_count_set(fs->super, free_blocks); 473 ext2fs_mark_super_dirty(fs); 474 } 475 } 476errout: 477 ext2fs_free_mem(&free_array); 478} 479 480static void check_inode_bitmaps(e2fsck_t ctx) 481{ 482 ext2_filsys fs = ctx->fs; 483 ext2_ino_t i; 484 unsigned int free_inodes = 0; 485 int group_free = 0; 486 int dirs_count = 0; 487 int group = 0; 488 unsigned int inodes = 0; 489 ext2_ino_t *free_array; 490 ext2_ino_t *dir_array; 491 int actual, bitmap; 492 errcode_t retval; 493 struct problem_context pctx; 494 int problem, save_problem, fixit, had_problem; 495 int csum_flag; 496 int skip_group = 0; 497 int redo_flag = 0; 498 ext2_ino_t first_free = fs->super->s_inodes_per_group + 1; 499 500 clear_problem_context(&pctx); 501 free_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx, 502 fs->group_desc_count * sizeof(ext2_ino_t), "free inode count array"); 503 504 dir_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx, 505 fs->group_desc_count * sizeof(ext2_ino_t), "directory count array"); 506 507 if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) || 508 (fs->super->s_inodes_count > 509 ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) { 510 pctx.num = 3; 511 pctx.blk = 1; 512 pctx.blk2 = fs->super->s_inodes_count; 513 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map); 514 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map); 515 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); 516 517 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 518 goto errout; 519 } 520 if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) || 521 (fs->super->s_inodes_count > 522 ext2fs_get_inode_bitmap_end2(fs->inode_map))) { 523 pctx.num = 4; 524 pctx.blk = 1; 525 pctx.blk2 = fs->super->s_inodes_count; 526 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map); 527 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map); 528 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); 529 530 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 531 goto errout; 532 } 533 534 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 535 EXT4_FEATURE_RO_COMPAT_GDT_CSUM); 536redo_counts: 537 had_problem = 0; 538 save_problem = 0; 539 pctx.ino = pctx.ino2 = 0; 540 if (csum_flag && 541 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT))) 542 skip_group++; 543 544 /* Protect loop from wrap-around if inodes_count is maxed */ 545 for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) { 546 bitmap = 0; 547 if (skip_group && 548 i % fs->super->s_inodes_per_group == 1) { 549 /* 550 * Current inode is the first inode 551 * in the current block group. 552 */ 553 if (ext2fs_test_inode_bitmap_range( 554 ctx->inode_used_map, i, 555 fs->super->s_inodes_per_group)) { 556 /* 557 * When the compared inodes in inodes bitmap 558 * are 0, count the free inode, 559 * skip the current block group. 560 */ 561 first_free = 1; 562 inodes = fs->super->s_inodes_per_group - 1; 563 group_free = inodes; 564 free_inodes += inodes; 565 i += inodes; 566 skip_group = 0; 567 goto do_counts; 568 } 569 } 570 571 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i); 572 if (redo_flag) 573 bitmap = actual; 574 else if (!skip_group) 575 bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i); 576 if (!actual == !bitmap) 577 goto do_counts; 578 579 if (!actual && bitmap) { 580 /* 581 * Inode wasn't used, but marked in bitmap 582 */ 583 problem = PR_5_INODE_UNUSED; 584 } else /* if (actual && !bitmap) */ { 585 /* 586 * Inode used, but not in bitmap 587 */ 588 problem = PR_5_INODE_USED; 589 590 /* We should never hit this, because it means that 591 * inodes were marked in use that weren't noticed 592 * in pass1 or pass 2. It is easier to fix the problem 593 * than to kill e2fsck and leave the user stuck. */ 594 if (skip_group) { 595 struct problem_context pctx2; 596 pctx2.blk = i; 597 pctx2.group = group; 598 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){ 599 ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); 600 skip_group = 0; 601 } 602 } 603 } 604 if (pctx.ino == 0) { 605 pctx.ino = pctx.ino2 = i; 606 save_problem = problem; 607 } else { 608 if ((problem == save_problem) && 609 (pctx.ino2 == i-1)) 610 pctx.ino2++; 611 else { 612 print_bitmap_problem(ctx, save_problem, &pctx); 613 pctx.ino = pctx.ino2 = i; 614 save_problem = problem; 615 } 616 } 617 ctx->flags |= E2F_FLAG_PROG_SUPPRESS; 618 had_problem++; 619 /* 620 * If there a problem we should turn off the discard so we 621 * do not compromise the filesystem. 622 */ 623 ctx->options &= ~E2F_OPT_DISCARD; 624 625do_counts: 626 inodes++; 627 if (bitmap) { 628 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i)) 629 dirs_count++; 630 if (inodes > first_free) { 631 e2fsck_discard_inodes(ctx, group, first_free, 632 inodes - first_free); 633 first_free = fs->super->s_inodes_per_group + 1; 634 } 635 } else { 636 group_free++; 637 free_inodes++; 638 if (first_free > inodes) 639 first_free = inodes; 640 } 641 642 if ((inodes == fs->super->s_inodes_per_group) || 643 (i == fs->super->s_inodes_count)) { 644 /* 645 * If the last inode is free, we can discard it as well. 646 */ 647 if (!bitmap && inodes >= first_free) 648 e2fsck_discard_inodes(ctx, group, first_free, 649 inodes - first_free + 1); 650 /* 651 * If discard zeroes data and the group inode table 652 * was not zeroed yet, set itable as zeroed 653 */ 654 if ((ctx->options & E2F_OPT_DISCARD) && 655 io_channel_discard_zeroes_data(fs->io) && 656 !(ext2fs_bg_flags_test(fs, group, 657 EXT2_BG_INODE_ZEROED))) { 658 ext2fs_bg_flags_set(fs, group, 659 EXT2_BG_INODE_ZEROED); 660 ext2fs_group_desc_csum_set(fs, group); 661 } 662 663 first_free = fs->super->s_inodes_per_group + 1; 664 free_array[group] = group_free; 665 dir_array[group] = dirs_count; 666 group ++; 667 inodes = 0; 668 skip_group = 0; 669 group_free = 0; 670 dirs_count = 0; 671 if (ctx->progress) 672 if ((ctx->progress)(ctx, 5, 673 group + fs->group_desc_count, 674 fs->group_desc_count*2)) 675 goto errout; 676 if (csum_flag && 677 (i != fs->super->s_inodes_count) && 678 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT) 679 )) 680 skip_group++; 681 } 682 } 683 if (pctx.ino) 684 print_bitmap_problem(ctx, save_problem, &pctx); 685 686 if (had_problem) 687 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP); 688 else 689 fixit = -1; 690 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; 691 692 if (fixit == 1) { 693 ext2fs_free_inode_bitmap(fs->inode_map); 694 retval = ext2fs_copy_bitmap(ctx->inode_used_map, 695 &fs->inode_map); 696 if (retval) { 697 clear_problem_context(&pctx); 698 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx); 699 ctx->flags |= E2F_FLAG_ABORT; 700 goto errout; 701 } 702 ext2fs_set_bitmap_padding(fs->inode_map); 703 ext2fs_mark_ib_dirty(fs); 704 705 /* redo counts */ 706 inodes = 0; free_inodes = 0; group_free = 0; 707 dirs_count = 0; group = 0; 708 memset(free_array, 0, fs->group_desc_count * sizeof(int)); 709 memset(dir_array, 0, fs->group_desc_count * sizeof(int)); 710 redo_flag++; 711 goto redo_counts; 712 } else if (fixit == 0) 713 ext2fs_unmark_valid(fs); 714 715 for (i = 0; i < fs->group_desc_count; i++) { 716 if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) { 717 pctx.group = i; 718 pctx.ino = ext2fs_bg_free_inodes_count(fs, i); 719 pctx.ino2 = free_array[i]; 720 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP, 721 &pctx)) { 722 ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]); 723 ext2fs_mark_super_dirty(fs); 724 } else 725 ext2fs_unmark_valid(fs); 726 } 727 if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) { 728 pctx.group = i; 729 pctx.ino = ext2fs_bg_used_dirs_count(fs, i); 730 pctx.ino2 = dir_array[i]; 731 732 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP, 733 &pctx)) { 734 ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]); 735 ext2fs_mark_super_dirty(fs); 736 } else 737 ext2fs_unmark_valid(fs); 738 } 739 } 740 if (free_inodes != fs->super->s_free_inodes_count) { 741 pctx.group = -1; 742 pctx.ino = fs->super->s_free_inodes_count; 743 pctx.ino2 = free_inodes; 744 745 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) { 746 fs->super->s_free_inodes_count = free_inodes; 747 ext2fs_mark_super_dirty(fs); 748 } 749 } 750errout: 751 ext2fs_free_mem(&free_array); 752 ext2fs_free_mem(&dir_array); 753} 754 755static void check_inode_end(e2fsck_t ctx) 756{ 757 ext2_filsys fs = ctx->fs; 758 ext2_ino_t end, save_inodes_count, i; 759 struct problem_context pctx; 760 761 clear_problem_context(&pctx); 762 763 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count; 764 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end, 765 &save_inodes_count); 766 if (pctx.errcode) { 767 pctx.num = 1; 768 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); 769 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 770 return; 771 } 772 if (save_inodes_count == end) 773 return; 774 775 /* protect loop from wrap-around if end is maxed */ 776 for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) { 777 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) { 778 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) { 779 for (; i <= end; i++) 780 ext2fs_mark_inode_bitmap(fs->inode_map, 781 i); 782 ext2fs_mark_ib_dirty(fs); 783 } else 784 ext2fs_unmark_valid(fs); 785 break; 786 } 787 } 788 789 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, 790 save_inodes_count, 0); 791 if (pctx.errcode) { 792 pctx.num = 2; 793 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); 794 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 795 return; 796 } 797} 798 799static void check_block_end(e2fsck_t ctx) 800{ 801 ext2_filsys fs = ctx->fs; 802 blk64_t end, save_blocks_count, i; 803 struct problem_context pctx; 804 805 clear_problem_context(&pctx); 806 807 end = ext2fs_get_block_bitmap_start2(fs->block_map) + 808 ((blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count) - 1; 809 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end, 810 &save_blocks_count); 811 if (pctx.errcode) { 812 pctx.num = 3; 813 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); 814 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 815 return; 816 } 817 if (save_blocks_count == end) 818 return; 819 820 /* Protect loop from wrap-around if end is maxed */ 821 for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) { 822 if (!ext2fs_test_block_bitmap2(fs->block_map, 823 EXT2FS_C2B(fs, i))) { 824 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) { 825 for (; i <= end; i++) 826 ext2fs_mark_block_bitmap2(fs->block_map, 827 EXT2FS_C2B(fs, i)); 828 ext2fs_mark_bb_dirty(fs); 829 } else 830 ext2fs_unmark_valid(fs); 831 break; 832 } 833 } 834 835 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, 836 save_blocks_count, 0); 837 if (pctx.errcode) { 838 pctx.num = 4; 839 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); 840 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 841 return; 842 } 843} 844 845 846 847