Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 112a3edf authored by Chris Mason's avatar Chris Mason
Browse files

Merge branch 'for-chris-4.9' of...

Merge branch 'for-chris-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/fdmanana/linux into for-linus-4.9
parents d9ed71e5 d5e84fd8
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
@@ -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;
	}