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:
parent
c3a34c08e0
commit
ee16b7c946
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/bectl/; revision=336699
@ -41,6 +41,28 @@
|
|||||||
#include "be.h"
|
#include "be.h"
|
||||||
#include "be_impl.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
|
* Initializes the libbe context to operate in the root boot environment
|
||||||
* dataset, for example, zroot/ROOT.
|
* dataset, for example, zroot/ROOT.
|
||||||
@ -48,16 +70,18 @@
|
|||||||
libbe_handle_t *
|
libbe_handle_t *
|
||||||
libbe_init(void)
|
libbe_init(void)
|
||||||
{
|
{
|
||||||
char buf[BE_MAXPATHLEN];
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
dev_t root_dev, boot_dev;
|
dev_t root_dev, boot_dev;
|
||||||
libbe_handle_t *lbh;
|
libbe_handle_t *lbh;
|
||||||
|
zfs_handle_t *rootds;
|
||||||
char *poolname, *pos;
|
char *poolname, *pos;
|
||||||
int pnamelen;
|
int pnamelen;
|
||||||
|
|
||||||
lbh = NULL;
|
lbh = NULL;
|
||||||
poolname = pos = NULL;
|
poolname = pos = NULL;
|
||||||
pnamelen = 0;
|
pnamelen = 0;
|
||||||
|
rootds = NULL;
|
||||||
|
|
||||||
/* Verify that /boot and / are mounted on the same filesystem */
|
/* Verify that /boot and / are mounted on the same filesystem */
|
||||||
/* TODO: use errno here?? */
|
/* TODO: use errno here?? */
|
||||||
if (stat("/", &sb) != 0)
|
if (stat("/", &sb) != 0)
|
||||||
@ -109,13 +133,11 @@ libbe_init(void)
|
|||||||
|
|
||||||
/* Obtain path to boot environment rootfs (currently booted) */
|
/* Obtain path to boot environment rootfs (currently booted) */
|
||||||
/* XXX Get dataset mounted at / by kenv/GUID from mountroot? */
|
/* 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;
|
goto err;
|
||||||
|
|
||||||
/* Remove leading 'zfs:' if present, otherwise use value as-is */
|
zfs_iter_filesystems(rootds, be_locate_rootfs, lbh);
|
||||||
if (strcmp(lbh->rootfs, "zfs:") == 0)
|
zfs_close(rootds);
|
||||||
strncpy(lbh->rootfs, strchr(lbh->rootfs, ':') + sizeof(char),
|
|
||||||
BE_MAXPATHLEN);
|
|
||||||
|
|
||||||
return (lbh);
|
return (lbh);
|
||||||
err:
|
err:
|
||||||
@ -126,6 +148,8 @@ libbe_init(void)
|
|||||||
libzfs_fini(lbh->lzh);
|
libzfs_fini(lbh->lzh);
|
||||||
free(lbh);
|
free(lbh);
|
||||||
}
|
}
|
||||||
|
if (rootds != NULL)
|
||||||
|
zfs_close(rootds);
|
||||||
free(poolname);
|
free(poolname);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user