fs: btrfs: Add more checksum algorithms

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>
This commit is contained in:
Qu Wenruo 2020-06-24 18:02:48 +02:00 committed by Tom Rini
parent 3b4b40c0d6
commit 565a4147d1
10 changed files with 130 additions and 62 deletions

View 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

View 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;

View 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;

55
fs/btrfs/crypto/hash.c Normal file
View file

@ -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);
}

17
fs/btrfs/crypto/hash.h Normal file
View file

@ -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

View 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)
{

22
fs/btrfs/disk-io.c Normal file
View file

@ -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;
}
}

20
fs/btrfs/disk-io.h Normal file
View file

@ -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

View file

@ -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);
}

View 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;