f2fs: use cryptoapi crc32 functions
authorKeith Mok <ek9852@gmail.com>
Wed, 2 Mar 2016 20:04:24 +0000 (12:04 -0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Fri, 18 Mar 2016 04:19:43 +0000 (21:19 -0700)
The crc function is done bit by bit.
Optimize this by use cryptoapi
crc32 function which is backed by h/w acceleration.

Signed-off-by: Keith Mok <ek9852@gmail.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/Kconfig
fs/f2fs/checkpoint.c
fs/f2fs/f2fs.h
fs/f2fs/super.c

index 402792bae503efdc49f3565a94c65c07eb792ac6..1f8982a957f15f72019bb87a198f24010789e34f 100644 (file)
@@ -1,6 +1,8 @@
 config F2FS_FS
        tristate "F2FS filesystem support"
        depends on BLOCK
+       select CRYPTO
+       select CRYPTO_CRC32
        help
          F2FS is based on Log-structured File System (LFS), which supports
          versatile "flash-friendly" features. The design has been focused on
index 4933b82feeddbe241651e0e9e1260b037a790564..0955312e5ca042fe45f88e0c10714d79f3fb8778 100644 (file)
@@ -635,7 +635,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
                goto invalid_cp1;
 
        crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset)));
-       if (!f2fs_crc_valid(crc, cp_block, crc_offset))
+       if (!f2fs_crc_valid(sbi, crc, cp_block, crc_offset))
                goto invalid_cp1;
 
        pre_version = cur_cp_version(cp_block);
@@ -650,7 +650,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
                goto invalid_cp2;
 
        crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset)));
-       if (!f2fs_crc_valid(crc, cp_block, crc_offset))
+       if (!f2fs_crc_valid(sbi, crc, cp_block, crc_offset))
                goto invalid_cp2;
 
        cur_version = cur_cp_version(cp_block);
@@ -1029,7 +1029,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
        get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
 
-       crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset));
+       crc32 = f2fs_crc32(sbi, ckpt, le32_to_cpu(ckpt->checksum_offset));
        *((__le32 *)((unsigned char *)ckpt +
                                le32_to_cpu(ckpt->checksum_offset)))
                                = cpu_to_le32(crc32);
index 6447e9002807f33af242a8d964207f16f7e42b4c..bbe2cd1265d0c41f63e9788a40805ca3c855304a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/bio.h>
 #include <linux/blkdev.h>
 #include <linux/fscrypto.h>
+#include <crypto/hash.h>
 
 #ifdef CONFIG_F2FS_CHECK_FS
 #define f2fs_bug_on(sbi, condition)    BUG_ON(condition)
@@ -83,27 +84,6 @@ struct f2fs_mount_info {
 #define F2FS_CLEAR_FEATURE(sb, mask)                                   \
        F2FS_SB(sb)->raw_super->feature &= ~cpu_to_le32(mask)
 
-#define CRCPOLY_LE 0xedb88320
-
-static inline __u32 f2fs_crc32(void *buf, size_t len)
-{
-       unsigned char *p = (unsigned char *)buf;
-       __u32 crc = F2FS_SUPER_MAGIC;
-       int i;
-
-       while (len--) {
-               crc ^= *p++;
-               for (i = 0; i < 8; i++)
-                       crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
-       }
-       return crc;
-}
-
-static inline bool f2fs_crc_valid(__u32 blk_crc, void *buf, size_t buf_size)
-{
-       return f2fs_crc32(buf, buf_size) == blk_crc;
-}
-
 /*
  * For checkpoint manager
  */
@@ -819,6 +799,9 @@ struct f2fs_sb_info {
        /* For write statistics */
        u64 sectors_written_start;
        u64 kbytes_written;
+
+       /* Reference to checksum algorithm driver via cryptoapi */
+       struct crypto_shash *s_chksum_driver;
 };
 
 /* For write statistics. Suppose sector size is 512 bytes,
@@ -856,6 +839,29 @@ static inline bool is_idle(struct f2fs_sb_info *sbi)
 /*
  * Inline functions
  */
+static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
+                          unsigned int length)
+{
+       SHASH_DESC_ON_STACK(shash, sbi->s_chksum_driver);
+       u32 *ctx = (u32 *)shash_desc_ctx(shash);
+       int err;
+
+       shash->tfm = sbi->s_chksum_driver;
+       shash->flags = 0;
+       *ctx = F2FS_SUPER_MAGIC;
+
+       err = crypto_shash_update(shash, address, length);
+       BUG_ON(err);
+
+       return *ctx;
+}
+
+static inline bool f2fs_crc_valid(struct f2fs_sb_info *sbi, __u32 blk_crc,
+                                 void *buf, size_t buf_size)
+{
+       return f2fs_crc32(sbi, buf, buf_size) == blk_crc;
+}
+
 static inline struct f2fs_inode_info *F2FS_I(struct inode *inode)
 {
        return container_of(inode, struct f2fs_inode_info, vfs_inode);
index 7b62016e66cd4800fd3c8ee916980f291c25eb62..15bb81f8dac259843b074cfb2737426b49c139a5 100644 (file)
@@ -590,6 +590,8 @@ static void f2fs_put_super(struct super_block *sb)
        wait_for_completion(&sbi->s_kobj_unregister);
 
        sb->s_fs_info = NULL;
+       if (sbi->s_chksum_driver)
+               crypto_free_shash(sbi->s_chksum_driver);
        kfree(sbi->raw_super);
        kfree(sbi);
 }
@@ -1310,6 +1312,15 @@ try_onemore:
        if (!sbi)
                return -ENOMEM;
 
+       /* Load the checksum driver */
+       sbi->s_chksum_driver = crypto_alloc_shash("crc32", 0, 0);
+       if (IS_ERR(sbi->s_chksum_driver)) {
+               f2fs_msg(sb, KERN_ERR, "Cannot load crc32 driver.");
+               err = PTR_ERR(sbi->s_chksum_driver);
+               sbi->s_chksum_driver = NULL;
+               goto free_sbi;
+       }
+
        /* set a block size */
        if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) {
                f2fs_msg(sb, KERN_ERR, "unable to set blocksize");
@@ -1568,6 +1579,8 @@ free_options:
 free_sb_buf:
        kfree(raw_super);
 free_sbi:
+       if (sbi->s_chksum_driver)
+               crypto_free_shash(sbi->s_chksum_driver);
        kfree(sbi);
 
        /* give only one another chance */