diff --git a/cmds-send.c b/cmds-send.c index 9b47e70..340a4d2 100644 --- a/cmds-send.c +++ b/cmds-send.c @@ -39,6 +39,7 @@ #include "send.h" #include "send-utils.h" +#include "send-analyser.h" static int g_verbose = 0; @@ -52,6 +53,9 @@ struct btrfs_send { char *root_path; struct subvol_uuid_search sus; + + int do_analyse; + struct btrfs_stream_analyser analyser; }; int find_mount_root(const char *path, char **mount_root) @@ -209,21 +213,34 @@ static void *dump_thread(void *arg_) char buf[4096]; int readed; - while (1) { - readed = read(s->send_fd, buf, sizeof(buf)); - if (readed < 0) { - ret = -errno; - fprintf(stderr, "ERROR: failed to read stream from " + if (!s->do_analyse) + { + while (1) { + readed = read(s->send_fd, buf, sizeof(buf)); + if (readed < 0) { + ret = -errno; + fprintf(stderr, "ERROR: failed to read stream from " "kernel. %s\n", strerror(-ret)); - goto out; + goto out; + } + if (!readed) { + ret = 0; + goto out; + } + ret = write_buf(s->dump_fd, buf, readed); + if (ret < 0) + goto out; } - if (!readed) { - ret = 0; - goto out; + } + else + { + while (1) { + ret = analyser_process(&s->analyser, s->send_fd); + if (ret == 0) + goto out; + if (ret < 0) + goto out; } - ret = write_buf(s->dump_fd, buf, readed); - if (ret < 0) - goto out; } out: @@ -234,6 +251,31 @@ out: return ERR_PTR(ret); } + +static void setup(struct btrfs_send *s, u64 root_id1, u64 root_id2) +{ + struct subvol_info *si1 = subvol_uuid_search(&s->sus, root_id1, NULL, 0, + NULL, subvol_search_by_root_id); + assert(si1); + s->analyser.fd1 = open(si1->path, O_RDONLY | O_NOATIME); + + struct subvol_info *si2 = subvol_uuid_search(&s->sus, root_id2, NULL, 0, + NULL, subvol_search_by_root_id); + assert(si2); + s->analyser.fd2 = open(si2->path, O_RDONLY | O_NOATIME); + + fprintf(stderr, "Comparing %s and %s.\n", si1->path, si2->path); +} + + +static void output(const char *path, unsigned int status, void *user) +{ + char *s = analyser_status_to_string(status); + printf("%s %s\n", s, path); + free(s); +} + + static int do_send(struct btrfs_send *send, u64 root_id, u64 parent_root) { int ret; @@ -274,6 +316,13 @@ static int do_send(struct btrfs_send *send, u64 root_id, u64 parent_root) io_send.send_fd = pipefd[1]; send->send_fd = pipefd[0]; + if (send->do_analyse) + { + analyser_create(&send->analyser); + setup(send, parent_root, root_id); + io_send.flags = BTRFS_SEND_FLAG_NO_FILE_DATA; + } + if (!ret) ret = pthread_create(&t_read, &t_attr, dump_thread, send); @@ -321,6 +370,11 @@ static int do_send(struct btrfs_send *send, u64 root_id, u64 parent_root) ret = 0; + if (send->do_analyse) + { + analyser_result(&send->analyser, output, NULL); + } + out: if (subvol_fd != -1) close(subvol_fd); @@ -427,7 +481,7 @@ int cmd_send_start(int argc, char **argv) memset(&send, 0, sizeof(send)); send.dump_fd = fileno(stdout); - while ((c = getopt(argc, argv, "vf:i:p:")) != -1) { + while ((c = getopt(argc, argv, "vf:i:p:a")) != -1) { switch (c) { case 'v': g_verbose++; @@ -468,6 +522,9 @@ int cmd_send_start(int argc, char **argv) goto out; } break; + case 'a': + send.do_analyse = 1; + break; case '?': default: fprintf(stderr, "ERROR: send args invalid.\n"); @@ -630,6 +687,7 @@ static const char * const cmd_send_usage[] = { "-v Enable verbose debug output. Each", " occurrency of this option increases the", " verbose level more.", + "-a Analyse the stream.", "-i Informs btrfs send that this subvolume,", " can be taken as 'clone source'. This can", " be used for incremental sends.",