stand/zfs: Add all bootenvs to environment

For the benefit of lualoader, add all bootenvs to environment when
init_zfs_bootenv is invoked. All of the boot environment logic can then be
implemented in pure lua, rather than going back and forth with C to
implement paging.

This stores all boot environments in bootenvs[idx] and the final count of
bootenvs in bootenvs_count.

While here, make a copy of currdev for init_zfs_bootenv since it will be
modifying it and the caller may not necessarily want that. Some of the logic
was shifted around so that the 'currdev' pointer remains at the beginning of
the string and 'beroot' is moved around as needed to modify it or ultimately
store it in zfs_be_root.

The original zfs_bootenv that this was copied from will be able to go away
only if/when forth eventually goes away.

Tested with:	lualoader (and local changes to add boot env. support)
Tested with:	forth
Reviewed by:	cem (earlier version), imp
Differential Revision:	https://reviews.freebsd.org/D14435
This commit is contained in:
Kyle Evans 2018-02-21 16:26:16 +00:00
parent 8f46043b21
commit 97875f4aa9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329727
2 changed files with 69 additions and 11 deletions

View File

@ -82,7 +82,7 @@ char *zfs_fmtdev(void *vdev);
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
int zfs_list(const char *name);
uint64_t ldi_get_size(void *);
void init_zfs_bootenv(char *currdev);
void init_zfs_bootenv(const char *currdev);
int zfs_bootenv(const char *name);
int zfs_belist_add(const char *name, uint64_t __unused);
int zfs_set_env(void);

View File

@ -60,7 +60,9 @@ static off_t zfs_seek(struct open_file *f, off_t offset, int where);
static int zfs_stat(struct open_file *f, struct stat *sb);
static int zfs_readdir(struct open_file *f, struct dirent *d);
struct devsw zfs_dev;
static void zfs_bootenv_initial(const char *);
truct devsw zfs_dev;
struct fs_ops zfs_fsops = {
"zfs",
@ -770,27 +772,83 @@ zfs_list(const char *name)
}
void
init_zfs_bootenv(char *currdev)
init_zfs_bootenv(const char *currdev_in)
{
char *beroot;
char *beroot, *currdev;
int currdev_len;
if (strlen(currdev) == 0)
currdev = NULL;
currdev_len = strlen(currdev_in);
if (currdev_len == 0)
return;
if(strncmp(currdev, "zfs:", 4) != 0)
if (strncmp(currdev_in, "zfs:", 4) != 0)
return;
currdev = strdup(currdev_in);
if (currdev == NULL)
return;
/* Remove the trailing : */
currdev[strlen(currdev) - 1] = '\0';
currdev[currdev_len - 1] = '\0';
setenv("zfs_be_active", currdev, 1);
setenv("zfs_be_currpage", "1", 1);
/* Forward past zfs: */
currdev = strchr(currdev, ':');
currdev++;
/* Remove the last element (current bootenv) */
beroot = strrchr(currdev, '/');
if (beroot != NULL)
beroot[0] = '\0';
beroot = currdev;
beroot = strchr(currdev, ':') + 1;
setenv("zfs_be_root", beroot, 1);
zfs_bootenv_initial(beroot);
free(currdev);
}
static void
zfs_bootenv_initial(const char *name)
{
char poolname[ZFS_MAXNAMELEN], *dsname;
char envname[32], envval[256];
uint64_t objid;
spa_t *spa;
int bootenvs_idx, len, rv;
SLIST_INIT(&zfs_be_head);
zfs_env_count = 0;
len = strlen(name);
dsname = strchr(name, '/');
if (dsname != NULL) {
len = dsname - name;
dsname++;
} else
dsname = "";
strlcpy(poolname, name, len + 1);
spa = spa_find_by_name(poolname);
if (spa == NULL)
return;
rv = zfs_lookup_dataset(spa, dsname, &objid);
if (rv != 0)
return;
rv = zfs_callback_dataset(spa, objid, zfs_belist_add);
bootenvs_idx = 0;
/* Populate the initial environment variables */
SLIST_FOREACH_SAFE(zfs_be, &zfs_be_head, entries, zfs_be_tmp) {
/* Enumerate all bootenvs for general usage */
snprintf(envname, sizeof(envname), "bootenvs[%d]", bootenvs_idx);
snprintf(envval, sizeof(envval), "zfs:%s/%s", name, zfs_be->name);
rv = setenv(envname, envval, 1);
if (rv != 0)
break;
bootenvs_idx++;
}
snprintf(envval, sizeof(envval), "%d", bootenvs_idx);
setenv("bootenvs_count", envval, 1);
/* Clean up the SLIST of ZFS BEs */
while (!SLIST_EMPTY(&zfs_be_head)) {
zfs_be = SLIST_FIRST(&zfs_be_head);
SLIST_REMOVE_HEAD(&zfs_be_head, entries);
free(zfs_be);
}
return;
}
int