From owner-svn-src-all@freebsd.org Sun Oct 20 22:05:59 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id CF40516C55A; Sun, 20 Oct 2019 22:05:59 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46xDP3586gz4Qpl; Sun, 20 Oct 2019 22:05:59 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 94D471A5EE; Sun, 20 Oct 2019 22:05:59 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x9KM5xZ8057866; Sun, 20 Oct 2019 22:05:59 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x9KM5w26057863; Sun, 20 Oct 2019 22:05:58 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201910202205.x9KM5w26057863@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Sun, 20 Oct 2019 22:05:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r353784 - in stable: 11/lib/libbe 11/sbin/bectl 12/lib/libbe 12/sbin/bectl X-SVN-Group: stable-12 X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in stable: 11/lib/libbe 11/sbin/bectl 12/lib/libbe 12/sbin/bectl X-SVN-Commit-Revision: 353784 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Oct 2019 22:05:59 -0000 Author: kevans Date: Sun Oct 20 22:05:57 2019 New Revision: 353784 URL: https://svnweb.freebsd.org/changeset/base/353784 Log: MFC r353644, r353646, r353663: bectl(8) origin auto-destroy r353644: libbe(3): add needed bits for be_destroy to auto-destroy some origins New BEs can be created from either an existing snapshot or an existing BE. If an existing BE is chosen (either implicitly via 'bectl create' or explicitly via 'bectl create -e foo bar', for instance), then bectl will create a snapshot of the current BE or "foo" with be_snapshot, with a name formatted like: strftime("%F-%T") and a serial added to it. This commit adds the needed bits for libbe or consumers to determine if a snapshot names matches one of these auto-created snapshots (with some light validation of the date/time/serial), and also a be_destroy flag to specify that the origin should be automatically destroyed if possible. A future commit to bectl will specify BE_DESTROY_AUTOORIGIN by default so we clean up the origin in the most common case, non-user-managed snapshots. r353646: bectl(8): destroy: use BE_DESTROY_AUTOORIGIN if -o is not specified -o will force the origin to be destroyed unconditionally. BE_DESTROY_AUTOORIGIN, on the other hand, will only destroy the origin if it matches the format used by be_snapshot. This lets us clean up the snapshots that are clearly not user-managed (because we're creating them) while leaving user-created snapshots in place and warning that they're still around when the BE created goes away. r353663: libbe(3): Fix destroy of imported BE w/ AUTOORIGIN Imported BE, much like the activated BE, will not have an origin that we can fetch/examine for destruction. be_destroy should not return BE_ERR_NOORIGIN for failure to get the origin property for BE_DESTROY_AUTOORIGIN, because we don't really know going into it that there's even an origin to be destroyed. BE_DESTROY_NEEDORIGIN has been renamed to BE_DESTROY_WANTORIGIN because only a subset of it *needs* the origin, so 'need' is too strong of verbiage. This was caught by jenkins and the bectl tests, but kevans failed to run the bectl tests prior to commit. Modified: stable/12/lib/libbe/be.c stable/12/lib/libbe/be.h stable/12/lib/libbe/libbe.3 stable/12/sbin/bectl/bectl.c Directory Properties: stable/12/ (props changed) Changes in other areas also in this revision: Modified: stable/11/lib/libbe/be.c stable/11/lib/libbe/be.h stable/11/lib/libbe/libbe.3 stable/11/sbin/bectl/bectl.c Directory Properties: stable/11/ (props changed) Modified: stable/12/lib/libbe/be.c ============================================================================== --- stable/12/lib/libbe/be.c Sun Oct 20 22:01:35 2019 (r353783) +++ stable/12/lib/libbe/be.c Sun Oct 20 22:05:57 2019 (r353784) @@ -229,6 +229,7 @@ be_destroy_cb(zfs_handle_t *zfs_hdl, void *data) return (0); } +#define BE_DESTROY_WANTORIGIN (BE_DESTROY_ORIGIN | BE_DESTROY_AUTOORIGIN) /* * Destroy the boot environment or snapshot specified by the name * parameter. Options are or'd together with the possible values: @@ -264,11 +265,25 @@ be_destroy(libbe_handle_t *lbh, const char *name, int if (fs == NULL) return (set_error(lbh, BE_ERR_ZFSOPEN)); - if ((options & BE_DESTROY_ORIGIN) != 0 && + if ((options & BE_DESTROY_WANTORIGIN) != 0 && zfs_prop_get(fs, ZFS_PROP_ORIGIN, origin, sizeof(origin), - NULL, NULL, 0, 1) != 0) + NULL, NULL, 0, 1) != 0 && + (options & BE_DESTROY_ORIGIN) != 0) return (set_error(lbh, BE_ERR_NOORIGIN)); + /* + * If the caller wants auto-origin destruction and the origin + * name matches one of our automatically created snapshot names + * (i.e. strftime("%F-%T") with a serial at the end), then + * we'll set the DESTROY_ORIGIN flag and nuke it + * be_is_auto_snapshot_name is exported from libbe(3) so that + * the caller can determine if it needs to warn about the origin + * not being destroyed or not. + */ + if ((options & BE_DESTROY_AUTOORIGIN) != 0 && *origin != '\0' && + be_is_auto_snapshot_name(lbh, origin)) + options |= BE_DESTROY_ORIGIN; + /* Don't destroy a mounted dataset unless force is specified */ if ((mounted = zfs_is_mounted(fs, NULL)) != 0) { if (force) { @@ -341,6 +356,25 @@ be_setup_snapshot_name(libbe_handle_t *lbh, char *buf, if (!zfs_dataset_exists(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT)) return; } +} + +bool +be_is_auto_snapshot_name(libbe_handle_t *lbh, const char *name) +{ + const char *snap; + int day, hour, minute, month, second, serial, year; + + if ((snap = strchr(name, '@')) == NULL) + return (false); + ++snap; + /* We'll grab the individual components and do some light validation. */ + if (sscanf(snap, "%d-%d-%d-%d:%d:%d-%d", &year, &month, &day, &hour, + &minute, &second, &serial) != 7) + return (false); + return (year >= 1970) && (month >= 1 && month <= 12) && + (day >= 1 && day <= 31) && (hour >= 0 && hour <= 23) && + (minute >= 0 && minute <= 59) && (second >= 0 && second <= 60) && + serial >= 0; } int Modified: stable/12/lib/libbe/be.h ============================================================================== --- stable/12/lib/libbe/be.h Sun Oct 20 22:01:35 2019 (r353783) +++ stable/12/lib/libbe/be.h Sun Oct 20 22:05:57 2019 (r353784) @@ -82,6 +82,8 @@ void be_prop_list_free(nvlist_t *be_list); int be_activate(libbe_handle_t *, const char *, bool); +bool be_is_auto_snapshot_name(libbe_handle_t *, const char *); + /* Bootenv creation functions */ int be_create(libbe_handle_t *, const char *); int be_create_depth(libbe_handle_t *, const char *, const char *, int); @@ -97,6 +99,7 @@ int be_rename(libbe_handle_t *, const char *, const ch typedef enum { BE_DESTROY_FORCE = 1 << 0, BE_DESTROY_ORIGIN = 1 << 1, + BE_DESTROY_AUTOORIGIN = 1 << 2, } be_destroy_opt_t; int be_destroy(libbe_handle_t *, const char *, int); Modified: stable/12/lib/libbe/libbe.3 ============================================================================== --- stable/12/lib/libbe/libbe.3 Sun Oct 20 22:01:35 2019 (r353783) +++ stable/12/lib/libbe/libbe.3 Sun Oct 20 22:05:57 2019 (r353784) @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 22, 2019 +.Dd October 16, 2019 .Dt LIBBE 3 .Os .Sh NAME @@ -59,6 +59,9 @@ .Ft const char * Ns .Fn be_root_path "libbe_handle_t *hdl" .Pp +.Ft bool Ns +.Fn be_is_auto_snapshot_name "libbe_handle_t *hdl" "const char *snap" +.Pp .Ft int .Fn be_create "libbe_handle_t *hdl" "const char *be_name" .Pp @@ -212,6 +215,18 @@ active on reboot. The .Fn be_root_path function returns the boot environment root path. +.Pp +The +.Fn be_is_auto_snapshot_name +function is used to determine if the given snapshot name matches the format that +the +.Fn be_snapshot +function will use by default if it is not given a snapshot name to use. +It returns +.Dv true +if the name matches the format, and +.Dv false +if it does not. .Pp The .Fn be_create Modified: stable/12/sbin/bectl/bectl.c ============================================================================== --- stable/12/sbin/bectl/bectl.c Sun Oct 20 22:01:35 2019 (r353783) +++ stable/12/sbin/bectl/bectl.c Sun Oct 20 22:05:57 2019 (r353784) @@ -376,6 +376,7 @@ bectl_cmd_destroy(int argc, char *argv[]) /* We'll emit a notice if there's an origin to be cleaned up */ if ((flags & BE_DESTROY_ORIGIN) == 0 && strchr(target, '@') == NULL) { + flags |= BE_DESTROY_AUTOORIGIN; if (be_root_concat(be, target, targetds) != 0) goto destroy; if (be_prop_list_alloc(&props) != 0) @@ -384,7 +385,8 @@ bectl_cmd_destroy(int argc, char *argv[]) be_prop_list_free(props); goto destroy; } - if (nvlist_lookup_string(props, "origin", &origin) == 0) + if (nvlist_lookup_string(props, "origin", &origin) == 0 && + !be_is_auto_snapshot_name(be, origin)) fprintf(stderr, "bectl destroy: leaving origin '%s' intact\n", origin); be_prop_list_free(props);