pass5.c revision c7e293251fa28aebb201a884c074f0b36cbacc20
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 char *actual_buf, *bitmap_buf; 216 217 actual_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize, 218 "actual bitmap buffer"); 219 bitmap_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize, 220 "bitmap block buffer"); 221 222 clear_problem_context(&pctx); 223 free_array = (unsigned int *) e2fsck_allocate_memory(ctx, 224 fs->group_desc_count * sizeof(unsigned int), "free block count array"); 225 226 if ((B2C(fs->super->s_first_data_block) < 227 ext2fs_get_block_bitmap_start2(ctx->block_found_map)) || 228 (B2C(ext2fs_blocks_count(fs->super)-1) > 229 ext2fs_get_block_bitmap_end2(ctx->block_found_map))) { 230 pctx.num = 1; 231 pctx.blk = B2C(fs->super->s_first_data_block); 232 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1); 233 pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map); 234 pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map); 235 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); 236 237 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 238 goto errout; 239 } 240 241 if ((B2C(fs->super->s_first_data_block) < 242 ext2fs_get_block_bitmap_start2(fs->block_map)) || 243 (B2C(ext2fs_blocks_count(fs->super)-1) > 244 ext2fs_get_block_bitmap_end2(fs->block_map))) { 245 pctx.num = 2; 246 pctx.blk = B2C(fs->super->s_first_data_block); 247 pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1); 248 pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map); 249 pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map); 250 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); 251 252 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 253 goto errout; 254 } 255 256 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 257 EXT4_FEATURE_RO_COMPAT_GDT_CSUM); 258redo_counts: 259 had_problem = 0; 260 save_problem = 0; 261 pctx.blk = pctx.blk2 = NO_BLK; 262 if (csum_flag && 263 (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) 264 skip_group++; 265 for (i = B2C(fs->super->s_first_data_block); 266 i < ext2fs_blocks_count(fs->super); 267 i += EXT2FS_CLUSTER_RATIO(fs)) { 268 int first_block_in_bg = (B2C(i) - 269 B2C(fs->super->s_first_data_block)) % 270 fs->super->s_clusters_per_group == 0; 271 int n, nbytes = fs->super->s_clusters_per_group / 8; 272 273 actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i); 274 275 /* 276 * Try to optimize pass5 by extracting a bitmap block 277 * as expected from what we have on disk, and then 278 * comparing the two. If they are identical, then 279 * update the free block counts and go on to the next 280 * block group. This is much faster than doing the 281 * individual bit-by-bit comparison. The one downside 282 * is that this doesn't work if we are asking e2fsck 283 * to do a discard operation. 284 */ 285 if (!first_block_in_bg || 286 (group == (int)fs->group_desc_count - 1) || 287 (ctx->options & E2F_OPT_DISCARD)) 288 goto no_optimize; 289 290 retval = ext2fs_get_block_bitmap_range2(ctx->block_found_map, 291 B2C(i), fs->super->s_clusters_per_group, 292 actual_buf); 293 if (retval) 294 goto no_optimize; 295 if (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)) 296 memset(bitmap_buf, 0, nbytes); 297 else { 298 retval = ext2fs_get_block_bitmap_range2(fs->block_map, 299 B2C(i), fs->super->s_clusters_per_group, 300 bitmap_buf); 301 if (retval) 302 goto no_optimize; 303 } 304 if (memcmp(actual_buf, bitmap_buf, nbytes) != 0) 305 goto no_optimize; 306 n = ext2fs_bitcount(actual_buf, nbytes); 307 group_free = fs->super->s_clusters_per_group - n; 308 free_blocks += group_free; 309 i += EXT2FS_C2B(fs, fs->super->s_clusters_per_group - 1); 310 goto next_group; 311 no_optimize: 312 313 if (skip_group) { 314 if (first_block_in_bg) { 315 super_blk = 0; 316 old_desc_blk = 0; 317 new_desc_blk = 0; 318 ext2fs_super_and_bgd_loc2(fs, group, &super_blk, 319 &old_desc_blk, &new_desc_blk, 0); 320 321 if (fs->super->s_feature_incompat & 322 EXT2_FEATURE_INCOMPAT_META_BG) 323 old_desc_blocks = 324 fs->super->s_first_meta_bg; 325 else 326 old_desc_blocks = fs->desc_blocks + 327 fs->super->s_reserved_gdt_blocks; 328 329 count = 0; 330 cmp_block = fs->super->s_clusters_per_group; 331 if (group == (int)fs->group_desc_count - 1) 332 cmp_block = EXT2FS_NUM_B2C(fs, 333 ext2fs_group_blocks_count(fs, group)); 334 } 335 336 bitmap = 0; 337 if (EQ_CLSTR(i, super_blk) || 338 (old_desc_blk && old_desc_blocks && 339 GE_CLSTR(i, old_desc_blk) && 340 LE_CLSTR(i, old_desc_blk + old_desc_blocks-1)) || 341 (new_desc_blk && EQ_CLSTR(i, new_desc_blk)) || 342 EQ_CLSTR(i, ext2fs_block_bitmap_loc(fs, group)) || 343 EQ_CLSTR(i, ext2fs_inode_bitmap_loc(fs, group)) || 344 (GE_CLSTR(i, ext2fs_inode_table_loc(fs, group)) && 345 LE_CLSTR(i, (ext2fs_inode_table_loc(fs, group) + 346 fs->inode_blocks_per_group - 1)))) { 347 bitmap = 1; 348 actual = (actual != 0); 349 count++; 350 cmp_block--; 351 } else if ((EXT2FS_B2C(fs, i) - count - 352 EXT2FS_B2C(fs, fs->super->s_first_data_block)) % 353 fs->super->s_clusters_per_group == 0) { 354 /* 355 * When the compare data blocks in block bitmap 356 * are 0, count the free block, 357 * skip the current block group. 358 */ 359 if (ext2fs_test_block_bitmap_range2( 360 ctx->block_found_map, 361 EXT2FS_B2C(fs, i), 362 cmp_block)) { 363 /* 364 * -1 means to skip the current block 365 * group. 366 */ 367 blocks = fs->super->s_clusters_per_group - 1; 368 group_free = cmp_block; 369 free_blocks += cmp_block; 370 /* 371 * The current block group's last block 372 * is set to i. 373 */ 374 i += EXT2FS_C2B(fs, cmp_block - 1); 375 bitmap = 1; 376 goto do_counts; 377 } 378 } 379 } else if (redo_flag) 380 bitmap = actual; 381 else 382 bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i); 383 384 if (!actual == !bitmap) 385 goto do_counts; 386 387 if (!actual && bitmap) { 388 /* 389 * Block not used, but marked in use in the bitmap. 390 */ 391 problem = PR_5_BLOCK_UNUSED; 392 } else { 393 /* 394 * Block used, but not marked in use in the bitmap. 395 */ 396 problem = PR_5_BLOCK_USED; 397 398 if (skip_group) { 399 struct problem_context pctx2; 400 pctx2.blk = i; 401 pctx2.group = group; 402 if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){ 403 ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); 404 skip_group = 0; 405 } 406 } 407 } 408 if (pctx.blk == NO_BLK) { 409 pctx.blk = pctx.blk2 = i; 410 save_problem = problem; 411 } else { 412 if ((problem == save_problem) && 413 (pctx.blk2 == i-1)) 414 pctx.blk2++; 415 else { 416 print_bitmap_problem(ctx, save_problem, &pctx); 417 pctx.blk = pctx.blk2 = i; 418 save_problem = problem; 419 } 420 } 421 ctx->flags |= E2F_FLAG_PROG_SUPPRESS; 422 had_problem++; 423 424 /* 425 * If there a problem we should turn off the discard so we 426 * do not compromise the filesystem. 427 */ 428 ctx->options &= ~E2F_OPT_DISCARD; 429 430 do_counts: 431 if (!bitmap) { 432 group_free++; 433 free_blocks++; 434 if (first_free > i) 435 first_free = i; 436 } else if (i > first_free) { 437 e2fsck_discard_blocks(ctx, first_free, 438 (i - first_free)); 439 first_free = ext2fs_blocks_count(fs->super); 440 } 441 blocks ++; 442 if ((blocks == fs->super->s_clusters_per_group) || 443 (EXT2FS_B2C(fs, i) == 444 EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) { 445 /* 446 * If the last block of this group is free, then we can 447 * discard it as well. 448 */ 449 if (!bitmap && i >= first_free) 450 e2fsck_discard_blocks(ctx, first_free, 451 (i - first_free) + 1); 452 next_group: 453 first_free = ext2fs_blocks_count(fs->super); 454 455 free_array[group] = group_free; 456 group ++; 457 blocks = 0; 458 group_free = 0; 459 skip_group = 0; 460 if (ctx->progress) 461 if ((ctx->progress)(ctx, 5, group, 462 fs->group_desc_count*2)) 463 goto errout; 464 if (csum_flag && 465 (i != ext2fs_blocks_count(fs->super)-1) && 466 ext2fs_bg_flags_test(fs, group, 467 EXT2_BG_BLOCK_UNINIT)) 468 skip_group++; 469 } 470 } 471 if (pctx.blk != NO_BLK) 472 print_bitmap_problem(ctx, save_problem, &pctx); 473 if (had_problem) 474 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP); 475 else 476 fixit = -1; 477 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; 478 479 if (fixit == 1) { 480 ext2fs_free_block_bitmap(fs->block_map); 481 retval = ext2fs_copy_bitmap(ctx->block_found_map, 482 &fs->block_map); 483 if (retval) { 484 clear_problem_context(&pctx); 485 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx); 486 ctx->flags |= E2F_FLAG_ABORT; 487 goto errout; 488 } 489 ext2fs_set_bitmap_padding(fs->block_map); 490 ext2fs_mark_bb_dirty(fs); 491 492 /* Redo the counts */ 493 blocks = 0; free_blocks = 0; group_free = 0; group = 0; 494 memset(free_array, 0, fs->group_desc_count * sizeof(int)); 495 redo_flag++; 496 goto redo_counts; 497 } else if (fixit == 0) 498 ext2fs_unmark_valid(fs); 499 500 for (i = 0; i < fs->group_desc_count; i++) { 501 if (free_array[i] != ext2fs_bg_free_blocks_count(fs, i)) { 502 pctx.group = i; 503 pctx.blk = ext2fs_bg_free_blocks_count(fs, i); 504 pctx.blk2 = free_array[i]; 505 506 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP, 507 &pctx)) { 508 ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]); 509 ext2fs_mark_super_dirty(fs); 510 } else 511 ext2fs_unmark_valid(fs); 512 } 513 } 514 free_blocks = EXT2FS_C2B(fs, free_blocks); 515 if (free_blocks != ext2fs_free_blocks_count(fs->super)) { 516 pctx.group = 0; 517 pctx.blk = ext2fs_free_blocks_count(fs->super); 518 pctx.blk2 = free_blocks; 519 520 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) { 521 ext2fs_free_blocks_count_set(fs->super, free_blocks); 522 ext2fs_mark_super_dirty(fs); 523 } 524 } 525errout: 526 ext2fs_free_mem(&free_array); 527 ext2fs_free_mem(&actual_buf); 528 ext2fs_free_mem(&bitmap_buf); 529} 530 531static void check_inode_bitmaps(e2fsck_t ctx) 532{ 533 ext2_filsys fs = ctx->fs; 534 ext2_ino_t i; 535 unsigned int free_inodes = 0; 536 int group_free = 0; 537 int dirs_count = 0; 538 int group = 0; 539 unsigned int inodes = 0; 540 ext2_ino_t *free_array; 541 ext2_ino_t *dir_array; 542 int actual, bitmap; 543 errcode_t retval; 544 struct problem_context pctx; 545 int problem, save_problem, fixit, had_problem; 546 int csum_flag; 547 int skip_group = 0; 548 int redo_flag = 0; 549 ext2_ino_t first_free = fs->super->s_inodes_per_group + 1; 550 551 clear_problem_context(&pctx); 552 free_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx, 553 fs->group_desc_count * sizeof(ext2_ino_t), "free inode count array"); 554 555 dir_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx, 556 fs->group_desc_count * sizeof(ext2_ino_t), "directory count array"); 557 558 if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) || 559 (fs->super->s_inodes_count > 560 ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) { 561 pctx.num = 3; 562 pctx.blk = 1; 563 pctx.blk2 = fs->super->s_inodes_count; 564 pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map); 565 pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map); 566 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); 567 568 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 569 goto errout; 570 } 571 if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) || 572 (fs->super->s_inodes_count > 573 ext2fs_get_inode_bitmap_end2(fs->inode_map))) { 574 pctx.num = 4; 575 pctx.blk = 1; 576 pctx.blk2 = fs->super->s_inodes_count; 577 pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map); 578 pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map); 579 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); 580 581 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 582 goto errout; 583 } 584 585 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 586 EXT4_FEATURE_RO_COMPAT_GDT_CSUM); 587redo_counts: 588 had_problem = 0; 589 save_problem = 0; 590 pctx.ino = pctx.ino2 = 0; 591 if (csum_flag && 592 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT))) 593 skip_group++; 594 595 /* Protect loop from wrap-around if inodes_count is maxed */ 596 for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) { 597 bitmap = 0; 598 if (skip_group && 599 i % fs->super->s_inodes_per_group == 1) { 600 /* 601 * Current inode is the first inode 602 * in the current block group. 603 */ 604 if (ext2fs_test_inode_bitmap_range( 605 ctx->inode_used_map, i, 606 fs->super->s_inodes_per_group)) { 607 /* 608 * When the compared inodes in inodes bitmap 609 * are 0, count the free inode, 610 * skip the current block group. 611 */ 612 first_free = 1; 613 inodes = fs->super->s_inodes_per_group - 1; 614 group_free = inodes; 615 free_inodes += inodes; 616 i += inodes; 617 skip_group = 0; 618 goto do_counts; 619 } 620 } 621 622 actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i); 623 if (redo_flag) 624 bitmap = actual; 625 else if (!skip_group) 626 bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i); 627 if (!actual == !bitmap) 628 goto do_counts; 629 630 if (!actual && bitmap) { 631 /* 632 * Inode wasn't used, but marked in bitmap 633 */ 634 problem = PR_5_INODE_UNUSED; 635 } else /* if (actual && !bitmap) */ { 636 /* 637 * Inode used, but not in bitmap 638 */ 639 problem = PR_5_INODE_USED; 640 641 /* We should never hit this, because it means that 642 * inodes were marked in use that weren't noticed 643 * in pass1 or pass 2. It is easier to fix the problem 644 * than to kill e2fsck and leave the user stuck. */ 645 if (skip_group) { 646 struct problem_context pctx2; 647 pctx2.blk = i; 648 pctx2.group = group; 649 if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){ 650 ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); 651 skip_group = 0; 652 } 653 } 654 } 655 if (pctx.ino == 0) { 656 pctx.ino = pctx.ino2 = i; 657 save_problem = problem; 658 } else { 659 if ((problem == save_problem) && 660 (pctx.ino2 == i-1)) 661 pctx.ino2++; 662 else { 663 print_bitmap_problem(ctx, save_problem, &pctx); 664 pctx.ino = pctx.ino2 = i; 665 save_problem = problem; 666 } 667 } 668 ctx->flags |= E2F_FLAG_PROG_SUPPRESS; 669 had_problem++; 670 /* 671 * If there a problem we should turn off the discard so we 672 * do not compromise the filesystem. 673 */ 674 ctx->options &= ~E2F_OPT_DISCARD; 675 676do_counts: 677 inodes++; 678 if (bitmap) { 679 if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i)) 680 dirs_count++; 681 if (inodes > first_free) { 682 e2fsck_discard_inodes(ctx, group, first_free, 683 inodes - first_free); 684 first_free = fs->super->s_inodes_per_group + 1; 685 } 686 } else { 687 group_free++; 688 free_inodes++; 689 if (first_free > inodes) 690 first_free = inodes; 691 } 692 693 if ((inodes == fs->super->s_inodes_per_group) || 694 (i == fs->super->s_inodes_count)) { 695 /* 696 * If the last inode is free, we can discard it as well. 697 */ 698 if (!bitmap && inodes >= first_free) 699 e2fsck_discard_inodes(ctx, group, first_free, 700 inodes - first_free + 1); 701 /* 702 * If discard zeroes data and the group inode table 703 * was not zeroed yet, set itable as zeroed 704 */ 705 if ((ctx->options & E2F_OPT_DISCARD) && 706 io_channel_discard_zeroes_data(fs->io) && 707 !(ext2fs_bg_flags_test(fs, group, 708 EXT2_BG_INODE_ZEROED))) { 709 ext2fs_bg_flags_set(fs, group, 710 EXT2_BG_INODE_ZEROED); 711 ext2fs_group_desc_csum_set(fs, group); 712 } 713 714 first_free = fs->super->s_inodes_per_group + 1; 715 free_array[group] = group_free; 716 dir_array[group] = dirs_count; 717 group ++; 718 inodes = 0; 719 skip_group = 0; 720 group_free = 0; 721 dirs_count = 0; 722 if (ctx->progress) 723 if ((ctx->progress)(ctx, 5, 724 group + fs->group_desc_count, 725 fs->group_desc_count*2)) 726 goto errout; 727 if (csum_flag && 728 (i != fs->super->s_inodes_count) && 729 (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT) 730 )) 731 skip_group++; 732 } 733 } 734 if (pctx.ino) 735 print_bitmap_problem(ctx, save_problem, &pctx); 736 737 if (had_problem) 738 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP); 739 else 740 fixit = -1; 741 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; 742 743 if (fixit == 1) { 744 ext2fs_free_inode_bitmap(fs->inode_map); 745 retval = ext2fs_copy_bitmap(ctx->inode_used_map, 746 &fs->inode_map); 747 if (retval) { 748 clear_problem_context(&pctx); 749 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx); 750 ctx->flags |= E2F_FLAG_ABORT; 751 goto errout; 752 } 753 ext2fs_set_bitmap_padding(fs->inode_map); 754 ext2fs_mark_ib_dirty(fs); 755 756 /* redo counts */ 757 inodes = 0; free_inodes = 0; group_free = 0; 758 dirs_count = 0; group = 0; 759 memset(free_array, 0, fs->group_desc_count * sizeof(int)); 760 memset(dir_array, 0, fs->group_desc_count * sizeof(int)); 761 redo_flag++; 762 goto redo_counts; 763 } else if (fixit == 0) 764 ext2fs_unmark_valid(fs); 765 766 for (i = 0; i < fs->group_desc_count; i++) { 767 if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) { 768 pctx.group = i; 769 pctx.ino = ext2fs_bg_free_inodes_count(fs, i); 770 pctx.ino2 = free_array[i]; 771 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP, 772 &pctx)) { 773 ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]); 774 ext2fs_mark_super_dirty(fs); 775 } else 776 ext2fs_unmark_valid(fs); 777 } 778 if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) { 779 pctx.group = i; 780 pctx.ino = ext2fs_bg_used_dirs_count(fs, i); 781 pctx.ino2 = dir_array[i]; 782 783 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP, 784 &pctx)) { 785 ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]); 786 ext2fs_mark_super_dirty(fs); 787 } else 788 ext2fs_unmark_valid(fs); 789 } 790 } 791 if (free_inodes != fs->super->s_free_inodes_count) { 792 pctx.group = -1; 793 pctx.ino = fs->super->s_free_inodes_count; 794 pctx.ino2 = free_inodes; 795 796 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) { 797 fs->super->s_free_inodes_count = free_inodes; 798 ext2fs_mark_super_dirty(fs); 799 } 800 } 801errout: 802 ext2fs_free_mem(&free_array); 803 ext2fs_free_mem(&dir_array); 804} 805 806static void check_inode_end(e2fsck_t ctx) 807{ 808 ext2_filsys fs = ctx->fs; 809 ext2_ino_t end, save_inodes_count, i; 810 struct problem_context pctx; 811 812 clear_problem_context(&pctx); 813 814 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count; 815 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end, 816 &save_inodes_count); 817 if (pctx.errcode) { 818 pctx.num = 1; 819 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); 820 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 821 return; 822 } 823 if (save_inodes_count == end) 824 return; 825 826 /* protect loop from wrap-around if end is maxed */ 827 for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) { 828 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) { 829 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) { 830 for (; i <= end; i++) 831 ext2fs_mark_inode_bitmap(fs->inode_map, 832 i); 833 ext2fs_mark_ib_dirty(fs); 834 } else 835 ext2fs_unmark_valid(fs); 836 break; 837 } 838 } 839 840 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, 841 save_inodes_count, 0); 842 if (pctx.errcode) { 843 pctx.num = 2; 844 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); 845 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 846 return; 847 } 848} 849 850static void check_block_end(e2fsck_t ctx) 851{ 852 ext2_filsys fs = ctx->fs; 853 blk64_t end, save_blocks_count, i; 854 struct problem_context pctx; 855 856 clear_problem_context(&pctx); 857 858 end = ext2fs_get_block_bitmap_start2(fs->block_map) + 859 ((blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count) - 1; 860 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end, 861 &save_blocks_count); 862 if (pctx.errcode) { 863 pctx.num = 3; 864 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); 865 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 866 return; 867 } 868 if (save_blocks_count == end) 869 return; 870 871 /* Protect loop from wrap-around if end is maxed */ 872 for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) { 873 if (!ext2fs_test_block_bitmap2(fs->block_map, 874 EXT2FS_C2B(fs, i))) { 875 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) { 876 for (; i <= end; i++) 877 ext2fs_mark_block_bitmap2(fs->block_map, 878 EXT2FS_C2B(fs, i)); 879 ext2fs_mark_bb_dirty(fs); 880 } else 881 ext2fs_unmark_valid(fs); 882 break; 883 } 884 } 885 886 pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, 887 save_blocks_count, 0); 888 if (pctx.errcode) { 889 pctx.num = 4; 890 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); 891 ctx->flags |= E2F_FLAG_ABORT; /* fatal */ 892 return; 893 } 894} 895 896 897 898