|
@@ -124,7 +124,7 @@ EXPORT_SYMBOL(__jbd2_debug);
|
|
|
/* Checksumming functions */
|
|
|
static int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
|
|
|
{
|
|
|
- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
|
|
+ if (!jbd2_journal_has_csum_v2or3(j))
|
|
|
return 1;
|
|
|
|
|
|
return sb->s_checksum_type == JBD2_CRC32C_CHKSUM;
|
|
@@ -145,7 +145,7 @@ static __be32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb)
|
|
|
|
|
|
static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
|
|
|
{
|
|
|
- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
|
|
+ if (!jbd2_journal_has_csum_v2or3(j))
|
|
|
return 1;
|
|
|
|
|
|
return sb->s_checksum == jbd2_superblock_csum(j, sb);
|
|
@@ -153,7 +153,7 @@ static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
|
|
|
|
|
|
static void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
|
|
|
{
|
|
|
- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
|
|
+ if (!jbd2_journal_has_csum_v2or3(j))
|
|
|
return;
|
|
|
|
|
|
sb->s_checksum = jbd2_superblock_csum(j, sb);
|
|
@@ -1522,21 +1522,29 @@ static int journal_get_superblock(journal_t *journal)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) &&
|
|
|
- JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
|
|
|
+ if (jbd2_journal_has_csum_v2or3(journal) &&
|
|
|
+ JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM)) {
|
|
|
/* Can't have checksum v1 and v2 on at the same time! */
|
|
|
printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 "
|
|
|
"at the same time!\n");
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) &&
|
|
|
+ JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
|
|
|
+ /* Can't have checksum v2 and v3 at the same time! */
|
|
|
+ printk(KERN_ERR "JBD2: Can't enable checksumming v2 and v3 "
|
|
|
+ "at the same time!\n");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
if (!jbd2_verify_csum_type(journal, sb)) {
|
|
|
printk(KERN_ERR "JBD2: Unknown checksum type\n");
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
/* Load the checksum driver */
|
|
|
- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
|
|
|
+ if (jbd2_journal_has_csum_v2or3(journal)) {
|
|
|
journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
|
|
|
if (IS_ERR(journal->j_chksum_driver)) {
|
|
|
printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
|
|
@@ -1553,7 +1561,7 @@ static int journal_get_superblock(journal_t *journal)
|
|
|
}
|
|
|
|
|
|
/* Precompute checksum seed for all metadata */
|
|
|
- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
|
|
+ if (jbd2_journal_has_csum_v2or3(journal))
|
|
|
journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
|
|
|
sizeof(sb->s_uuid));
|
|
|
|
|
@@ -1813,8 +1821,14 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
|
|
|
if (!jbd2_journal_check_available_features(journal, compat, ro, incompat))
|
|
|
return 0;
|
|
|
|
|
|
- /* Asking for checksumming v2 and v1? Only give them v2. */
|
|
|
- if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2 &&
|
|
|
+ /* If enabling v2 checksums, turn on v3 instead */
|
|
|
+ if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2) {
|
|
|
+ incompat &= ~JBD2_FEATURE_INCOMPAT_CSUM_V2;
|
|
|
+ incompat |= JBD2_FEATURE_INCOMPAT_CSUM_V3;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Asking for checksumming v3 and v1? Only give them v3. */
|
|
|
+ if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V3 &&
|
|
|
compat & JBD2_FEATURE_COMPAT_CHECKSUM)
|
|
|
compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM;
|
|
|
|
|
@@ -1823,8 +1837,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
|
|
|
|
|
|
sb = journal->j_superblock;
|
|
|
|
|
|
- /* If enabling v2 checksums, update superblock */
|
|
|
- if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
|
|
|
+ /* If enabling v3 checksums, update superblock */
|
|
|
+ if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
|
|
|
sb->s_checksum_type = JBD2_CRC32C_CHKSUM;
|
|
|
sb->s_feature_compat &=
|
|
|
~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
|
|
@@ -1842,8 +1856,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
|
|
|
}
|
|
|
|
|
|
/* Precompute checksum seed for all metadata */
|
|
|
- if (JBD2_HAS_INCOMPAT_FEATURE(journal,
|
|
|
- JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
|
|
+ if (jbd2_journal_has_csum_v2or3(journal))
|
|
|
journal->j_csum_seed = jbd2_chksum(journal, ~0,
|
|
|
sb->s_uuid,
|
|
|
sizeof(sb->s_uuid));
|
|
@@ -1852,7 +1865,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
|
|
|
/* If enabling v1 checksums, downgrade superblock */
|
|
|
if (COMPAT_FEATURE_ON(JBD2_FEATURE_COMPAT_CHECKSUM))
|
|
|
sb->s_feature_incompat &=
|
|
|
- ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2);
|
|
|
+ ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2 |
|
|
|
+ JBD2_FEATURE_INCOMPAT_CSUM_V3);
|
|
|
|
|
|
sb->s_feature_compat |= cpu_to_be32(compat);
|
|
|
sb->s_feature_ro_compat |= cpu_to_be32(ro);
|
|
@@ -2165,16 +2179,20 @@ int jbd2_journal_blocks_per_page(struct inode *inode)
|
|
|
*/
|
|
|
size_t journal_tag_bytes(journal_t *journal)
|
|
|
{
|
|
|
- journal_block_tag_t tag;
|
|
|
- size_t x = 0;
|
|
|
+ size_t sz;
|
|
|
+
|
|
|
+ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3))
|
|
|
+ return sizeof(journal_block_tag3_t);
|
|
|
+
|
|
|
+ sz = sizeof(journal_block_tag_t);
|
|
|
|
|
|
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
|
|
|
- x += sizeof(tag.t_checksum);
|
|
|
+ sz += sizeof(__u16);
|
|
|
|
|
|
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
|
|
|
- return x + JBD2_TAG_SIZE64;
|
|
|
+ return sz;
|
|
|
else
|
|
|
- return x + JBD2_TAG_SIZE32;
|
|
|
+ return sz - sizeof(__u32);
|
|
|
}
|
|
|
|
|
|
/*
|