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[]) 538 { 539 blk64_t *blist = NULL, *rlist = NULL; 540 size_t bn = 0, rn = 0; 541 FILE *fp = NULL; 542 int opt; 543 int flags = 0; 544 errcode_t err; 545 546 if (current_journal == NULL) { 547 printf("Journal not open.\n"); 548 return; 549 } 550 551 reset_getopt(); 552 while ((opt = getopt(argc, argv, "b:r:c")) != -1) { 553 switch (opt) { 554 case 'b': 555 err = read_list(optarg, &blist, &bn); 556 if (err) 557 com_err(argv[0], err, 558 "while reading block list"); 559 break; 560 case 'r': 561 err = read_list(optarg, &rlist, &rn); 562 if (err) 563 com_err(argv[0], err, 564 "while reading revoke list"); 565 break; 566 case 'c': 567 flags |= JOURNAL_WRITE_NO_COMMIT; 568 break; 569 default: 570 printf("%s [-b blocks] [-r revoke] [-c] file\n", 571 argv[0]); 572 printf("-b: Write these blocks into transaction.\n"); 573 printf("-c: Do not commit transaction.\n"); 574 printf("-r: Revoke these blocks from transaction.\n"); 575 576 goto out; 577 } 578 } 579 580 if (bn > 0 && optind != argc - 1) { 581 printf("Need a file to read blocks from.\n"); 582 return; 583 } 584 585 if (bn > 0) { 586 fp = fopen(argv[optind], "r"); 587 if (fp == NULL) { 588 com_err(argv[0], errno, 589 "while opening journal data file"); 590 goto out; 591 } 592 } 593 594 err = journal_write(current_journal, flags, blist, bn, 595 rlist, rn, fp); 596 if (err) 597 com_err("journal_write", err, "while writing journal"); 598 599 if (fp) 600 fclose(fp); 601 out: 602 if (blist) 603 free(blist); 604 if (rlist) 605 free(rlist); 606 } 607 608 /* Make sure we wrap around the log correctly! */ 609 #define wrap(journal, var) \ 610 do { \ 611 if (var >= (journal)->j_last) \ 612 var -= ((journal)->j_last - (journal)->j_first); \ 613 } while (0) 614 615 /* 616 * Count the number of in-use tags in a journal descriptor block. 617 */ 618 619 static int count_tags(journal_t *journal, char *buf) 620 { 621 char *tagp; 622 journal_block_tag_t *tag; 623 int nr = 0, size = journal->j_blocksize; 624 int tag_bytes = journal_tag_bytes(journal); 625 626 if (journal_has_csum_v2or3(journal)) 627 size -= sizeof(struct journal_block_tail); 628 629 tagp = buf + sizeof(journal_header_t); 630 631 while ((tagp - buf + tag_bytes) <= size) { 632 tag = (journal_block_tag_t *) tagp; 633 634 nr++; 635 tagp += tag_bytes; 636 if (!(tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID))) 637 tagp += 16; 638 639 if (tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG)) 640 break; 641 } 642 643 return nr; 644 } 645 646 static errcode_t journal_find_head(journal_t *journal) 647 { 648 unsigned int next_commit_ID; 649 blk64_t next_log_block, head_block; 650 int err; 651 journal_superblock_t *sb; 652 journal_header_t *tmp; 653 struct buffer_head *bh; 654 unsigned int sequence; 655 int blocktype; 656 657 /* 658 * First thing is to establish what we expect to find in the log 659 * (in terms of transaction IDs), and where (in terms of log 660 * block offsets): query the superblock. 661 */ 662 663 sb = journal->j_superblock; 664 next_commit_ID = ext2fs_be32_to_cpu(sb->s_sequence); 665 next_log_block = ext2fs_be32_to_cpu(sb->s_start); 666 head_block = next_log_block; 667 668 if (next_log_block == 0) 669 return 0; 670 671 bh = getblk(journal->j_dev, 0, journal->j_blocksize); 672 if (bh == NULL) 673 return ENOMEM; 674 675 /* 676 * Now we walk through the log, transaction by transaction, 677 * making sure that each transaction has a commit block in the 678 * expected place. Each complete transaction gets replayed back 679 * into the main filesystem. 680 */ 681 while (1) { 682 dbg_printf("Scanning for sequence ID %u at %lu/%lu\n", 683 next_commit_ID, (unsigned long)next_log_block, 684 journal->j_last); 685 686 /* Skip over each chunk of the transaction looking 687 * either the next descriptor block or the final commit 688 * record. */ 689 err = journal_bmap(journal, next_log_block, &bh->b_blocknr); 690 if (err) 691 goto err; 692 mark_buffer_uptodate(bh, 0); 693 ll_rw_block(READ, 1, &bh); 694 err = bh->b_err; 695 if (err) 696 goto err; 697 698 next_log_block++; 699 wrap(journal, next_log_block); 700 701 /* What kind of buffer is it? 702 * 703 * If it is a descriptor block, check that it has the 704 * expected sequence number. Otherwise, we're all done 705 * here. */ 706 707 tmp = (journal_header_t *)bh->b_data; 708 709 if (tmp->h_magic != ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) { 710 dbg_printf("JBD2: wrong magic 0x%x\n", tmp->h_magic); 711 goto err; 712 } 713 714 blocktype = ext2fs_be32_to_cpu(tmp->h_blocktype); 715 sequence = ext2fs_be32_to_cpu(tmp->h_sequence); 716 dbg_printf("Found magic %d, sequence %d\n", 717 blocktype, sequence); 718 719 if (sequence != next_commit_ID) { 720 dbg_printf("JBD2: Wrong sequence %d (wanted %d)\n", 721 sequence, next_commit_ID); 722 goto err; 723 } 724 725 /* OK, we have a valid descriptor block which matches 726 * all of the sequence number checks. What are we going 727 * to do with it? That depends on the pass... */ 728 729 switch (blocktype) { 730 case JFS_DESCRIPTOR_BLOCK: 731 next_log_block += count_tags(journal, bh->b_data); 732 wrap(journal, next_log_block); 733 continue; 734 735 case JFS_COMMIT_BLOCK: 736 head_block = next_log_block; 737 next_commit_ID++; 738 continue; 739 740 case JFS_REVOKE_BLOCK: 741 continue; 742 743 default: 744 dbg_printf("Unrecognised magic %d, end of scan.\n", 745 blocktype); 746 err = -EINVAL; 747 goto err; 748 } 749 } 750 751 err: 752 if (err == 0) { 753 dbg_printf("head seq=%d blk=%llu\n", next_commit_ID, 754 head_block); 755 journal->j_transaction_sequence = next_commit_ID; 756 journal->j_head = head_block; 757 } 758 brelse(bh); 759 return err; 760 } 761 762 static void update_journal_csum(journal_t *journal, int ver) 763 { 764 journal_superblock_t *jsb; 765 766 if (journal->j_format_version < 2) 767 return; 768 769 if (journal->j_tail != 0 || 770 ext2fs_has_feature_journal_needs_recovery( 771 journal->j_fs_dev->k_fs->super)) { 772 printf("Journal needs recovery, will not add csums.\n"); 773 return; 774 } 775 776 /* metadata_csum implies journal csum v3 */ 777 jsb = journal->j_superblock; 778 if (ext2fs_has_feature_metadata_csum(journal->j_fs_dev->k_fs->super)) { 779 printf("Setting csum v%d\n", ver); 780 switch (ver) { 781 case 2: 782 jfs_clear_feature_csum3(journal); 783 jfs_set_feature_csum2(journal); 784 jfs_clear_feature_checksum(journal); 785 break; 786 case 3: 787 jfs_set_feature_csum3(journal); 788 jfs_clear_feature_csum2(journal); 789 jfs_clear_feature_checksum(journal); 790 break; 791 default: 792 printf("Unknown checksum v%d\n", ver); 793 break; 794 } 795 journal->j_superblock->s_checksum_type = JBD2_CRC32C_CHKSUM; 796 journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid, 797 sizeof(jsb->s_uuid)); 798 } else { 799 jfs_clear_feature_csum3(journal); 800 jfs_clear_feature_csum2(journal); 801 jfs_set_feature_checksum(journal); 802 } 803 } 804 805 static void update_uuid(journal_t *journal) 806 { 807 size_t z; 808 ext2_filsys fs; 809 810 if (journal->j_format_version < 2) 811 return; 812 813 for (z = 0; z < sizeof(journal->j_superblock->s_uuid); z++) 814 if (journal->j_superblock->s_uuid[z]) 815 break; 816 if (z == 0) 817 return; 818 819 fs = journal->j_fs_dev->k_fs; 820 if (!ext2fs_has_feature_64bit(fs->super)) 821 return; 822 823 if (jfs_has_feature_64bit(journal) && 824 ext2fs_has_feature_64bit(fs->super)) 825 return; 826 827 if (journal->j_tail != 0 || 828 ext2fs_has_feature_journal_needs_recovery(fs->super)) { 829 printf("Journal needs recovery, will not set 64bit.\n"); 830 return; 831 } 832 833 memcpy(journal->j_superblock->s_uuid, fs->super->s_uuid, 834 sizeof(fs->super->s_uuid)); 835 } 836 837 static void update_64bit_flag(journal_t *journal) 838 { 839 if (journal->j_format_version < 2) 840 return; 841 842 if (!ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super)) 843 return; 844 845 if (jfs_has_feature_64bit(journal) && 846 ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super)) 847 return; 848 849 if (journal->j_tail != 0 || 850 ext2fs_has_feature_journal_needs_recovery( 851 journal->j_fs_dev->k_fs->super)) { 852 printf("Journal needs recovery, will not set 64bit.\n"); 853 return; 854 } 855 856 jfs_set_feature_64bit(journal); 857 } 858 859 void do_journal_open(int argc, char *argv[]) 860 { 861 int opt, enable_csum = 0, csum_ver = 3; 862 journal_t *journal; 863 errcode_t err; 864 865 if (check_fs_open(argv[0])) 866 return; 867 if (check_fs_read_write(argv[0])) 868 return; 869 if (check_fs_bitmaps(argv[0])) 870 return; 871 if (current_journal) { 872 printf("Journal is already open.\n"); 873 return; 874 } 875 if (!ext2fs_has_feature_journal(current_fs->super)) { 876 printf("Journalling is not enabled on this filesystem.\n"); 877 return; 878 } 879 880 reset_getopt(); 881 while ((opt = getopt(argc, argv, "cv:f:")) != -1) { 882 switch (opt) { 883 case 'c': 884 enable_csum = 1; 885 break; 886 case 'f': 887 if (current_fs->journal_name) 888 free(current_fs->journal_name); 889 current_fs->journal_name = strdup(optarg); 890 break; 891 case 'v': 892 csum_ver = atoi(optarg); 893 if (csum_ver != 2 && csum_ver != 3) { 894 printf("Unknown journal csum v%d\n", csum_ver); 895 csum_ver = 3; 896 } 897 break; 898 default: 899 printf("%s: [-c] [-v ver] [-f ext_jnl]\n", argv[0]); 900 printf("-c: Enable journal checksumming.\n"); 901 printf("-v: Use this version checksum format.\n"); 902 printf("-j: Load this external journal.\n"); 903 } 904 } 905 906 err = ext2fs_open_journal(current_fs, ¤t_journal); 907 if (err) { 908 com_err(argv[0], err, "while opening journal"); 909 return; 910 } 911 journal = current_journal; 912 913 dbg_printf("JOURNAL: seq=%d tailseq=%d start=%lu first=%lu " 914 "maxlen=%lu\n", journal->j_tail_sequence, 915 journal->j_transaction_sequence, journal->j_tail, 916 journal->j_first, journal->j_last); 917 918 update_uuid(journal); 919 update_64bit_flag(journal); 920 if (enable_csum) 921 update_journal_csum(journal, csum_ver); 922 923 err = journal_find_head(journal); 924 if (err) 925 com_err(argv[0], err, "while examining journal"); 926 } 927 928 void do_journal_close(int argc EXT2FS_ATTR((unused)), 929 char *argv[] EXT2FS_ATTR((unused))) 930 { 931 if (current_journal == NULL) { 932 printf("Journal not open.\n"); 933 return; 934 } 935 936 ext2fs_close_journal(current_fs, ¤t_journal); 937 } 938 939 void do_journal_run(int argc EXT2FS_ATTR((unused)), char *argv[]) 940 { 941 errcode_t err; 942 943 if (check_fs_open(argv[0])) 944 return; 945 if (check_fs_read_write(argv[0])) 946 return; 947 if (check_fs_bitmaps(argv[0])) 948 return; 949 if (current_journal) { 950 printf("Please close the journal before recovering it.\n"); 951 return; 952 } 953 954 err = ext2fs_run_ext3_journal(¤t_fs); 955 if (err) 956 com_err("journal_run", err, "while recovering journal"); 957 else { 958 ext2fs_clear_feature_journal_needs_recovery(current_fs->super); 959 ext2fs_mark_super_dirty(current_fs); 960 } 961 } 962