Loading fs/btrfs/send.c +58 −0 Original line number Diff line number Diff line Loading @@ -5805,6 +5805,64 @@ static int changed_extent(struct send_ctx *sctx, int ret = 0; if (sctx->cur_ino != sctx->cmp_key->objectid) { if (result == BTRFS_COMPARE_TREE_CHANGED) { struct extent_buffer *leaf_l; struct extent_buffer *leaf_r; struct btrfs_file_extent_item *ei_l; struct btrfs_file_extent_item *ei_r; leaf_l = sctx->left_path->nodes[0]; leaf_r = sctx->right_path->nodes[0]; ei_l = btrfs_item_ptr(leaf_l, sctx->left_path->slots[0], struct btrfs_file_extent_item); ei_r = btrfs_item_ptr(leaf_r, sctx->right_path->slots[0], struct btrfs_file_extent_item); /* * We may have found an extent item that has changed * only its disk_bytenr field and the corresponding * inode item was not updated. This case happens due to * very specific timings during relocation when a leaf * that contains file extent items is COWed while * relocation is ongoing and its in the stage where it * updates data pointers. So when this happens we can * safely ignore it since we know it's the same extent, * but just at different logical and physical locations * (when an extent is fully replaced with a new one, we * know the generation number must have changed too, * since snapshot creation implies committing the current * transaction, and the inode item must have been updated * as well). * This replacement of the disk_bytenr happens at * relocation.c:replace_file_extents() through * relocation.c:btrfs_reloc_cow_block(). */ if (btrfs_file_extent_generation(leaf_l, ei_l) == btrfs_file_extent_generation(leaf_r, ei_r) && btrfs_file_extent_ram_bytes(leaf_l, ei_l) == btrfs_file_extent_ram_bytes(leaf_r, ei_r) && btrfs_file_extent_compression(leaf_l, ei_l) == btrfs_file_extent_compression(leaf_r, ei_r) && btrfs_file_extent_encryption(leaf_l, ei_l) == btrfs_file_extent_encryption(leaf_r, ei_r) && btrfs_file_extent_other_encoding(leaf_l, ei_l) == btrfs_file_extent_other_encoding(leaf_r, ei_r) && btrfs_file_extent_type(leaf_l, ei_l) == btrfs_file_extent_type(leaf_r, ei_r) && btrfs_file_extent_disk_bytenr(leaf_l, ei_l) != btrfs_file_extent_disk_bytenr(leaf_r, ei_r) && btrfs_file_extent_disk_num_bytes(leaf_l, ei_l) == btrfs_file_extent_disk_num_bytes(leaf_r, ei_r) && btrfs_file_extent_offset(leaf_l, ei_l) == btrfs_file_extent_offset(leaf_r, ei_r) && btrfs_file_extent_num_bytes(leaf_l, ei_l) == btrfs_file_extent_num_bytes(leaf_r, ei_r)) return 0; } inconsistent_snapshot_error(sctx, result, "extent"); return -EIO; } Loading Loading
fs/btrfs/send.c +58 −0 Original line number Diff line number Diff line Loading @@ -5805,6 +5805,64 @@ static int changed_extent(struct send_ctx *sctx, int ret = 0; if (sctx->cur_ino != sctx->cmp_key->objectid) { if (result == BTRFS_COMPARE_TREE_CHANGED) { struct extent_buffer *leaf_l; struct extent_buffer *leaf_r; struct btrfs_file_extent_item *ei_l; struct btrfs_file_extent_item *ei_r; leaf_l = sctx->left_path->nodes[0]; leaf_r = sctx->right_path->nodes[0]; ei_l = btrfs_item_ptr(leaf_l, sctx->left_path->slots[0], struct btrfs_file_extent_item); ei_r = btrfs_item_ptr(leaf_r, sctx->right_path->slots[0], struct btrfs_file_extent_item); /* * We may have found an extent item that has changed * only its disk_bytenr field and the corresponding * inode item was not updated. This case happens due to * very specific timings during relocation when a leaf * that contains file extent items is COWed while * relocation is ongoing and its in the stage where it * updates data pointers. So when this happens we can * safely ignore it since we know it's the same extent, * but just at different logical and physical locations * (when an extent is fully replaced with a new one, we * know the generation number must have changed too, * since snapshot creation implies committing the current * transaction, and the inode item must have been updated * as well). * This replacement of the disk_bytenr happens at * relocation.c:replace_file_extents() through * relocation.c:btrfs_reloc_cow_block(). */ if (btrfs_file_extent_generation(leaf_l, ei_l) == btrfs_file_extent_generation(leaf_r, ei_r) && btrfs_file_extent_ram_bytes(leaf_l, ei_l) == btrfs_file_extent_ram_bytes(leaf_r, ei_r) && btrfs_file_extent_compression(leaf_l, ei_l) == btrfs_file_extent_compression(leaf_r, ei_r) && btrfs_file_extent_encryption(leaf_l, ei_l) == btrfs_file_extent_encryption(leaf_r, ei_r) && btrfs_file_extent_other_encoding(leaf_l, ei_l) == btrfs_file_extent_other_encoding(leaf_r, ei_r) && btrfs_file_extent_type(leaf_l, ei_l) == btrfs_file_extent_type(leaf_r, ei_r) && btrfs_file_extent_disk_bytenr(leaf_l, ei_l) != btrfs_file_extent_disk_bytenr(leaf_r, ei_r) && btrfs_file_extent_disk_num_bytes(leaf_l, ei_l) == btrfs_file_extent_disk_num_bytes(leaf_r, ei_r) && btrfs_file_extent_offset(leaf_l, ei_l) == btrfs_file_extent_offset(leaf_r, ei_r) && btrfs_file_extent_num_bytes(leaf_l, ei_l) == btrfs_file_extent_num_bytes(leaf_r, ei_r)) return 0; } inconsistent_snapshot_error(sctx, result, "extent"); return -EIO; } Loading