diff --git a/check/mode-common.c b/check/mode-common.c index a38d2afc..175e90f7 100644 --- a/check/mode-common.c +++ b/check/mode-common.c @@ -1209,18 +1209,19 @@ static int populate_csum(struct btrfs_trans_handle *trans, struct btrfs_root *csum_root, char *buf, u64 start, u64 len) { + struct btrfs_fs_info *fs_info = trans->fs_info; u64 offset = 0; - u64 sectorsize; + u64 sectorsize = fs_info->sectorsize; int ret = 0; while (offset < len) { - sectorsize = gfs_info->sectorsize; - ret = read_data_from_disk(gfs_info, buf, start + offset, + ret = read_data_from_disk(fs_info, buf, start + offset, §orsize, 0); if (ret) break; - ret = btrfs_csum_file_block(trans, start + len, start + offset, - buf, sectorsize); + ret = btrfs_csum_file_block(trans, start + offset, + BTRFS_EXTENT_CSUM_OBJECTID, + fs_info->csum_type, buf); if (ret) break; offset += sectorsize; diff --git a/convert/main.c b/convert/main.c index 9781200d..0a62101d 100644 --- a/convert/main.c +++ b/convert/main.c @@ -182,7 +182,8 @@ static int csum_disk_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 disk_bytenr, u64 num_bytes) { - u32 blocksize = root->fs_info->sectorsize; + struct btrfs_fs_info *fs_info = trans->fs_info; + u32 blocksize = fs_info->sectorsize; u64 offset; char *buffer; int ret = 0; @@ -193,7 +194,7 @@ static int csum_disk_extent(struct btrfs_trans_handle *trans, for (offset = 0; offset < num_bytes; offset += blocksize) { u64 read_len = blocksize; - ret = read_data_from_disk(root->fs_info, buffer, + ret = read_data_from_disk(fs_info, buffer, disk_bytenr + offset, &read_len, 0); if (ret) break; @@ -203,10 +204,9 @@ static int csum_disk_extent(struct btrfs_trans_handle *trans, ret = -EIO; break; } - ret = btrfs_csum_file_block(trans, - disk_bytenr + num_bytes, - disk_bytenr + offset, - buffer, blocksize); + ret = btrfs_csum_file_block(trans, disk_bytenr + offset, + BTRFS_EXTENT_CSUM_OBJECTID, + fs_info->csum_type, buffer); if (ret) break; } diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c index 9b59a4b7..1a2f5f14 100644 --- a/kernel-shared/file-item.c +++ b/kernel-shared/file-item.c @@ -134,7 +134,7 @@ static struct btrfs_csum_item * btrfs_lookup_csum(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, - u64 bytenr, int cow) + u64 bytenr, u64 csum_objectid, u16 csum_type, int cow) { int ret; struct btrfs_key file_key; @@ -142,10 +142,10 @@ btrfs_lookup_csum(struct btrfs_trans_handle *trans, struct btrfs_csum_item *item; struct extent_buffer *leaf; u64 csum_offset = 0; - u16 csum_size = root->fs_info->csum_size; + u16 csum_size = btrfs_csum_type_size(csum_type); int csums_in_item; - file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; + file_key.objectid = csum_objectid; file_key.offset = bytenr; file_key.type = BTRFS_EXTENT_CSUM_KEY; ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); @@ -159,7 +159,8 @@ btrfs_lookup_csum(struct btrfs_trans_handle *trans, goto fail; path->slots[0]--; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); - if (found_key.type != BTRFS_EXTENT_CSUM_KEY) + if (found_key.type != BTRFS_EXTENT_CSUM_KEY || + found_key.objectid != csum_objectid) goto fail; csum_offset = (bytenr - found_key.offset) / @@ -182,10 +183,10 @@ fail: return ERR_PTR(ret); } -int btrfs_csum_file_block(struct btrfs_trans_handle *trans, - u64 alloc_end, u64 bytenr, char *data, size_t len) +int btrfs_csum_file_block(struct btrfs_trans_handle *trans, u64 logical, + u64 csum_objectid, u32 csum_type, const char *data) { - struct btrfs_root *root = btrfs_csum_root(trans->fs_info, bytenr); + struct btrfs_root *root = btrfs_csum_root(trans->fs_info, logical); int ret = 0; struct btrfs_key file_key; struct btrfs_key found_key; @@ -199,18 +200,18 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, u32 sectorsize = root->fs_info->sectorsize; u32 nritems; u32 ins_size; - u16 csum_size = root->fs_info->csum_size; - u16 csum_type = root->fs_info->csum_type; + u16 csum_size = btrfs_csum_type_size(csum_type); path = btrfs_alloc_path(); if (!path) return -ENOMEM; - file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; - file_key.offset = bytenr; + file_key.objectid = csum_objectid; + file_key.offset = logical; file_key.type = BTRFS_EXTENT_CSUM_KEY; - item = btrfs_lookup_csum(trans, root, path, bytenr, 1); + item = btrfs_lookup_csum(trans, root, path, logical, csum_objectid, + csum_type, 1); if (!IS_ERR(item)) { leaf = path->nodes[0]; ret = 0; @@ -241,7 +242,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, slot = 0; } btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); - if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || + if (found_key.objectid != csum_objectid || found_key.type != BTRFS_EXTENT_CSUM_KEY) { found_next = 1; goto insert; @@ -270,7 +271,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); csum_offset = (file_key.offset - found_key.offset) / sectorsize; - if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || + if (found_key.objectid != csum_objectid || found_key.type != BTRFS_EXTENT_CSUM_KEY || csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) { goto insert; @@ -290,7 +291,7 @@ insert: btrfs_release_path(path); csum_offset = 0; if (found_next) { - u64 tmp = min(alloc_end, next_offset); + u64 tmp = min(logical + sectorsize, next_offset); tmp -= file_key.offset; tmp /= sectorsize; tmp = max((u64)1, tmp); @@ -314,7 +315,8 @@ csum: item = (struct btrfs_csum_item *)((unsigned char *)item + csum_offset * csum_size); found: - btrfs_csum_data(root->fs_info, csum_type, (u8 *)data, csum_result, len); + btrfs_csum_data(root->fs_info, csum_type, (u8 *)data, csum_result, + sectorsize); write_extent_buffer(leaf, csum_result, (unsigned long)item, csum_size); btrfs_mark_buffer_dirty(path->nodes[0]); diff --git a/kernel-shared/file-item.h b/kernel-shared/file-item.h index 25dfecca..efbe5f20 100644 --- a/kernel-shared/file-item.h +++ b/kernel-shared/file-item.h @@ -80,8 +80,8 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 pos, u64 offset, u64 disk_num_bytes, u64 num_bytes); -int btrfs_csum_file_block(struct btrfs_trans_handle *trans, - u64 alloc_end, u64 bytenr, char *data, size_t len); +int btrfs_csum_file_block(struct btrfs_trans_handle *trans, u64 logical, + u64 csum_objectid, u32 csum_type, const char *data); int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 offset, const char *buffer, size_t size); diff --git a/kernel-shared/tree-checker.c b/kernel-shared/tree-checker.c index b28e4282..10797589 100644 --- a/kernel-shared/tree-checker.c +++ b/kernel-shared/tree-checker.c @@ -367,6 +367,11 @@ static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key, u32 sectorsize = fs_info->sectorsize; const u32 csumsize = fs_info->csum_size; + /* For fs under csum change, we should not check the regular csum items. */ + if (unlikely(btrfs_super_flags(fs_info->super_copy) & + (BTRFS_SUPER_FLAG_CHANGING_DATA_CSUM | + BTRFS_SUPER_FLAG_CHANGING_META_CSUM))) + return 0; if (unlikely(key->objectid != BTRFS_EXTENT_CSUM_OBJECTID)) { generic_err(leaf, slot, "invalid key objectid for csum item, have %llu expect %llu", diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c index 5fd3c6fe..4f7feb52 100644 --- a/mkfs/rootdir.c +++ b/mkfs/rootdir.c @@ -306,12 +306,13 @@ static int add_file_items(struct btrfs_trans_handle *trans, struct btrfs_inode_item *btrfs_inode, u64 objectid, struct stat *st, const char *path_name) { + struct btrfs_fs_info *fs_info = trans->fs_info; int ret = -1; ssize_t ret_read; u64 bytes_read = 0; struct btrfs_key key; int blocks; - u32 sectorsize = root->fs_info->sectorsize; + u32 sectorsize = fs_info->sectorsize; u64 first_block = 0; u64 file_pos = 0; u64 cur_bytes; @@ -332,7 +333,7 @@ static int add_file_items(struct btrfs_trans_handle *trans, if (st->st_size % sectorsize) blocks += 1; - if (st->st_size <= BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info) && + if (st->st_size <= BTRFS_MAX_INLINE_DATA_SIZE(fs_info) && st->st_size < sectorsize) { char *buffer = malloc(st->st_size); @@ -397,9 +398,9 @@ again: goto end; } - ret = btrfs_csum_file_block(trans, - first_block + bytes_read + sectorsize, - first_block + bytes_read, buf, sectorsize); + ret = btrfs_csum_file_block(trans, first_block + bytes_read, + BTRFS_EXTENT_CSUM_OBJECTID, + fs_info->csum_type, buf); if (ret) goto end; diff --git a/tune/change-csum.c b/tune/change-csum.c index 9d1b529e..a30d142c 100644 --- a/tune/change-csum.c +++ b/tune/change-csum.c @@ -21,6 +21,7 @@ #include "kernel-shared/ctree.h" #include "kernel-shared/disk-io.h" #include "kernel-shared/volumes.h" +#include "kernel-shared/file-item.h" #include "kernel-shared/extent_io.h" #include "kernel-shared/transaction.h" #include "common/messages.h" @@ -180,7 +181,14 @@ static int generate_new_csum_range(struct btrfs_trans_handle *trans, goto out; } /* Calculate new csum and insert it into the csum tree. */ - ret = -EOPNOTSUPP; + ret = btrfs_csum_file_block(trans, cur, + BTRFS_CSUM_CHANGE_OBJECTID, new_csum_type, buf); + if (ret < 0) { + errno = -ret; + error("failed to insert new csum for data at logical %llu: %m", + cur); + goto out; + } } out: free(buf);