1 /* 2 * do_journal.c --- Scribble onto the journal! 3 * 4 * Copyright (C) 2014 Oracle. This file may be redistributed 5 * under the terms of the GNU Public License. 6 */ 7 8 #include "config.h" 9 #include <stdio.h> 10 #ifdef HAVE_GETOPT_H 11 #include <getopt.h> 12 #else 13 extern int optind; 14 extern char *optarg; 15 #endif 16 #include <ctype.h> 17 #include <unistd.h> 18 #ifdef HAVE_SYS_TIME_H 19 #include <sys/time.h> 20 #endif 21 22 #include "debugfs.h" 23 #include "ext2fs/kernel-jbd.h" 24 #include "journal.h" 25 26 #undef DEBUG 27 28 #ifdef DEBUG 29 # define dbg_printf(f, a...) do {printf("JFS DEBUG: " f, ## a); \ 30 fflush(stdout); \ 31 } while (0) 32 #else 33 # define dbg_printf(f, a...) 34 #endif 35 36 #define JOURNAL_CHECK_TRANS_MAGIC(x) \ 37 do { \ 38 if ((x)->magic != J_TRANS_MAGIC) \ 39 return EXT2_ET_INVALID_ARGUMENT; \ 40 } while (0) 41 42 #define J_TRANS_MAGIC 0xD15EA5ED 43 #define J_TRANS_OPEN 1 44 #define J_TRANS_COMMITTED 2 45 struct journal_transaction_s { 46 unsigned int magic; 47 ext2_filsys fs; 48 journal_t *journal; 49 blk64_t block; 50 blk64_t start, end; 51 tid_t tid; 52 int flags; 53 }; 54 55 typedef struct journal_transaction_s journal_transaction_t; 56 57 static journal_t *current_journal = NULL; 58 59 static void journal_dump_trans(journal_transaction_t *trans EXT2FS_ATTR((unused)), 60 const char *tag EXT2FS_ATTR((unused))) 61 { 62 dbg_printf("TRANS %p(%s): tid=%d start=%llu block=%llu end=%llu " 63 "flags=0x%x\n", trans, tag, trans->tid, trans->start, 64 trans->block, trans->end, trans->flags); 65 } 66 67 static errcode_t journal_commit_trans(journal_transaction_t *trans) 68 { 69 struct buffer_head *bh, *cbh = NULL; 70 struct commit_header *commit; 71 #ifdef HAVE_SYS_TIME_H 72 struct timeval tv; 73 #endif 74 errcode_t err; 75 76 JOURNAL_CHECK_TRANS_MAGIC(trans); 77 78 if ((trans->flags & J_TRANS_COMMITTED) || 79 !(trans->flags & J_TRANS_OPEN)) 80 return EXT2_ET_INVALID_ARGUMENT; 81 82 bh = getblk(trans->journal->j_dev, 0, trans->journal->j_blocksize); 83 if (bh == NULL) 84 return ENOMEM; 85 86 /* write the descriptor block header */ 87 commit = (struct commit_header *)bh->b_data; 88 commit->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER); 89 commit->h_blocktype = ext2fs_cpu_to_be32(JFS_COMMIT_BLOCK); 90 commit->h_sequence = ext2fs_cpu_to_be32(trans->tid); 91 if (jfs_has_feature_checksum(trans->journal)) { 92 __u32 csum_v1 = ~0; 93 blk64_t cblk; 94 95 cbh = getblk(trans->journal->j_dev, 0, 96 trans->journal->j_blocksize); 97 if (cbh == NULL) { 98 err = ENOMEM; 99 goto error; 100 } 101 102 for (cblk = trans->start; cblk < trans->block; cblk++) { 103 err = journal_bmap(trans->journal, cblk, 104 &cbh->b_blocknr); 105 if (err) 106 goto error; 107 mark_buffer_uptodate(cbh, 0); 108 ll_rw_block(READ, 1, &cbh); 109 err = cbh->b_err; 110 if (err) 111 goto error; 112 csum_v1 = ext2fs_crc32_be(csum_v1, 113 (unsigned char const *)cbh->b_data, 114 cbh->b_size); 115 } 116 117 commit->h_chksum_type = JFS_CRC32_CHKSUM; 118 commit->h_chksum_size = JFS_CRC32_CHKSUM_SIZE; 119 commit->h_chksum[0] = ext2fs_cpu_to_be32(csum_v1); 120 } else { 121 commit->h_chksum_type = 0; 122 commit->h_chksum_size = 0; 123 commit->h_chksum[0] = 0; 124 } 125 #ifdef HAVE_SYS_TIME_H 126 gettimeofday(&tv, NULL); 127 commit->h_commit_sec = ext2fs_cpu_to_be32(tv.tv_sec); 128 commit->h_commit_nsec = ext2fs_cpu_to_be32(tv.tv_usec * 1000); 129 #else 130 commit->h_commit_sec = 0; 131 commit->h_commit_nsec = 0; 132 #endif 133 134 /* Write block */ 135 jbd2_commit_block_csum_set(trans->journal, bh); 136 err = journal_bmap(trans->journal, trans->block, &bh->b_blocknr); 137 if (err) 138 goto error; 139 140 dbg_printf("Writing commit block at %llu:%llu\n", trans->block, 141 bh->b_blocknr); 142 mark_buffer_dirty(bh); 143 ll_rw_block(WRITE, 1, &bh); 144 err = bh->b_err; 145 if (err) 146 goto error; 147 trans->flags |= J_TRANS_COMMITTED; 148 trans->flags &= ~J_TRANS_OPEN; 149 trans->block++; 150 151 ext2fs_set_feature_journal_needs_recovery(trans->fs->super); 152 ext2fs_mark_super_dirty(trans->fs); 153 error: 154 if (cbh) 155 brelse(cbh); 156 brelse(bh); 157 return err; 158 } 159 160 static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans, 161 blk64_t *revoke_list, 162 size_t revoke_len) 163 { 164 journal_revoke_header_t *jrb; 165 void *buf; 166 size_t i, offset; 167 blk64_t curr_blk; 168 unsigned int sz; 169 unsigned csum_size = 0; 170 struct buffer_head *bh; 171 errcode_t err; 172 173 JOURNAL_CHECK_TRANS_MAGIC(trans); 174 175 if ((trans->flags & J_TRANS_COMMITTED) || 176 !(trans->flags & J_TRANS_OPEN)) 177 return EXT2_ET_INVALID_ARGUMENT; 178 179 if (revoke_len == 0) 180 return 0; 181 182 /* Do we need to leave space at the end for a checksum? */ 183 if (journal_has_csum_v2or3(trans->journal)) 184 csum_size = sizeof(struct journal_revoke_tail); 185 186 curr_blk = trans->block; 187 188 bh = getblk(trans->journal->j_dev, curr_blk, 189 trans->journal->j_blocksize); 190 if (bh == NULL) 191 return ENOMEM; 192 jrb = buf = bh->b_data; 193 jrb->r_header.h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER); 194 jrb->r_header.h_blocktype = ext2fs_cpu_to_be32(JFS_REVOKE_BLOCK); 195 jrb->r_header.h_sequence = ext2fs_cpu_to_be32(trans->tid); 196 offset = sizeof(*jrb); 197 198 if (jfs_has_feature_64bit(trans->journal)) 199 sz = 8; 200 else 201 sz = 4; 202 203 for (i = 0; i < revoke_len; i++) { 204 /* Block full, write to journal */ 205 if (offset + sz > trans->journal->j_blocksize - csum_size) { 206 jrb->r_count = ext2fs_cpu_to_be32(offset); 207 jbd2_revoke_csum_set(trans->journal, bh); 208 209 err = journal_bmap(trans->journal, curr_blk, 210 &bh->b_blocknr); 211 if (err) 212 goto error; 213 dbg_printf("Writing revoke block at %llu:%llu\n", 214 curr_blk, bh->b_blocknr); 215 mark_buffer_dirty(bh); 216 ll_rw_block(WRITE, 1, &bh); 217 err = bh->b_err; 218 if (err) 219 goto error; 220 221 offset = sizeof(*jrb); 222 curr_blk++; 223 } 224 225 if (revoke_list[i] >= 226 ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) { 227 err = EXT2_ET_BAD_BLOCK_NUM; 228 goto error; 229 } 230 231 if (jfs_has_feature_64bit(trans->journal)) 232 *((__u64 *)(&((char *)buf)[offset])) = 233 ext2fs_cpu_to_be64(revoke_list[i]); 234 else 235 *((__u32 *)(&((char *)buf)[offset])) = 236 ext2fs_cpu_to_be32(revoke_list[i]); 237 offset += sz; 238 } 239 240 if (offset > 0) { 241 jrb->r_count = ext2fs_cpu_to_be32(offset); 242 jbd2_revoke_csum_set(trans->journal, bh); 243 244 err = journal_bmap(trans->journal, curr_blk, &bh->b_blocknr); 245 if (err) 246 goto error; 247 dbg_printf("Writing revoke block at %llu:%llu\n", 248 curr_blk, bh->b_blocknr); 249 mark_buffer_dirty(bh); 250 ll_rw_block(WRITE, 1, &bh); 251 err = bh->b_err; 252 if (err) 253 goto error; 254 curr_blk++; 255 } 256 257 error: 258 trans->block = curr_blk; 259 brelse(bh); 260 return err; 261 } 262 263 static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans, 264 blk64_t *block_list, size_t block_len, 265 FILE *fp) 266 { 267 blk64_t curr_blk, jdb_blk; 268 size_t i, j; 269 int csum_size = 0; 270 journal_header_t *jdb; 271 journal_block_tag_t *jdbt; 272 int tag_bytes; 273 void *buf = NULL, *jdb_buf = NULL; 274 struct buffer_head *bh = NULL, *data_bh; 275 errcode_t err; 276 277 JOURNAL_CHECK_TRANS_MAGIC(trans); 278 279 if ((trans->flags & J_TRANS_COMMITTED) || 280 !(trans->flags & J_TRANS_OPEN)) 281 return EXT2_ET_INVALID_ARGUMENT; 282 283 if (block_len == 0) 284 return 0; 285 286 /* Do we need to leave space at the end for a checksum? */ 287 if (journal_has_csum_v2or3(trans->journal)) 288 csum_size = sizeof(struct journal_block_tail); 289 290 curr_blk = jdb_blk = trans->block; 291 292 data_bh = getblk(trans->journal->j_dev, curr_blk, 293 trans->journal->j_blocksize); 294 if (data_bh == NULL) 295 return ENOMEM; 296 buf = data_bh->b_data; 297 298 /* write the descriptor block header */ 299 bh = getblk(trans->journal->j_dev, curr_blk, 300 trans->journal->j_blocksize); 301 if (bh == NULL) { 302 err = ENOMEM; 303 goto error; 304 } 305 jdb = jdb_buf = bh->b_data; 306 jdb->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER); 307 jdb->h_blocktype = ext2fs_cpu_to_be32(JFS_DESCRIPTOR_BLOCK); 308 jdb->h_sequence = ext2fs_cpu_to_be32(trans->tid); 309 jdbt = (journal_block_tag_t *)(jdb + 1); 310 311 curr_blk++; 312 for (i = 0; i < block_len; i++) { 313 j = fread(data_bh->b_data, trans->journal->j_blocksize, 1, fp); 314 if (j != 1) { 315 err = errno; 316 goto error; 317 } 318 319 tag_bytes = journal_tag_bytes(trans->journal); 320 321 /* No space left in descriptor block, write it out */ 322 if ((char *)jdbt + tag_bytes > 323 (char *)jdb_buf + trans->journal->j_blocksize - csum_size) { 324 jbd2_descr_block_csum_set(trans->journal, bh); 325 err = journal_bmap(trans->journal, jdb_blk, 326 &bh->b_blocknr); 327 if (err) 328 goto error; 329 dbg_printf("Writing descriptor block at %llu:%llu\n", 330 jdb_blk, bh->b_blocknr); 331 mark_buffer_dirty(bh); 332 ll_rw_block(WRITE, 1, &bh); 333 err = bh->b_err; 334 if (err) 335 goto error; 336 337 jdbt = (journal_block_tag_t *)(jdb + 1); 338 jdb_blk = curr_blk; 339 curr_blk++; 340 } 341 342 if (block_list[i] >= 343 ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) { 344 err = EXT2_ET_BAD_BLOCK_NUM; 345 goto error; 346 } 347 348 /* Fill out the block tag */ 349 jdbt->t_blocknr = ext2fs_cpu_to_be32(block_list[i] & 0xFFFFFFFF); 350 jdbt->t_flags = 0; 351 if (jdbt != (journal_block_tag_t *)(jdb + 1)) 352 jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID); 353 else { 354 memcpy(jdbt + tag_bytes, 355 trans->journal->j_superblock->s_uuid, 356 sizeof(trans->journal->j_superblock->s_uuid)); 357 tag_bytes += 16; 358 } 359 if (i == block_len - 1) 360 jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG); 361 if (*((__u32 *)buf) == ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) { 362 *((__u32 *)buf) = 0; 363 jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_ESCAPE); 364 } 365 if (jfs_has_feature_64bit(trans->journal)) 366 jdbt->t_blocknr_high = ext2fs_cpu_to_be32(block_list[i] >> 32); 367 jbd2_block_tag_csum_set(trans->journal, jdbt, data_bh, 368 trans->tid); 369 370 /* Write the data block */ 371 err = journal_bmap(trans->journal, curr_blk, 372 &data_bh->b_blocknr); 373 if (err) 374 goto error; 375 dbg_printf("Writing data block %llu at %llu:%llu tag %d\n", 376 block_list[i], curr_blk, data_bh->b_blocknr, 377 tag_bytes); 378 mark_buffer_dirty(data_bh); 379 ll_rw_block(WRITE, 1, &data_bh); 380 err = data_bh->b_err; 381 if (err) 382 goto error; 383 384 curr_blk++; 385 jdbt = (journal_block_tag_t *)(((char *)jdbt) + tag_bytes); 386 } 387 388 /* Write out the last descriptor block */ 389 if (jdbt != (journal_block_tag_t *)(jdb + 1)) { 390 jbd2_descr_block_csum_set(trans->journal, bh); 391 err = journal_bmap(trans->journal, jdb_blk, &bh->b_blocknr); 392 if (err) 393 goto error; 394 dbg_printf("Writing descriptor block at %llu:%llu\n", 395 jdb_blk, bh->b_blocknr); 396 mark_buffer_dirty(bh); 397 ll_rw_block(WRITE, 1, &bh); 398 err = bh->b_err; 399 if (err) 400 goto error; 401 } 402 403 error: 404 trans->block = curr_blk; 405 if (bh) 406 brelse(bh); 407 brelse(data_bh); 408 return err; 409 } 410 411 static blk64_t journal_guess_blocks(journal_t *journal, blk64_t data_blocks, 412 blk64_t revoke_blocks) 413 { 414 blk64_t ret = 1; 415 unsigned int bs, sz; 416 417 /* Estimate # of revoke blocks */ 418 bs = journal->j_blocksize; 419 if (journal_has_csum_v2or3(journal)) 420 bs -= sizeof(struct journal_revoke_tail); 421 sz = jfs_has_feature_64bit(journal) ? sizeof(__u64) : sizeof(__u32); 422 ret += revoke_blocks * sz / bs; 423 424 /* Estimate # of data blocks */ 425 bs = journal->j_blocksize - 16; 426 if (journal_has_csum_v2or3(journal)) 427 bs -= sizeof(struct journal_block_tail); 428 sz = journal_tag_bytes(journal); 429 ret += data_blocks * sz / bs; 430 431 ret += data_blocks; 432 433 return ret; 434 } 435 436 static errcode_t journal_open_trans(journal_t *journal, 437 journal_transaction_t *trans, 438 blk64_t blocks) 439 { 440 trans->fs = journal->j_fs_dev->k_fs; 441 trans->journal = journal; 442 trans->flags = J_TRANS_OPEN; 443 444 if (journal->j_tail == 0) { 445 /* Clean journal, start at the tail */ 446 trans->tid = journal->j_tail_sequence; 447 trans->start = journal->j_first; 448 } else { 449 /* Put new transaction at the head of the list */ 450 trans->tid = journal->j_transaction_sequence; 451 trans->start = journal->j_head; 452 } 453 454 trans->block = trans->start; 455 if (trans->start + blocks > journal->j_last) 456 return ENOSPC; 457 trans->end = trans->block + blocks; 458 journal_dump_trans(trans, "new transaction"); 459 460 trans->magic = J_TRANS_MAGIC; 461 return 0; 462 } 463 464 static errcode_t journal_close_trans(journal_transaction_t *trans) 465 { 466 journal_t *journal; 467 468 JOURNAL_CHECK_TRANS_MAGIC(trans); 469 470 if (!(trans->flags & J_TRANS_COMMITTED)) 471 return 0; 472 473 journal = trans->journal; 474 if (journal->j_tail == 0) { 475 /* Update the tail */ 476 journal->j_tail_sequence = trans->tid; 477 journal->j_tail = trans->start; 478 journal->j_superblock->s_start = ext2fs_cpu_to_be32(trans->start); 479 } 480 481 /* Update the head */ 482 journal->j_head = trans->end + 1; 483 journal->j_transaction_sequence = trans->tid + 1; 484 485 trans->magic = 0; 486 487 /* Mark ourselves as needing recovery */ 488 if (!ext2fs_has_feature_journal_needs_recovery(trans->fs->super)) { 489 ext2fs_set_feature_journal_needs_recovery(trans->fs->super); 490 ext2fs_mark_super_dirty(trans->fs); 491 } 492 493 return 0; 494 } 495 496 #define JOURNAL_WRITE_NO_COMMIT 1 497 static errcode_t journal_write(journal_t *journal, 498 int flags, blk64_t *block_list, 499 size_t block_len, blk64_t *revoke_list, 500 size_t revoke_len, FILE *fp) 501 { 502 blk64_t blocks; 503 journal_transaction_t trans; 504 errcode_t err; 505 506 if (revoke_len > 0) { 507 jfs_set_feature_revoke(journal); 508 mark_buffer_dirty(journal->j_sb_buffer); 509 } 510 511 blocks = journal_guess_blocks(journal, block_len, revoke_len); 512 err = journal_open_trans(journal, &trans, blocks); 513 if (err) 514 goto error; 515 516 err = journal_add_blocks_to_trans(&trans, block_list, block_len, fp); 517 if (err) 518 goto error; 519 520 err = journal_add_revoke_to_trans(&trans, revoke_list, revoke_len); 521 if (err) 522 goto error; 523 524 if (!(flags & JOURNAL_WRITE_NO_COMMIT)) { 525 err = journal_commit_trans(&trans); 526 if (err) 527 goto error; 528 } 529 530 err = journal_close_trans(&trans); 531 if (err) 532 goto error; 533 error: 534 return err; 535 } 536 537 void do_journal_write(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), 538 void *infop EXT2FS_ATTR((unused))) 539 { 540 blk64_t *blist = NULL, *rlist = NULL; 541 size_t bn = 0, rn = 0; 542 FILE *fp = NULL; 543 int opt; 544 int flags = 0; 545 errcode_t err; 546 547 if (current_journal == NULL) { 548 printf("Journal not open.\n"); 549 return; 550 } 551 552 reset_getopt(); 553 while ((opt = getopt(argc, argv, "b:r:c")) != -1) { 554 switch (opt) { 555 case 'b': 556 err = read_list(optarg, &blist, &bn); 557 if (err) 558 com_err(argv[0], err, 559 "while reading block list"); 560 break; 561 case 'r': 562 err = read_list(optarg, &rlist, &rn); 563 if (err) 564 com_err(argv[0], err, 565 "while reading revoke list"); 566 break; 567 case 'c': 568 flags |= JOURNAL_WRITE_NO_COMMIT; 569 break; 570 default: 571 printf("%s [-b blocks] [-r revoke] [-c] file\n", 572 argv[0]); 573 printf("-b: Write these blocks into transaction.\n"); 574 printf("-c: Do not commit transaction.\n"); 575 printf("-r: Revoke these blocks from transaction.\n"); 576 577 goto out; 578 } 579 } 580 581 if (bn > 0 && optind != argc - 1) { 582 printf("Need a file to read blocks from.\n"); 583 return; 584 } 585 586 if (bn > 0) { 587 fp = fopen(argv[optind], "r"); 588 if (fp == NULL) { 589 com_err(argv[0], errno, 590 "while opening journal data file"); 591 goto out; 592 } 593 } 594 595 err = journal_write(current_journal, flags, blist, bn, 596 rlist, rn, fp); 597 if (err) 598 com_err("journal_write", err, "while writing journal"); 599 600 if (fp) 601 fclose(fp); 602 out: 603 if (blist) 604 free(blist); 605 if (rlist) 606 free(rlist); 607 } 608 609 /* Make sure we wrap around the log correctly! */ 610 #define wrap(journal, var) \ 611 do { \ 612 if (var >= (journal)->j_last) \ 613 var -= ((journal)->j_last - (journal)->j_first); \ 614 } while (0) 615 616 /* 617 * Count the number of in-use tags in a journal descriptor block. 618 */ 619 620 static int count_tags(journal_t *journal, char *buf) 621 { 622 char *tagp; 623 journal_block_tag_t *tag; 624 int nr = 0, size = journal->j_blocksize; 625 int tag_bytes = journal_tag_bytes(journal); 626 627 if (journal_has_csum_v2or3(journal)) 628 size -= sizeof(struct journal_block_tail); 629 630 tagp = buf + sizeof(journal_header_t); 631 632 while ((tagp - buf + tag_bytes) <= size) { 633 tag = (journal_block_tag_t *) tagp; 634 635 nr++; 636 tagp += tag_bytes; 637 if (!(tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID))) 638 tagp += 16; 639 640 if (tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG)) 641 break; 642 } 643 644 return nr; 645 } 646 647 static errcode_t journal_find_head(journal_t *journal) 648 { 649 unsigned int next_commit_ID; 650 blk64_t next_log_block, head_block; 651 int err; 652 journal_superblock_t *sb; 653 journal_header_t *tmp; 654 struct buffer_head *bh; 655 unsigned int sequence; 656 int blocktype; 657 658 /* 659 * First thing is to establish what we expect to find in the log 660 * (in terms of transaction IDs), and where (in terms of log 661 * block offsets): query the superblock. 662 */ 663 664 sb = journal->j_superblock; 665 next_commit_ID = ext2fs_be32_to_cpu(sb->s_sequence); 666 next_log_block = ext2fs_be32_to_cpu(sb->s_start); 667 head_block = next_log_block; 668 669 if (next_log_block == 0) 670 return 0; 671 672 bh = getblk(journal->j_dev, 0, journal->j_blocksize); 673 if (bh == NULL) 674 return ENOMEM; 675 676 /* 677 * Now we walk through the log, transaction by transaction, 678 * making sure that each transaction has a commit block in the 679 * expected place. Each complete transaction gets replayed back 680 * into the main filesystem. 681 */ 682 while (1) { 683 dbg_printf("Scanning for sequence ID %u at %lu/%lu\n", 684 next_commit_ID, (unsigned long)next_log_block, 685 journal->j_last); 686 687 /* Skip over each chunk of the transaction looking 688 * either the next descriptor block or the final commit 689 * record. */ 690 err = journal_bmap(journal, next_log_block, &bh->b_blocknr); 691 if (err) 692 goto err; 693 mark_buffer_uptodate(bh, 0); 694 ll_rw_block(READ, 1, &bh); 695 err = bh->b_err; 696 if (err) 697 goto err; 698 699 next_log_block++; 700 wrap(journal, next_log_block); 701 702 /* What kind of buffer is it? 703 * 704 * If it is a descriptor block, check that it has the 705 * expected sequence number. Otherwise, we're all done 706 * here. */ 707 708 tmp = (journal_header_t *)bh->b_data; 709 710 if (tmp->h_magic != ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) { 711 dbg_printf("JBD2: wrong magic 0x%x\n", tmp->h_magic); 712 goto err; 713 } 714 715 blocktype = ext2fs_be32_to_cpu(tmp->h_blocktype); 716 sequence = ext2fs_be32_to_cpu(tmp->h_sequence); 717 dbg_printf("Found magic %d, sequence %d\n", 718 blocktype, sequence); 719 720 if (sequence != next_commit_ID) { 721 dbg_printf("JBD2: Wrong sequence %d (wanted %d)\n", 722 sequence, next_commit_ID); 723 goto err; 724 } 725 726 /* OK, we have a valid descriptor block which matches 727 * all of the sequence number checks. What are we going 728 * to do with it? That depends on the pass... */ 729 730 switch (blocktype) { 731 case JFS_DESCRIPTOR_BLOCK: 732 next_log_block += count_tags(journal, bh->b_data); 733 wrap(journal, next_log_block); 734 continue; 735 736 case JFS_COMMIT_BLOCK: 737 head_block = next_log_block; 738 next_commit_ID++; 739 continue; 740 741 case JFS_REVOKE_BLOCK: 742 continue; 743 744 default: 745 dbg_printf("Unrecognised magic %d, end of scan.\n", 746 blocktype); 747 err = -EINVAL; 748 goto err; 749 } 750 } 751 752 err: 753 if (err == 0) { 754 dbg_printf("head seq=%d blk=%llu\n", next_commit_ID, 755 head_block); 756 journal->j_transaction_sequence = next_commit_ID; 757 journal->j_head = head_block; 758 } 759 brelse(bh); 760 return err; 761 } 762 763 static void update_journal_csum(journal_t *journal, int ver) 764 { 765 journal_superblock_t *jsb; 766 767 if (journal->j_format_version < 2) 768 return; 769 770 if (journal->j_tail != 0 || 771 ext2fs_has_feature_journal_needs_recovery( 772 journal->j_fs_dev->k_fs->super)) { 773 printf("Journal needs recovery, will not add csums.\n"); 774 return; 775 } 776 777 /* metadata_csum implies journal csum v3 */ 778 jsb = journal->j_superblock; 779 if (ext2fs_has_feature_metadata_csum(journal->j_fs_dev->k_fs->super)) { 780 printf("Setting csum v%d\n", ver); 781 switch (ver) { 782 case 2: 783 jfs_clear_feature_csum3(journal); 784 jfs_set_feature_csum2(journal); 785 jfs_clear_feature_checksum(journal); 786 break; 787 case 3: 788 jfs_set_feature_csum3(journal); 789 jfs_clear_feature_csum2(journal); 790 jfs_clear_feature_checksum(journal); 791 break; 792 default: 793 printf("Unknown checksum v%d\n", ver); 794 break; 795 } 796 journal->j_superblock->s_checksum_type = JBD2_CRC32C_CHKSUM; 797 journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid, 798 sizeof(jsb->s_uuid)); 799 } else { 800 jfs_clear_feature_csum3(journal); 801 jfs_clear_feature_csum2(journal); 802 jfs_set_feature_checksum(journal); 803 } 804 } 805 806 static void update_uuid(journal_t *journal) 807 { 808 size_t z; 809 ext2_filsys fs; 810 811 if (journal->j_format_version < 2) 812 return; 813 814 for (z = 0; z < sizeof(journal->j_superblock->s_uuid); z++) 815 if (journal->j_superblock->s_uuid[z]) 816 break; 817 if (z == 0) 818 return; 819 820 fs = journal->j_fs_dev->k_fs; 821 if (!ext2fs_has_feature_64bit(fs->super)) 822 return; 823 824 if (jfs_has_feature_64bit(journal) && 825 ext2fs_has_feature_64bit(fs->super)) 826 return; 827 828 if (journal->j_tail != 0 || 829 ext2fs_has_feature_journal_needs_recovery(fs->super)) { 830 printf("Journal needs recovery, will not set 64bit.\n"); 831 return; 832 } 833 834 memcpy(journal->j_superblock->s_uuid, fs->super->s_uuid, 835 sizeof(fs->super->s_uuid)); 836 } 837 838 static void update_64bit_flag(journal_t *journal) 839 { 840 if (journal->j_format_version < 2) 841 return; 842 843 if (!ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super)) 844 return; 845 846 if (jfs_has_feature_64bit(journal) && 847 ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super)) 848 return; 849 850 if (journal->j_tail != 0 || 851 ext2fs_has_feature_journal_needs_recovery( 852 journal->j_fs_dev->k_fs->super)) { 853 printf("Journal needs recovery, will not set 64bit.\n"); 854 return; 855 } 856 857 jfs_set_feature_64bit(journal); 858 } 859 860 void do_journal_open(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), 861 void *infop EXT2FS_ATTR((unused))) 862 { 863 int opt, enable_csum = 0, csum_ver = 3; 864 journal_t *journal; 865 errcode_t err; 866 867 if (check_fs_open(argv[0])) 868 return; 869 if (check_fs_read_write(argv[0])) 870 return; 871 if (check_fs_bitmaps(argv[0])) 872 return; 873 if (current_journal) { 874 printf("Journal is already open.\n"); 875 return; 876 } 877 if (!ext2fs_has_feature_journal(current_fs->super)) { 878 printf("Journalling is not enabled on this filesystem.\n"); 879 return; 880 } 881 882 reset_getopt(); 883 while ((opt = getopt(argc, argv, "cv:f:")) != -1) { 884 switch (opt) { 885 case 'c': 886 enable_csum = 1; 887 break; 888 case 'f': 889 if (current_fs->journal_name) 890 free(current_fs->journal_name); 891 current_fs->journal_name = strdup(optarg); 892 break; 893 case 'v': 894 csum_ver = atoi(optarg); 895 if (csum_ver != 2 && csum_ver != 3) { 896 printf("Unknown journal csum v%d\n", csum_ver); 897 csum_ver = 3; 898 } 899 break; 900 default: 901 printf("%s: [-c] [-v ver] [-f ext_jnl]\n", argv[0]); 902 printf("-c: Enable journal checksumming.\n"); 903 printf("-v: Use this version checksum format.\n"); 904 printf("-f: Load this external journal.\n"); 905 } 906 } 907 908 err = ext2fs_open_journal(current_fs, ¤t_journal); 909 if (err) { 910 com_err(argv[0], err, "while opening journal"); 911 return; 912 } 913 journal = current_journal; 914 915 dbg_printf("JOURNAL: seq=%d tailseq=%d start=%lu first=%lu " 916 "maxlen=%lu\n", journal->j_tail_sequence, 917 journal->j_transaction_sequence, journal->j_tail, 918 journal->j_first, journal->j_last); 919 920 update_uuid(journal); 921 update_64bit_flag(journal); 922 if (enable_csum) 923 update_journal_csum(journal, csum_ver); 924 925 err = journal_find_head(journal); 926 if (err) 927 com_err(argv[0], err, "while examining journal"); 928 } 929 930 void do_journal_close(int argc EXT2FS_ATTR((unused)), 931 char *argv[] EXT2FS_ATTR((unused)), 932 int sci_idx EXT2FS_ATTR((unused)), 933 void *infop EXT2FS_ATTR((unused))) 934 { 935 if (current_journal == NULL) { 936 printf("Journal not open.\n"); 937 return; 938 } 939 940 ext2fs_close_journal(current_fs, ¤t_journal); 941 } 942 943 void do_journal_run(int argc EXT2FS_ATTR((unused)), char *argv[], 944 int sci_idx EXT2FS_ATTR((unused)), 945 void *infop EXT2FS_ATTR((unused))) 946 { 947 errcode_t err; 948 949 if (check_fs_open(argv[0])) 950 return; 951 if (check_fs_read_write(argv[0])) 952 return; 953 if (check_fs_bitmaps(argv[0])) 954 return; 955 if (current_journal) { 956 printf("Please close the journal before recovering it.\n"); 957 return; 958 } 959 960 err = ext2fs_run_ext3_journal(¤t_fs); 961 if (err) 962 com_err("journal_run", err, "while recovering journal"); 963 else { 964 ext2fs_clear_feature_journal_needs_recovery(current_fs->super); 965 ext2fs_mark_super_dirty(current_fs); 966 } 967 } 968