.. | .. |
---|
35 | 35 | int nr_revoke_hits; |
---|
36 | 36 | }; |
---|
37 | 37 | |
---|
38 | | -enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY}; |
---|
39 | 38 | static int do_one_pass(journal_t *journal, |
---|
40 | 39 | struct recovery_info *info, enum passtype pass); |
---|
41 | 40 | static int scan_revoke_records(journal_t *, struct buffer_head *, |
---|
.. | .. |
---|
75 | 74 | |
---|
76 | 75 | /* Do up to 128K of readahead */ |
---|
77 | 76 | max = start + (128 * 1024 / journal->j_blocksize); |
---|
78 | | - if (max > journal->j_maxlen) |
---|
79 | | - max = journal->j_maxlen; |
---|
| 77 | + if (max > journal->j_total_len) |
---|
| 78 | + max = journal->j_total_len; |
---|
80 | 79 | |
---|
81 | 80 | /* Do the readahead itself. We'll submit MAXBUF buffer_heads at |
---|
82 | 81 | * a time to the block device IO layer. */ |
---|
.. | .. |
---|
135 | 134 | |
---|
136 | 135 | *bhp = NULL; |
---|
137 | 136 | |
---|
138 | | - if (offset >= journal->j_maxlen) { |
---|
| 137 | + if (offset >= journal->j_total_len) { |
---|
139 | 138 | printk(KERN_ERR "JBD2: corrupted journal superblock\n"); |
---|
140 | 139 | return -EFSCORRUPTED; |
---|
141 | 140 | } |
---|
.. | .. |
---|
225 | 224 | /* Make sure we wrap around the log correctly! */ |
---|
226 | 225 | #define wrap(journal, var) \ |
---|
227 | 226 | do { \ |
---|
228 | | - if (var >= (journal)->j_last) \ |
---|
229 | | - var -= ((journal)->j_last - (journal)->j_first); \ |
---|
| 227 | + unsigned long _wrap_last = \ |
---|
| 228 | + jbd2_has_feature_fast_commit(journal) ? \ |
---|
| 229 | + (journal)->j_fc_last : (journal)->j_last; \ |
---|
| 230 | + \ |
---|
| 231 | + if (var >= _wrap_last) \ |
---|
| 232 | + var -= (_wrap_last - (journal)->j_first); \ |
---|
230 | 233 | } while (0) |
---|
| 234 | + |
---|
| 235 | +static int fc_do_one_pass(journal_t *journal, |
---|
| 236 | + struct recovery_info *info, enum passtype pass) |
---|
| 237 | +{ |
---|
| 238 | + unsigned int expected_commit_id = info->end_transaction; |
---|
| 239 | + unsigned long next_fc_block; |
---|
| 240 | + struct buffer_head *bh; |
---|
| 241 | + int err = 0; |
---|
| 242 | + |
---|
| 243 | + next_fc_block = journal->j_fc_first; |
---|
| 244 | + if (!journal->j_fc_replay_callback) |
---|
| 245 | + return 0; |
---|
| 246 | + |
---|
| 247 | + while (next_fc_block <= journal->j_fc_last) { |
---|
| 248 | + jbd_debug(3, "Fast commit replay: next block %ld\n", |
---|
| 249 | + next_fc_block); |
---|
| 250 | + err = jread(&bh, journal, next_fc_block); |
---|
| 251 | + if (err) { |
---|
| 252 | + jbd_debug(3, "Fast commit replay: read error\n"); |
---|
| 253 | + break; |
---|
| 254 | + } |
---|
| 255 | + |
---|
| 256 | + err = journal->j_fc_replay_callback(journal, bh, pass, |
---|
| 257 | + next_fc_block - journal->j_fc_first, |
---|
| 258 | + expected_commit_id); |
---|
| 259 | + brelse(bh); |
---|
| 260 | + next_fc_block++; |
---|
| 261 | + if (err < 0 || err == JBD2_FC_REPLAY_STOP) |
---|
| 262 | + break; |
---|
| 263 | + err = 0; |
---|
| 264 | + } |
---|
| 265 | + |
---|
| 266 | + if (err) |
---|
| 267 | + jbd_debug(3, "Fast commit replay failed, err = %d\n", err); |
---|
| 268 | + |
---|
| 269 | + return err; |
---|
| 270 | +} |
---|
231 | 271 | |
---|
232 | 272 | /** |
---|
233 | 273 | * jbd2_journal_recover - recovers a on-disk journal |
---|
.. | .. |
---|
286 | 326 | err = err2; |
---|
287 | 327 | /* Make sure all replayed data is on permanent storage */ |
---|
288 | 328 | if (journal->j_flags & JBD2_BARRIER) { |
---|
289 | | - err2 = blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); |
---|
| 329 | + err2 = blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL); |
---|
290 | 330 | if (!err) |
---|
291 | 331 | err = err2; |
---|
292 | 332 | } |
---|
.. | .. |
---|
428 | 468 | __u32 crc32_sum = ~0; /* Transactional Checksums */ |
---|
429 | 469 | int descr_csum_size = 0; |
---|
430 | 470 | int block_error = 0; |
---|
| 471 | + bool need_check_commit_time = false; |
---|
| 472 | + __u64 last_trans_commit_time = 0, commit_time; |
---|
431 | 473 | |
---|
432 | 474 | /* |
---|
433 | 475 | * First thing is to establish what we expect to find in the log |
---|
.. | .. |
---|
470 | 512 | break; |
---|
471 | 513 | |
---|
472 | 514 | jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n", |
---|
473 | | - next_commit_ID, next_log_block, journal->j_last); |
---|
| 515 | + next_commit_ID, next_log_block, |
---|
| 516 | + jbd2_has_feature_fast_commit(journal) ? |
---|
| 517 | + journal->j_fc_last : journal->j_last); |
---|
474 | 518 | |
---|
475 | 519 | /* Skip over each chunk of the transaction looking |
---|
476 | 520 | * either the next descriptor block or the final commit |
---|
.. | .. |
---|
520 | 564 | if (descr_csum_size > 0 && |
---|
521 | 565 | !jbd2_descriptor_block_csum_verify(journal, |
---|
522 | 566 | bh->b_data)) { |
---|
523 | | - printk(KERN_ERR "JBD2: Invalid checksum " |
---|
524 | | - "recovering block %lu in log\n", |
---|
525 | | - next_log_block); |
---|
526 | | - err = -EFSBADCRC; |
---|
527 | | - brelse(bh); |
---|
528 | | - goto failed; |
---|
| 567 | + /* |
---|
| 568 | + * PASS_SCAN can see stale blocks due to lazy |
---|
| 569 | + * journal init. Don't error out on those yet. |
---|
| 570 | + */ |
---|
| 571 | + if (pass != PASS_SCAN) { |
---|
| 572 | + pr_err("JBD2: Invalid checksum recovering block %lu in log\n", |
---|
| 573 | + next_log_block); |
---|
| 574 | + err = -EFSBADCRC; |
---|
| 575 | + brelse(bh); |
---|
| 576 | + goto failed; |
---|
| 577 | + } |
---|
| 578 | + need_check_commit_time = true; |
---|
| 579 | + jbd_debug(1, |
---|
| 580 | + "invalid descriptor block found in %lu\n", |
---|
| 581 | + next_log_block); |
---|
529 | 582 | } |
---|
530 | 583 | |
---|
531 | 584 | /* If it is a valid descriptor block, replay it |
---|
.. | .. |
---|
535 | 588 | if (pass != PASS_REPLAY) { |
---|
536 | 589 | if (pass == PASS_SCAN && |
---|
537 | 590 | jbd2_has_feature_checksum(journal) && |
---|
| 591 | + !need_check_commit_time && |
---|
538 | 592 | !info->end_transaction) { |
---|
539 | 593 | if (calc_chksums(journal, bh, |
---|
540 | 594 | &next_log_block, |
---|
.. | .. |
---|
683 | 737 | * mentioned conditions. Hence assume |
---|
684 | 738 | * "Interrupted Commit".) |
---|
685 | 739 | */ |
---|
| 740 | + commit_time = be64_to_cpu( |
---|
| 741 | + ((struct commit_header *)bh->b_data)->h_commit_sec); |
---|
| 742 | + /* |
---|
| 743 | + * If need_check_commit_time is set, it means we are in |
---|
| 744 | + * PASS_SCAN and csum verify failed before. If |
---|
| 745 | + * commit_time is increasing, it's the same journal, |
---|
| 746 | + * otherwise it is stale journal block, just end this |
---|
| 747 | + * recovery. |
---|
| 748 | + */ |
---|
| 749 | + if (need_check_commit_time) { |
---|
| 750 | + if (commit_time >= last_trans_commit_time) { |
---|
| 751 | + pr_err("JBD2: Invalid checksum found in transaction %u\n", |
---|
| 752 | + next_commit_ID); |
---|
| 753 | + err = -EFSBADCRC; |
---|
| 754 | + brelse(bh); |
---|
| 755 | + goto failed; |
---|
| 756 | + } |
---|
| 757 | + ignore_crc_mismatch: |
---|
| 758 | + /* |
---|
| 759 | + * It likely does not belong to same journal, |
---|
| 760 | + * just end this recovery with success. |
---|
| 761 | + */ |
---|
| 762 | + jbd_debug(1, "JBD2: Invalid checksum ignored in transaction %u, likely stale data\n", |
---|
| 763 | + next_commit_ID); |
---|
| 764 | + err = 0; |
---|
| 765 | + brelse(bh); |
---|
| 766 | + goto done; |
---|
| 767 | + } |
---|
686 | 768 | |
---|
687 | | - /* Found an expected commit block: if checksums |
---|
688 | | - * are present verify them in PASS_SCAN; else not |
---|
| 769 | + /* |
---|
| 770 | + * Found an expected commit block: if checksums |
---|
| 771 | + * are present, verify them in PASS_SCAN; else not |
---|
689 | 772 | * much to do other than move on to the next sequence |
---|
690 | | - * number. */ |
---|
| 773 | + * number. |
---|
| 774 | + */ |
---|
691 | 775 | if (pass == PASS_SCAN && |
---|
692 | 776 | jbd2_has_feature_checksum(journal)) { |
---|
693 | | - int chksum_err, chksum_seen; |
---|
694 | 777 | struct commit_header *cbh = |
---|
695 | 778 | (struct commit_header *)bh->b_data; |
---|
696 | 779 | unsigned found_chksum = |
---|
697 | 780 | be32_to_cpu(cbh->h_chksum[0]); |
---|
698 | | - |
---|
699 | | - chksum_err = chksum_seen = 0; |
---|
700 | 781 | |
---|
701 | 782 | if (info->end_transaction) { |
---|
702 | 783 | journal->j_failed_commit = |
---|
.. | .. |
---|
705 | 786 | break; |
---|
706 | 787 | } |
---|
707 | 788 | |
---|
708 | | - if (crc32_sum == found_chksum && |
---|
709 | | - cbh->h_chksum_type == JBD2_CRC32_CHKSUM && |
---|
710 | | - cbh->h_chksum_size == |
---|
711 | | - JBD2_CRC32_CHKSUM_SIZE) |
---|
712 | | - chksum_seen = 1; |
---|
713 | | - else if (!(cbh->h_chksum_type == 0 && |
---|
714 | | - cbh->h_chksum_size == 0 && |
---|
715 | | - found_chksum == 0 && |
---|
716 | | - !chksum_seen)) |
---|
717 | | - /* |
---|
718 | | - * If fs is mounted using an old kernel and then |
---|
719 | | - * kernel with journal_chksum is used then we |
---|
720 | | - * get a situation where the journal flag has |
---|
721 | | - * checksum flag set but checksums are not |
---|
722 | | - * present i.e chksum = 0, in the individual |
---|
723 | | - * commit blocks. |
---|
724 | | - * Hence to avoid checksum failures, in this |
---|
725 | | - * situation, this extra check is added. |
---|
726 | | - */ |
---|
727 | | - chksum_err = 1; |
---|
| 789 | + /* Neither checksum match nor unused? */ |
---|
| 790 | + if (!((crc32_sum == found_chksum && |
---|
| 791 | + cbh->h_chksum_type == |
---|
| 792 | + JBD2_CRC32_CHKSUM && |
---|
| 793 | + cbh->h_chksum_size == |
---|
| 794 | + JBD2_CRC32_CHKSUM_SIZE) || |
---|
| 795 | + (cbh->h_chksum_type == 0 && |
---|
| 796 | + cbh->h_chksum_size == 0 && |
---|
| 797 | + found_chksum == 0))) |
---|
| 798 | + goto chksum_error; |
---|
728 | 799 | |
---|
729 | | - if (chksum_err) { |
---|
730 | | - info->end_transaction = next_commit_ID; |
---|
731 | | - |
---|
732 | | - if (!jbd2_has_feature_async_commit(journal)) { |
---|
733 | | - journal->j_failed_commit = |
---|
734 | | - next_commit_ID; |
---|
735 | | - brelse(bh); |
---|
736 | | - break; |
---|
737 | | - } |
---|
738 | | - } |
---|
739 | 800 | crc32_sum = ~0; |
---|
740 | 801 | } |
---|
741 | 802 | if (pass == PASS_SCAN && |
---|
742 | 803 | !jbd2_commit_block_csum_verify(journal, |
---|
743 | 804 | bh->b_data)) { |
---|
| 805 | + chksum_error: |
---|
| 806 | + if (commit_time < last_trans_commit_time) |
---|
| 807 | + goto ignore_crc_mismatch; |
---|
744 | 808 | info->end_transaction = next_commit_ID; |
---|
745 | 809 | |
---|
746 | 810 | if (!jbd2_has_feature_async_commit(journal)) { |
---|
.. | .. |
---|
750 | 814 | break; |
---|
751 | 815 | } |
---|
752 | 816 | } |
---|
| 817 | + if (pass == PASS_SCAN) |
---|
| 818 | + last_trans_commit_time = commit_time; |
---|
753 | 819 | brelse(bh); |
---|
754 | 820 | next_commit_ID++; |
---|
755 | 821 | continue; |
---|
756 | 822 | |
---|
757 | 823 | case JBD2_REVOKE_BLOCK: |
---|
| 824 | + /* |
---|
| 825 | + * Check revoke block crc in pass_scan, if csum verify |
---|
| 826 | + * failed, check commit block time later. |
---|
| 827 | + */ |
---|
| 828 | + if (pass == PASS_SCAN && |
---|
| 829 | + !jbd2_descriptor_block_csum_verify(journal, |
---|
| 830 | + bh->b_data)) { |
---|
| 831 | + jbd_debug(1, "JBD2: invalid revoke block found in %lu\n", |
---|
| 832 | + next_log_block); |
---|
| 833 | + need_check_commit_time = true; |
---|
| 834 | + } |
---|
758 | 835 | /* If we aren't in the REVOKE pass, then we can |
---|
759 | 836 | * just skip over this block. */ |
---|
760 | 837 | if (pass != PASS_REVOKE) { |
---|
.. | .. |
---|
799 | 876 | success = -EIO; |
---|
800 | 877 | } |
---|
801 | 878 | } |
---|
| 879 | + |
---|
| 880 | + if (jbd2_has_feature_fast_commit(journal) && pass != PASS_REVOKE) { |
---|
| 881 | + err = fc_do_one_pass(journal, info, pass); |
---|
| 882 | + if (err) |
---|
| 883 | + success = err; |
---|
| 884 | + } |
---|
| 885 | + |
---|
802 | 886 | if (block_error && success == 0) |
---|
803 | 887 | success = -EIO; |
---|
804 | 888 | return success; |
---|
.. | .. |
---|
821 | 905 | header = (jbd2_journal_revoke_header_t *) bh->b_data; |
---|
822 | 906 | offset = sizeof(jbd2_journal_revoke_header_t); |
---|
823 | 907 | rcount = be32_to_cpu(header->r_count); |
---|
824 | | - |
---|
825 | | - if (!jbd2_descriptor_block_csum_verify(journal, header)) |
---|
826 | | - return -EFSBADCRC; |
---|
827 | 908 | |
---|
828 | 909 | if (jbd2_journal_has_csum_v2or3(journal)) |
---|
829 | 910 | csum_size = sizeof(struct jbd2_journal_block_tail); |
---|