@@ -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 <subvol> Informs btrfs send that this subvolume,",
" can be taken as 'clone source'. This can",
" be used for incremental sends.",