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:
		
							parent
							
								
									3b4b40c0d6
								
							
						
					
					
						commit
						565a4147d1
					
				|  | @ -3,4 +3,4 @@ | ||||||
| # 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
 | # 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 \
 | 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 | ||||||
|  |  | ||||||
|  | @ -5,11 +5,12 @@ | ||||||
|  * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz |  * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "btrfs.h" |  | ||||||
| #include <config.h> | #include <config.h> | ||||||
| #include <malloc.h> | #include <malloc.h> | ||||||
| #include <uuid.h> | #include <uuid.h> | ||||||
| #include <linux/time.h> | #include <linux/time.h> | ||||||
|  | #include "btrfs.h" | ||||||
|  | #include "crypto/hash.h" | ||||||
| 
 | 
 | ||||||
| struct btrfs_info btrfs_info; | struct btrfs_info btrfs_info; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,17 +23,6 @@ struct btrfs_info { | ||||||
| 
 | 
 | ||||||
| extern struct btrfs_info 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 */ | /* dev.c */ | ||||||
| extern struct blk_desc *btrfs_blk_desc; | extern struct blk_desc *btrfs_blk_desc; | ||||||
| extern struct disk_partition *btrfs_part_info; | extern struct disk_partition *btrfs_part_info; | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  | } | ||||||
|  | @ -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 | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "btrfs.h" | #include "btrfs.h" | ||||||
|  | #include "disk-io.h" | ||||||
| 
 | 
 | ||||||
| static int verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total) | static int verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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 | ||||||
|  | @ -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); |  | ||||||
| } |  | ||||||
|  | @ -11,6 +11,7 @@ | ||||||
| #include <part.h> | #include <part.h> | ||||||
| #include <linux/compat.h> | #include <linux/compat.h> | ||||||
| #include "btrfs.h" | #include "btrfs.h" | ||||||
|  | #include "disk-io.h" | ||||||
| 
 | 
 | ||||||
| #define BTRFS_SUPER_FLAG_SUPP	(BTRFS_HEADER_FLAG_WRITTEN	\ | #define BTRFS_SUPER_FLAG_SUPP	(BTRFS_HEADER_FLAG_WRITTEN	\ | ||||||
| 				 | BTRFS_HEADER_FLAG_RELOC	\ | 				 | 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; | 		(struct btrfs_super_block *) raw_disk_sb; | ||||||
| 	u16 csum_type = le16_to_cpu(disk_sb->csum_type); | 	u16 csum_type = le16_to_cpu(disk_sb->csum_type); | ||||||
| 
 | 
 | ||||||
| 	if (csum_type == BTRFS_CSUM_TYPE_CRC32) { | 	if (csum_type == BTRFS_CSUM_TYPE_CRC32 || | ||||||
| 		u32 crc = ~(u32) 0; | 	    csum_type == BTRFS_CSUM_TYPE_SHA256 || | ||||||
| 		const int csum_size = sizeof(crc); | 	    csum_type == BTRFS_CSUM_TYPE_XXHASH) { | ||||||
| 		char result[csum_size]; | 		u8 result[BTRFS_CSUM_SIZE]; | ||||||
| 
 | 
 | ||||||
| 		crc = btrfs_csum_data(raw_disk_sb + BTRFS_CSUM_SIZE, crc, | 		btrfs_csum_data(csum_type, (u8 *)raw_disk_sb + BTRFS_CSUM_SIZE, | ||||||
| 				      BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); | 			result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); | ||||||
| 		btrfs_csum_final(crc, result); |  | ||||||
| 
 | 
 | ||||||
| 		if (memcmp(raw_disk_sb, result, csum_size)) | 		if (memcmp(raw_disk_sb, result, BTRFS_CSUM_SIZE)) | ||||||
| 			return -1; | 			return -EIO; | ||||||
| 	} else { | 	} else if (csum_type == BTRFS_CSUM_TYPE_BLAKE2) { | ||||||
| 		return -1; | 		printf("Blake2 csum type is not supported yet\n"); | ||||||
|  | 		return -ENOTSUPP; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue