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

Commit 37b8d27d authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason
Browse files

Btrfs: use received_uuid of parent during send



Neil Horman pointed out a problem where if he did something like this

receive A
snap A B
change B
send -p A B

and then on another box do

recieve A
receive B

the receive B would fail because we use the UUID of A for the clone sources for
B.  This makes sense most of the time because normally you are sending from the
original sources, not a received source.  However when you use a recieved subvol
its UUID is going to be something completely different, so if you then try to
receive the diff on a different volume it won't find the UUID because the new A
will be something else.  The only constant is the received uuid.  So instead
check to see if we have received_uuid set on the root, and if so use that as the
clone source, as btrfs receive looks for matches either in received_uuid or
uuid.  Thanks,

Reported-by: default avatarNeil Horman <nhorman@redhat.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fb.com>
Reviewed-by: default avatarHugo Mills <hugo@carfax.org.uk>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent 0eeff236
Loading
Loading
Loading
Loading
+21 −4
Original line number Original line Diff line number Diff line
@@ -2356,8 +2356,12 @@ static int send_subvol_begin(struct send_ctx *sctx)
	TLV_PUT_U64(sctx, BTRFS_SEND_A_CTRANSID,
	TLV_PUT_U64(sctx, BTRFS_SEND_A_CTRANSID,
		    le64_to_cpu(sctx->send_root->root_item.ctransid));
		    le64_to_cpu(sctx->send_root->root_item.ctransid));
	if (parent_root) {
	if (parent_root) {
		if (!btrfs_is_empty_uuid(parent_root->root_item.received_uuid))
			TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID,
			TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID,
				sctx->parent_root->root_item.uuid);
				     parent_root->root_item.received_uuid);
		else
			TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID,
				     parent_root->root_item.uuid);
		TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_CTRANSID,
		TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_CTRANSID,
			    le64_to_cpu(sctx->parent_root->root_item.ctransid));
			    le64_to_cpu(sctx->parent_root->root_item.ctransid));
	}
	}
@@ -4586,6 +4590,19 @@ verbose_printk("btrfs: send_clone offset=%llu, len=%d, clone_root=%llu, "
	if (ret < 0)
	if (ret < 0)
		goto out;
		goto out;


	/*
	 * If the parent we're using has a received_uuid set then use that as
	 * our clone source as that is what we will look for when doing a
	 * receive.
	 *
	 * This covers the case that we create a snapshot off of a received
	 * subvolume and then use that as the parent and try to receive on a
	 * different host.
	 */
	if (!btrfs_is_empty_uuid(clone_root->root->root_item.received_uuid))
		TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID,
			     clone_root->root->root_item.received_uuid);
	else
		TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID,
		TLV_PUT_UUID(sctx, BTRFS_SEND_A_CLONE_UUID,
			     clone_root->root->root_item.uuid);
			     clone_root->root->root_item.uuid);
	TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_CTRANSID,
	TLV_PUT_U64(sctx, BTRFS_SEND_A_CLONE_CTRANSID,