Merge branch 'for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "My patch fixes the btrfs list_head abuse that we tracked down during Dave Jones' memory corruption investigation. With both Jens and my patches in place, I'm no longer able to trigger problems. Filipe is fixing a difficult old bug between snapshots, balance and send. Dave is cooking a few more for the next rc, but these are tested and ready" * 'for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: btrfs: fix races on root_log_ctx lists btrfs: fix incremental send failure caused by balance
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user