Linux Btrfs filesystem development
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox