mirror of
https://github.com/kdave/btrfs-progs
synced 2025-02-16 09:46:55 +00:00
btrfs-progs: update checksumming api
Update the checksumming API to be able to cope with more checksum types than just CRC32C. The finalization call is merged into btrfs_csum_data. There are some fixme's and asserts added that need to be resolved. Co-developed-by: David Sterba <dsterba@suse.com> Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
926e9c8e14
commit
ed33908b44
@ -33,31 +33,24 @@ static int csum_size;
|
|||||||
|
|
||||||
static int check_csum_superblock(void *sb)
|
static int check_csum_superblock(void *sb)
|
||||||
{
|
{
|
||||||
u8 result[csum_size];
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
u32 crc = ~(u32)0;
|
|
||||||
u16 csum_type = btrfs_super_csum_type(sb);
|
u16 csum_type = btrfs_super_csum_type(sb);
|
||||||
|
|
||||||
crc = btrfs_csum_data(csum_type,
|
btrfs_csum_data(csum_type, (char *)sb + BTRFS_CSUM_SIZE,
|
||||||
(char *)sb + BTRFS_CSUM_SIZE,
|
result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
||||||
(u8 *)&crc,
|
|
||||||
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
|
||||||
btrfs_csum_final(csum_type, crc, result);
|
|
||||||
|
|
||||||
return !memcmp(sb, &result, csum_size);
|
return !memcmp(sb, result, csum_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_block_csum(void *block)
|
static void update_block_csum(void *block)
|
||||||
{
|
{
|
||||||
u8 result[csum_size];
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
struct btrfs_header *hdr;
|
struct btrfs_header *hdr;
|
||||||
u32 crc = ~(u32)0;
|
|
||||||
u16 csum_type = btrfs_super_csum_type(block);
|
u16 csum_type = btrfs_super_csum_type(block);
|
||||||
|
|
||||||
crc = btrfs_csum_data(csum_type, (char *)block + BTRFS_CSUM_SIZE,
|
btrfs_csum_data(csum_type, (char *)block + BTRFS_CSUM_SIZE,
|
||||||
(u8 *)&crc,
|
result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
||||||
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
|
||||||
|
|
||||||
btrfs_csum_final(csum_type, crc, result);
|
|
||||||
memset(block, 0, BTRFS_CSUM_SIZE);
|
memset(block, 0, BTRFS_CSUM_SIZE);
|
||||||
hdr = (struct btrfs_header *)block;
|
hdr = (struct btrfs_header *)block;
|
||||||
memcpy(&hdr->csum, result, csum_size);
|
memcpy(&hdr->csum, result, csum_size);
|
||||||
|
20
check/main.c
20
check/main.c
@ -5620,10 +5620,10 @@ static int check_extent_csums(struct btrfs_root *root, u64 bytenr,
|
|||||||
u64 offset = 0;
|
u64 offset = 0;
|
||||||
u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
|
u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
|
||||||
u16 csum_type = btrfs_super_csum_type(fs_info->super_copy);
|
u16 csum_type = btrfs_super_csum_type(fs_info->super_copy);
|
||||||
char *data;
|
u8 *data;
|
||||||
unsigned long csum_offset;
|
unsigned long csum_offset;
|
||||||
u32 csum;
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
u32 csum_expected;
|
u8 csum_expected[BTRFS_CSUM_SIZE];
|
||||||
u64 read_len;
|
u64 read_len;
|
||||||
u64 data_checked = 0;
|
u64 data_checked = 0;
|
||||||
u64 tmp;
|
u64 tmp;
|
||||||
@ -5649,7 +5649,7 @@ static int check_extent_csums(struct btrfs_root *root, u64 bytenr,
|
|||||||
for (mirror = 1; mirror <= num_copies; mirror++) {
|
for (mirror = 1; mirror <= num_copies; mirror++) {
|
||||||
read_len = num_bytes - offset;
|
read_len = num_bytes - offset;
|
||||||
/* read as much space once a time */
|
/* read as much space once a time */
|
||||||
ret = read_extent_data(fs_info, data + offset,
|
ret = read_extent_data(fs_info, (char *)data + offset,
|
||||||
bytenr + offset, &read_len, mirror);
|
bytenr + offset, &read_len, mirror);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
@ -5657,24 +5657,22 @@ static int check_extent_csums(struct btrfs_root *root, u64 bytenr,
|
|||||||
data_checked = 0;
|
data_checked = 0;
|
||||||
/* verify every 4k data's checksum */
|
/* verify every 4k data's checksum */
|
||||||
while (data_checked < read_len) {
|
while (data_checked < read_len) {
|
||||||
csum = ~(u32)0;
|
|
||||||
tmp = offset + data_checked;
|
tmp = offset + data_checked;
|
||||||
|
|
||||||
csum = btrfs_csum_data(csum_type,
|
btrfs_csum_data(csum_type, data + tmp,
|
||||||
(char *)data + tmp,
|
result, fs_info->sectorsize);
|
||||||
(u8 *)&csum, fs_info->sectorsize);
|
|
||||||
btrfs_csum_final(csum_type, csum, (u8 *)&csum);
|
|
||||||
|
|
||||||
csum_offset = leaf_offset +
|
csum_offset = leaf_offset +
|
||||||
tmp / fs_info->sectorsize * csum_size;
|
tmp / fs_info->sectorsize * csum_size;
|
||||||
read_extent_buffer(eb, (char *)&csum_expected,
|
read_extent_buffer(eb, (char *)&csum_expected,
|
||||||
csum_offset, csum_size);
|
csum_offset, csum_size);
|
||||||
if (csum != csum_expected) {
|
if (memcmp(result, csum_expected, csum_size) != 0) {
|
||||||
csum_mismatch = true;
|
csum_mismatch = true;
|
||||||
|
/* FIXME: format of the checksum value */
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"mirror %d bytenr %llu csum %u expected csum %u\n",
|
"mirror %d bytenr %llu csum %u expected csum %u\n",
|
||||||
mirror, bytenr + tmp,
|
mirror, bytenr + tmp,
|
||||||
csum, csum_expected);
|
result[0], csum_expected[0]);
|
||||||
}
|
}
|
||||||
data_checked += fs_info->sectorsize;
|
data_checked += fs_info->sectorsize;
|
||||||
}
|
}
|
||||||
|
@ -38,14 +38,11 @@
|
|||||||
static int check_csum_sblock(void *sb, int csum_size, u16 csum_type)
|
static int check_csum_sblock(void *sb, int csum_size, u16 csum_type)
|
||||||
{
|
{
|
||||||
u8 result[BTRFS_CSUM_SIZE];
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
u32 crc = ~(u32)0;
|
|
||||||
|
|
||||||
crc = btrfs_csum_data(csum_type, (char *)sb + BTRFS_CSUM_SIZE,
|
btrfs_csum_data(csum_type, (u8 *)sb + BTRFS_CSUM_SIZE,
|
||||||
(u8 *)&crc,
|
result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
||||||
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
|
||||||
btrfs_csum_final(csum_type, crc, result);
|
|
||||||
|
|
||||||
return !memcmp(sb, &result, csum_size);
|
return !memcmp(sb, result, csum_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_sys_chunk_array(struct btrfs_super_block *sb)
|
static void print_sys_chunk_array(struct btrfs_super_block *sb)
|
||||||
|
@ -1892,7 +1892,11 @@ static int check_one_csum(int fd, u64 start, u32 len, u32 tree_csum,
|
|||||||
{
|
{
|
||||||
char *data;
|
char *data;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 csum_result = ~(u32)0;
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
|
int csum_size = 0;
|
||||||
|
u8 expected_csum[BTRFS_CSUM_SIZE];
|
||||||
|
|
||||||
|
ASSERT(0);
|
||||||
|
|
||||||
data = malloc(len);
|
data = malloc(len);
|
||||||
if (!data)
|
if (!data)
|
||||||
@ -1903,9 +1907,9 @@ static int check_one_csum(int fd, u64 start, u32 len, u32 tree_csum,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
csum_result = btrfs_csum_data(csum_type, data, (u8 *)&csum_result, len);
|
put_unaligned_le32(tree_csum, expected_csum);
|
||||||
btrfs_csum_final(csum_type, csum_result, (u8 *)&csum_result);
|
btrfs_csum_data(csum_type, (u8 *)data, result, len);
|
||||||
if (csum_result != tree_csum)
|
if (memcmp(result, expected_csum, csum_size) != 0)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
out:
|
out:
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -62,14 +62,13 @@ static int reserve_free_space(struct cache_tree *free_tree, u64 len,
|
|||||||
static inline int write_temp_super(int fd, struct btrfs_super_block *sb,
|
static inline int write_temp_super(int fd, struct btrfs_super_block *sb,
|
||||||
u64 sb_bytenr)
|
u64 sb_bytenr)
|
||||||
{
|
{
|
||||||
u32 crc = ~(u32)0;
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
u16 csum_type = btrfs_super_csum_type(sb);
|
u16 csum_type = btrfs_super_csum_type(sb);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
crc = btrfs_csum_data(csum_type, (char *)sb + BTRFS_CSUM_SIZE,
|
btrfs_csum_data(csum_type, (u8 *)sb + BTRFS_CSUM_SIZE,
|
||||||
(u8 *)&crc,
|
result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
||||||
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
memcpy(&sb->csum[0], result, BTRFS_CSUM_SIZE);
|
||||||
btrfs_csum_final(csum_type, crc, &sb->csum[0]);
|
|
||||||
ret = pwrite(fd, sb, BTRFS_SUPER_INFO_SIZE, sb_bytenr);
|
ret = pwrite(fd, sb, BTRFS_SUPER_INFO_SIZE, sb_bytenr);
|
||||||
if (ret < BTRFS_SUPER_INFO_SIZE)
|
if (ret < BTRFS_SUPER_INFO_SIZE)
|
||||||
ret = (ret < 0 ? -errno : -EIO);
|
ret = (ret < 0 ? -errno : -EIO);
|
||||||
|
60
disk-io.c
60
disk-io.c
@ -138,26 +138,23 @@ static void print_tree_block_error(struct btrfs_fs_info *fs_info,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 btrfs_csum_data(u16 csum_type, char *data, u8 *seed, size_t len)
|
int btrfs_csum_data(u16 csum_type, const u8 *data, u8 *out, size_t len)
|
||||||
{
|
{
|
||||||
|
u32 crc = ~(u32)0;
|
||||||
|
|
||||||
|
memset(out, 0, BTRFS_CSUM_SIZE);
|
||||||
|
|
||||||
switch (csum_type) {
|
switch (csum_type) {
|
||||||
case BTRFS_CSUM_TYPE_CRC32:
|
case BTRFS_CSUM_TYPE_CRC32:
|
||||||
return crc32c(*(u32*)seed, data, len);
|
crc = crc32c(crc, data, len);
|
||||||
default: /* Not reached */
|
put_unaligned_le32(~crc, out);
|
||||||
return ~(u32)0;
|
return 0;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "ERROR: unknown csum type: %d\n", csum_type);
|
||||||
|
ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
return -1;
|
||||||
|
|
||||||
void btrfs_csum_final(u16 csum_type, u32 crc, u8 *result)
|
|
||||||
{
|
|
||||||
switch (csum_type) {
|
|
||||||
case BTRFS_CSUM_TYPE_CRC32:
|
|
||||||
put_unaligned_le32(~crc, result);
|
|
||||||
break;
|
|
||||||
default: /* Not reached */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __csum_tree_block_size(struct extent_buffer *buf, u16 csum_size,
|
static int __csum_tree_block_size(struct extent_buffer *buf, u16 csum_size,
|
||||||
@ -165,20 +162,19 @@ static int __csum_tree_block_size(struct extent_buffer *buf, u16 csum_size,
|
|||||||
{
|
{
|
||||||
u8 result[BTRFS_CSUM_SIZE];
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
u32 len;
|
u32 len;
|
||||||
u32 crc = ~(u32)0;
|
|
||||||
|
|
||||||
len = buf->len - BTRFS_CSUM_SIZE;
|
len = buf->len - BTRFS_CSUM_SIZE;
|
||||||
crc = btrfs_csum_data(csum_type, buf->data + BTRFS_CSUM_SIZE,
|
btrfs_csum_data(csum_type, (u8 *)buf->data + BTRFS_CSUM_SIZE,
|
||||||
(u8 *)&crc, len);
|
result, len);
|
||||||
btrfs_csum_final(csum_type, crc, result);
|
|
||||||
|
|
||||||
if (verify) {
|
if (verify) {
|
||||||
if (memcmp_extent_buffer(buf, result, 0, csum_size)) {
|
if (memcmp_extent_buffer(buf, result, 0, csum_size)) {
|
||||||
|
/* FIXME: format */
|
||||||
if (!silent)
|
if (!silent)
|
||||||
printk("checksum verify failed on %llu found %08X wanted %08X\n",
|
printk("checksum verify failed on %llu found %08X wanted %08X\n",
|
||||||
(unsigned long long)buf->start,
|
(unsigned long long)buf->start,
|
||||||
*((u32 *)result),
|
result[0],
|
||||||
*((u32*)(char *)buf->data));
|
buf->data[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1367,7 +1363,6 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
|||||||
int btrfs_check_super(struct btrfs_super_block *sb, unsigned sbflags)
|
int btrfs_check_super(struct btrfs_super_block *sb, unsigned sbflags)
|
||||||
{
|
{
|
||||||
u8 result[BTRFS_CSUM_SIZE];
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
u32 crc;
|
|
||||||
u16 csum_type;
|
u16 csum_type;
|
||||||
int csum_size;
|
int csum_size;
|
||||||
u8 *metadata_uuid;
|
u8 *metadata_uuid;
|
||||||
@ -1388,11 +1383,8 @@ int btrfs_check_super(struct btrfs_super_block *sb, unsigned sbflags)
|
|||||||
}
|
}
|
||||||
csum_size = btrfs_csum_sizes[csum_type];
|
csum_size = btrfs_csum_sizes[csum_type];
|
||||||
|
|
||||||
crc = ~(u32)0;
|
btrfs_csum_data(csum_type, (u8 *)sb + BTRFS_CSUM_SIZE,
|
||||||
crc = btrfs_csum_data(csum_type,(char *)sb + BTRFS_CSUM_SIZE,
|
result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
||||||
(u8 *)&crc,
|
|
||||||
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
|
||||||
btrfs_csum_final(csum_type, crc, result);
|
|
||||||
|
|
||||||
if (memcmp(result, sb->csum, csum_size)) {
|
if (memcmp(result, sb->csum, csum_size)) {
|
||||||
error("superblock checksum mismatch");
|
error("superblock checksum mismatch");
|
||||||
@ -1628,7 +1620,7 @@ static int write_dev_supers(struct btrfs_fs_info *fs_info,
|
|||||||
struct btrfs_device *device)
|
struct btrfs_device *device)
|
||||||
{
|
{
|
||||||
u64 bytenr;
|
u64 bytenr;
|
||||||
u32 crc;
|
u8 result[BTRFS_CSUM_SIZE];
|
||||||
int i, ret;
|
int i, ret;
|
||||||
u16 csum_type = btrfs_super_csum_type(sb);
|
u16 csum_type = btrfs_super_csum_type(sb);
|
||||||
|
|
||||||
@ -1645,10 +1637,9 @@ static int write_dev_supers(struct btrfs_fs_info *fs_info,
|
|||||||
}
|
}
|
||||||
if (fs_info->super_bytenr != BTRFS_SUPER_INFO_OFFSET) {
|
if (fs_info->super_bytenr != BTRFS_SUPER_INFO_OFFSET) {
|
||||||
btrfs_set_super_bytenr(sb, fs_info->super_bytenr);
|
btrfs_set_super_bytenr(sb, fs_info->super_bytenr);
|
||||||
crc = ~(u32)0;
|
btrfs_csum_data(csum_type, (u8 *)sb + BTRFS_CSUM_SIZE, result,
|
||||||
crc = btrfs_csum_data(csum_type, (char *)sb + BTRFS_CSUM_SIZE, (u8 *)&crc,
|
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
||||||
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
memcpy(&sb->csum[0], result, BTRFS_CSUM_SIZE);
|
||||||
btrfs_csum_final(csum_type, crc, &sb->csum[0]);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* super_copy is BTRFS_SUPER_INFO_SIZE bytes and is
|
* super_copy is BTRFS_SUPER_INFO_SIZE bytes and is
|
||||||
@ -1681,10 +1672,9 @@ static int write_dev_supers(struct btrfs_fs_info *fs_info,
|
|||||||
|
|
||||||
btrfs_set_super_bytenr(sb, bytenr);
|
btrfs_set_super_bytenr(sb, bytenr);
|
||||||
|
|
||||||
crc = ~(u32)0;
|
btrfs_csum_data(csum_type, (u8 *)sb + BTRFS_CSUM_SIZE, result,
|
||||||
crc = btrfs_csum_data(csum_type, (char *)sb + BTRFS_CSUM_SIZE, (u8 *)&crc,
|
|
||||||
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
||||||
btrfs_csum_final(csum_type, crc, &sb->csum[0]);
|
memcpy(&sb->csum[0], result, BTRFS_CSUM_SIZE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* super_copy is BTRFS_SUPER_INFO_SIZE bytes and is
|
* super_copy is BTRFS_SUPER_INFO_SIZE bytes and is
|
||||||
|
@ -186,8 +186,7 @@ int btrfs_free_fs_root(struct btrfs_root *root);
|
|||||||
void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
|
void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
|
||||||
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
|
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
|
||||||
int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
|
int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
|
||||||
u32 btrfs_csum_data(u16 csum_type, char *data, u8 *seed, size_t len);
|
int btrfs_csum_data(u16 csum_type, const u8 *data, u8 *out, size_t len);
|
||||||
void btrfs_csum_final(u16 csum_type, u32 crc, u8 *result);
|
|
||||||
|
|
||||||
int btrfs_open_device(struct btrfs_device *dev);
|
int btrfs_open_device(struct btrfs_device *dev);
|
||||||
int csum_tree_block_size(struct extent_buffer *buf, u16 csum_sectorsize,
|
int csum_tree_block_size(struct extent_buffer *buf, u16 csum_sectorsize,
|
||||||
|
@ -195,7 +195,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
|
|||||||
struct btrfs_csum_item *item;
|
struct btrfs_csum_item *item;
|
||||||
struct extent_buffer *leaf = NULL;
|
struct extent_buffer *leaf = NULL;
|
||||||
u64 csum_offset;
|
u64 csum_offset;
|
||||||
u32 csum_result = ~(u32)0;
|
u8 csum_result[BTRFS_CSUM_SIZE];
|
||||||
u32 sectorsize = root->fs_info->sectorsize;
|
u32 sectorsize = root->fs_info->sectorsize;
|
||||||
u32 nritems;
|
u32 nritems;
|
||||||
u32 ins_size;
|
u32 ins_size;
|
||||||
@ -315,14 +315,14 @@ csum:
|
|||||||
item = (struct btrfs_csum_item *)((unsigned char *)item +
|
item = (struct btrfs_csum_item *)((unsigned char *)item +
|
||||||
csum_offset * csum_size);
|
csum_offset * csum_size);
|
||||||
found:
|
found:
|
||||||
csum_result = btrfs_csum_data(csum_type, data, (u8 *)&csum_result, len);
|
btrfs_csum_data(csum_type, (u8 *)data, csum_result, len);
|
||||||
btrfs_csum_final(csum_type, csum_result, (u8 *)&csum_result);
|
/* FIXME: does not make sense for non-crc32c */
|
||||||
if (csum_result == 0) {
|
if (csum_result == 0) {
|
||||||
printk("csum result is 0 for block %llu\n",
|
printk("csum result is 0 for block %llu\n",
|
||||||
(unsigned long long)bytenr);
|
(unsigned long long)bytenr);
|
||||||
}
|
}
|
||||||
|
|
||||||
write_extent_buffer(leaf, &csum_result, (unsigned long)item,
|
write_extent_buffer(leaf, csum_result, (unsigned long)item,
|
||||||
csum_size);
|
csum_size);
|
||||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||||
fail:
|
fail:
|
||||||
|
Loading…
Reference in New Issue
Block a user