aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Behrens <sbehrens@giantdisaster.de>2013-04-10 13:10:52 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:54:44 -0400
commitc2c71324ecb471c932bc1ff59e46ffcf82f274fc (patch)
tree8de6bb57594560bf381e4e5cc9bfaccc8e3caf60
parent692206b153ea0d08d6015521ed27a6739cbf6f9f (diff)
Btrfs: allow omitting stream header and end-cmd for btrfs send
Two new flags are added to allow omitting the stream header and the end command for btrfs send streams. This is used in cases where you send multiple snapshots back-to-back in one stream. This used to be encoded like this (with 2 snapshots in this example): <stream header> + <sequence of commands> + <end cmd> + <stream header> + <sequence of commands> + <end cmd> + EOF The new format (if the two new flags are used) is this one: <stream header> + <sequence of commands> + <sequence of commands> + <end cmd> Note that the currently existing receivers treat <end cmd> only as an indication that a new <stream header> is following. This means, you can just skip the sequence <end cmd> <stream header> without loosing compatibility. As long as an EOF is following, the currently existing receivers handle the new format (if the two new flags are used) exactly as the old one. So what is the benefit of this change? The goal is to be able to use a single stream (one TCP connection) to multiplex a request/response handshake plus Btrfs send streams, all in the same stream. In this case you cannot evaluate an EOF condition as an end of the Btrfs send stream. You need something else, and the <end cmd> is just perfect for this purpose. The summary is: The format change is driven by the need to send several Btrfs send streams over a single TCP connections, with the ability for a repeated request/response handshake in the middle. And this format change does not break any existing tool, it is completely compatible. You could compare the old behaviour of the Btrfs send stream to the one of ftp where you need a seperate request/response channel and newly opened data transfer channels for each file, while the new behaviour is more like http using a single stream for everything. Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
-rw-r--r--fs/btrfs/send.c24
-rw-r--r--include/uapi/linux/btrfs.h20
2 files changed, 33 insertions, 11 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index c85e7c6b4598..e0c69a106c77 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -4529,9 +4529,11 @@ static int send_subvol(struct send_ctx *sctx)
4529{ 4529{
4530 int ret; 4530 int ret;
4531 4531
4532 ret = send_header(sctx); 4532 if (!(sctx->flags & BTRFS_SEND_FLAG_OMIT_STREAM_HEADER)) {
4533 if (ret < 0) 4533 ret = send_header(sctx);
4534 goto out; 4534 if (ret < 0)
4535 goto out;
4536 }
4535 4537
4536 ret = send_subvol_begin(sctx); 4538 ret = send_subvol_begin(sctx);
4537 if (ret < 0) 4539 if (ret < 0)
@@ -4593,7 +4595,7 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
4593 goto out; 4595 goto out;
4594 } 4596 }
4595 4597
4596 if (arg->flags & ~BTRFS_SEND_FLAG_NO_FILE_DATA) { 4598 if (arg->flags & ~BTRFS_SEND_FLAG_MASK) {
4597 ret = -EINVAL; 4599 ret = -EINVAL;
4598 goto out; 4600 goto out;
4599 } 4601 }
@@ -4704,12 +4706,14 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
4704 if (ret < 0) 4706 if (ret < 0)
4705 goto out; 4707 goto out;
4706 4708
4707 ret = begin_cmd(sctx, BTRFS_SEND_C_END); 4709 if (!(sctx->flags & BTRFS_SEND_FLAG_OMIT_END_CMD)) {
4708 if (ret < 0) 4710 ret = begin_cmd(sctx, BTRFS_SEND_C_END);
4709 goto out; 4711 if (ret < 0)
4710 ret = send_cmd(sctx); 4712 goto out;
4711 if (ret < 0) 4713 ret = send_cmd(sctx);
4712 goto out; 4714 if (ret < 0)
4715 goto out;
4716 }
4713 4717
4714out: 4718out:
4715 kfree(arg); 4719 kfree(arg);
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
index fa3a5f9338fc..5e39e859a848 100644
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -412,7 +412,25 @@ struct btrfs_ioctl_received_subvol_args {
412 * search of clone sources doesn't find an extent. UPDATE_EXTENT 412 * search of clone sources doesn't find an extent. UPDATE_EXTENT
413 * commands will be sent instead of WRITE commands. 413 * commands will be sent instead of WRITE commands.
414 */ 414 */
415#define BTRFS_SEND_FLAG_NO_FILE_DATA 0x1 415#define BTRFS_SEND_FLAG_NO_FILE_DATA 0x1
416
417/*
418 * Do not add the leading stream header. Used when multiple snapshots
419 * are sent back to back.
420 */
421#define BTRFS_SEND_FLAG_OMIT_STREAM_HEADER 0x2
422
423/*
424 * Omit the command at the end of the stream that indicated the end
425 * of the stream. This option is used when multiple snapshots are
426 * sent back to back.
427 */
428#define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4
429
430#define BTRFS_SEND_FLAG_MASK \
431 (BTRFS_SEND_FLAG_NO_FILE_DATA | \
432 BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \
433 BTRFS_SEND_FLAG_OMIT_END_CMD)
416 434
417struct btrfs_ioctl_send_args { 435struct btrfs_ioctl_send_args {
418 __s64 send_fd; /* in */ 436 __s64 send_fd; /* in */