Date: Sun, 28 Apr 2019 03:49:40 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r346802 - in stable: 11/etc/mtree 11/lib/libbe 11/lib/libbe/tests 12/etc/mtree 12/lib/libbe 12/lib/libbe/tests Message-ID: <201904280349.x3S3nesu010686@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Sun Apr 28 03:49:40 2019 New Revision: 346802 URL: https://svnweb.freebsd.org/changeset/base/346802 Log: MFC r346545-r346546, r346680, r346700, r346705 r346545: libbe(3): allow creation of arbitrary depth boot environments libbe currently only provides an API to create a recursive boot environment, without any formal support for intentionally limiting the depth. This changeset adds an API, be_create_depth, that may be used to arbitrarily restrict the depth of the new BE. r346546: libbe(3): Add a test for be creation r346680: libbe(3): Copy received properties as well This was inherently broken on send|recv datasets. r346700: libbe(3): Fix mis-application of patch (SHLIBDIR) Rob's patch in D18564 cemented the SHLIBDIR because bsd.own.mk (included by src.opts.mk) sets it to /usr/lib. r346546 did somehow not apply this part of the patch, leaving it to get installed to the wrong place and subsequently removed via ObsoleteFiles. r346705: libbe(3): Fix libcompat build SHLIBDIR should still be optionally set, just before src.opts.mk is included so that libcompat can properly override it. This fixes lib32 failures reported by both Jenkins and Michael Butler. Added: stable/11/lib/libbe/tests/ - copied from r346546, head/lib/libbe/tests/ Modified: stable/11/etc/mtree/BSD.tests.dist stable/11/lib/libbe/Makefile stable/11/lib/libbe/be.c stable/11/lib/libbe/be.h stable/11/lib/libbe/be_impl.h stable/11/lib/libbe/libbe.3 Directory Properties: stable/11/ (props changed) Changes in other areas also in this revision: Added: stable/12/lib/libbe/tests/ - copied from r346546, head/lib/libbe/tests/ Modified: stable/12/etc/mtree/BSD.tests.dist stable/12/lib/libbe/Makefile stable/12/lib/libbe/be.c stable/12/lib/libbe/be.h stable/12/lib/libbe/be_impl.h stable/12/lib/libbe/libbe.3 Directory Properties: stable/12/ (props changed) Modified: stable/11/etc/mtree/BSD.tests.dist ============================================================================== --- stable/11/etc/mtree/BSD.tests.dist Sun Apr 28 02:27:04 2019 (r346801) +++ stable/11/etc/mtree/BSD.tests.dist Sun Apr 28 03:49:40 2019 (r346802) @@ -264,6 +264,8 @@ .. libarchive .. + libbe + .. libc c063 .. Modified: stable/11/lib/libbe/Makefile ============================================================================== --- stable/11/lib/libbe/Makefile Sun Apr 28 02:27:04 2019 (r346801) +++ stable/11/lib/libbe/Makefile Sun Apr 28 03:49:40 2019 (r346802) @@ -1,8 +1,11 @@ # $FreeBSD$ +SHLIBDIR?= /lib + +.include <src.opts.mk> + PACKAGE= lib${LIB} LIB= be -SHLIBDIR?= /lib SHLIB_MAJOR= 1 SHLIB_MINOR= 0 @@ -27,5 +30,8 @@ CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/ CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/head CFLAGS+= -DNEED_SOLARIS_BOOLEAN + +HAS_TESTS= YES +SUBDIR.${MK_TESTS}+= tests .include <bsd.lib.mk> Modified: stable/11/lib/libbe/be.c ============================================================================== --- stable/11/lib/libbe/be.c Sun Apr 28 02:27:04 2019 (r346801) +++ stable/11/lib/libbe/be.c Sun Apr 28 03:49:40 2019 (r346802) @@ -372,7 +372,6 @@ be_snapshot(libbe_handle_t *lbh, const char *source, c sizeof(buf)) >= sizeof(buf)) return (set_error(lbh, BE_ERR_INVALIDNAME)); } - if ((err = zfs_snapshot(lbh->lzh, buf, recursive, NULL)) != 0) { switch (err) { case EZFS_INVALIDNAME: @@ -432,8 +431,12 @@ be_deep_clone_prop(int prop, void *cb) /* Just continue if we fail to read a property */ return (ZPROP_CONT); - /* Only copy locally defined properties */ - if (src != ZPROP_SRC_LOCAL) + /* + * Only copy locally defined or received properties. This continues + * to avoid temporary/default/local properties intentionally without + * breaking received datasets. + */ + if (src != ZPROP_SRC_LOCAL && src != ZPROP_SRC_RECEIVED) return (ZPROP_CONT); /* Augment mountpoint with altroot, if needed */ @@ -446,43 +449,78 @@ be_deep_clone_prop(int prop, void *cb) return (ZPROP_CONT); } +/* + * Return the corresponding boot environment path for a given + * dataset path, the constructed path is placed in 'result'. + * + * example: say our new boot environment name is 'bootenv' and + * the dataset path is 'zroot/ROOT/default/data/set'. + * + * result should produce: 'zroot/ROOT/bootenv/data/set' + */ static int -be_deep_clone(zfs_handle_t *ds, void *data) +be_get_path(struct libbe_deep_clone *ldc, const char *dspath, char *result, int result_size) { + char *pos; + char *child_dataset; + + /* match the root path for the boot environments */ + pos = strstr(dspath, ldc->lbh->root); + + /* no match, different pools? */ + if (pos == NULL) + return (BE_ERR_BADPATH); + + /* root path of the new boot environment */ + snprintf(result, result_size, "%s/%s", ldc->lbh->root, ldc->bename); + + /* gets us to the parent dataset, the +1 consumes a trailing slash */ + pos += strlen(ldc->lbh->root) + 1; + + /* skip the parent dataset */ + if ((child_dataset = strchr(pos, '/')) != NULL) + strlcat(result, child_dataset, result_size); + + return (BE_ERR_SUCCESS); +} + +static int +be_clone_cb(zfs_handle_t *ds, void *data) +{ int err; char be_path[BE_MAXPATHLEN]; char snap_path[BE_MAXPATHLEN]; const char *dspath; - char *dsname; zfs_handle_t *snap_hdl; nvlist_t *props; - struct libbe_deep_clone *isdc, sdc; + struct libbe_deep_clone *ldc; struct libbe_dccb dccb; - isdc = (struct libbe_deep_clone *)data; + ldc = (struct libbe_deep_clone *)data; dspath = zfs_get_name(ds); - if ((dsname = strrchr(dspath, '/')) == NULL) - return (BE_ERR_UNKNOWN); - dsname++; - if (isdc->bename == NULL) - snprintf(be_path, sizeof(be_path), "%s/%s", isdc->be_root, dsname); - else - snprintf(be_path, sizeof(be_path), "%s/%s", isdc->be_root, isdc->bename); + snprintf(snap_path, sizeof(snap_path), "%s@%s", dspath, ldc->snapname); - snprintf(snap_path, sizeof(snap_path), "%s@%s", dspath, isdc->snapname); + /* construct the boot environment path from the dataset we're cloning */ + if (be_get_path(ldc, dspath, be_path, sizeof(be_path)) != BE_ERR_SUCCESS) + return (set_error(ldc->lbh, BE_ERR_UNKNOWN)); - if (zfs_dataset_exists(isdc->lbh->lzh, be_path, ZFS_TYPE_DATASET)) - return (set_error(isdc->lbh, BE_ERR_EXISTS)); + /* the dataset to be created (i.e. the boot environment) already exists */ + if (zfs_dataset_exists(ldc->lbh->lzh, be_path, ZFS_TYPE_DATASET)) + return (set_error(ldc->lbh, BE_ERR_EXISTS)); + /* no snapshot found for this dataset, silently skip it */ + if (!zfs_dataset_exists(ldc->lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) + return (0); + if ((snap_hdl = - zfs_open(isdc->lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) == NULL) - return (set_error(isdc->lbh, BE_ERR_ZFSOPEN)); + zfs_open(ldc->lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) == NULL) + return (set_error(ldc->lbh, BE_ERR_ZFSOPEN)); nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP); nvlist_add_string(props, "canmount", "noauto"); - dccb.lbh = isdc->lbh; + dccb.lbh = ldc->lbh; dccb.zhp = ds; dccb.props = props; if (zprop_iter(be_deep_clone_prop, &dccb, B_FALSE, B_FALSE, @@ -490,58 +528,55 @@ be_deep_clone(zfs_handle_t *ds, void *data) return (-1); if ((err = zfs_clone(snap_hdl, be_path, props)) != 0) - err = BE_ERR_ZFSCLONE; + return (set_error(ldc->lbh, BE_ERR_ZFSCLONE)); nvlist_free(props); zfs_close(snap_hdl); - /* Failed to clone */ - if (err != BE_ERR_SUCCESS) - return (set_error(isdc->lbh, err)); + if (ldc->depth_limit == -1 || ldc->depth < ldc->depth_limit) { + ldc->depth++; + err = zfs_iter_filesystems(ds, be_clone_cb, ldc); + ldc->depth--; + } - sdc.lbh = isdc->lbh; - sdc.bename = NULL; - sdc.snapname = isdc->snapname; - sdc.be_root = (char *)&be_path; - - err = zfs_iter_filesystems(ds, be_deep_clone, &sdc); - - return (err); + return (set_error(ldc->lbh, err)); } /* - * Create the boot environment from pre-existing snapshot - */ -int -be_create_from_existing_snap(libbe_handle_t *lbh, const char *name, - const char *snap) + * Create a boot environment with a given name from a given snapshot. + * Snapshots can be in the format 'zroot/ROOT/default@snapshot' or + * 'default@snapshot'. In the latter case, 'default@snapshot' will be prepended + * with the root path that libbe was initailized with. +*/ +static int +be_clone(libbe_handle_t *lbh, const char *bename, const char *snapshot, int depth) { int err; - char be_path[BE_MAXPATHLEN]; char snap_path[BE_MAXPATHLEN]; - const char *bename; char *parentname, *snapname; zfs_handle_t *parent_hdl; - struct libbe_deep_clone sdc; + struct libbe_deep_clone ldc; - if ((err = be_validate_name(lbh, name)) != 0) + /* ensure the boot environment name is valid */ + if ((err = be_validate_name(lbh, bename)) != 0) return (set_error(lbh, err)); - if ((err = be_root_concat(lbh, snap, snap_path)) != 0) + + /* + * prepend the boot environment root path if we're + * given a partial snapshot name. + */ + if ((err = be_root_concat(lbh, snapshot, snap_path)) != 0) return (set_error(lbh, err)); + + /* ensure the snapshot exists */ if ((err = be_validate_snap(lbh, snap_path)) != 0) return (set_error(lbh, err)); - if ((err = be_root_concat(lbh, name, be_path)) != 0) - return (set_error(lbh, err)); - - if ((bename = strrchr(name, '/')) == NULL) - bename = name; - else - bename++; - + /* get a copy of the snapshot path so we can disect it */ if ((parentname = strdup(snap_path)) == NULL) return (set_error(lbh, BE_ERR_UNKNOWN)); + /* split dataset name from snapshot name */ snapname = strchr(parentname, '@'); if (snapname == NULL) { free(parentname); @@ -550,32 +585,56 @@ be_create_from_existing_snap(libbe_handle_t *lbh, cons *snapname = '\0'; snapname++; - sdc.lbh = lbh; - sdc.bename = bename; - sdc.snapname = snapname; - sdc.be_root = lbh->root; + /* set-up the boot environment */ + ldc.lbh = lbh; + ldc.bename = bename; + ldc.snapname = snapname; + ldc.depth = 0; + ldc.depth_limit = depth; + /* the boot environment will be cloned from this dataset */ parent_hdl = zfs_open(lbh->lzh, parentname, ZFS_TYPE_DATASET); - err = be_deep_clone(parent_hdl, &sdc); + /* create the boot environment */ + err = be_clone_cb(parent_hdl, &ldc); + free(parentname); return (set_error(lbh, err)); } +/* + * Create a boot environment from pre-existing snapshot, specifying a depth. + */ +int be_create_depth(libbe_handle_t *lbh, const char *bename, + const char *snap, int depth) +{ + return (be_clone(lbh, bename, snap, depth)); +} /* + * Create the boot environment from pre-existing snapshot + */ +int +be_create_from_existing_snap(libbe_handle_t *lbh, const char *bename, + const char *snap) +{ + return (be_clone(lbh, bename, snap, -1)); +} + + +/* * Create a boot environment from an existing boot environment */ int -be_create_from_existing(libbe_handle_t *lbh, const char *name, const char *old) +be_create_from_existing(libbe_handle_t *lbh, const char *bename, const char *old) { int err; - char buf[BE_MAXPATHLEN]; + char snap[BE_MAXPATHLEN]; - if ((err = be_snapshot(lbh, old, NULL, true, (char *)&buf)) != 0) + if ((err = be_snapshot(lbh, old, NULL, true, snap)) != 0) return (set_error(lbh, err)); - err = be_create_from_existing_snap(lbh, name, (char *)buf); + err = be_clone(lbh, bename, snap, -1); return (set_error(lbh, err)); } Modified: stable/11/lib/libbe/be.h ============================================================================== --- stable/11/lib/libbe/be.h Sun Apr 28 02:27:04 2019 (r346801) +++ stable/11/lib/libbe/be.h Sun Apr 28 03:49:40 2019 (r346802) @@ -84,6 +84,7 @@ int be_activate(libbe_handle_t *, const char *, bool); /* Bootenv creation functions */ int be_create(libbe_handle_t *, const char *); +int be_create_depth(libbe_handle_t *, const char *, const char *, int); int be_create_from_existing(libbe_handle_t *, const char *, const char *); int be_create_from_existing_snap(libbe_handle_t *, const char *, const char *); int be_snapshot(libbe_handle_t *, const char *, const char *, bool, char *); Modified: stable/11/lib/libbe/be_impl.h ============================================================================== --- stable/11/lib/libbe/be_impl.h Sun Apr 28 02:27:04 2019 (r346801) +++ stable/11/lib/libbe/be_impl.h Sun Apr 28 03:49:40 2019 (r346802) @@ -50,7 +50,8 @@ struct libbe_deep_clone { libbe_handle_t *lbh; const char *bename; const char *snapname; - const char *be_root; + int depth; + int depth_limit; }; struct libbe_dccb { Modified: stable/11/lib/libbe/libbe.3 ============================================================================== --- stable/11/lib/libbe/libbe.3 Sun Apr 28 02:27:04 2019 (r346801) +++ stable/11/lib/libbe/libbe.3 Sun Apr 28 03:49:40 2019 (r346802) @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 12, 2019 +.Dd April 22, 2019 .Dt LIBBE 3 .Os .Sh NAME @@ -63,6 +63,9 @@ .Fn be_create "libbe_handle_t *hdl" "const char *be_name" .Pp .Ft int +.Fn be_create_depth "libbe_handle_t *hdl" "const char *be_name" "const char *snap" "int depth" +.Pp +.Ft int .Fn be_create_from_existing "libbe_handle_t *hdl" "const char *be_name" "const char *be_origin" .Pp .Ft int @@ -213,19 +216,29 @@ function returns the boot environment root path. The .Fn be_create function creates a boot environment with the given name. -It will be created from a snapshot of the currently booted boot environment. +The new boot environment will be created from a recursive snapshot of the +currently booted boot environment. .Pp The +.Fn be_create_depth +function creates a boot environment with the given name from an existing +snapshot. +The depth parameter specifies the depth of recursion that will be cloned from +the existing snapshot. +A depth of '0' is no recursion and '-1' is unlimited (i.e., a recursive boot +environment). +.Pp +The .Fn be_create_from_existing function creates a boot environment with the given name from the name of an existing boot environment. -A snapshot will be made of the base boot environment, and the new boot -environment will be created from that. +A recursive snapshot will be made of the origin boot environment, and the new +boot environment will be created from that. .Pp The .Fn be_create_from_existing_snap -function creates a boot environment with the given name from an existing -snapshot. +function creates a recursive boot environment with the given name from an +existing snapshot. .Pp The .Fn be_rename
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904280349.x3S3nesu010686>