Commit dd348f05 authored by Eric Biggers's avatar Eric Biggers
Browse files

jbd2: switch to using the crc32c library



Now that the crc32c() library function directly takes advantage of
architecture-specific optimizations, it is unnecessary to go through the
crypto API.  Just use crc32c().  This is much simpler, and it improves
performance due to eliminating the crypto API overhead.

Reviewed-by: default avatarArd Biesheuvel <ardb@kernel.org>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Acked-by: default avatarTheodore Ts'o <tytso@mit.edu>
Link: https://lore.kernel.org/r/20241202010844.144356-18-ebiggers@kernel.org


Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
parent f2b4fa19
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -2,8 +2,6 @@
config JBD2
	tristate
	select CRC32
	select CRYPTO
	select CRYPTO_CRC32C
	help
	  This is a generic journaling layer for block devices that support
	  both 32-bit and 64-bit block numbers.  It is currently used by
+3 −27
Original line number Diff line number Diff line
@@ -1369,20 +1369,12 @@ static int journal_check_superblock(journal_t *journal)
		return err;
	}

	/* Load the checksum driver */
	if (jbd2_journal_has_csum_v2or3_feature(journal)) {
		if (sb->s_checksum_type != JBD2_CRC32C_CHKSUM) {
			printk(KERN_ERR "JBD2: Unknown checksum type\n");
			return err;
		}

		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");
			err = PTR_ERR(journal->j_chksum_driver);
			journal->j_chksum_driver = NULL;
			return err;
		}
		/* Check superblock checksum */
		if (sb->s_checksum != jbd2_superblock_csum(journal, sb)) {
			printk(KERN_ERR "JBD2: journal checksum error\n");
@@ -1608,8 +1600,6 @@ static journal_t *journal_init_common(struct block_device *bdev,

err_cleanup:
	percpu_counter_destroy(&journal->j_checkpoint_jh_count);
	if (journal->j_chksum_driver)
		crypto_free_shash(journal->j_chksum_driver);
	kfree(journal->j_wbuf);
	jbd2_journal_destroy_revoke(journal);
	journal_fail_superblock(journal);
@@ -2191,8 +2181,6 @@ int jbd2_journal_destroy(journal_t *journal)
	iput(journal->j_inode);
	if (journal->j_revoke)
		jbd2_journal_destroy_revoke(journal);
	if (journal->j_chksum_driver)
		crypto_free_shash(journal->j_chksum_driver);
	kfree(journal->j_fc_wbuf);
	kfree(journal->j_wbuf);
	kfree(journal);
@@ -2337,27 +2325,15 @@ int jbd2_journal_set_features(journal_t *journal, unsigned long compat,
		}
	}

	/* Load the checksum driver if necessary */
	if ((journal->j_chksum_driver == NULL) &&
	    INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
		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");
			journal->j_chksum_driver = NULL;
			return 0;
		}
		/* Precompute checksum seed for all metadata */
		journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
						   sizeof(sb->s_uuid));
	}

	lock_buffer(journal->j_sb_buffer);

	/* If enabling v3 checksums, update superblock */
	/* If enabling v3 checksums, update superblock and precompute seed */
	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);
		journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
						   sizeof(sb->s_uuid));
	}

	/* If enabling v1 checksums, downgrade superblock */
+3 −30
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@
#include <linux/slab.h>
#include <linux/bit_spinlock.h>
#include <linux/blkdev.h>
#include <crypto/hash.h>
#include <linux/crc32c.h>
#endif

#define journal_oom_retry 1
@@ -1241,13 +1241,6 @@ struct journal_s
	 */
	void *j_private;

	/**
	 * @j_chksum_driver:
	 *
	 * Reference to checksum algorithm driver via cryptoapi.
	 */
	struct crypto_shash *j_chksum_driver;

	/**
	 * @j_csum_seed:
	 *
@@ -1750,10 +1743,7 @@ static inline bool jbd2_journal_has_csum_v2or3_feature(journal_t *j)

static inline int jbd2_journal_has_csum_v2or3(journal_t *journal)
{
	WARN_ON_ONCE(jbd2_journal_has_csum_v2or3_feature(journal) &&
		     journal->j_chksum_driver == NULL);

	return journal->j_chksum_driver != NULL;
	return jbd2_journal_has_csum_v2or3_feature(journal);
}

static inline int jbd2_journal_get_num_fc_blks(journal_superblock_t *jsb)
@@ -1790,27 +1780,10 @@ static inline unsigned long jbd2_log_space_left(journal_t *journal)
#define BJ_Reserved	4	/* Buffer is reserved for access by journal */
#define BJ_Types	5

/* JBD uses a CRC32 checksum */
#define JBD_MAX_CHECKSUM_SIZE 4

static inline u32 jbd2_chksum(journal_t *journal, u32 crc,
			      const void *address, unsigned int length)
{
	DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx,
		DIV_ROUND_UP(JBD_MAX_CHECKSUM_SIZE,
			     sizeof(*((struct shash_desc *)0)->__ctx)));
	int err;

	BUG_ON(crypto_shash_descsize(journal->j_chksum_driver) >
		JBD_MAX_CHECKSUM_SIZE);

	desc->tfm = journal->j_chksum_driver;
	*(u32 *)desc->__ctx = crc;

	err = crypto_shash_update(desc, address, length);
	BUG_ON(err);

	return *(u32 *)desc->__ctx;
	return crc32c(crc, address, length);
}

/* Return most recent uncommitted transaction */