lkml.org 
[lkml]   [2012]   [Jan]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH 16/23] jbd2: Enable journal clients to enable v2 checksumming
    From
    Date
    Add in the necessary code so that journal clients can enable the new journal
    checksumming features.

    Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
    ---
    fs/ext4/super.c | 55 ++++++++++++++++++++++++++++++++++++++++-------------
    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 1b2d91b..1d7c5fb 100644
    --- a/fs/ext4/super.c
    +++ b/fs/ext4/super.c
    @@ -3172,6 +3172,44 @@ static void ext4_destroy_lazyinit_thread(void)
    kthread_stop(ext4_lazyinit_task);
    }

    +static int set_journal_csum_feature_set(struct super_block *sb)
    +{
    + int ret = 1;
    + int compat, incompat;
    + struct ext4_sb_info *sbi = EXT4_SB(sb);
    +
    + if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
    + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
    + /* journal checksum v2 */
    + compat = 0;
    + incompat = JBD2_FEATURE_INCOMPAT_CSUM_V2;
    + } else {
    + /* journal checksum v1 */
    + compat = JBD2_FEATURE_COMPAT_CHECKSUM;
    + incompat = 0;
    + }
    +
    + if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
    + ret = jbd2_journal_set_features(sbi->s_journal,
    + compat, 0,
    + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT |
    + incompat);
    + } else if (test_opt(sb, JOURNAL_CHECKSUM)) {
    + ret = jbd2_journal_set_features(sbi->s_journal,
    + compat, 0,
    + incompat);
    + jbd2_journal_clear_features(sbi->s_journal, 0, 0,
    + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
    + } else {
    + jbd2_journal_clear_features(sbi->s_journal,
    + JBD2_FEATURE_COMPAT_CHECKSUM, 0,
    + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT |
    + JBD2_FEATURE_INCOMPAT_CSUM_V2);
    + }
    +
    + return ret;
    +}
    +
    static int ext4_fill_super(struct super_block *sb, void *data, int silent)
    {
    char *orig_data = kstrdup(data, GFP_KERNEL);
    @@ -3761,19 +3799,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
    goto failed_mount_wq;
    }

    - if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
    - jbd2_journal_set_features(sbi->s_journal,
    - JBD2_FEATURE_COMPAT_CHECKSUM, 0,
    - JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
    - } else if (test_opt(sb, JOURNAL_CHECKSUM)) {
    - jbd2_journal_set_features(sbi->s_journal,
    - JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
    - jbd2_journal_clear_features(sbi->s_journal, 0, 0,
    - JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
    - } else {
    - jbd2_journal_clear_features(sbi->s_journal,
    - JBD2_FEATURE_COMPAT_CHECKSUM, 0,
    - JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
    + if (!set_journal_csum_feature_set(sb)) {
    + ext4_msg(sb, KERN_ERR, "Failed to set journal checksum "
    + "feature set");
    + goto failed_mount_wq;
    }

    /* We have now updated the journal if required, so we can
    diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
    index 0fa0123..300b46f 100644
    --- a/fs/jbd2/journal.c
    +++ b/fs/jbd2/journal.c
    @@ -100,6 +100,15 @@ static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
    static void __journal_abort_soft (journal_t *journal, int errno);
    static int jbd2_journal_create_slab(size_t slab_size);

    +/* Checksumming functions */
    +int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
    +{
    + if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
    + return 1;
    +
    + return sb->s_checksum_type == JBD2_CRC32C_CHKSUM;
    +}
    +
    /*
    * Helper function used to manage commit timeouts
    */
    @@ -1222,6 +1231,9 @@ static int journal_get_superblock(journal_t *journal)
    }
    }

    + if (buffer_verified(bh))
    + return 0;
    +
    sb = journal->j_superblock;

    err = -EINVAL;
    @@ -1259,6 +1271,21 @@ 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)) {
    + /* Can't have checksum v1 and v2 on at the same time! */
    + printk(KERN_ERR "JBD: Can't enable checksumming v1 and v2 "
    + "at the same time!\n");
    + goto out;
    + }
    +
    + if (!jbd2_verify_csum_type(journal, sb)) {
    + printk(KERN_ERR "JBD: Unknown checksum type\n");
    + goto out;
    + }
    +
    + set_buffer_verified(bh);
    +
    return 0;

    out:
    @@ -1502,6 +1529,10 @@ int jbd2_journal_check_available_features (journal_t *journal, unsigned long com
    int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
    unsigned long ro, unsigned long incompat)
    {
    +#define INCOMPAT_FEATURE_ON(f) \
    + ((incompat & (f)) && !(sb->s_feature_incompat & cpu_to_be32(f)))
    +#define COMPAT_FEATURE_ON(f) \
    + ((compat & (f)) && !(sb->s_feature_compat & cpu_to_be32(f)))
    journal_superblock_t *sb;

    if (jbd2_journal_check_used_features(journal, compat, ro, incompat))
    @@ -1510,16 +1541,35 @@ 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 &&
    + compat & JBD2_FEATURE_COMPAT_CHECKSUM)
    + compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM;
    +
    jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n",
    compat, ro, incompat);

    sb = journal->j_superblock;

    + /* If enabling v2 checksums, update superblock */
    + if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
    + sb->s_checksum_type = JBD2_CRC32C_CHKSUM;
    + sb->s_feature_compat &=
    + ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
    + }
    +
    + /* 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);
    +
    sb->s_feature_compat |= cpu_to_be32(compat);
    sb->s_feature_ro_compat |= cpu_to_be32(ro);
    sb->s_feature_incompat |= cpu_to_be32(incompat);

    return 1;
    +#undef COMPAT_FEATURE_ON
    +#undef INCOMPAT_FEATURE_ON
    }

    /*


    \
     
     \ /
      Last update: 2012-01-07 09:33    [W:0.029 / U:32.436 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site