From: Filipe Manana <fdman...@gmail.com>

This increases the send stream version from version 1 to version 2, adding
new commands:

1) total data size - used to tell the receiver how much file data the stream
   will add or update;

2) fallocate - used to pre-allocate space for files and to punch holes in files;

3) inode set flags;

4) set inode otime.

This is preparation work for subsequent changes that implement the new features.

This doesn't break compatibility with older kernels or clients. In order to get
a version 2 send stream, new flags must be passed to the send ioctl.

Signed-off-by: Filipe David Borba Manana <fdman...@gmail.com>
---
 cmds-send.c   | 61 ++++++++++++++++++++++++++++++++++++---------------
 ioctl.h       | 15 +++++++++++++
 send-stream.c |  2 +-
 send.h        | 23 ++++++++++++++++++-
 4 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/cmds-send.c b/cmds-send.c
index c5ecdaa1..0ec557c7 100644
--- a/cmds-send.c
+++ b/cmds-send.c
@@ -52,6 +52,7 @@
  * the 'At subvol' message.
  */
 static int g_verbose = 1;
+static int g_stream_version = BTRFS_SEND_STREAM_VERSION_1;
 
 struct btrfs_send {
        int send_fd;
@@ -343,6 +344,8 @@ static int do_send(struct btrfs_send *send, u64 
parent_root_id,
                io_send.flags |= BTRFS_SEND_FLAG_OMIT_STREAM_HEADER;
        if (!is_last_subvol)
                io_send.flags |= BTRFS_SEND_FLAG_OMIT_END_CMD;
+       if (g_stream_version == BTRFS_SEND_STREAM_VERSION_2)
+               io_send.flags |= BTRFS_SEND_FLAG_STREAM_V2;
        ret = ioctl(subvol_fd, BTRFS_IOC_SEND, &io_send);
        if (ret < 0) {
                ret = -errno;
@@ -513,7 +516,8 @@ int cmd_send(int argc, char **argv)
                static const struct option long_options[] = {
                        { "verbose", no_argument, NULL, 'v' },
                        { "quiet", no_argument, NULL, 'q' },
-                       { "no-data", no_argument, NULL, GETOPT_VAL_SEND_NO_DATA 
}
+                       { "no-data", no_argument, NULL, GETOPT_VAL_SEND_NO_DATA 
},
+                       { "stream-version", 1, NULL, 'V' },
                };
                int c = getopt_long(argc, argv, "vqec:f:i:p:", long_options, 
NULL);
 
@@ -597,6 +601,24 @@ int cmd_send(int argc, char **argv)
                        error("option -i was removed, use -c instead");
                        ret = 1;
                        goto out;
+               case 'V':
+                       if (sscanf(optarg, "%d", &g_stream_version) != 1) {
+                               fprintf(stderr,
+                                       "ERROR: invalid value for stream 
version: %s\n",
+                                       optarg);
+                               ret = 1;
+                               goto out;
+                       }
+                       if (g_stream_version <= 0 ||
+                           g_stream_version > BTRFS_SEND_STREAM_VERSION_MAX) {
+                               fprintf(stderr,
+                                       "ERROR: unsupported stream version %d, 
minimum: 1, maximum: %d\n",
+                                       g_stream_version,
+                                       BTRFS_SEND_STREAM_VERSION_MAX);
+                               ret = 1;
+                               goto out;
+                       }
+                       break;
                case GETOPT_VAL_SEND_NO_DATA:
                        send_flags |= BTRFS_SEND_FLAG_NO_FILE_DATA;
                        break;
@@ -776,7 +798,7 @@ out:
 }
 
 const char * const cmd_send_usage[] = {
-       "btrfs send [-ve] [-p <parent>] [-c <clone-src>] [-f <outfile>] 
<subvol> [<subvol>...]",
+       "btrfs send [-ve] [--stream-version <version>] [-p <parent>] [-c 
<clone-src>] [-f <outfile>] <subvol> [<subvol>...]",
        "Send the subvolume(s) to stdout.",
        "Sends the subvolume(s) specified by <subvol> to stdout.",
        "<subvol> should be read-only here.",
@@ -790,21 +812,24 @@ const char * const cmd_send_usage[] = {
        "which case 'btrfs send' will determine a suitable parent among the",
        "clone sources itself.",
        "\n",
-       "-e               If sending multiple subvols at once, use the new",
-       "                 format and omit the end-cmd between the subvols.",
-       "-p <parent>      Send an incremental stream from <parent> to",
-       "                 <subvol>.",
-       "-c <clone-src>   Use this snapshot as a clone source for an ",
-       "                 incremental send (multiple allowed)",
-       "-f <outfile>     Output is normally written to stdout. To write to",
-       "                 a file, use this option. An alternative would be to",
-       "                 use pipes.",
-       "--no-data        send in NO_FILE_DATA mode, Note: the output stream",
-       "                 does not contain any file data and thus cannot be 
used",
-       "                 to transfer changes. This mode is faster and useful 
to",
-       "                 show the differences in metadata.",
-       "-v|--verbose     enable verbose output to stderr, each occurrence of",
-       "                 this option increases verbosity",
-       "-q|--quiet       suppress all messages, except errors",
+       "-e                          If sending multiple subvols at once, use 
the new",
+       "                            format and omit the end-cmd between the 
subvols.",
+       "-p <parent>                 Send an incremental stream from <parent> 
to",
+       "                            <subvol>.",
+       "-c <clone-src>              Use this snapshot as a clone source for an 
",
+       "                            incremental send (multiple allowed)",
+       "-f <outfile>                Output is normally written to stdout. To 
write to",
+       "                            a file, use this option. An alternative 
would be to",
+       "                            use pipes.",
+       "--no-data                   send in NO_FILE_DATA mode, Note: the 
output stream",
+       "                            does not contain any file data and thus 
cannot be used",
+       "                            to transfer changes. This mode is faster 
and useful to",
+       "                            show the differences in metadata.",
+       "-v|--verbose                enable verbose output to stderr, each 
occurrence of",
+       "                            this option increases verbosity",
+       "-q|--quiet                  suppress all messages, except errors",
+       "--stream-version <version>  Ask the kernel to produce a specific send 
stream",
+       "                            version. More recent stream versions 
provide new",
+       "                            features and better performance. Default 
value is 1.",
        NULL
 };
diff --git a/ioctl.h b/ioctl.h
index 709e996f..9d490aca 100644
--- a/ioctl.h
+++ b/ioctl.h
@@ -632,6 +632,21 @@ BUILD_ASSERT(sizeof(struct 
btrfs_ioctl_received_subvol_args_32) == 192);
         BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \
         BTRFS_SEND_FLAG_OMIT_END_CMD)
 
+/*
+ * The sum of all length fields the receiver will get in write, clone and
+ * fallocate commands.
+ * This can be used by the receiver to compute progress, at the expense of some
+ * initial metadata scan performed by the sender (kernel).
+ *
+ * Added in send stream version 2.
+ */
+#define BTRFS_SEND_FLAG_CALCULATE_DATA_SIZE    0x8
+
+/*
+ * Used by a client to request a version 2 of the send stream.
+ */
+#define BTRFS_SEND_FLAG_STREAM_V2               0x10
+
 struct btrfs_ioctl_send_args {
        __s64 send_fd;                  /* in */
        __u64 clone_sources_count;      /* in */
diff --git a/send-stream.c b/send-stream.c
index 78f2571a..86956d28 100644
--- a/send-stream.c
+++ b/send-stream.c
@@ -503,7 +503,7 @@ int btrfs_read_and_process_send_stream(int fd,
        }
 
        sctx.version = le32_to_cpu(hdr.version);
-       if (sctx.version > BTRFS_SEND_STREAM_VERSION) {
+       if (sctx.version > BTRFS_SEND_STREAM_VERSION_MAX) {
                ret = -EINVAL;
                error("stream version %d not supported, please use newer 
version",
                                sctx.version);
diff --git a/send.h b/send.h
index fe613cbb..eb14fba3 100644
--- a/send.h
+++ b/send.h
@@ -27,7 +27,10 @@ extern "C" {
 #endif
 
 #define BTRFS_SEND_STREAM_MAGIC "btrfs-stream"
-#define BTRFS_SEND_STREAM_VERSION 1
+#define BTRFS_SEND_STREAM_VERSION_1 1
+#define BTRFS_SEND_STREAM_VERSION_2 2
+/* Max supported stream version. */
+#define BTRFS_SEND_STREAM_VERSION_MAX BTRFS_SEND_STREAM_VERSION_2
 
 #define BTRFS_SEND_BUF_SIZE SZ_64K
 #define BTRFS_SEND_READ_SIZE (1024 * 48)
@@ -94,6 +97,15 @@ enum btrfs_send_cmd {
 
        BTRFS_SEND_C_END,
        BTRFS_SEND_C_UPDATE_EXTENT,
+
+       /*
+        * The following commands were added in stream version 2.
+        */
+       BTRFS_SEND_C_TOTAL_DATA_SIZE,
+       BTRFS_SEND_C_FALLOCATE,
+       BTRFS_SEND_C_INODE_SET_FLAGS,
+       BTRFS_SEND_C_UTIMES2, /* Same as UTIMES, but it includes OTIME too. */
+
        __BTRFS_SEND_C_MAX,
 };
 #define BTRFS_SEND_C_MAX (__BTRFS_SEND_C_MAX - 1)
@@ -132,10 +144,19 @@ enum {
        BTRFS_SEND_A_CLONE_OFFSET,
        BTRFS_SEND_A_CLONE_LEN,
 
+       /*
+        * The following attributes were added in stream version 2.
+        */
+       BTRFS_SEND_A_FALLOCATE_FLAGS, /* 32 bits */
+       BTRFS_SEND_A_INODE_FLAGS,     /* 32 bits */
+
        __BTRFS_SEND_A_MAX,
 };
 #define BTRFS_SEND_A_MAX (__BTRFS_SEND_A_MAX - 1)
 
+#define BTRFS_SEND_A_FALLOCATE_FLAG_KEEP_SIZE   (1 << 0)
+#define BTRFS_SEND_A_FALLOCATE_FLAG_PUNCH_HOLE  (1 << 1)
+
 #ifdef __KERNEL__
 long btrfs_ioctl_send(struct file *mnt_file, void __user *arg);
 #endif
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to