aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/recovery.c22
-rw-r--r--fs/jbd2/revoke.c27
2 files changed, 48 insertions, 1 deletions
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index 980f3d6b5f88..728ecd0705d9 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -706,6 +706,25 @@ static int do_one_pass(journal_t *journal,
706 return err; 706 return err;
707} 707}
708 708
709static int jbd2_revoke_block_csum_verify(journal_t *j,
710 void *buf)
711{
712 struct jbd2_journal_revoke_tail *tail;
713 __u32 provided, calculated;
714
715 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
716 return 1;
717
718 tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize -
719 sizeof(struct jbd2_journal_revoke_tail));
720 provided = tail->r_checksum;
721 tail->r_checksum = 0;
722 calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
723 tail->r_checksum = provided;
724
725 provided = be32_to_cpu(provided);
726 return provided == calculated;
727}
709 728
710/* Scan a revoke record, marking all blocks mentioned as revoked. */ 729/* Scan a revoke record, marking all blocks mentioned as revoked. */
711 730
@@ -720,6 +739,9 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
720 offset = sizeof(jbd2_journal_revoke_header_t); 739 offset = sizeof(jbd2_journal_revoke_header_t);
721 max = be32_to_cpu(header->r_count); 740 max = be32_to_cpu(header->r_count);
722 741
742 if (!jbd2_revoke_block_csum_verify(journal, header))
743 return -EINVAL;
744
723 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) 745 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
724 record_len = 8; 746 record_len = 8;
725 747
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 6973705d6a3d..f30b80b4ce8b 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -578,6 +578,7 @@ static void write_one_revoke_record(journal_t *journal,
578 struct jbd2_revoke_record_s *record, 578 struct jbd2_revoke_record_s *record,
579 int write_op) 579 int write_op)
580{ 580{
581 int csum_size = 0;
581 struct journal_head *descriptor; 582 struct journal_head *descriptor;
582 int offset; 583 int offset;
583 journal_header_t *header; 584 journal_header_t *header;
@@ -592,9 +593,13 @@ static void write_one_revoke_record(journal_t *journal,
592 descriptor = *descriptorp; 593 descriptor = *descriptorp;
593 offset = *offsetp; 594 offset = *offsetp;
594 595
596 /* Do we need to leave space at the end for a checksum? */
597 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
598 csum_size = sizeof(struct jbd2_journal_revoke_tail);
599
595 /* Make sure we have a descriptor with space left for the record */ 600 /* Make sure we have a descriptor with space left for the record */
596 if (descriptor) { 601 if (descriptor) {
597 if (offset == journal->j_blocksize) { 602 if (offset >= journal->j_blocksize - csum_size) {
598 flush_descriptor(journal, descriptor, offset, write_op); 603 flush_descriptor(journal, descriptor, offset, write_op);
599 descriptor = NULL; 604 descriptor = NULL;
600 } 605 }
@@ -631,6 +636,24 @@ static void write_one_revoke_record(journal_t *journal,
631 *offsetp = offset; 636 *offsetp = offset;
632} 637}
633 638
639static void jbd2_revoke_csum_set(journal_t *j,
640 struct journal_head *descriptor)
641{
642 struct jbd2_journal_revoke_tail *tail;
643 __u32 csum;
644
645 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
646 return;
647
648 tail = (struct jbd2_journal_revoke_tail *)
649 (jh2bh(descriptor)->b_data + j->j_blocksize -
650 sizeof(struct jbd2_journal_revoke_tail));
651 tail->r_checksum = 0;
652 csum = jbd2_chksum(j, j->j_csum_seed, jh2bh(descriptor)->b_data,
653 j->j_blocksize);
654 tail->r_checksum = cpu_to_be32(csum);
655}
656
634/* 657/*
635 * Flush a revoke descriptor out to the journal. If we are aborting, 658 * Flush a revoke descriptor out to the journal. If we are aborting,
636 * this is a noop; otherwise we are generating a buffer which needs to 659 * this is a noop; otherwise we are generating a buffer which needs to
@@ -652,6 +675,8 @@ static void flush_descriptor(journal_t *journal,
652 675
653 header = (jbd2_journal_revoke_header_t *) jh2bh(descriptor)->b_data; 676 header = (jbd2_journal_revoke_header_t *) jh2bh(descriptor)->b_data;
654 header->r_count = cpu_to_be32(offset); 677 header->r_count = cpu_to_be32(offset);
678 jbd2_revoke_csum_set(journal, descriptor);
679
655 set_buffer_jwrite(bh); 680 set_buffer_jwrite(bh);
656 BUFFER_TRACE(bh, "write"); 681 BUFFER_TRACE(bh, "write");
657 set_buffer_dirty(bh); 682 set_buffer_dirty(bh);