diff options
-rw-r--r-- | fs/ext4/super.c | 55 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 50 |
2 files changed, 92 insertions, 13 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 88c2054fb938..8dfb42e380ea 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -3013,6 +3013,44 @@ static void ext4_destroy_lazyinit_thread(void) | |||
3013 | kthread_stop(ext4_lazyinit_task); | 3013 | kthread_stop(ext4_lazyinit_task); |
3014 | } | 3014 | } |
3015 | 3015 | ||
3016 | static int set_journal_csum_feature_set(struct super_block *sb) | ||
3017 | { | ||
3018 | int ret = 1; | ||
3019 | int compat, incompat; | ||
3020 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
3021 | |||
3022 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
3023 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { | ||
3024 | /* journal checksum v2 */ | ||
3025 | compat = 0; | ||
3026 | incompat = JBD2_FEATURE_INCOMPAT_CSUM_V2; | ||
3027 | } else { | ||
3028 | /* journal checksum v1 */ | ||
3029 | compat = JBD2_FEATURE_COMPAT_CHECKSUM; | ||
3030 | incompat = 0; | ||
3031 | } | ||
3032 | |||
3033 | if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) { | ||
3034 | ret = jbd2_journal_set_features(sbi->s_journal, | ||
3035 | compat, 0, | ||
3036 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | | ||
3037 | incompat); | ||
3038 | } else if (test_opt(sb, JOURNAL_CHECKSUM)) { | ||
3039 | ret = jbd2_journal_set_features(sbi->s_journal, | ||
3040 | compat, 0, | ||
3041 | incompat); | ||
3042 | jbd2_journal_clear_features(sbi->s_journal, 0, 0, | ||
3043 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | ||
3044 | } else { | ||
3045 | jbd2_journal_clear_features(sbi->s_journal, | ||
3046 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, | ||
3047 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | | ||
3048 | JBD2_FEATURE_INCOMPAT_CSUM_V2); | ||
3049 | } | ||
3050 | |||
3051 | return ret; | ||
3052 | } | ||
3053 | |||
3016 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) | 3054 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) |
3017 | { | 3055 | { |
3018 | char *orig_data = kstrdup(data, GFP_KERNEL); | 3056 | char *orig_data = kstrdup(data, GFP_KERNEL); |
@@ -3610,19 +3648,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3610 | goto failed_mount_wq; | 3648 | goto failed_mount_wq; |
3611 | } | 3649 | } |
3612 | 3650 | ||
3613 | if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) { | 3651 | if (!set_journal_csum_feature_set(sb)) { |
3614 | jbd2_journal_set_features(sbi->s_journal, | 3652 | ext4_msg(sb, KERN_ERR, "Failed to set journal checksum " |
3615 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, | 3653 | "feature set"); |
3616 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | 3654 | goto failed_mount_wq; |
3617 | } else if (test_opt(sb, JOURNAL_CHECKSUM)) { | ||
3618 | jbd2_journal_set_features(sbi->s_journal, | ||
3619 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0); | ||
3620 | jbd2_journal_clear_features(sbi->s_journal, 0, 0, | ||
3621 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | ||
3622 | } else { | ||
3623 | jbd2_journal_clear_features(sbi->s_journal, | ||
3624 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, | ||
3625 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | ||
3626 | } | 3655 | } |
3627 | 3656 | ||
3628 | /* We have now updated the journal if required, so we can | 3657 | /* We have now updated the journal if required, so we can |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 1afb701622b0..63175f9391ab 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -97,6 +97,15 @@ EXPORT_SYMBOL(jbd2_inode_cache); | |||
97 | static void __journal_abort_soft (journal_t *journal, int errno); | 97 | static void __journal_abort_soft (journal_t *journal, int errno); |
98 | static int jbd2_journal_create_slab(size_t slab_size); | 98 | static int jbd2_journal_create_slab(size_t slab_size); |
99 | 99 | ||
100 | /* Checksumming functions */ | ||
101 | int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) | ||
102 | { | ||
103 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
104 | return 1; | ||
105 | |||
106 | return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; | ||
107 | } | ||
108 | |||
100 | /* | 109 | /* |
101 | * Helper function used to manage commit timeouts | 110 | * Helper function used to manage commit timeouts |
102 | */ | 111 | */ |
@@ -1376,6 +1385,9 @@ static int journal_get_superblock(journal_t *journal) | |||
1376 | } | 1385 | } |
1377 | } | 1386 | } |
1378 | 1387 | ||
1388 | if (buffer_verified(bh)) | ||
1389 | return 0; | ||
1390 | |||
1379 | sb = journal->j_superblock; | 1391 | sb = journal->j_superblock; |
1380 | 1392 | ||
1381 | err = -EINVAL; | 1393 | err = -EINVAL; |
@@ -1413,6 +1425,21 @@ static int journal_get_superblock(journal_t *journal) | |||
1413 | goto out; | 1425 | goto out; |
1414 | } | 1426 | } |
1415 | 1427 | ||
1428 | if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) && | ||
1429 | JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) { | ||
1430 | /* Can't have checksum v1 and v2 on at the same time! */ | ||
1431 | printk(KERN_ERR "JBD: Can't enable checksumming v1 and v2 " | ||
1432 | "at the same time!\n"); | ||
1433 | goto out; | ||
1434 | } | ||
1435 | |||
1436 | if (!jbd2_verify_csum_type(journal, sb)) { | ||
1437 | printk(KERN_ERR "JBD: Unknown checksum type\n"); | ||
1438 | goto out; | ||
1439 | } | ||
1440 | |||
1441 | set_buffer_verified(bh); | ||
1442 | |||
1416 | return 0; | 1443 | return 0; |
1417 | 1444 | ||
1418 | out: | 1445 | out: |
@@ -1653,6 +1680,10 @@ int jbd2_journal_check_available_features (journal_t *journal, unsigned long com | |||
1653 | int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | 1680 | int jbd2_journal_set_features (journal_t *journal, unsigned long compat, |
1654 | unsigned long ro, unsigned long incompat) | 1681 | unsigned long ro, unsigned long incompat) |
1655 | { | 1682 | { |
1683 | #define INCOMPAT_FEATURE_ON(f) \ | ||
1684 | ((incompat & (f)) && !(sb->s_feature_incompat & cpu_to_be32(f))) | ||
1685 | #define COMPAT_FEATURE_ON(f) \ | ||
1686 | ((compat & (f)) && !(sb->s_feature_compat & cpu_to_be32(f))) | ||
1656 | journal_superblock_t *sb; | 1687 | journal_superblock_t *sb; |
1657 | 1688 | ||
1658 | if (jbd2_journal_check_used_features(journal, compat, ro, incompat)) | 1689 | if (jbd2_journal_check_used_features(journal, compat, ro, incompat)) |
@@ -1661,16 +1692,35 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | |||
1661 | if (!jbd2_journal_check_available_features(journal, compat, ro, incompat)) | 1692 | if (!jbd2_journal_check_available_features(journal, compat, ro, incompat)) |
1662 | return 0; | 1693 | return 0; |
1663 | 1694 | ||
1695 | /* Asking for checksumming v2 and v1? Only give them v2. */ | ||
1696 | if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2 && | ||
1697 | compat & JBD2_FEATURE_COMPAT_CHECKSUM) | ||
1698 | compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM; | ||
1699 | |||
1664 | jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n", | 1700 | jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n", |
1665 | compat, ro, incompat); | 1701 | compat, ro, incompat); |
1666 | 1702 | ||
1667 | sb = journal->j_superblock; | 1703 | sb = journal->j_superblock; |
1668 | 1704 | ||
1705 | /* If enabling v2 checksums, update superblock */ | ||
1706 | if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V2)) { | ||
1707 | sb->s_checksum_type = JBD2_CRC32C_CHKSUM; | ||
1708 | sb->s_feature_compat &= | ||
1709 | ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); | ||
1710 | } | ||
1711 | |||
1712 | /* If enabling v1 checksums, downgrade superblock */ | ||
1713 | if (COMPAT_FEATURE_ON(JBD2_FEATURE_COMPAT_CHECKSUM)) | ||
1714 | sb->s_feature_incompat &= | ||
1715 | ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2); | ||
1716 | |||
1669 | sb->s_feature_compat |= cpu_to_be32(compat); | 1717 | sb->s_feature_compat |= cpu_to_be32(compat); |
1670 | sb->s_feature_ro_compat |= cpu_to_be32(ro); | 1718 | sb->s_feature_ro_compat |= cpu_to_be32(ro); |
1671 | sb->s_feature_incompat |= cpu_to_be32(incompat); | 1719 | sb->s_feature_incompat |= cpu_to_be32(incompat); |
1672 | 1720 | ||
1673 | return 1; | 1721 | return 1; |
1722 | #undef COMPAT_FEATURE_ON | ||
1723 | #undef INCOMPAT_FEATURE_ON | ||
1674 | } | 1724 | } |
1675 | 1725 | ||
1676 | /* | 1726 | /* |