aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/journal.c47
-rw-r--r--include/linux/jbd2.h3
2 files changed, 50 insertions, 0 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index f04ab6c4b428..9072f03d30b5 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -106,6 +106,34 @@ int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
106 return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; 106 return sb->s_checksum_type == JBD2_CRC32C_CHKSUM;
107} 107}
108 108
109static __u32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb)
110{
111 __u32 csum, old_csum;
112
113 old_csum = sb->s_checksum;
114 sb->s_checksum = 0;
115 csum = jbd2_chksum(j, ~0, (char *)sb, sizeof(journal_superblock_t));
116 sb->s_checksum = old_csum;
117
118 return cpu_to_be32(csum);
119}
120
121int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
122{
123 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
124 return 1;
125
126 return sb->s_checksum == jbd2_superblock_csum(j, sb);
127}
128
129void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
130{
131 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
132 return;
133
134 sb->s_checksum = jbd2_superblock_csum(j, sb);
135}
136
109/* 137/*
110 * Helper function used to manage commit timeouts 138 * Helper function used to manage commit timeouts
111 */ 139 */
@@ -1357,6 +1385,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal)
1357 jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", 1385 jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
1358 journal->j_errno); 1386 journal->j_errno);
1359 sb->s_errno = cpu_to_be32(journal->j_errno); 1387 sb->s_errno = cpu_to_be32(journal->j_errno);
1388 jbd2_superblock_csum_set(journal, sb);
1360 read_unlock(&journal->j_state_lock); 1389 read_unlock(&journal->j_state_lock);
1361 1390
1362 jbd2_write_superblock(journal, WRITE_SYNC); 1391 jbd2_write_superblock(journal, WRITE_SYNC);
@@ -1449,6 +1478,17 @@ static int journal_get_superblock(journal_t *journal)
1449 } 1478 }
1450 } 1479 }
1451 1480
1481 /* Check superblock checksum */
1482 if (!jbd2_superblock_csum_verify(journal, sb)) {
1483 printk(KERN_ERR "JBD: journal checksum error\n");
1484 goto out;
1485 }
1486
1487 /* Precompute checksum seed for all metadata */
1488 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
1489 journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
1490 sizeof(sb->s_uuid));
1491
1452 set_buffer_verified(bh); 1492 set_buffer_verified(bh);
1453 1493
1454 return 0; 1494 return 0;
@@ -1732,6 +1772,13 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
1732 return 0; 1772 return 0;
1733 } 1773 }
1734 } 1774 }
1775
1776 /* Precompute checksum seed for all metadata */
1777 if (JBD2_HAS_INCOMPAT_FEATURE(journal,
1778 JBD2_FEATURE_INCOMPAT_CSUM_V2))
1779 journal->j_csum_seed = jbd2_chksum(journal, ~0,
1780 sb->s_uuid,
1781 sizeof(sb->s_uuid));
1735 } 1782 }
1736 1783
1737 /* If enabling v1 checksums, downgrade superblock */ 1784 /* If enabling v1 checksums, downgrade superblock */
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 71e77dddebf1..a9632bc55d97 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -969,6 +969,9 @@ struct journal_s
969 969
970 /* Reference to checksum algorithm driver via cryptoapi */ 970 /* Reference to checksum algorithm driver via cryptoapi */
971 struct crypto_shash *j_chksum_driver; 971 struct crypto_shash *j_chksum_driver;
972
973 /* Precomputed journal UUID checksum for seeding other checksums */
974 __u32 j_csum_seed;
972}; 975};
973 976
974/* 977/*