2 * Copyright (C) 2012 Alexander Block. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
20 #include "kerncompat.h"
29 #include <sys/types.h>
30 #include <sys/ioctl.h>
35 #include <uuid/uuid.h>
45 #include "send-utils.h"
47 #define SEND_BUFFER_SIZE (64 * 1024)
50 * Default is 1 for historical reasons, changing may break scripts that expect
51 * the 'At subvol' message.
53 static int g_verbose = 1;
61 u64 clone_sources_count;
64 struct subvol_uuid_search sus;
67 static int get_root_id(struct btrfs_send *sctx, const char *path, u64 *root_id)
69 struct subvol_info *si;
71 si = subvol_uuid_search(&sctx->sus, 0, NULL, 0, path,
72 subvol_search_by_path);
75 *root_id = si->root_id;
81 static struct subvol_info *get_parent(struct btrfs_send *sctx, u64 root_id)
83 struct subvol_info *si_tmp;
84 struct subvol_info *si;
86 si_tmp = subvol_uuid_search(&sctx->sus, root_id, NULL, 0, NULL,
87 subvol_search_by_root_id);
91 si = subvol_uuid_search(&sctx->sus, 0, si_tmp->parent_uuid, 0, NULL,
92 subvol_search_by_uuid);
98 static int find_good_parent(struct btrfs_send *sctx, u64 root_id, u64 *found)
101 struct subvol_info *parent = NULL;
102 struct subvol_info *parent2 = NULL;
103 struct subvol_info *best_parent = NULL;
104 u64 best_diff = (u64)-1;
107 parent = get_parent(sctx, root_id);
108 if (IS_ERR(parent)) {
109 ret = PTR_ERR(parent);
113 for (i = 0; i < sctx->clone_sources_count; i++) {
114 if (sctx->clone_sources[i] == parent->root_id) {
115 best_parent = parent;
121 for (i = 0; i < sctx->clone_sources_count; i++) {
124 parent2 = get_parent(sctx, sctx->clone_sources[i]);
127 if (parent2->root_id != parent->root_id) {
136 parent2 = subvol_uuid_search(&sctx->sus,
137 sctx->clone_sources[i], NULL, 0, NULL,
138 subvol_search_by_root_id);
139 if (IS_ERR(parent2)) {
140 ret = PTR_ERR(parent2);
143 tmp = parent2->ctransid - parent->ctransid;
146 if (tmp < best_diff) {
148 free(best_parent->path);
151 best_parent = parent2;
167 *found = best_parent->root_id;
176 free(best_parent->path);
182 static int add_clone_source(struct btrfs_send *sctx, u64 root_id)
186 tmp = sctx->clone_sources;
187 sctx->clone_sources = realloc(sctx->clone_sources,
188 sizeof(*sctx->clone_sources) * (sctx->clone_sources_count + 1));
190 if (!sctx->clone_sources) {
194 sctx->clone_sources[sctx->clone_sources_count++] = root_id;
200 static int write_buf(int fd, const char *buf, size_t size)
208 wbytes = write(fd, buf + pos, size - pos);
211 error("failed to dump stream: %s", strerror(-ret));
216 error("failed to dump stream: %s", strerror(-ret));
227 static void* read_sent_data_copy(void *arg)
230 struct btrfs_send *sctx = (struct btrfs_send*)arg;
231 char buf[SEND_BUFFER_SIZE];
236 rbytes = read(sctx->send_fd, buf, sizeof(buf));
239 error("failed to read stream from kernel: %s",
247 ret = write_buf(sctx->dump_fd, buf, rbytes);
260 static void *read_sent_data(void *arg)
263 struct btrfs_send *sctx = (struct btrfs_send*)arg;
268 /* Source is a pipe, output is either file or stdout */
269 sbytes = splice(sctx->send_fd, NULL, sctx->dump_fd,
270 NULL, SEND_BUFFER_SIZE, SPLICE_F_MORE);
273 error("failed to read stream from kernel: %s",
290 static int do_send(struct btrfs_send *send, u64 parent_root_id,
291 int is_first_subvol, int is_last_subvol, const char *subvol,
296 struct btrfs_ioctl_send_args io_send;
299 int pipefd[2] = {-1, -1};
301 subvol_fd = openat(send->mnt_fd, subvol, O_RDONLY | O_NOATIME);
304 error("cannot open %s: %s", subvol, strerror(-ret));
311 error("pipe failed: %s", strerror(-ret));
315 memset(&io_send, 0, sizeof(io_send));
316 io_send.send_fd = pipefd[1];
317 send->send_fd = pipefd[0];
320 ret = pthread_create(&t_read, NULL, read_sent_data, send);
323 error("thread setup failed: %s", strerror(-ret));
327 io_send.flags = flags;
328 io_send.clone_sources = (__u64*)send->clone_sources;
329 io_send.clone_sources_count = send->clone_sources_count;
330 io_send.parent_root = parent_root_id;
331 if (!is_first_subvol)
332 io_send.flags |= BTRFS_SEND_FLAG_OMIT_STREAM_HEADER;
334 io_send.flags |= BTRFS_SEND_FLAG_OMIT_END_CMD;
335 ret = ioctl(subvol_fd, BTRFS_IOC_SEND, &io_send);
338 error("send ioctl failed with %d: %s", ret, strerror(-ret));
339 if (ret == -EINVAL && (!is_first_subvol || !is_last_subvol))
341 "Try upgrading your kernel or don't use -e.\n");
345 fprintf(stderr, "BTRFS_IOC_SEND returned %d\n", ret);
348 fprintf(stderr, "joining genl thread\n");
353 ret = pthread_join(t_read, &t_err);
356 error("pthread_join failed: %s", strerror(-ret));
360 ret = (long int)t_err;
361 error("failed to process send stream, ret=%ld (%s)",
362 (long int)t_err, strerror(-ret));
378 static int init_root_path(struct btrfs_send *sctx, const char *subvol)
385 ret = find_mount_root(subvol, &sctx->root_path);
387 error("failed to determine mount point for %s: %s",
388 subvol, strerror(-ret));
393 error("%s doesn't belong to btrfs mount point", subvol);
398 sctx->mnt_fd = open(sctx->root_path, O_RDONLY | O_NOATIME);
399 if (sctx->mnt_fd < 0) {
401 error("cannot open '%s': %s", sctx->root_path, strerror(-ret));
405 ret = subvol_uuid_search_init(sctx->mnt_fd, &sctx->sus);
407 error("failed to initialize subvol search: %s",
417 static int is_subvol_ro(struct btrfs_send *sctx, const char *subvol)
423 fd = openat(sctx->mnt_fd, subvol, O_RDONLY | O_NOATIME);
426 error("cannot open %s: %s", subvol, strerror(-ret));
430 ret = ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
433 error("failed to get flags for subvolume %s: %s",
434 subvol, strerror(-ret));
438 if (flags & BTRFS_SUBVOL_RDONLY)
450 static int set_root_info(struct btrfs_send *sctx, const char *subvol,
455 ret = init_root_path(sctx, subvol);
459 ret = get_root_id(sctx, subvol_strip_mountpoint(sctx->root_path, subvol),
462 error("cannot resolve rootid for %s", subvol);
470 static void free_send_info(struct btrfs_send *sctx)
472 if (sctx->mnt_fd >= 0) {
476 free(sctx->root_path);
477 sctx->root_path = NULL;
478 subvol_uuid_search_finit(&sctx->sus);
481 int cmd_send(int argc, char **argv)
485 char outname[PATH_MAX];
486 struct btrfs_send send;
488 char *mount_root = NULL;
489 char *snapshot_parent = NULL;
491 u64 parent_root_id = 0;
493 int new_end_cmd_semantic = 0;
496 memset(&send, 0, sizeof(send));
497 send.dump_fd = fileno(stdout);
501 enum { GETOPT_VAL_SEND_NO_DATA = 256 };
502 static const struct option long_options[] = {
503 { "verbose", no_argument, NULL, 'v' },
504 { "quiet", no_argument, NULL, 'q' },
505 { "no-data", no_argument, NULL, GETOPT_VAL_SEND_NO_DATA }
507 int c = getopt_long(argc, argv, "vqec:f:i:p:", long_options, NULL);
520 new_end_cmd_semantic = 1;
523 subvol = realpath(optarg, NULL);
526 error("realpath %s failed: %s\n", optarg, strerror(-ret));
530 ret = set_root_info(&send, subvol, &root_id);
534 ret = is_subvol_ro(&send, subvol);
539 error("cloned subvolume %s is not read-only", subvol);
543 ret = add_clone_source(&send, root_id);
545 error("cannot add clone source: %s", strerror(-ret));
550 free_send_info(&send);
554 if (arg_copy_path(outname, optarg, sizeof(outname))) {
555 error("output file path too long (%zu)", strlen(optarg));
561 if (snapshot_parent) {
562 error("you cannot have more than one parent (-p)");
566 snapshot_parent = realpath(optarg, NULL);
567 if (!snapshot_parent) {
569 error("realpath %s failed: %s", optarg, strerror(-ret));
573 ret = is_subvol_ro(&send, snapshot_parent);
578 error("parent subvolume %s is not read-only",
586 error("option -i was removed, use -c instead");
589 case GETOPT_VAL_SEND_NO_DATA:
590 send_flags |= BTRFS_SEND_FLAG_NO_FILE_DATA;
594 error("send arguments invalid");
600 if (check_argc_min(argc - optind, 1))
601 usage(cmd_send_usage);
607 * Try to use an existing file first. Even if send runs as
608 * root, it might not have permissions to create file (eg. on a
609 * NFS) but it should still be able to use a pre-created file.
611 tmpfd = open(outname, O_WRONLY | O_TRUNC);
614 tmpfd = open(outname,
615 O_CREAT | O_WRONLY | O_TRUNC, 0600);
617 send.dump_fd = tmpfd;
618 if (send.dump_fd == -1) {
620 error("cannot create '%s': %s", outname, strerror(-ret));
625 if (isatty(send.dump_fd)) {
627 "not dumping send stream into a terminal, redirect it into a file");
632 /* use first send subvol to determine mount_root */
633 subvol = realpath(argv[optind], NULL);
636 error("unable to resolve %s", argv[optind]);
640 ret = init_root_path(&send, subvol);
644 if (snapshot_parent != NULL) {
645 ret = get_root_id(&send,
646 subvol_strip_mountpoint(send.root_path, snapshot_parent),
649 error("could not resolve rootid for %s", snapshot_parent);
653 ret = add_clone_source(&send, parent_root_id);
655 error("cannot add clone source: %s", strerror(-ret));
660 for (i = optind; i < argc; i++) {
662 subvol = realpath(argv[i], NULL);
665 error("unable to resolve %s", argv[i]);
669 ret = find_mount_root(subvol, &mount_root);
671 error("find_mount_root failed on %s: %s", subvol,
676 error("%s does not belong to btrfs mount point",
681 if (strcmp(send.root_path, mount_root) != 0) {
683 error("all subvolumes must be from the same filesystem");
688 ret = is_subvol_ro(&send, subvol);
693 error("subvolume %s is not read-only", subvol);
698 if ((send_flags & BTRFS_SEND_FLAG_NO_FILE_DATA) && g_verbose > 1)
700 fprintf(stderr, "Mode NO_FILE_DATA enabled\n");
702 for (i = optind; i < argc; i++) {
710 fprintf(stderr, "At subvol %s\n", subvol);
712 subvol = realpath(subvol, NULL);
715 error("realpath %s failed: %s", argv[i], strerror(-ret));
719 if (!full_send && !snapshot_parent) {
720 ret = set_root_info(&send, subvol, &root_id);
724 ret = find_good_parent(&send, root_id, &parent_root_id);
726 error("parent determination failed for %lld",
732 if (new_end_cmd_semantic) {
733 /* require new kernel */
734 is_first_subvol = (i == optind);
735 is_last_subvol = (i == argc - 1);
737 /* be compatible to old and new kernel */
741 ret = do_send(&send, parent_root_id, is_first_subvol,
742 is_last_subvol, subvol, send_flags);
746 if (!full_send && !snapshot_parent) {
747 /* done with this subvol, so add it to the clone sources */
748 ret = add_clone_source(&send, root_id);
750 error("cannot add clone source: %s", strerror(-ret));
753 free_send_info(&send);
761 free(snapshot_parent);
762 free(send.clone_sources);
763 free_send_info(&send);
767 const char * const cmd_send_usage[] = {
768 "btrfs send [-ve] [-p <parent>] [-c <clone-src>] [-f <outfile>] <subvol> [<subvol>...]",
769 "Send the subvolume(s) to stdout.",
770 "Sends the subvolume(s) specified by <subvol> to stdout.",
771 "<subvol> should be read-only here.",
772 "By default, this will send the whole subvolume. To do an incremental",
773 "send, use '-p <parent>'. If you want to allow btrfs to clone from",
774 "any additional local snapshots, use '-c <clone-src>' (multiple times",
775 "where applicable). You must not specify clone sources unless you",
776 "guarantee that these snapshots are exactly in the same state on both",
777 "sides, the sender and the receiver. It is allowed to omit the",
778 "'-p <parent>' option when '-c <clone-src>' options are given, in",
779 "which case 'btrfs send' will determine a suitable parent among the",
780 "clone sources itself.",
782 "-e If sending multiple subvols at once, use the new",
783 " format and omit the end-cmd between the subvols.",
784 "-p <parent> Send an incremental stream from <parent> to",
786 "-c <clone-src> Use this snapshot as a clone source for an ",
787 " incremental send (multiple allowed)",
788 "-f <outfile> Output is normally written to stdout. To write to",
789 " a file, use this option. An alternative would be to",
791 "--no-data send in NO_FILE_DATA mode, Note: the output stream",
792 " does not contain any file data and thus cannot be used",
793 " to transfer changes. This mode is faster and useful to",
794 " show the differences in metadata.",
795 "-v|--verbose enable verbose output to stderr, each occurrence of",
796 " this option increases verbosity",
797 "-q|--quiet suppress all messages, except errors",