libbe(3): Find rootfs instead by enumerating child datasets of BE root

This makes us more resilient to a rename of the bootfs, but still wouldn't
withstand pool renames or guid renames. More importantly, this allows `bectl
create <foo>` work out of the box to create a boot environment based on the
currently booted one.
This commit is contained in:
Kyle Evans 2018-07-25 03:30:01 +00:00
parent c3a34c08e0
commit ee16b7c946
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/bectl/; revision=336699

View File

@ -41,6 +41,28 @@
#include "be.h"
#include "be_impl.h"
/*
* Iterator function for locating the rootfs amongst the children of the
* zfs_be_root set by loader(8). data is expected to be a libbe_handle_t *.
*/
static int
be_locate_rootfs(zfs_handle_t *chkds, void *data)
{
libbe_handle_t *lbh;
char *mntpoint;
lbh = (libbe_handle_t *)data;
if (lbh == NULL)
return (1);
if (zfs_is_mounted(chkds, &mntpoint) && strcmp(mntpoint, "/") == 0) {
strncpy(lbh->rootfs, zfs_get_name(chkds), BE_MAXPATHLEN);
return (1);
}
return (0);
}
/*
* Initializes the libbe context to operate in the root boot environment
* dataset, for example, zroot/ROOT.
@ -48,16 +70,18 @@
libbe_handle_t *
libbe_init(void)
{
char buf[BE_MAXPATHLEN];
struct stat sb;
dev_t root_dev, boot_dev;
libbe_handle_t *lbh;
zfs_handle_t *rootds;
char *poolname, *pos;
int pnamelen;
lbh = NULL;
poolname = pos = NULL;
pnamelen = 0;
rootds = NULL;
/* Verify that /boot and / are mounted on the same filesystem */
/* TODO: use errno here?? */
if (stat("/", &sb) != 0)
@ -109,13 +133,11 @@ libbe_init(void)
/* Obtain path to boot environment rootfs (currently booted) */
/* XXX Get dataset mounted at / by kenv/GUID from mountroot? */
if ((kenv(KENV_GET, "zfs_be_active", lbh->rootfs, BE_MAXPATHLEN)) == -1)
if ((rootds = zfs_open(lbh->lzh, lbh->root, ZFS_TYPE_DATASET)) == NULL)
goto err;
/* Remove leading 'zfs:' if present, otherwise use value as-is */
if (strcmp(lbh->rootfs, "zfs:") == 0)
strncpy(lbh->rootfs, strchr(lbh->rootfs, ':') + sizeof(char),
BE_MAXPATHLEN);
zfs_iter_filesystems(rootds, be_locate_rootfs, lbh);
zfs_close(rootds);
return (lbh);
err:
@ -126,6 +148,8 @@ libbe_init(void)
libzfs_fini(lbh->lzh);
free(lbh);
}
if (rootds != NULL)
zfs_close(rootds);
free(poolname);
return (NULL);
}