fs: btrfs: Add more checksum algorithms
authorQu Wenruo <wqu@suse.com>
Wed, 24 Jun 2020 16:02:48 +0000 (18:02 +0200)
committerTom Rini <trini@konsulko.com>
Tue, 8 Sep 2020 00:57:27 +0000 (20:57 -0400)
This mostly crossports crypto/hash.[ch] from btrfs-progs.

The differences are:
- No blake2 support
  No blake2 related library in U-Boot yet.

- Use uboot xxhash/sha256 directly
  No need to implement the code as U-Boot has already provided the
  interface.

This adds the support for the following csums:
- SHA256
- XXHASH

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Marek BehĂșn <marek.behun@nic.cz>
fs/btrfs/Makefile
fs/btrfs/btrfs.c
fs/btrfs/btrfs.h
fs/btrfs/crypto/hash.c [new file with mode: 0644]
fs/btrfs/crypto/hash.h [new file with mode: 0644]
fs/btrfs/dir-item.c
fs/btrfs/disk-io.c [new file with mode: 0644]
fs/btrfs/disk-io.h [new file with mode: 0644]
fs/btrfs/hash.c [deleted file]
fs/btrfs/super.c

index 9b31592..84b3b5e 100644 (file)
@@ -3,4 +3,4 @@
 # 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
 
 obj-y := btrfs.o chunk-map.o compression.o ctree.o dev.o dir-item.o \
-       extent-io.o hash.o inode.o root.o subvolume.o super.o
+       extent-io.o inode.o root.o subvolume.o super.o crypto/hash.o disk-io.o
index 9f2888b..d5a87c1 100644 (file)
@@ -5,11 +5,12 @@
  * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
  */
 
-#include "btrfs.h"
 #include <config.h>
 #include <malloc.h>
 #include <uuid.h>
 #include <linux/time.h>
+#include "btrfs.h"
+#include "crypto/hash.h"
 
 struct btrfs_info btrfs_info;
 
