All of lore.kernel.org
 help / color / mirror / Atom feed
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.

  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.