Index: lib/libbe/be.h =================================================================== --- lib/libbe/be.h +++ lib/libbe/be.h @@ -79,6 +79,7 @@ int be_prop_list_alloc(nvlist_t **be_list); void be_prop_list_free(nvlist_t *be_list); +int be_nextboot_options(libbe_handle_t *, const char *); int be_activate(libbe_handle_t *, const char *, bool); /* Bootenv creation functions */ Index: lib/libbe/be.c =================================================================== --- lib/libbe/be.c +++ lib/libbe/be.c @@ -912,14 +912,40 @@ return (0); } +int +be_nextboot_options(libbe_handle_t *lbh, const char *opts) +{ + nvlist_t *config, *vdevs; + uint64_t pool_guid; + + if (opts == NULL) + return (set_error(lbh, BE_ERR_UNKNOWN)); + + config = zpool_get_config(lbh->active_phandle, NULL); + if (config == NULL) + /* config should be fetchable... */ + return (set_error(lbh, BE_ERR_UNKNOWN)); + + if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, + &pool_guid) != 0) + /* Similarly, it shouldn't be possible */ + return (set_error(lbh, BE_ERR_UNKNOWN)); + + /* We have no config tree */ + if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, + &vdevs) != 0) + return (set_error(lbh, BE_ERR_NOPOOL)); + + return (be_set_nextboot(lbh, vdevs, pool_guid, opts)); +} + int be_activate(libbe_handle_t *lbh, const char *bootenv, bool temporary) { char be_path[BE_MAXPATHLEN]; char buf[BE_MAXPATHLEN]; - nvlist_t *config, *dsprops, *vdevs; + nvlist_t *dsprops; char *origin; - uint64_t pool_guid; zfs_handle_t *zhp; int err; @@ -930,25 +956,9 @@ return (set_error(lbh, err)); if (temporary) { - config = zpool_get_config(lbh->active_phandle, NULL); - if (config == NULL) - /* config should be fetchable... */ - return (set_error(lbh, BE_ERR_UNKNOWN)); - - if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, - &pool_guid) != 0) - /* Similarly, it shouldn't be possible */ - return (set_error(lbh, BE_ERR_UNKNOWN)); - /* Expected format according to zfsbootcfg(8) man */ snprintf(buf, sizeof(buf), "zfs:%s:", be_path); - - /* We have no config tree */ - if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, - &vdevs) != 0) - return (set_error(lbh, BE_ERR_NOPOOL)); - - return (be_set_nextboot(lbh, vdevs, pool_guid, buf)); + return (be_nextboot_options(lbh, buf)); } else { if (be_deactivate(lbh, lbh->bootfs) != 0) return (-1); Index: lib/libbe/libbe.3 =================================================================== --- lib/libbe/libbe.3 +++ lib/libbe/libbe.3 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 21, 2018 +.Dd January 28, 2019 .Dt LIBBE 3 .Os .Sh NAME @@ -72,6 +72,8 @@ .Fn be_rename "libbe_handle_t *hdl" "const char *be_old" "const char *be_new" .Pp .Ft int +.Fn be_nextboot_options "libbe_handle_t *hdl" "const char *options" +.Ft int .Fn be_activate "libbe_handle_t *hdl" "const char *be_name" "bool temporary" .Ft int .Fn be_destroy "libbe_handle_t *hdl" "const char *be_name" "int options" @@ -237,6 +239,15 @@ .Cm rename .Pp The +.Fn be_nextboot_options +function sets nextboot options for the next boot. +This function is mutually exclusive with the +.Fn be_activate +function with the +.Fa temporary +flag set, as they both write to the same label area. +.Pp +The .Fn be_activate function makes a boot environment active on the next boot. If the Index: sbin/zfsbootcfg/Makefile =================================================================== --- sbin/zfsbootcfg/Makefile +++ sbin/zfsbootcfg/Makefile @@ -2,25 +2,15 @@ # $FreeBSD$ PROG= zfsbootcfg -WARNS?= 1 MAN= zfsbootcfg.8 -LIBADD+=zfs -LIBADD+=nvpair -LIBADD+=umem -LIBADD+=uutil -LIBADD+=geom +LIBADD+= be +LIBADD+= nvpair +LIBADD+= util -CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include -CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/lib/libumem CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common -CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs_core/common -CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzpool/common -CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libnvpair CFLAGS+= -I${SRCTOP}/sys/cddl/compat/opensolaris -CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/fs/zfs CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common -CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/head CFLAGS+= -DNEED_SOLARIS_BOOLEAN Index: sbin/zfsbootcfg/zfsbootcfg.8 =================================================================== --- sbin/zfsbootcfg/zfsbootcfg.8 +++ sbin/zfsbootcfg/zfsbootcfg.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 24, 2017 +.Dd January 28, 2019 .Dt ZFSBOOTCFG 8 .Os .Sh NAME @@ -55,18 +55,6 @@ .Xr gptzfsboot 8 read the boot option information from the first disk found in the first ZFS pool found. -.Sh ENVIRONMENT -.Bl -tag -width vfs.zfs.boot.primary_pool -compact -.It Ev vfs.zfs.boot.primary_pool -The -.Xr kenv 1 -variable that identifies a pool for which the options are written. -.It Ev vfs.zfs.boot.primary_vdev -The -.Xr kenv 1 -variable that identifies a disk within the pool where the options -are written. -.El .Sh EXAMPLES Try to boot to a new .Em boot environment @@ -93,13 +81,8 @@ .Sh CAVEATS At the moment, .Nm -uses the -.Ev vfs.zfs.boot.primary_pool -and -.Ev vfs.zfs.boot.primary_vdev -.Xr kenv 1 -variables to determine a ZFS pool and a disk in it where the options -are to be stored. +uses the dataset mounted as root to determine a ZFS pool and a disk in it where +the options are to be stored. The variables are set by the ZFS boot chain, so there is an assumption that the same boot disk is going to be used for the next reboot. There is no Index: sbin/zfsbootcfg/zfsbootcfg.c =================================================================== --- sbin/zfsbootcfg/zfsbootcfg.c +++ sbin/zfsbootcfg/zfsbootcfg.c @@ -26,73 +26,39 @@ #include __FBSDID("$FreeBSD$"); -#include -#include -#include -#include -#include -#include #include -#include -#include +#include /* Keep in sync with zfsboot.c. */ #define MAX_COMMAND_LEN 512 int main(int argc, const char * const *argv) { - char buf[32]; - libzfs_handle_t *hdl; - uint64_t pool_guid; - uint64_t vdev_guid; - int zfs_fd; - int len; + libbe_handle_t *lbh; if (argc != 2) { fprintf(stderr, "usage: zfsbootcfg \n"); return (1); } - len = strlen(argv[1]); - if (len >= MAX_COMMAND_LEN) { + if (strlen(argv[1]) >= MAX_COMMAND_LEN) { fprintf(stderr, "options string is too long\n"); return (1); } - if (kenv(KENV_GET, "vfs.zfs.boot.primary_pool", buf, sizeof(buf)) <= 0) { - perror("can't get vfs.zfs.boot.primary_pool"); - return (1); - } - pool_guid = strtoumax(buf, NULL, 10); - if (pool_guid == 0) { - perror("can't parse vfs.zfs.boot.primary_pool"); - return (1); - } - - if (kenv(KENV_GET, "vfs.zfs.boot.primary_vdev", buf, sizeof(buf)) <= 0) { - perror("can't get vfs.zfs.boot.primary_vdev"); - return (1); - } - vdev_guid = strtoumax(buf, NULL, 10); - if (vdev_guid == 0) { - perror("can't parse vfs.zfs.boot.primary_vdev"); - return (1); - } - - if ((hdl = libzfs_init()) == NULL) { + if ((lbh = libbe_init(NULL)) == NULL) { (void) fprintf(stderr, "internal error: failed to " - "initialize ZFS library\n"); + "initialize BE library\n"); return (1); } - if (zpool_nextboot(hdl, pool_guid, vdev_guid, argv[1]) != 0) { - perror("ZFS_IOC_NEXTBOOT failed"); - libzfs_fini(hdl); - return (1); + if (be_nextboot_options(lbh, argv[1]) != 0) { + perror("be_nextboot_options failed"); + libbe_close(lbh); } - libzfs_fini(hdl); + libbe_close(lbh); printf("zfs next boot options are successfully written\n"); return (0); }