Changeset View
Changeset View
Standalone View
Standalone View
sys/boot/zfs/zfs.c
Show First 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
#include <string.h> | #include <string.h> | ||||
#include <stand.h> | #include <stand.h> | ||||
#include <bootstrap.h> | #include <bootstrap.h> | ||||
#include "libzfs.h" | #include "libzfs.h" | ||||
#include "zfsimpl.c" | #include "zfsimpl.c" | ||||
/* Define the range of indexes to be populated with ZFS Boot Environments */ | |||||
#define ZFS_BE_FIRST 4 | |||||
#define ZFS_BE_LAST 8 | |||||
static int zfs_open(const char *path, struct open_file *f); | static int zfs_open(const char *path, struct open_file *f); | ||||
static int zfs_write(struct open_file *f, void *buf, size_t size, size_t *resid); | static int zfs_write(struct open_file *f, void *buf, size_t size, size_t *resid); | ||||
static int zfs_close(struct open_file *f); | static int zfs_close(struct open_file *f); | ||||
static int zfs_read(struct open_file *f, void *buf, size_t size, size_t *resid); | static int zfs_read(struct open_file *f, void *buf, size_t size, size_t *resid); | ||||
static off_t zfs_seek(struct open_file *f, off_t offset, int where); | 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_stat(struct open_file *f, struct stat *sb); | ||||
static int zfs_readdir(struct open_file *f, struct dirent *d); | static int zfs_readdir(struct open_file *f, struct dirent *d); | ||||
Show All 16 Lines | |||||
struct file { | struct file { | ||||
off_t f_seekp; /* seek pointer */ | off_t f_seekp; /* seek pointer */ | ||||
dnode_phys_t f_dnode; | dnode_phys_t f_dnode; | ||||
uint64_t f_zap_type; /* zap type for readdir */ | uint64_t f_zap_type; /* zap type for readdir */ | ||||
uint64_t f_num_leafs; /* number of fzap leaf blocks */ | uint64_t f_num_leafs; /* number of fzap leaf blocks */ | ||||
zap_leaf_phys_t *f_zap_leaf; /* zap leaf buffer */ | zap_leaf_phys_t *f_zap_leaf; /* zap leaf buffer */ | ||||
}; | }; | ||||
static int zfs_env_index; | |||||
static int zfs_env_count; | |||||
SLIST_HEAD(zfs_be_list, zfs_be_entry) zfs_be_head = SLIST_HEAD_INITIALIZER(zfs_be_head); | |||||
struct zfs_be_list *zfs_be_headp; | |||||
struct zfs_be_entry { | |||||
const char *name; | |||||
SLIST_ENTRY(zfs_be_entry) entries; | |||||
} *zfs_be, *zfs_be_tmp; | |||||
/* | /* | ||||
* Open a file. | * Open a file. | ||||
*/ | */ | ||||
static int | static int | ||||
zfs_open(const char *upath, struct open_file *f) | zfs_open(const char *upath, struct open_file *f) | ||||
{ | { | ||||
struct zfsmount *mount = (struct zfsmount *)f->f_devdata; | struct zfsmount *mount = (struct zfsmount *)f->f_devdata; | ||||
struct file *fp; | struct file *fp; | ||||
▲ Show 20 Lines • Show All 595 Lines • ▼ Show 20 Lines | zfs_list(const char *name) | ||||
poolname[len] = '\0'; | poolname[len] = '\0'; | ||||
spa = spa_find_by_name(poolname); | spa = spa_find_by_name(poolname); | ||||
if (!spa) | if (!spa) | ||||
return (ENXIO); | return (ENXIO); | ||||
rv = zfs_lookup_dataset(spa, dsname, &objid); | rv = zfs_lookup_dataset(spa, dsname, &objid); | ||||
if (rv != 0) | if (rv != 0) | ||||
return (rv); | return (rv); | ||||
rv = zfs_list_dataset(spa, objid); | rv = zfs_list_dataset(spa, objid); | ||||
smh: Avoid assignment and just:
return (zfs_list_dataset(spa, objid)); | |||||
return (rv); | |||||
} | |||||
int | |||||
zfs_bootenv(const char *name) | |||||
{ | |||||
static char poolname[ZFS_MAXNAMELEN], *dsname; | |||||
char becount[4]; | |||||
uint64_t objid; | |||||
spa_t *spa; | |||||
int len, rv, pages, perpage, currpage; | |||||
if (strcmp(name, getenv("zfs_be_root")) != 0) { | |||||
setenv("zfs_be_root", name, 1); | |||||
smhUnsubmitted Done Inline Actionscheck the return codes? more below too. smh: check the return codes? more below too. | |||||
} | |||||
SLIST_INIT(&zfs_be_head); | |||||
zfs_env_count = 0; | |||||
len = strlen(name); | |||||
dsname = strchr(name, '/'); | |||||
if (dsname != NULL) { | |||||
len = dsname - name; | |||||
dsname++; | |||||
} else | |||||
dsname = ""; | |||||
memcpy(poolname, name, len); | |||||
poolname[len] = '\0'; | |||||
spa = spa_find_by_name(poolname); | |||||
if (!spa) | |||||
return (ENXIO); | |||||
rv = zfs_lookup_dataset(spa, dsname, &objid); | |||||
if (rv != 0) | |||||
return (rv); | |||||
rv = zfs_callback_dataset(spa, objid, zfs_belist_add); | |||||
/* Calculate and store the number of pages of BEs */ | |||||
perpage = (ZFS_BE_LAST - ZFS_BE_FIRST + 1); | |||||
pages = (zfs_env_count / perpage) + ((zfs_env_count % perpage) > 0 ? 1 : 0); | |||||
snprintf(becount, 4, "%d", pages); | |||||
setenv("zfs_be_pages", becount, 1); | |||||
/* Roll over the page counter if it has exceeded the maximum */ | |||||
currpage = strtol(getenv("zfs_be_currpage"), NULL, 10); | |||||
if (currpage > pages) { | |||||
setenv("zfs_be_currpage", "1", 1); | |||||
} | |||||
/* Populate the menu environment variables */ | |||||
zfs_set_env(); | |||||
/* 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 (rv); | |||||
} | |||||
int | |||||
zfs_belist_add(const char *name) | |||||
{ | |||||
/* Add the boot environment to the head of the SLIST */ | |||||
zfs_be = malloc(sizeof(struct zfs_be_entry)); | |||||
zfs_be->name = name; | |||||
SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries); | |||||
zfs_env_count++; | |||||
return 0; | |||||
smhUnsubmitted Done Inline Actionsstyle(9) braces around return. smh: style(9) braces around return. | |||||
} | |||||
Done Inline ActionsInstead of unchecked malloc you could use static buffers? then in the next snprintf instead of hardcoding the size you could sizeof(envname) And the free in the end becomes useless bapt: Instead of unchecked malloc you could use static buffers?
char envname[32] ?
then in the next… | |||||
int | |||||
zfs_set_env(void) | |||||
{ | |||||
char envname[32], envval[256]; | |||||
char *beroot, *pagenum; | |||||
int rv, page, ctr; | |||||
beroot = getenv("zfs_be_root"); | |||||
pagenum = getenv("zfs_be_currpage"); | |||||
if (pagenum != NULL) { | |||||
page = strtol(pagenum, NULL, 10); | |||||
} else { | |||||
page = 1; | |||||
} | |||||
if (beroot == NULL) { | |||||
smhUnsubmitted Done Inline Actionsmove up to return early. smh: move up to return early. | |||||
return (1); | |||||
} | |||||
ctr = 1; | |||||
zfs_env_index = ZFS_BE_FIRST; | |||||
SLIST_FOREACH_SAFE(zfs_be, &zfs_be_head, entries, zfs_be_tmp) { | |||||
/* Skip to the requested page number */ | |||||
if (ctr <= ((ZFS_BE_LAST - ZFS_BE_FIRST + 1) * (page - 1))) { | |||||
ctr++; | |||||
continue; | |||||
} | |||||
snprintf(envname, 32, "bootenvmenu_caption[%d]", zfs_env_index); | |||||
snprintf(envval, 256, "%s", zfs_be->name); | |||||
rv = setenv(envname, envval, 1); | |||||
if (rv){ | |||||
smhUnsubmitted Done Inline Actionsstyle(9) more below too. if (rv != 0) return (rv); smh: style(9) more below too.
if (rv != 0)
return (rv); | |||||
return (rv); | |||||
smhUnsubmitted Done Inline ActionsCould the early returns here leave it in an inconsistent state that may course an issue? smh: Could the early returns here leave it in an inconsistent state that may course an issue? | |||||
allanjudeAuthorUnsubmitted Done Inline ActionsPossibly, switching them to break allanjude: Possibly, switching them to break | |||||
} | |||||
snprintf(envname, 32, "bootenvansi_caption[%d]", zfs_env_index); | |||||
smhUnsubmitted Done Inline Actionsuse sizeof(envname), more below. smh: use sizeof(envname), more below. | |||||
rv = setenv(envname, envval, 1); | |||||
if (rv){ | |||||
return (rv); | |||||
} | |||||
snprintf(envname, 32, "bootenvmenu_command[%d]", zfs_env_index); | |||||
rv = setenv(envname, "set_bootenv", 1); | |||||
if (rv){ | |||||
return (rv); | |||||
} | |||||
snprintf(envname, 32, "bootenv_root[%d]", zfs_env_index); | |||||
snprintf(envval, 256, "zfs:%s/%s", beroot, zfs_be->name); | |||||
smhUnsubmitted Done Inline Actionsuse sizeof(enval) smh: use sizeof(enval) | |||||
rv = setenv(envname, envval, 1); | |||||
if (rv){ | |||||
return (rv); | |||||
} | |||||
if (zfs_env_index >= ZFS_BE_LAST) { | |||||
zfs_env_index++; | |||||
smhUnsubmitted Done Inline ActionsAs zfs_env_index is always incremented could be extracted above so we have the following instead? zfs_env_index++; if (zfs_env_index > ZFS_BE_LAST) break; smh: As zfs_env_index is always incremented could be extracted above so we have the following… | |||||
break; | |||||
} | |||||
zfs_env_index++; | |||||
} | |||||
for (; zfs_env_index <= ZFS_BE_LAST; zfs_env_index++) { | |||||
snprintf(envname, 32, "bootenvmenu_caption[%d]", zfs_env_index); | |||||
smhUnsubmitted Done Inline Actionsuse sizeof(envname) more below smh: use sizeof(envname) more below | |||||
rv = unsetenv(envname); | |||||
snprintf(envname, 32, "bootenvansi_caption[%d]", zfs_env_index); | |||||
rv = unsetenv(envname); | |||||
snprintf(envname, 32, "bootenvmenu_command[%d]", zfs_env_index); | |||||
rv = unsetenv(envname); | |||||
snprintf(envname, 32, "bootenv_root[%d]", zfs_env_index); | |||||
rv = unsetenv(envname); | |||||
} | |||||
return (rv); | return (rv); | ||||
smhUnsubmitted Done Inline Actionsrv here is likely to be useless due to use by loop above, should that use a seperate var or just (void)unsetenv(envname) ? smh: rv here is likely to be useless due to use by loop above, should that use a seperate var or… | |||||
} | } | ||||
No newline at end of file |
Avoid assignment and just: