From 02fced3067798cbc5472f180e4c6d36f4c441a77 Mon Sep 17 00:00:00 2001 From: tony-zfs <62951051+tony-zfs@users.noreply.github.com> Date: Thu, 23 Jul 2020 20:44:03 -0400 Subject: [PATCH] Add support to decode a resume token Adding a new subcommand to zstream called token. This now allows users to decode a resume token to retrieve the toname field. This can be useful for tools that need this information. The syntax works as follows zstream token . Reviewed-by: Matt Ahrens Reviewed-by: Brian Behlendorf Reviewed-by: Paul Zuchowski Signed-off-by: Tony Perkins Closes #10558 --- cmd/zstream/Makefile.am | 3 +- cmd/zstream/zstream.c | 5 ++ cmd/zstream/zstream.h | 1 + cmd/zstream/zstream_token.c | 78 +++++++++++++++++++ man/man8/zstream.8 | 9 +++ .../tests/functional/rsend/rsend.kshlib | 16 ++++ .../functional/rsend/send-c_zstreamdump.ksh | 16 ++++ 7 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 cmd/zstream/zstream_token.c diff --git a/cmd/zstream/Makefile.am b/cmd/zstream/Makefile.am index 5e0312f23..5e2ac5d69 100644 --- a/cmd/zstream/Makefile.am +++ b/cmd/zstream/Makefile.am @@ -6,7 +6,8 @@ zstream_SOURCES = \ zstream.c \ zstream.h \ zstream_dump.c \ - zstream_redup.c + zstream_redup.c \ + zstream_token.c zstream_LDADD = \ $(abs_top_builddir)/lib/libzfs/libzfs.la \ diff --git a/cmd/zstream/zstream.c b/cmd/zstream/zstream.c index 95578c97c..cbcb560a8 100644 --- a/cmd/zstream/zstream.c +++ b/cmd/zstream/zstream.c @@ -15,6 +15,7 @@ /* * Copyright (c) 2020 by Delphix. All rights reserved. + * Copyright (c) 2020 by Datto Inc. All rights reserved. */ #include #include @@ -39,6 +40,8 @@ zstream_usage(void) "\tzstream dump [-vCd] FILE\n" "\t... | zstream dump [-vCd]\n" "\n" + "\tzstream token resume_token\n" + "\n" "\tzstream redup [-v] FILE | ...\n"); exit(1); } @@ -53,6 +56,8 @@ main(int argc, char *argv[]) if (strcmp(subcommand, "dump") == 0) { return (zstream_do_dump(argc - 1, argv + 1)); + } else if (strcmp(subcommand, "token") == 0) { + return (zstream_do_token(argc - 1, argv + 1)); } else if (strcmp(subcommand, "redup") == 0) { return (zstream_do_redup(argc - 1, argv + 1)); } else { diff --git a/cmd/zstream/zstream.h b/cmd/zstream/zstream.h index 5a7f4bce9..319fecb28 100644 --- a/cmd/zstream/zstream.h +++ b/cmd/zstream/zstream.h @@ -26,6 +26,7 @@ extern "C" { extern int zstream_do_redup(int, char *[]); extern int zstream_do_dump(int, char *[]); +extern int zstream_do_token(int, char *[]); extern void zstream_usage(void); #ifdef __cplusplus diff --git a/cmd/zstream/zstream_token.c b/cmd/zstream/zstream_token.c new file mode 100644 index 000000000..36a76a4bb --- /dev/null +++ b/cmd/zstream/zstream_token.c @@ -0,0 +1,78 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Portions Copyright 2012 Martin Matuska + */ + +/* + * Copyright (c) 2020 by Datto Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include "zstream.h" + +int +zstream_do_token(int argc, char *argv[]) +{ + char *resume_token = NULL; + + if (argc < 2) { + (void) fprintf(stderr, "Need to pass the resume token\n"); + zstream_usage(); + } + + resume_token = argv[1]; + + libzfs_handle_t *hdl = libzfs_init(); + + nvlist_t *resume_nvl = + zfs_send_resume_token_to_nvlist(hdl, resume_token); + + if (resume_nvl == NULL) { + (void) fprintf(stderr, + "Unable to parse resume token: %s\n", + libzfs_error_description(hdl)); + libzfs_fini(hdl); + return (1); + } + + dump_nvlist(resume_nvl, 5); + nvlist_free(resume_nvl); + + libzfs_fini(hdl); + return (0); +} diff --git a/man/man8/zstream.8 b/man/man8/zstream.8 index 1c4d3fa9a..f27d08c7b 100644 --- a/man/man8/zstream.8 +++ b/man/man8/zstream.8 @@ -35,6 +35,9 @@ .Cm redup .Op Fl v .Ar file +.Nm +.Cm token +.Ar resume_token .Sh DESCRIPTION .sp .LP @@ -67,6 +70,12 @@ Implies verbose. .El .It Xo .Nm +.Cm token +.Ar resume_token +.Xc +Dumps zfs resume token information +.It Xo +.Nm .Cm redup .Op Fl v .Ar file diff --git a/tests/zfs-tests/tests/functional/rsend/rsend.kshlib b/tests/zfs-tests/tests/functional/rsend/rsend.kshlib index b4819245e..c82b0f008 100644 --- a/tests/zfs-tests/tests/functional/rsend/rsend.kshlib +++ b/tests/zfs-tests/tests/functional/rsend/rsend.kshlib @@ -26,6 +26,7 @@ # # Copyright (c) 2013, 2018 by Delphix. All rights reserved. +# Copyright (c) 2020 by Datto Inc. All rights reserved. # . $STF_SUITE/include/libtest.shlib @@ -657,6 +658,21 @@ function resume_test log_must zfs recv -suv $recvfs /$streamfs/1" + mess_send_file /$streamfs/1 + log_mustnot zfs recv -suv $recvfs < /$streamfs/1 2>&1 + token=$(zfs get -Hp -o value receive_resume_token $recvfs) + echo "$token" > /$streamfs/resume_token + + return 0 +} + # # Setup filesystems for the resumable send/receive tests # diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_zstreamdump.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_zstreamdump.ksh index 52abfe7ed..b4dc00cec 100755 --- a/tests/zfs-tests/tests/functional/rsend/send-c_zstreamdump.ksh +++ b/tests/zfs-tests/tests/functional/rsend/send-c_zstreamdump.ksh @@ -13,6 +13,7 @@ # # Copyright (c) 2015 by Delphix. All rights reserved. +# Copyright (c) 2020 by Datto, Inc. All rights reserved. # . $STF_SUITE/tests/functional/rsend/rsend.kshlib @@ -26,6 +27,9 @@ # 1. Create a full compressed send stream # 2. Verify zstreamdump shows this stream has the relevant features # 3. Verify zstreamdump's accounting of logical and compressed size is correct +# 4. Verify the toname from a resume token +# 5. Verify it fails with corrupted resume token +# 6. Verify it fails with missing resume token # verify_runnable "both" @@ -34,8 +38,11 @@ log_assert "Verify zstreamdump correctly interprets compressed send streams." log_onexit cleanup_pool $POOL2 typeset sendfs=$POOL2/fs +typeset streamfs=$POOL2/fs2 +typeset recvfs=$POOL2/fs3 log_must zfs create -o compress=lz4 $sendfs +log_must zfs create -o compress=lz4 $streamfs typeset dir=$(get_prop mountpoint $sendfs) write_compressible $dir 16m log_must zfs snapshot $sendfs@full @@ -56,4 +63,13 @@ csize_prop=$(get_prop used $sendfs) within_percent $csize $csize_prop 90 || log_fail \ "$csize and $csize_prop differed by too much" +x=$(get_resume_token "zfs send -c $sendfs@full" $streamfs $recvfs) +resume_token=$(cat /$streamfs/resume_token) +to_name_fs=$sendfs +log_must eval "zstream token $resume_token | grep $to_name_fs" + +bad_resume_token="1-1162e8285b-100789c6360" +log_mustnot eval "zstream token $bad_resume_token 2>&1" +log_mustnot eval "zstream token 2>&1" + log_pass "zstreamdump correctly interprets compressed send streams."