super.c revision c3ffaf833b7ddb3c1d422c71f59e1623029ede0c
1/* 2 * e2fsck.c - superblock checks 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#ifdef HAVE_ERRNO_H 13#include <errno.h> 14#endif 15 16#ifndef EXT2_SKIP_UUID 17#include "uuid/uuid.h" 18#endif 19#include "e2fsck.h" 20#include "problem.h" 21 22#define MIN_CHECK 1 23#define MAX_CHECK 2 24 25static void check_super_value(e2fsck_t ctx, const char *descr, 26 unsigned long value, int flags, 27 unsigned long min_val, unsigned long max_val) 28{ 29 struct problem_context pctx; 30 31 if (((flags & MIN_CHECK) && (value < min_val)) || 32 ((flags & MAX_CHECK) && (value > max_val))) { 33 clear_problem_context(&pctx); 34 pctx.num = value; 35 pctx.str = descr; 36 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx); 37 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */ 38 } 39} 40 41/* 42 * This routine may get stubbed out in special compilations of the 43 * e2fsck code.. 44 */ 45#ifndef EXT2_SPECIAL_DEVICE_SIZE 46errcode_t e2fsck_get_device_size(e2fsck_t ctx) 47{ 48 return (ext2fs_get_device_size(ctx->filesystem_name, 49 EXT2_BLOCK_SIZE(ctx->fs->super), 50 &ctx->num_blocks)); 51} 52#endif 53 54/* 55 * helper function to release an inode 56 */ 57struct process_block_struct { 58 e2fsck_t ctx; 59 char *buf; 60 struct problem_context *pctx; 61 int truncating; 62 int truncate_offset; 63 e2_blkcnt_t truncate_block; 64 int truncated_blocks; 65 int abort; 66 errcode_t errcode; 67}; 68 69static int release_inode_block(ext2_filsys fs, 70 blk_t *block_nr, 71 e2_blkcnt_t blockcnt, 72 blk_t ref_blk EXT2FS_ATTR((unused)), 73 int ref_offset EXT2FS_ATTR((unused)), 74 void *priv_data) 75{ 76 struct process_block_struct *pb; 77 e2fsck_t ctx; 78 struct problem_context *pctx; 79 blk_t blk = *block_nr; 80 int retval = 0; 81 82 pb = (struct process_block_struct *) priv_data; 83 ctx = pb->ctx; 84 pctx = pb->pctx; 85 86 pctx->blk = blk; 87 pctx->blkcount = blockcnt; 88 89 if (HOLE_BLKADDR(blk)) 90 return 0; 91 92 if ((blk < fs->super->s_first_data_block) || 93 (blk >= fs->super->s_blocks_count)) { 94 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx); 95 return_abort: 96 pb->abort = 1; 97 return BLOCK_ABORT; 98 } 99 100 if (!ext2fs_test_block_bitmap(fs->block_map, blk)) { 101 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx); 102 goto return_abort; 103 } 104 105 /* 106 * If we are deleting an orphan, then we leave the fields alone. 107 * If we are truncating an orphan, then update the inode fields 108 * and clean up any partial block data. 109 */ 110 if (pb->truncating) { 111 /* 112 * We only remove indirect blocks if they are 113 * completely empty. 114 */ 115 if (blockcnt < 0) { 116 int i, limit; 117 blk_t *bp; 118 119 pb->errcode = io_channel_read_blk(fs->io, blk, 1, 120 pb->buf); 121 if (pb->errcode) 122 goto return_abort; 123 124 limit = fs->blocksize >> 2; 125 for (i = 0, bp = (blk_t *) pb->buf; 126 i < limit; i++, bp++) 127 if (*bp) 128 return 0; 129 } 130 /* 131 * We don't remove direct blocks until we've reached 132 * the truncation block. 133 */ 134 if (blockcnt >= 0 && blockcnt < pb->truncate_block) 135 return 0; 136 /* 137 * If part of the last block needs truncating, we do 138 * it here. 139 */ 140 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) { 141 pb->errcode = io_channel_read_blk(fs->io, blk, 1, 142 pb->buf); 143 if (pb->errcode) 144 goto return_abort; 145 memset(pb->buf + pb->truncate_offset, 0, 146 fs->blocksize - pb->truncate_offset); 147 pb->errcode = io_channel_write_blk(fs->io, blk, 1, 148 pb->buf); 149 if (pb->errcode) 150 goto return_abort; 151 } 152 pb->truncated_blocks++; 153 *block_nr = 0; 154 retval |= BLOCK_CHANGED; 155 } 156 157 ext2fs_block_alloc_stats(fs, blk, -1); 158 return retval; 159} 160 161/* 162 * This function releases an inode. Returns 1 if an inconsistency was 163 * found. If the inode has a link count, then it is being truncated and 164 * not deleted. 165 */ 166static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, 167 struct ext2_inode *inode, char *block_buf, 168 struct problem_context *pctx) 169{ 170 struct process_block_struct pb; 171 ext2_filsys fs = ctx->fs; 172 errcode_t retval; 173 __u32 count; 174 175 if (!ext2fs_inode_has_valid_blocks(inode)) 176 return 0; 177 178 pb.buf = block_buf + 3 * ctx->fs->blocksize; 179 pb.ctx = ctx; 180 pb.abort = 0; 181 pb.errcode = 0; 182 pb.pctx = pctx; 183 if (inode->i_links_count) { 184 pb.truncating = 1; 185 pb.truncate_block = (e2_blkcnt_t) 186 ((((long long)inode->i_size_high << 32) + 187 inode->i_size + fs->blocksize - 1) / 188 fs->blocksize); 189 pb.truncate_offset = inode->i_size % fs->blocksize; 190 } else { 191 pb.truncating = 0; 192 pb.truncate_block = 0; 193 pb.truncate_offset = 0; 194 } 195 pb.truncated_blocks = 0; 196 retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE, 197 block_buf, release_inode_block, &pb); 198 if (retval) { 199 com_err("release_inode_blocks", retval, 200 _("while calling ext2fs_block_iterate for inode %d"), 201 ino); 202 return 1; 203 } 204 if (pb.abort) 205 return 1; 206 207 /* Refresh the inode since ext2fs_block_iterate may have changed it */ 208 e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks"); 209 210 if (pb.truncated_blocks) 211 inode->i_blocks -= pb.truncated_blocks * 212 (fs->blocksize / 512); 213 214 if (inode->i_file_acl) { 215 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl, 216 block_buf, -1, &count); 217 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) { 218 retval = 0; 219 count = 1; 220 } 221 if (retval) { 222 com_err("release_inode_blocks", retval, 223 _("while calling ext2fs_adjust_ea_refocunt for inode %d"), 224 ino); 225 return 1; 226 } 227 if (count == 0) 228 ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1); 229 inode->i_file_acl = 0; 230 } 231 return 0; 232} 233 234/* 235 * This function releases all of the orphan inodes. It returns 1 if 236 * it hit some error, and 0 on success. 237 */ 238static int release_orphan_inodes(e2fsck_t ctx) 239{ 240 ext2_filsys fs = ctx->fs; 241 ext2_ino_t ino, next_ino; 242 struct ext2_inode inode; 243 struct problem_context pctx; 244 char *block_buf; 245 246 if ((ino = fs->super->s_last_orphan) == 0) 247 return 0; 248 249 /* 250 * Win or lose, we won't be using the head of the orphan inode 251 * list again. 252 */ 253 fs->super->s_last_orphan = 0; 254 ext2fs_mark_super_dirty(fs); 255 256 /* 257 * If the filesystem contains errors, don't run the orphan 258 * list, since the orphan list can't be trusted; and we're 259 * going to be running a full e2fsck run anyway... 260 */ 261 if (fs->super->s_state & EXT2_ERROR_FS) 262 return 0; 263 264 if ((ino < EXT2_FIRST_INODE(fs->super)) || 265 (ino > fs->super->s_inodes_count)) { 266 clear_problem_context(&pctx); 267 pctx.ino = ino; 268 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx); 269 return 1; 270 } 271 272 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4, 273 "block iterate buffer"); 274 e2fsck_read_bitmaps(ctx); 275 276 while (ino) { 277 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes"); 278 clear_problem_context(&pctx); 279 pctx.ino = ino; 280 pctx.inode = &inode; 281 pctx.str = inode.i_links_count ? _("Truncating") : 282 _("Clearing"); 283 284 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx); 285 286 next_ino = inode.i_dtime; 287 if (next_ino && 288 ((next_ino < EXT2_FIRST_INODE(fs->super)) || 289 (next_ino > fs->super->s_inodes_count))) { 290 pctx.ino = next_ino; 291 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx); 292 goto return_abort; 293 } 294 295 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx)) 296 goto return_abort; 297 298 if (!inode.i_links_count) { 299 ext2fs_inode_alloc_stats2(fs, ino, -1, 300 LINUX_S_ISDIR(inode.i_mode)); 301 inode.i_dtime = time(0); 302 } else { 303 inode.i_dtime = 0; 304 } 305 e2fsck_write_inode(ctx, ino, &inode, "delete_file"); 306 ino = next_ino; 307 } 308 ext2fs_free_mem(&block_buf); 309 return 0; 310return_abort: 311 ext2fs_free_mem(&block_buf); 312 return 1; 313} 314 315/* 316 * Check the resize inode to make sure it is sane. We check both for 317 * the case where on-line resizing is not enabled (in which case the 318 * resize inode should be cleared) as well as the case where on-line 319 * resizing is enabled. 320 */ 321void check_resize_inode(e2fsck_t ctx) 322{ 323 ext2_filsys fs = ctx->fs; 324 struct ext2_inode inode; 325 struct problem_context pctx; 326 int i, j, gdt_off, ind_off; 327 blk_t blk, pblk, expect; 328 __u32 *dind_buf = 0, *ind_buf; 329 errcode_t retval; 330 331 clear_problem_context(&pctx); 332 pctx.ino = EXT2_RESIZE_INO; 333 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); 334 if (retval) { 335 ctx->flags |= E2F_FLAG_RESIZE_INODE; 336 return; 337 } 338 339 /* 340 * If the resize inode feature isn't set, then 341 * s_reserved_gdt_blocks must be zero, and the resize inode 342 * must be cleared. 343 */ 344 if (!(fs->super->s_feature_compat & 345 EXT2_FEATURE_COMPAT_RESIZE_INODE)) { 346 if (fs->super->s_reserved_gdt_blocks) { 347 pctx.num = fs->super->s_reserved_gdt_blocks; 348 if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS, 349 &pctx)) { 350 fs->super->s_reserved_gdt_blocks = 0; 351 ext2fs_mark_super_dirty(fs); 352 } 353 } 354 for (i=0; i < EXT2_N_BLOCKS; i++) { 355 if (inode.i_block[i]) 356 break; 357 } 358 if ((i < EXT2_N_BLOCKS) && 359 fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) { 360 memset(&inode, 0, sizeof(inode)); 361 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode, 362 "clear_resize"); 363 } 364 return; 365 } 366 /* 367 * The resize inode feature is enabled; check to make sure the 368 * only block in use is the double indirect block 369 */ 370 blk = inode.i_block[EXT2_DIND_BLOCK]; 371 for (i=0; i < EXT2_N_BLOCKS; i++) { 372 if (i != EXT2_DIND_BLOCK && inode.i_block[i]) 373 break; 374 } 375 if ((i < EXT2_N_BLOCKS) || !blk || 376 (blk < fs->super->s_first_data_block || 377 blk >= fs->super->s_blocks_count)) { 378 resize_inode_invalid: 379 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) { 380 memset(&inode, 0, sizeof(inode)); 381 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode, 382 "clear_resize"); 383 ctx->flags |= E2F_FLAG_RESIZE_INODE; 384 } 385 if (!(ctx->options & E2F_OPT_READONLY)) { 386 fs->super->s_state &= ~EXT2_VALID_FS; 387 ext2fs_mark_super_dirty(fs); 388 } 389 goto cleanup; 390 } 391 dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2, 392 "resize dind buffer"); 393 ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize); 394 395 retval = io_channel_read_blk(fs->io, blk, 1, dind_buf); 396 if (retval) 397 goto resize_inode_invalid; 398 399 gdt_off = fs->desc_blocks; 400 pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks; 401 for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4; 402 i++, gdt_off++, pblk++) { 403 gdt_off %= fs->blocksize/4; 404 if (dind_buf[gdt_off] != pblk) 405 goto resize_inode_invalid; 406 retval = io_channel_read_blk(fs->io, pblk, 1, ind_buf); 407 if (retval) 408 goto resize_inode_invalid; 409 ind_off = 0; 410 for (j = 1; j < fs->group_desc_count; j++) { 411 if (!ext2fs_bg_has_super(fs, j)) 412 continue; 413 expect = pblk + (j * fs->super->s_blocks_per_group); 414 if (ind_buf[ind_off] != expect) 415 goto resize_inode_invalid; 416 ind_off++; 417 } 418 } 419 420cleanup: 421 if (dind_buf) 422 ext2fs_free_mem(&dind_buf); 423 424 } 425 426void check_super_block(e2fsck_t ctx) 427{ 428 ext2_filsys fs = ctx->fs; 429 blk_t first_block, last_block; 430 struct ext2_super_block *sb = fs->super; 431 blk_t blocks_per_group = fs->super->s_blocks_per_group; 432 blk_t bpg_max; 433 int inodes_per_block; 434 int ipg_max; 435 dgrp_t i; 436 blk_t should_be; 437 struct problem_context pctx; 438 __u32 free_blocks = 0, free_inodes = 0; 439 440 inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super); 441 ipg_max = inodes_per_block * (blocks_per_group - 4); 442 if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb)) 443 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb); 444 bpg_max = 8 * EXT2_BLOCK_SIZE(sb); 445 if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb)) 446 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb); 447 448 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx, 449 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap"); 450 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx, 451 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap"); 452 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx, 453 sizeof(int) * fs->group_desc_count, "invalid_inode_table"); 454 455 clear_problem_context(&pctx); 456 457 /* 458 * Verify the super block constants... 459 */ 460 check_super_value(ctx, "inodes_count", sb->s_inodes_count, 461 MIN_CHECK, 1, 0); 462 check_super_value(ctx, "blocks_count", sb->s_blocks_count, 463 MIN_CHECK, 1, 0); 464 check_super_value(ctx, "first_data_block", sb->s_first_data_block, 465 MAX_CHECK, 0, sb->s_blocks_count); 466 check_super_value(ctx, "log_block_size", sb->s_log_block_size, 467 MIN_CHECK | MAX_CHECK, 0, 468 EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE); 469 check_super_value(ctx, "log_frag_size", sb->s_log_frag_size, 470 MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size); 471 check_super_value(ctx, "frags_per_group", sb->s_frags_per_group, 472 MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group, 473 bpg_max); 474 check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group, 475 MIN_CHECK | MAX_CHECK, 8, bpg_max); 476 check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group, 477 MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max); 478 check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count, 479 MAX_CHECK, 0, sb->s_blocks_count / 4); 480 check_super_value(ctx, "reserved_gdt_blocks", 481 sb->s_reserved_gdt_blocks, MAX_CHECK, 0, 482 fs->blocksize/4); 483 484 if (!ctx->num_blocks) { 485 pctx.errcode = e2fsck_get_device_size(ctx); 486 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) { 487 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx); 488 ctx->flags |= E2F_FLAG_ABORT; 489 return; 490 } 491 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) && 492 (ctx->num_blocks < sb->s_blocks_count)) { 493 pctx.blk = sb->s_blocks_count; 494 pctx.blk2 = ctx->num_blocks; 495 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) { 496 ctx->flags |= E2F_FLAG_ABORT; 497 return; 498 } 499 } 500 } 501 502 if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) { 503 pctx.blk = EXT2_BLOCK_SIZE(sb); 504 pctx.blk2 = EXT2_FRAG_SIZE(sb); 505 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx); 506 ctx->flags |= E2F_FLAG_ABORT; 507 return; 508 } 509 510 should_be = sb->s_frags_per_group >> 511 (sb->s_log_block_size - sb->s_log_frag_size); 512 if (sb->s_blocks_per_group != should_be) { 513 pctx.blk = sb->s_blocks_per_group; 514 pctx.blk2 = should_be; 515 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx); 516 ctx->flags |= E2F_FLAG_ABORT; 517 return; 518 } 519 520 should_be = (sb->s_log_block_size == 0) ? 1 : 0; 521 if (sb->s_first_data_block != should_be) { 522 pctx.blk = sb->s_first_data_block; 523 pctx.blk2 = should_be; 524 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx); 525 ctx->flags |= E2F_FLAG_ABORT; 526 return; 527 } 528 529 should_be = sb->s_inodes_per_group * fs->group_desc_count; 530 if (sb->s_inodes_count != should_be) { 531 pctx.ino = sb->s_inodes_count; 532 pctx.ino2 = should_be; 533 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) { 534 sb->s_inodes_count = should_be; 535 ext2fs_mark_super_dirty(fs); 536 } 537 } 538 539 /* 540 * Verify the group descriptors.... 541 */ 542 first_block = fs->super->s_first_data_block; 543 last_block = first_block + blocks_per_group; 544 545 for (i = 0; i < fs->group_desc_count; i++) { 546 pctx.group = i; 547 548 if (i == fs->group_desc_count - 1) 549 last_block = fs->super->s_blocks_count; 550 if ((fs->group_desc[i].bg_block_bitmap < first_block) || 551 (fs->group_desc[i].bg_block_bitmap >= last_block)) { 552 pctx.blk = fs->group_desc[i].bg_block_bitmap; 553 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx)) 554 fs->group_desc[i].bg_block_bitmap = 0; 555 } 556 if (fs->group_desc[i].bg_block_bitmap == 0) { 557 ctx->invalid_block_bitmap_flag[i]++; 558 ctx->invalid_bitmaps++; 559 } 560 if ((fs->group_desc[i].bg_inode_bitmap < first_block) || 561 (fs->group_desc[i].bg_inode_bitmap >= last_block)) { 562 pctx.blk = fs->group_desc[i].bg_inode_bitmap; 563 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx)) 564 fs->group_desc[i].bg_inode_bitmap = 0; 565 } 566 if (fs->group_desc[i].bg_inode_bitmap == 0) { 567 ctx->invalid_inode_bitmap_flag[i]++; 568 ctx->invalid_bitmaps++; 569 } 570 if ((fs->group_desc[i].bg_inode_table < first_block) || 571 ((fs->group_desc[i].bg_inode_table + 572 fs->inode_blocks_per_group - 1) >= last_block)) { 573 pctx.blk = fs->group_desc[i].bg_inode_table; 574 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx)) 575 fs->group_desc[i].bg_inode_table = 0; 576 } 577 if (fs->group_desc[i].bg_inode_table == 0) { 578 ctx->invalid_inode_table_flag[i]++; 579 ctx->invalid_bitmaps++; 580 } 581 free_blocks += fs->group_desc[i].bg_free_blocks_count; 582 free_inodes += fs->group_desc[i].bg_free_inodes_count; 583 first_block += fs->super->s_blocks_per_group; 584 last_block += fs->super->s_blocks_per_group; 585 } 586 /* 587 * If we have invalid bitmaps, set the error state of the 588 * filesystem. 589 */ 590 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) { 591 fs->super->s_state &= ~EXT2_VALID_FS; 592 ext2fs_mark_super_dirty(fs); 593 } 594 595 clear_problem_context(&pctx); 596 597#ifndef EXT2_SKIP_UUID 598 /* 599 * If the UUID field isn't assigned, assign it. 600 */ 601 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) { 602 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) { 603 uuid_generate(sb->s_uuid); 604 ext2fs_mark_super_dirty(fs); 605 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 606 } 607 } 608#endif 609 610 /* 611 * Update the global counts from the block group counts. This 612 * is needed for an experimental patch which eliminates 613 * locking the entire filesystem when allocating blocks or 614 * inodes; if the filesystem is not unmounted cleanly, the 615 * global counts may not be accurate. 616 */ 617 if (!(ctx->options & E2F_OPT_READONLY) && 618 ((free_blocks != fs->super->s_free_blocks_count) || 619 (free_inodes != fs->super->s_free_inodes_count))) { 620 fs->super->s_free_blocks_count = free_blocks; 621 fs->super->s_free_inodes_count = free_inodes; 622 ext2fs_mark_super_dirty(fs); 623 } 624 625 /* 626 * For the Hurd, check to see if the filetype option is set, 627 * since it doesn't support it. 628 */ 629 if (!(ctx->options & E2F_OPT_READONLY) && 630 fs->super->s_creator_os == EXT2_OS_HURD && 631 (fs->super->s_feature_incompat & 632 EXT2_FEATURE_INCOMPAT_FILETYPE)) { 633 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) { 634 fs->super->s_feature_incompat &= 635 ~EXT2_FEATURE_INCOMPAT_FILETYPE; 636 ext2fs_mark_super_dirty(fs); 637 638 } 639 } 640 641 /* 642 * If we have any of the compatibility flags set, we need to have a 643 * revision 1 filesystem. Most kernels will not check the flags on 644 * a rev 0 filesystem and we may have corruption issues because of 645 * the incompatible changes to the filesystem. 646 */ 647 if (!(ctx->options & E2F_OPT_READONLY) && 648 fs->super->s_rev_level == EXT2_GOOD_OLD_REV && 649 (fs->super->s_feature_compat || 650 fs->super->s_feature_ro_compat || 651 fs->super->s_feature_incompat) && 652 fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) { 653 ext2fs_update_dynamic_rev(fs); 654 ext2fs_mark_super_dirty(fs); 655 } 656 657 check_resize_inode(ctx); 658 659 /* 660 * Clean up any orphan inodes, if present. 661 */ 662 if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) { 663 fs->super->s_state &= ~EXT2_VALID_FS; 664 ext2fs_mark_super_dirty(fs); 665 } 666 667 /* 668 * Move the ext3 journal file, if necessary. 669 */ 670 e2fsck_move_ext3_journal(ctx); 671 return; 672} 673