From: Omar Sandoval <osandov@osandov.com>
To: David Sterba <dsterba@suse.com>
Cc: linux-btrfs@vger.kernel.org, nborisov@suse.com
Subject: Re: [PATCH RFC] btrfs-progs: send protocol v2 stub, UTIMES2, OTIME
Date: Mon, 18 Oct 2021 14:42:34 -0700 [thread overview]
Message-ID: <YW3qStSa9LiaankG@relinquished.localdomain> (raw)
In-Reply-To: <20211018144717.20275-1-dsterba@suse.com>
On Mon, Oct 18, 2021 at 04:47:17PM +0200, David Sterba wrote:
> This is counterpart for the protocol version update.
>
> - version 2 protocol
> - new protocol command UTIMES2, same as utimes with additional otime
> data
> - send: add command line options to specify version, compare against
> current running kernel supported version
> - receive: parse UTIMES2
> - receive: parse OTIME
>
> TODO:
>
> - libbtrfs compatibility is missing, ie. this will break anything that
> uses send stream (snapper), this needs library version update and
> maybe some ifdefs in the headers
>
> Signed-off-by: David Sterba <dsterba@suse.com>
> ---
> cmds/receive-dump.c | 31 ++++++++++++++++-
> cmds/receive.c | 79 ++++++++++++++++++++++++++++++++++++++++++++
> cmds/send.c | 66 ++++++++++++++++++++++++++++++++++--
> common/send-stream.c | 14 ++++++++
> common/send-stream.h | 5 +++
> ioctl.h | 12 +++++--
> kernel-shared/send.h | 11 +++++-
> 7 files changed, 212 insertions(+), 6 deletions(-)
>
> diff --git a/cmds/receive.c b/cmds/receive.c
> index 4d123a1f8782..dfb37a502598 100644
> --- a/cmds/receive.c
> +++ b/cmds/receive.c
> @@ -967,6 +967,83 @@ static int process_utimes(const char *path, struct timespec *at,
> return ret;
> }
>
> +static int process_utimes2(const char *path, struct timespec *at,
> + struct timespec *mt, struct timespec *ct,
> + struct timespec *ot, void *user)
> +{
> + int ret = 0;
> + struct btrfs_receive *rctx = user;
> + char full_path[PATH_MAX];
> + struct timespec tv[2];
> +
> + ret = path_cat_out(full_path, rctx->full_subvol_path, path);
> + if (ret < 0) {
> + error("utimes2: path invalid: %s", path);
> + goto out;
> + }
> +
> + if (bconf.verbose >= 3)
> + fprintf(stderr, "utimes2 %s\n", path);
> +
> + tv[0] = *at;
> + tv[1] = *mt;
> + ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
> + if (ret < 0) {
> + ret = -errno;
> + error("utimes2 %s failed: %m", path);
> + goto out;
> + }
> +
> +out:
> + return ret;
> +}
> +
> +/* TODO: Copied from receive-dump.c */
> +static int sprintf_timespec(struct timespec *ts, char *dest, int max_size)
> +{
> + struct tm tm;
> + int ret;
> +
> + if (!localtime_r(&ts->tv_sec, &tm)) {
> + error("failed to convert time %lld.%.9ld to local time",
> + (long long)ts->tv_sec, ts->tv_nsec);
> + return -EINVAL;
> + }
> + ret = strftime(dest, max_size, "%FT%T%z", &tm);
> + if (ret == 0) {
> + error(
> + "time %lld.%ld is too long to convert into readable string",
> + (long long)ts->tv_sec, ts->tv_nsec);
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> +
> +static int process_otime(const char *path, struct timespec *ot, void *user)
> +{
> + int ret;
> + struct btrfs_receive *rctx = user;
> + char full_path[PATH_MAX];
> +
> + ret = path_cat_out(full_path, rctx->full_subvol_path, path);
> + if (ret < 0) {
> + error("otime: path invalid: %s", path);
> + goto out;
> + }
> +
> + if (bconf.verbose >= 3) {
> + char ot_str[128];
> +
> + if (sprintf_timespec(ot, ot_str, sizeof(ot_str) - 1) < 0)
> + goto out;
> + fprintf(stderr, "otime %s\n", ot_str);
> + }
> +
> +out:
> + return 0;
> +}
Are you planning to do anything with otime (e.g., storing it in an
xattr) in the future?
> static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
> diff --git a/cmds/send.c b/cmds/send.c
> index 1810233137aa..f529f0b0a6a0 100644
> --- a/cmds/send.c
> +++ b/cmds/send.c
> @@ -57,6 +57,8 @@ struct btrfs_send {
> u64 clone_sources_count;
>
> char *root_path;
> + u32 proto;
> + u32 proto_supported;
> };
>
> static int get_root_id(struct btrfs_send *sctx, const char *path, u64 *root_id)
> @@ -257,6 +259,13 @@ static int do_send(struct btrfs_send *send, u64 parent_root_id,
> memset(&io_send, 0, sizeof(io_send));
> io_send.send_fd = pipefd[1];
> send->send_fd = pipefd[0];
> + io_send.flags = flags;
> +
> + if (send->proto_supported > 1) {
> + /* Versioned stream supported, requesting default or specific number */
> + io_send.version = send->proto;
> + io_send.flags |= BTRFS_SEND_FLAG_VERSION;
> + }
>
> if (!ret)
> ret = pthread_create(&t_read, NULL, read_sent_data, send);
> @@ -267,7 +276,6 @@ static int do_send(struct btrfs_send *send, u64 parent_root_id,
> goto out;
> }
>
> - io_send.flags = flags;
> io_send.clone_sources = (__u64*)send->clone_sources;
> io_send.clone_sources_count = send->clone_sources_count;
> io_send.parent_root = parent_root_id;
> @@ -275,6 +283,7 @@ 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;
> +
> ret = ioctl(subvol_fd, BTRFS_IOC_SEND, &io_send);
> if (ret < 0) {
> ret = -errno;
> @@ -419,6 +428,33 @@ static void free_send_info(struct btrfs_send *sctx)
> sctx->root_path = NULL;
> }
>
> +static u32 get_sysfs_proto_supported(void)
> +{
> + int fd;
> + int ret;
> + char buf[32] = {};
> + char *end = NULL;
> + u64 version;
> +
> + fd = sysfs_open_file("features/send_stream_version");
> + if (fd < 0) {
> + /* No file is either no version support or old kernel with just v1 */
> + return 1;
> + }
> + ret = sysfs_read_file(fd, buf, sizeof(buf));
> + close(fd);
> + if (ret <= 0)
> + return 1;
> + version = strtoull(buf, &end, 10);
> + if (version == ULLONG_MAX && errno == ERANGE)
> + return 1;
> + if (version > U32_MAX) {
> + warning("sysfs/send_stream_version too big: %llu", version);
> + version = 1;
> + }
> + return version;
> +}
> +
> static const char * const cmd_send_usage[] = {
> "btrfs send [-ve] [-p <parent>] [-c <clone-src>] [-f <outfile>] <subvol> [<subvol>...]",
> "Send the subvolume(s) to stdout.",
> @@ -447,6 +483,7 @@ static const char * const cmd_send_usage[] = {
> " 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.",
> + "--proto N request maximum protocol version N (default: highest supported by running kernel)",
Can we default to version 1 and provide a way to opt in to the latest
version? I'm concerned with a kernel upgrade suddenly creating a send
stream that the receiving side can't handle. Making this opt-in rather
than opt-out seems safer.
next prev parent reply other threads:[~2021-10-18 21:42 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-18 14:41 [PATCH RFC] btrfs: send: v2 protocol and example OTIME changes David Sterba
2021-10-18 14:47 ` [PATCH RFC] btrfs-progs: send protocol v2 stub, UTIMES2, OTIME David Sterba
2021-10-18 21:42 ` Omar Sandoval [this message]
2021-10-19 12:53 ` David Sterba
2021-10-19 14:11 ` Josef Bacik
2021-10-19 17:27 ` Omar Sandoval
2021-10-18 15:36 ` [PATCH RFC] btrfs: send: v2 protocol and example OTIME changes Filipe Manana
2021-10-18 21:26 ` Omar Sandoval
2021-10-19 10:51 ` David Sterba
2021-10-19 7:30 ` Nikolay Borisov
2021-10-19 17:38 ` Omar Sandoval
2021-10-19 20:25 ` David Sterba
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YW3qStSa9LiaankG@relinquished.localdomain \
--to=osandov@osandov.com \
--cc=dsterba@suse.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=nborisov@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox