diff --git a/cmds-send.c b/cmds-send.c index 5607f2a7..d2f76914 100644 --- a/cmds-send.c +++ b/cmds-send.c @@ -236,7 +236,7 @@ out: return ERR_PTR(ret); } -static int do_send(struct btrfs_send *send, u64 root_id, u64 parent_root) +static int do_send(struct btrfs_send *send, u64 root_id, u64 parent_root_id) { int ret; pthread_t t_read; @@ -289,7 +289,7 @@ static int do_send(struct btrfs_send *send, u64 root_id, u64 parent_root) io_send.clone_sources = (__u64*)send->clone_sources; io_send.clone_sources_count = send->clone_sources_count; - io_send.parent_root = parent_root; + io_send.parent_root = parent_root_id; ret = ioctl(subvol_fd, BTRFS_IOC_SEND, &io_send); if (ret) { ret = -errno; @@ -426,6 +426,7 @@ int cmd_send_start(int argc, char **argv) char *snapshot_parent = NULL; u64 root_id; u64 parent_root_id = 0; + int full_send = 1; memset(&send, 0, sizeof(send)); send.dump_fd = fileno(stdout); @@ -435,12 +436,12 @@ int cmd_send_start(int argc, char **argv) return 1; } - while ((c = getopt(argc, argv, "vf:i:p:")) != -1) { + while ((c = getopt(argc, argv, "vc:f:i:p:")) != -1) { switch (c) { case 'v': g_verbose++; break; - case 'i': { + case 'c': subvol = realpath(optarg, NULL); if (!subvol) { ret = -errno; @@ -462,12 +463,16 @@ int cmd_send_start(int argc, char **argv) } add_clone_source(&send, root_id); free(subvol); + full_send = 0; break; - } case 'f': outname = optarg; break; case 'p': + if (snapshot_parent) { + fprintf(stderr, "ERROR: you cannot have more than one parent (-p)\n"); + return 1; + } snapshot_parent = realpath(optarg, NULL); if (!snapshot_parent) { ret = -errno; @@ -475,7 +480,12 @@ int cmd_send_start(int argc, char **argv) "%s\n", optarg, strerror(-ret)); goto out; } + full_send = 0; break; + case 'i': + fprintf(stderr, + "ERROR: -i was removed, use -c instead\n"); + return 1; case '?': default: fprintf(stderr, "ERROR: send args invalid.\n"); @@ -581,10 +591,13 @@ int cmd_send_start(int argc, char **argv) goto out; } - if (!parent_root_id) { + if (!full_send && !parent_root_id) { ret = find_good_parent(&send, root_id, &parent_root_id); - if (ret < 0) - parent_root_id = 0; + if (ret < 0) { + fprintf(stderr, "ERROR: parent determination failed for %lld\n", + root_id); + goto out; + } } ret = is_subvol_ro(&send, subvol); @@ -605,6 +618,7 @@ int cmd_send_start(int argc, char **argv) add_clone_source(&send, root_id); parent_root_id = 0; + full_send = 0; free(subvol); } @@ -622,32 +636,28 @@ static const char * const send_cmd_group_usage[] = { }; static const char * const cmd_send_usage[] = { - "btrfs send [-v] [-i ] [-p ] ", + "btrfs send [-v] [-p ] [-c ] ", "Send the subvolume to stdout.", "Sends the subvolume specified by to stdout.", - "By default, this will send the whole subvolume. To do", - "an incremental send, one or multiple '-i '", - "arguments have to be specified. A 'clone source' is", - "a subvolume that is known to exist on the receiving", - "side in exactly the same state as on the sending side.\n", - "Normally, a good snapshot parent is searched automatically", - "in the list of 'clone sources'. To override this, use", - "'-p ' to manually specify a snapshot parent.", - "A manually specified snapshot parent is also regarded", - "as 'clone source'.\n", - "-v Enable verbose debug output. Each", - " occurrency of this option increases the", - " verbose level more.", - "-i Informs btrfs send that this subvolume,", - " can be taken as 'clone source'. This can", - " be used for incremental sends.", - "-p Disable automatic snaphot parent", - " determination and use as parent.", - " This subvolume is also added to the list", - " of 'clone sources' (see -i).", - "-f Output is normally written to stdout.", - " To write to a file, use this option.", - " An alternative would be to use pipes.", + "By default, this will send the whole subvolume. To do an incremental", + "send, use '-p '. If you want to allow btrfs to clone from", + "any additional local snapshots, use -c (multiple times", + "where applicable). You must not specify clone sources unless you", + "guarantee that these snapshots are exactly in the same state on both", + "sides, the sender and the receiver. It is allowed to omit the", + "'-p ' option when '-c ' options are given, in", + "which case 'btrfs send' will determine a suitable parent among the", + "clone sources itself.", + "\n", + "-v Enable verbose debug output. Each occurrency of", + " this option increases the verbose level more.", + "-p Send an incremental stream from to", + " .", + "-c Use this snapshot as a clone source for an ", + " incremental send (multiple allowed)", + "-f Output is normally written to stdout. To write to", + " a file, use this option. An alternative would be to", + " use pipes.", NULL };