1 /* 2 * journal.c --- code for handling the "ext3" journal 3 * 4 * Copyright (C) 2000 Andreas Dilger 5 * Copyright (C) 2000 Theodore Ts'o 6 * 7 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie 8 * Copyright (C) 1999 Red Hat Software 9 * 10 * This file may be redistributed under the terms of the 11 * GNU General Public License version 2 or at your discretion 12 * any later version. 13 */ 14 15 #include "config.h" 16 #ifdef HAVE_SYS_MOUNT_H 17 #include <sys/param.h> 18 #include <sys/mount.h> 19 #define MNT_FL (MS_MGC_VAL | MS_RDONLY) 20 #endif 21 #ifdef HAVE_SYS_STAT_H 22 #include <sys/stat.h> 23 #endif 24 25 #define E2FSCK_INCLUDE_INLINE_FUNCS 26 #include "uuid/uuid.h" 27 #include "journal.h" 28 29 #ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jfs-debug */ 30 static int bh_count = 0; 31 #endif 32 33 #if EXT2_FLAT_INCLUDES 34 #include "blkid.h" 35 #else 36 #include "blkid/blkid.h" 37 #endif 38 39 /* 40 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths. 41 * This creates a larger static binary, and a smaller binary using 42 * shared libraries. It's also probably slightly less CPU-efficient, 43 * which is why it's not on by default. But, it's a good way of 44 * testing the functions in inode_io.c and fileio.c. 45 */ 46 #undef USE_INODE_IO 47 48 /* Checksumming functions */ 49 static int ext2fs_journal_verify_csum_type(journal_t *j, 50 journal_superblock_t *jsb) 51 { 52 if (!journal_has_csum_v2or3(j)) 53 return 1; 54 55 return jsb->s_checksum_type == JBD2_CRC32C_CHKSUM; 56 } 57 58 static __u32 ext2fs_journal_sb_csum(journal_superblock_t *jsb) 59 { 60 __u32 crc, old_crc; 61 62 old_crc = jsb->s_checksum; 63 jsb->s_checksum = 0; 64 crc = ext2fs_crc32c_le(~0, (unsigned char *)jsb, 65 sizeof(journal_superblock_t)); 66 jsb->s_checksum = old_crc; 67 68 return crc; 69 } 70 71 static int ext2fs_journal_sb_csum_verify(journal_t *j, 72 journal_superblock_t *jsb) 73 { 74 __u32 provided, calculated; 75 76 if (!journal_has_csum_v2or3(j)) 77 return 1; 78 79 provided = ext2fs_be32_to_cpu(jsb->s_checksum); 80 calculated = ext2fs_journal_sb_csum(jsb); 81 82 return provided == calculated; 83 } 84 85 static errcode_t ext2fs_journal_sb_csum_set(journal_t *j, 86 journal_superblock_t *jsb) 87 { 88 __u32 crc; 89 90 if (!journal_has_csum_v2or3(j)) 91 return 0; 92 93 crc = ext2fs_journal_sb_csum(jsb); 94 jsb->s_checksum = ext2fs_cpu_to_be32(crc); 95 return 0; 96 } 97 98 /* Kernel compatibility functions for handling the journal. These allow us 99 * to use the recovery.c file virtually unchanged from the kernel, so we 100 * don't have to do much to keep kernel and user recovery in sync. 101 */ 102 int journal_bmap(journal_t *journal, blk64_t block, unsigned long long *phys) 103 { 104 #ifdef USE_INODE_IO 105 *phys = block; 106 return 0; 107 #else 108 struct inode *inode = journal->j_inode; 109 errcode_t retval; 110 blk64_t pblk; 111 112 if (!inode) { 113 *phys = block; 114 return 0; 115 } 116 117 retval = ext2fs_bmap2(inode->i_fs, inode->i_ino, 118 &inode->i_ext2, NULL, 0, block, 0, &pblk); 119 *phys = pblk; 120 return (int) retval; 121 #endif 122 } 123 124 struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize) 125 { 126 struct buffer_head *bh; 127 int bufsize = sizeof(*bh) + kdev->k_fs->blocksize - 128 sizeof(bh->b_data); 129 errcode_t retval; 130 131 retval = ext2fs_get_memzero(bufsize, &bh); 132 if (retval) 133 return NULL; 134 135 #ifdef CONFIG_JBD_DEBUG 136 if (journal_enable_debug >= 3) 137 bh_count++; 138 #endif 139 jfs_debug(4, "getblk for block %llu (%d bytes)(total %d)\n", 140 (unsigned long long) blocknr, blocksize, bh_count); 141 142 bh->b_fs = kdev->k_fs; 143 if (kdev->k_dev == K_DEV_FS) 144 bh->b_io = kdev->k_fs->io; 145 else 146 bh->b_io = kdev->k_fs->journal_io; 147 bh->b_size = blocksize; 148 bh->b_blocknr = blocknr; 149 150 return bh; 151 } 152 153 int sync_blockdev(kdev_t kdev) 154 { 155 io_channel io; 156 157 if (kdev->k_dev == K_DEV_FS) 158 io = kdev->k_fs->io; 159 else 160 io = kdev->k_fs->journal_io; 161 162 return io_channel_flush(io) ? EIO : 0; 163 } 164 165 void ll_rw_block(int rw, int nr, struct buffer_head *bhp[]) 166 { 167 errcode_t retval; 168 struct buffer_head *bh; 169 170 for (; nr > 0; --nr) { 171 bh = *bhp++; 172 if (rw == READ && !bh->b_uptodate) { 173 jfs_debug(3, "reading block %llu/%p\n", 174 bh->b_blocknr, (void *) bh); 175 retval = io_channel_read_blk64(bh->b_io, 176 bh->b_blocknr, 177 1, bh->b_data); 178 if (retval) { 179 com_err(bh->b_fs->device_name, retval, 180 "while reading block %llu\n", 181 bh->b_blocknr); 182 bh->b_err = (int) retval; 183 continue; 184 } 185 bh->b_uptodate = 1; 186 } else if (rw == WRITE && bh->b_dirty) { 187 jfs_debug(3, "writing block %llu/%p\n", 188 bh->b_blocknr, 189 (void *) bh); 190 retval = io_channel_write_blk64(bh->b_io, 191 bh->b_blocknr, 192 1, bh->b_data); 193 if (retval) { 194 com_err(bh->b_fs->device_name, retval, 195 "while writing block %llu\n", 196 bh->b_blocknr); 197 bh->b_err = (int) retval; 198 continue; 199 } 200 bh->b_dirty = 0; 201 bh->b_uptodate = 1; 202 } else { 203 jfs_debug(3, "no-op %s for block %llu\n", 204 rw == READ ? "read" : "write", 205 bh->b_blocknr); 206 } 207 } 208 } 209 210 void mark_buffer_dirty(struct buffer_head *bh) 211 { 212 bh->b_dirty = 1; 213 } 214 215 static void mark_buffer_clean(struct buffer_head *bh) 216 { 217 bh->b_dirty = 0; 218 } 219 220 void brelse(struct buffer_head *bh) 221 { 222 if (bh->b_dirty) 223 ll_rw_block(WRITE, 1, &bh); 224 jfs_debug(3, "freeing block %llu/%p (total %d)\n", 225 bh->b_blocknr, (void *) bh, --bh_count); 226 ext2fs_free_mem(&bh); 227 } 228 229 int buffer_uptodate(struct buffer_head *bh) 230 { 231 return bh->b_uptodate; 232 } 233 234 void mark_buffer_uptodate(struct buffer_head *bh, int val) 235 { 236 bh->b_uptodate = val; 237 } 238 239 void wait_on_buffer(struct buffer_head *bh) 240 { 241 if (!bh->b_uptodate) 242 ll_rw_block(READ, 1, &bh); 243 } 244 245 246 static void ext2fs_clear_recover(ext2_filsys fs, int error) 247 { 248 ext2fs_clear_feature_journal_needs_recovery(fs->super); 249 250 /* if we had an error doing journal recovery, we need a full fsck */ 251 if (error) 252 fs->super->s_state &= ~EXT2_VALID_FS; 253 ext2fs_mark_super_dirty(fs); 254 } 255 256 /* 257 * This is a helper function to check the validity of the journal. 258 */ 259 struct process_block_struct { 260 e2_blkcnt_t last_block; 261 }; 262 263 static int process_journal_block(ext2_filsys fs, 264 blk64_t *block_nr, 265 e2_blkcnt_t blockcnt, 266 blk64_t ref_block EXT2FS_ATTR((unused)), 267 int ref_offset EXT2FS_ATTR((unused)), 268 void *priv_data) 269 { 270 struct process_block_struct *p; 271 blk64_t blk = *block_nr; 272 273 p = (struct process_block_struct *) priv_data; 274 275 if (!blk || blk < fs->super->s_first_data_block || 276 blk >= ext2fs_blocks_count(fs->super)) 277 return BLOCK_ABORT; 278 279 if (blockcnt >= 0) 280 p->last_block = blockcnt; 281 return 0; 282 } 283 284 static errcode_t ext2fs_get_journal(ext2_filsys fs, journal_t **ret_journal) 285 { 286 struct process_block_struct pb; 287 struct ext2_super_block *sb = fs->super; 288 struct ext2_super_block jsuper; 289 struct buffer_head *bh; 290 struct inode *j_inode = NULL; 291 struct kdev_s *dev_fs = NULL, *dev_journal; 292 const char *journal_name = 0; 293 journal_t *journal = NULL; 294 errcode_t retval = 0; 295 io_manager io_ptr = 0; 296 unsigned long long start = 0; 297 int ext_journal = 0; 298 int tried_backup_jnl = 0; 299 300 retval = ext2fs_get_memzero(sizeof(journal_t), &journal); 301 if (retval) 302 return retval; 303 304 retval = ext2fs_get_memzero(2 * sizeof(struct kdev_s), &dev_fs); 305 if (retval) 306 goto errout; 307 dev_journal = dev_fs+1; 308 309 dev_fs->k_fs = dev_journal->k_fs = fs; 310 dev_fs->k_dev = K_DEV_FS; 311 dev_journal->k_dev = K_DEV_JOURNAL; 312 313 journal->j_dev = dev_journal; 314 journal->j_fs_dev = dev_fs; 315 journal->j_inode = NULL; 316 journal->j_blocksize = fs->blocksize; 317 318 if (uuid_is_null(sb->s_journal_uuid)) { 319 if (!sb->s_journal_inum) { 320 retval = EXT2_ET_BAD_INODE_NUM; 321 goto errout; 322 } 323 retval = ext2fs_get_memzero(sizeof(*j_inode), &j_inode); 324 if (retval) 325 goto errout; 326 327 j_inode->i_fs = fs; 328 j_inode->i_ino = sb->s_journal_inum; 329 330 retval = ext2fs_read_inode(fs, sb->s_journal_inum, 331 &j_inode->i_ext2); 332 if (retval) { 333 try_backup_journal: 334 if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS || 335 tried_backup_jnl) 336 goto errout; 337 memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode)); 338 memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks, 339 EXT2_N_BLOCKS*4); 340 j_inode->i_ext2.i_size_high = sb->s_jnl_blocks[15]; 341 j_inode->i_ext2.i_size = sb->s_jnl_blocks[16]; 342 j_inode->i_ext2.i_links_count = 1; 343 j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600; 344 tried_backup_jnl++; 345 } 346 if (!j_inode->i_ext2.i_links_count || 347 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) { 348 retval = EXT2_ET_NO_JOURNAL; 349 goto try_backup_journal; 350 } 351 if (EXT2_I_SIZE(&j_inode->i_ext2) / journal->j_blocksize < 352 JFS_MIN_JOURNAL_BLOCKS) { 353 retval = EXT2_ET_JOURNAL_TOO_SMALL; 354 goto try_backup_journal; 355 } 356 pb.last_block = -1; 357 retval = ext2fs_block_iterate3(fs, j_inode->i_ino, 358 BLOCK_FLAG_HOLE, 0, 359 process_journal_block, &pb); 360 if ((pb.last_block + 1) * fs->blocksize < 361 (int) EXT2_I_SIZE(&j_inode->i_ext2)) { 362 retval = EXT2_ET_JOURNAL_TOO_SMALL; 363 goto try_backup_journal; 364 } 365 if (tried_backup_jnl && (fs->flags & EXT2_FLAG_RW)) { 366 retval = ext2fs_write_inode(fs, sb->s_journal_inum, 367 &j_inode->i_ext2); 368 if (retval) 369 goto errout; 370 } 371 372 journal->j_maxlen = EXT2_I_SIZE(&j_inode->i_ext2) / 373 journal->j_blocksize; 374 375 #ifdef USE_INODE_IO 376 retval = ext2fs_inode_io_intern2(fs, sb->s_journal_inum, 377 &j_inode->i_ext2, 378 &journal_name); 379 if (retval) 380 goto errout; 381 382 io_ptr = inode_io_manager; 383 #else 384 journal->j_inode = j_inode; 385 fs->journal_io = fs->io; 386 retval = (errcode_t)journal_bmap(journal, 0, &start); 387 if (retval) 388 goto errout; 389 #endif 390 } else { 391 ext_journal = 1; 392 if (!fs->journal_name) { 393 char uuid[37]; 394 blkid_cache blkid; 395 396 blkid_get_cache(&blkid, NULL); 397 uuid_unparse(sb->s_journal_uuid, uuid); 398 fs->journal_name = blkid_get_devname(blkid, 399 "UUID", uuid); 400 if (!fs->journal_name) 401 fs->journal_name = blkid_devno_to_devname(sb->s_journal_dev); 402 blkid_put_cache(blkid); 403 } 404 journal_name = fs->journal_name; 405 406 if (!journal_name) { 407 retval = EXT2_ET_LOAD_EXT_JOURNAL; 408 goto errout; 409 } 410 411 jfs_debug(1, "Using journal file %s\n", journal_name); 412 io_ptr = unix_io_manager; 413 } 414 415 #if 0 416 test_io_backing_manager = io_ptr; 417 io_ptr = test_io_manager; 418 #endif 419 #ifndef USE_INODE_IO 420 if (ext_journal) 421 #endif 422 { 423 retval = io_ptr->open(journal_name, fs->flags & EXT2_FLAG_RW, 424 &fs->journal_io); 425 } 426 if (retval) 427 goto errout; 428 429 io_channel_set_blksize(fs->journal_io, fs->blocksize); 430 431 if (ext_journal) { 432 blk64_t maxlen; 433 434 start = ext2fs_journal_sb_start(fs->blocksize) - 1; 435 bh = getblk(dev_journal, start, fs->blocksize); 436 if (!bh) { 437 retval = EXT2_ET_NO_MEMORY; 438 goto errout; 439 } 440 ll_rw_block(READ, 1, &bh); 441 retval = bh->b_err; 442 if (retval) { 443 brelse(bh); 444 goto errout; 445 } 446 memcpy(&jsuper, start ? bh->b_data : 447 bh->b_data + SUPERBLOCK_OFFSET, 448 sizeof(jsuper)); 449 #ifdef WORDS_BIGENDIAN 450 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) 451 ext2fs_swap_super(&jsuper); 452 #endif 453 if (jsuper.s_magic != EXT2_SUPER_MAGIC || 454 !ext2fs_has_feature_journal_dev(&jsuper)) { 455 retval = EXT2_ET_LOAD_EXT_JOURNAL; 456 brelse(bh); 457 goto errout; 458 } 459 /* Make sure the journal UUID is correct */ 460 if (memcmp(jsuper.s_uuid, fs->super->s_journal_uuid, 461 sizeof(jsuper.s_uuid))) { 462 retval = EXT2_ET_LOAD_EXT_JOURNAL; 463 brelse(bh); 464 goto errout; 465 } 466 467 /* Check the superblock checksum */ 468 if (ext2fs_has_feature_metadata_csum(&jsuper)) { 469 struct struct_ext2_filsys fsx; 470 struct ext2_super_block superx; 471 void *p; 472 473 p = start ? bh->b_data : bh->b_data + SUPERBLOCK_OFFSET; 474 memcpy(&fsx, fs, sizeof(fsx)); 475 memcpy(&superx, fs->super, sizeof(superx)); 476 fsx.super = &superx; 477 ext2fs_set_feature_metadata_csum(fsx.super); 478 if (!ext2fs_superblock_csum_verify(&fsx, p)) { 479 retval = EXT2_ET_LOAD_EXT_JOURNAL; 480 brelse(bh); 481 goto errout; 482 } 483 } 484 brelse(bh); 485 486 maxlen = ext2fs_blocks_count(&jsuper); 487 journal->j_maxlen = (maxlen < 1ULL << 32) ? maxlen : 488 (1ULL << 32) - 1; 489 start++; 490 } 491 492 bh = getblk(dev_journal, start, journal->j_blocksize); 493 if (!bh) { 494 retval = EXT2_ET_NO_MEMORY; 495 goto errout; 496 } 497 498 journal->j_sb_buffer = bh; 499 journal->j_superblock = (journal_superblock_t *)bh->b_data; 500 501 #ifdef USE_INODE_IO 502 if (j_inode) 503 ext2fs_free_mem(&j_inode); 504 #endif 505 506 *ret_journal = journal; 507 return 0; 508 509 errout: 510 if (dev_fs) 511 ext2fs_free_mem(&dev_fs); 512 if (j_inode) 513 ext2fs_free_mem(&j_inode); 514 if (journal) 515 ext2fs_free_mem(&journal); 516 return retval; 517 } 518 519 static errcode_t ext2fs_journal_fix_bad_inode(ext2_filsys fs) 520 { 521 struct ext2_super_block *sb = fs->super; 522 int recover = ext2fs_has_feature_journal_needs_recovery(fs->super); 523 int has_journal = ext2fs_has_feature_journal(fs->super); 524 525 if (has_journal || sb->s_journal_inum) { 526 /* The journal inode is bogus, remove and force full fsck */ 527 return EXT2_ET_BAD_INODE_NUM; 528 } else if (recover) { 529 return EXT2_ET_UNSUPP_FEATURE; 530 } 531 return 0; 532 } 533 534 #define V1_SB_SIZE 0x0024 535 static void clear_v2_journal_fields(journal_t *journal) 536 { 537 ext2_filsys fs = journal->j_dev->k_fs; 538 539 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0, 540 fs->blocksize-V1_SB_SIZE); 541 mark_buffer_dirty(journal->j_sb_buffer); 542 } 543 544 545 static errcode_t ext2fs_journal_load(journal_t *journal) 546 { 547 ext2_filsys fs = journal->j_dev->k_fs; 548 journal_superblock_t *jsb; 549 struct buffer_head *jbh = journal->j_sb_buffer; 550 551 ll_rw_block(READ, 1, &jbh); 552 if (jbh->b_err) 553 return jbh->b_err; 554 555 jsb = journal->j_superblock; 556 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */ 557 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER)) 558 return ext2fs_journal_fix_bad_inode(fs); 559 560 switch (ntohl(jsb->s_header.h_blocktype)) { 561 case JFS_SUPERBLOCK_V1: 562 journal->j_format_version = 1; 563 if (jsb->s_feature_compat || 564 jsb->s_feature_incompat || 565 jsb->s_feature_ro_compat || 566 jsb->s_nr_users) 567 clear_v2_journal_fields(journal); 568 break; 569 570 case JFS_SUPERBLOCK_V2: 571 journal->j_format_version = 2; 572 if (ntohl(jsb->s_nr_users) > 1 && 573 uuid_is_null(fs->super->s_journal_uuid)) 574 clear_v2_journal_fields(journal); 575 if (ntohl(jsb->s_nr_users) > 1) 576 return EXT2_ET_JOURNAL_UNSUPP_VERSION; 577 break; 578 579 /* 580 * These should never appear in a journal super block, so if 581 * they do, the journal is badly corrupted. 582 */ 583 case JFS_DESCRIPTOR_BLOCK: 584 case JFS_COMMIT_BLOCK: 585 case JFS_REVOKE_BLOCK: 586 return EXT2_ET_CORRUPT_JOURNAL_SB; 587 588 /* If we don't understand the superblock major type, but there 589 * is a magic number, then it is likely to be a new format we 590 * just don't understand, so leave it alone. */ 591 default: 592 return EXT2_ET_JOURNAL_UNSUPP_VERSION; 593 } 594 595 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES)) 596 return EXT2_ET_UNSUPP_FEATURE; 597 598 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES)) 599 return EXT2_ET_RO_UNSUPP_FEATURE; 600 601 /* Checksum v1-3 are mutually exclusive features. */ 602 if (jfs_has_feature_csum2(journal) && jfs_has_feature_csum3(journal)) 603 return EXT2_ET_CORRUPT_JOURNAL_SB; 604 605 if (journal_has_csum_v2or3(journal) && 606 jfs_has_feature_checksum(journal)) 607 return EXT2_ET_CORRUPT_JOURNAL_SB; 608 609 if (!ext2fs_journal_verify_csum_type(journal, jsb) || 610 !ext2fs_journal_sb_csum_verify(journal, jsb)) 611 return EXT2_ET_CORRUPT_JOURNAL_SB; 612 613 if (journal_has_csum_v2or3(journal)) 614 journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid, 615 sizeof(jsb->s_uuid)); 616 617 /* We have now checked whether we know enough about the journal 618 * format to be able to proceed safely, so any other checks that 619 * fail we should attempt to recover from. */ 620 if (jsb->s_blocksize != htonl(journal->j_blocksize)) 621 return EXT2_ET_CORRUPT_JOURNAL_SB; 622 623 if (ntohl(jsb->s_maxlen) < journal->j_maxlen) 624 journal->j_maxlen = ntohl(jsb->s_maxlen); 625 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) 626 return EXT2_ET_CORRUPT_JOURNAL_SB; 627 628 journal->j_tail_sequence = ntohl(jsb->s_sequence); 629 journal->j_transaction_sequence = journal->j_tail_sequence; 630 journal->j_tail = ntohl(jsb->s_start); 631 journal->j_first = ntohl(jsb->s_first); 632 journal->j_last = ntohl(jsb->s_maxlen); 633 634 return 0; 635 } 636 637 static void ext2fs_journal_release(ext2_filsys fs, journal_t *journal, 638 int reset, int drop) 639 { 640 journal_superblock_t *jsb; 641 642 if (drop) 643 mark_buffer_clean(journal->j_sb_buffer); 644 else if (fs->flags & EXT2_FLAG_RW) { 645 jsb = journal->j_superblock; 646 jsb->s_sequence = htonl(journal->j_tail_sequence); 647 if (reset) 648 jsb->s_start = 0; /* this marks the journal as empty */ 649 ext2fs_journal_sb_csum_set(journal, jsb); 650 mark_buffer_dirty(journal->j_sb_buffer); 651 } 652 brelse(journal->j_sb_buffer); 653 654 if (fs && fs->journal_io) { 655 if (fs->io != fs->journal_io) 656 io_channel_close(fs->journal_io); 657 fs->journal_io = NULL; 658 } 659 660 #ifndef USE_INODE_IO 661 if (journal->j_inode) 662 ext2fs_free_mem(&journal->j_inode); 663 #endif 664 if (journal->j_fs_dev) 665 ext2fs_free_mem(&journal->j_fs_dev); 666 ext2fs_free_mem(&journal); 667 } 668 669 /* 670 * This function makes sure that the superblock fields regarding the 671 * journal are consistent. 672 */ 673 static errcode_t ext2fs_check_ext3_journal(ext2_filsys fs) 674 { 675 struct ext2_super_block *sb = fs->super; 676 journal_t *journal; 677 int recover = ext2fs_has_feature_journal_needs_recovery(fs->super); 678 errcode_t retval; 679 680 /* If we don't have any journal features, don't do anything more */ 681 if (!ext2fs_has_feature_journal(sb) && 682 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 && 683 uuid_is_null(sb->s_journal_uuid)) 684 return 0; 685 686 retval = ext2fs_get_journal(fs, &journal); 687 if (retval) 688 return retval; 689 690 retval = ext2fs_journal_load(journal); 691 if (retval) 692 goto err; 693 694 /* 695 * We want to make the flags consistent here. We will not leave with 696 * needs_recovery set but has_journal clear. We can't get in a loop 697 * with -y, -n, or -p, only if a user isn't making up their mind. 698 */ 699 if (!ext2fs_has_feature_journal(sb)) { 700 retval = EXT2_ET_JOURNAL_FLAGS_WRONG; 701 goto err; 702 } 703 704 if (ext2fs_has_feature_journal(sb) && 705 !ext2fs_has_feature_journal_needs_recovery(sb) && 706 journal->j_superblock->s_start != 0) { 707 retval = EXT2_ET_JOURNAL_FLAGS_WRONG; 708 goto err; 709 } 710 711 /* 712 * If we don't need to do replay the journal, check to see if 713 * the journal's errno is set; if so, we need to mark the file 714 * system as being corrupt and clear the journal's s_errno. 715 */ 716 if (!ext2fs_has_feature_journal_needs_recovery(sb) && 717 journal->j_superblock->s_errno) { 718 fs->super->s_state |= EXT2_ERROR_FS; 719 ext2fs_mark_super_dirty(fs); 720 journal->j_superblock->s_errno = 0; 721 ext2fs_journal_sb_csum_set(journal, journal->j_superblock); 722 mark_buffer_dirty(journal->j_sb_buffer); 723 } 724 725 err: 726 ext2fs_journal_release(fs, journal, 0, retval ? 1 : 0); 727 return retval; 728 } 729 730 static errcode_t recover_ext3_journal(ext2_filsys fs) 731 { 732 journal_t *journal; 733 errcode_t retval; 734 735 journal_init_revoke_caches(); 736 retval = ext2fs_get_journal(fs, &journal); 737 if (retval) 738 return retval; 739 740 retval = ext2fs_journal_load(journal); 741 if (retval) 742 goto errout; 743 744 retval = journal_init_revoke(journal, 1024); 745 if (retval) 746 goto errout; 747 748 retval = -journal_recover(journal); 749 if (retval) 750 goto errout; 751 752 if (journal->j_failed_commit) { 753 journal->j_superblock->s_errno = -EINVAL; 754 mark_buffer_dirty(journal->j_sb_buffer); 755 } 756 757 errout: 758 journal_destroy_revoke(journal); 759 journal_destroy_revoke_caches(); 760 ext2fs_journal_release(fs, journal, 1, 0); 761 return retval; 762 } 763 764 errcode_t ext2fs_run_ext3_journal(ext2_filsys *fsp) 765 { 766 ext2_filsys fs = *fsp; 767 io_manager io_ptr = fs->io->manager; 768 errcode_t retval, recover_retval; 769 io_stats stats = 0; 770 unsigned long long kbytes_written = 0; 771 char *fsname; 772 int fsflags; 773 int fsblocksize; 774 775 if (!(fs->flags & EXT2_FLAG_RW)) 776 return EXT2_ET_FILE_RO; 777 778 if (fs->flags & EXT2_FLAG_DIRTY) 779 ext2fs_flush(fs); /* Force out any modifications */ 780 781 recover_retval = recover_ext3_journal(fs); 782 783 /* 784 * Reload the filesystem context to get up-to-date data from disk 785 * because journal recovery will change the filesystem under us. 786 */ 787 if (fs->super->s_kbytes_written && 788 fs->io->manager->get_stats) 789 fs->io->manager->get_stats(fs->io, &stats); 790 if (stats && stats->bytes_written) 791 kbytes_written = stats->bytes_written >> 10; 792 793 ext2fs_mmp_stop(fs); 794 fsname = strdup(fs->device_name); 795 fsflags = fs->flags; 796 fsblocksize = fs->blocksize; 797 ext2fs_free(fs); 798 retval = ext2fs_open(fsname, fsflags, 799 0, fsblocksize, io_ptr, 800 fsp); 801 free(fsname); 802 if (retval) 803 return retval; 804 805 fs = *fsp; 806 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 807 fs->super->s_kbytes_written += kbytes_written; 808 809 /* Set the superblock flags */ 810 ext2fs_clear_recover(fs, recover_retval != 0); 811 812 /* 813 * Do one last sanity check, and propagate journal->s_errno to 814 * the EXT2_ERROR_FS flag in the fs superblock if needed. 815 */ 816 retval = ext2fs_check_ext3_journal(fs); 817 return retval ? retval : recover_retval; 818 } 819 820 errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j) 821 { 822 journal_t *journal; 823 errcode_t retval; 824 825 journal_init_revoke_caches(); 826 retval = ext2fs_get_journal(fs, &journal); 827 if (retval) 828 return retval; 829 830 retval = ext2fs_journal_load(journal); 831 if (retval) 832 goto errout; 833 834 retval = journal_init_revoke(journal, 1024); 835 if (retval) 836 goto errout; 837 838 if (journal->j_failed_commit) { 839 journal->j_superblock->s_errno = -EINVAL; 840 mark_buffer_dirty(journal->j_sb_buffer); 841 } 842 843 *j = journal; 844 return 0; 845 846 errout: 847 journal_destroy_revoke(journal); 848 journal_destroy_revoke_caches(); 849 ext2fs_journal_release(fs, journal, 1, 0); 850 return retval; 851 } 852 853 errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j) 854 { 855 journal_t *journal = *j; 856 857 journal_destroy_revoke(journal); 858 journal_destroy_revoke_caches(); 859 ext2fs_journal_release(fs, journal, 0, 0); 860 *j = NULL; 861 862 return 0; 863 } 864 865 void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh) 866 { 867 struct commit_header *h; 868 __u32 csum; 869 870 if (!journal_has_csum_v2or3(j)) 871 return; 872 873 h = (struct commit_header *)(bh->b_data); 874 h->h_chksum_type = 0; 875 h->h_chksum_size = 0; 876 h->h_chksum[0] = 0; 877 csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize); 878 h->h_chksum[0] = ext2fs_cpu_to_be32(csum); 879 } 880 881 void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh) 882 { 883 struct journal_revoke_tail *tail; 884 __u32 csum; 885 886 if (!journal_has_csum_v2or3(j)) 887 return; 888 889 tail = (struct journal_revoke_tail *)(bh->b_data + j->j_blocksize - 890 sizeof(struct journal_revoke_tail)); 891 tail->r_checksum = 0; 892 csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize); 893 tail->r_checksum = ext2fs_cpu_to_be32(csum); 894 } 895 896 void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh) 897 { 898 struct journal_block_tail *tail; 899 __u32 csum; 900 901 if (!journal_has_csum_v2or3(j)) 902 return; 903 904 tail = (struct journal_block_tail *)(bh->b_data + j->j_blocksize - 905 sizeof(struct journal_block_tail)); 906 tail->t_checksum = 0; 907 csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize); 908 tail->t_checksum = ext2fs_cpu_to_be32(csum); 909 } 910 911 void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, 912 struct buffer_head *bh, __u32 sequence) 913 { 914 journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; 915 __u32 csum32; 916 __be32 seq; 917 918 if (!journal_has_csum_v2or3(j)) 919 return; 920 921 seq = ext2fs_cpu_to_be32(sequence); 922 csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); 923 csum32 = jbd2_chksum(j, csum32, bh->b_data, bh->b_size); 924 925 if (jfs_has_feature_csum3(j)) 926 tag3->t_checksum = ext2fs_cpu_to_be32(csum32); 927 else 928 tag->t_checksum = ext2fs_cpu_to_be16(csum32); 929 } 930 931