index 25a8cf6..1aacbc8 100644 (file)
@@ -23,17 +23,6 @@ struct btrfs_info {
 
 extern struct btrfs_info btrfs_info;
 
-/* hash.c */
-void btrfs_hash_init(void);
-u32 btrfs_crc32c(u32, const void *, size_t);
-u32 btrfs_csum_data(char *, u32, size_t);
-void btrfs_csum_final(u32, void *);
-
-static inline u64 btrfs_name_hash(const char *name, int len)
-{
-       return btrfs_crc32c((u32) ~1, name, len);
-}
-
 /* dev.c */
 extern struct blk_desc *btrfs_blk_desc;
 extern struct disk_partition *btrfs_part_info;
diff --git a/fs/btrfs/crypto/hash.c b/fs/btrfs/crypto/hash.c
new file mode 100644 (file)
index 0000000..fb51f63
--- /dev/null
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/xxhash.h>
+#include <linux/unaligned/access_ok.h>
+#include <linux/types.h>
+#include <u-boot/sha256.h>
+#include <u-boot/crc.h>
+
+static u32 btrfs_crc32c_table[256];
+
+void btrfs_hash_init(void)
+{
+       static int inited = 0;
+
+       if (!inited) {
+               crc32c_init(btrfs_crc32c_table, 0x82F63B78);
+               inited = 1;
+       }
+}
+
+int hash_sha256(const u8 *buf, size_t length, u8 *out)
+{
+       sha256_context ctx;
+
+       sha256_starts(&ctx);
+       sha256_update(&ctx, buf, length);
+       sha256_finish(&ctx, out);
+
+       return 0;
+}
+
+int hash_xxhash(const u8 *buf, size_t length, u8 *out)
+{
+       u64 hash;
+
+       hash = xxh64(buf, length, 0);
+       put_unaligned_le64(hash, out);
+
+       return 0;
+}
+
+int hash_crc32c(const u8 *buf, size_t length, u8 *out)
+{
+       u32 crc;
+
+       crc = crc32c_cal((u32)~0, (char *)buf, length, btrfs_crc32c_table);
+       put_unaligned_le32(~crc, out);
+
+       return 0;
+}
+
+u32 crc32c(u32 seed, const void * data, size_t len)
+{
+       return crc32c_cal(seed, data, len, btrfs_crc32c_table);
+}
diff --git a/fs/btrfs/crypto/hash.h b/fs/btrfs/crypto/hash.h
new file mode 100644 (file)
index 0000000..d1ba1fa
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef CRYPTO_HASH_H
+#define CRYPTO_HASH_H
+
+#include <linux/types.h>
+
+#define CRYPTO_HASH_SIZE_MAX   32
+
+void btrfs_hash_init(void);
+int hash_crc32c(const u8 *buf, size_t length, u8 *out);
+int hash_xxhash(const u8 *buf, size_t length, u8 *out);
+int hash_sha256(const u8 *buf, size_t length, u8 *out);
+
+u32 crc32c(u32 seed, const void * data, size_t len);
+
+/* Blake2B is not yet supported due to lack of library */
+
+#endif
index 63b5bf0..1ff446a 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "btrfs.h"
+#include "disk-io.h"
 
 static int verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total)
 {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
new file mode 100644 (file)
index 0000000..58c32b5
--- /dev/null
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <common.h>
+#include <fs_internal.h>
+#include "disk-io.h"
+#include "crypto/hash.h"
+
+int btrfs_csum_data(u16 csum_type, const u8 *data, u8 *out, size_t len)
+{
+       memset(out, 0, BTRFS_CSUM_SIZE);
+
+       switch (csum_type) {
+       case BTRFS_CSUM_TYPE_CRC32:
+               return hash_crc32c(data, len, out);
+       case BTRFS_CSUM_TYPE_XXHASH:
+               return hash_xxhash(data, len, out);
+       case BTRFS_CSUM_TYPE_SHA256:
+               return hash_sha256(data, len, out);
+       default:
+               printf("Unknown csum type %d\n", csum_type);
+               return -EINVAL;
+       }
+}
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
new file mode 100644 (file)
index 0000000..efb7158
--- /dev/null
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+#ifndef __BTRFS_DISK_IO_H__
+#define __BTRFS_DISK_IO_H__
+
+#include "crypto/hash.h"
+#include "ctree.h"
+#include "disk-io.h"
+
+static inline u64 btrfs_name_hash(const char *name, int len)
+{
+       u32 crc;
+
+       crc = crc32c((u32)~1, (unsigned char *)name, len);
+
+       return (u64)crc;
+}
+
+int btrfs_csum_data(u16 csum_type, const u8 *data, u8 *out, size_t len);
+
+#endif
diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c
deleted file mode 100644 (file)
index 52a8cea..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * BTRFS filesystem implementation for U-Boot
- *
- * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
- */
-
-#include "btrfs.h"
-#include <u-boot/crc.h>
-#include <asm/unaligned.h>
-
-static u32 btrfs_crc32c_table[256];
-
-void btrfs_hash_init(void)
-{
-       static int inited = 0;
-
-       if (!inited) {
-               crc32c_init(btrfs_crc32c_table, 0x82F63B78);
-               inited = 1;
-       }
-}
-
-u32 btrfs_crc32c(u32 crc, const void *data, size_t length)
-{
-       return crc32c_cal(crc, (const char *) data, length,
-                         btrfs_crc32c_table);
-}
-
-u32 btrfs_csum_data(char *data, u32 seed, size_t len)
-{
-       return btrfs_crc32c(seed, data, len);
-}
-
-void btrfs_csum_final(u32 crc, void *result)
-{
-       put_unaligned(cpu_to_le32(~crc), (u32 *)result);
-}
index 913a4d4..101572b 100644 (file)
@@ -11,6 +11,7 @@
 #include <part.h>
 #include <linux/compat.h>
 #include "btrfs.h"
+#include "disk-io.h"
 
 #define BTRFS_SUPER_FLAG_SUPP  (BTRFS_HEADER_FLAG_WRITTEN      \
                                 | BTRFS_HEADER_FLAG_RELOC      \
@@ -61,19 +62,19 @@ static int btrfs_check_super_csum(char *raw_disk_sb)
                (struct btrfs_super_block *) raw_disk_sb;
        u16 csum_type = le16_to_cpu(disk_sb->csum_type);
 
-       if (csum_type == BTRFS_CSUM_TYPE_CRC32) {
-               u32 crc = ~(u32) 0;
-               const int csum_size = sizeof(crc);
-               char result[csum_size];
+       if (csum_type == BTRFS_CSUM_TYPE_CRC32 ||
+           csum_type == BTRFS_CSUM_TYPE_SHA256 ||
+           csum_type == BTRFS_CSUM_TYPE_XXHASH) {
+               u8 result[BTRFS_CSUM_SIZE];
 
-               crc = btrfs_csum_data(raw_disk_sb + BTRFS_CSUM_SIZE, crc,
-                                     BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
-               btrfs_csum_final(crc, result);
+               btrfs_csum_data(csum_type, (u8 *)raw_disk_sb + BTRFS_CSUM_SIZE,
+                       result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
 
-               if (memcmp(raw_disk_sb, result, csum_size))
-                       return -1;
-       } else {
-               return -1;
+               if (memcmp(raw_disk_sb, result, BTRFS_CSUM_SIZE))
+                       return -EIO;
+       } else if (csum_type == BTRFS_CSUM_TYPE_BLAKE2) {
+               printf("Blake2 csum type is not supported yet\n");
+               return -ENOTSUPP;
        }
 
        return 0;