Changeset View
Changeset View
Standalone View
Standalone View
head/sbin/zfsbootcfg/zfsbootcfg.c
Show All 34 Lines | |||||
#include <string.h> | #include <string.h> | ||||
#include <kenv.h> | #include <kenv.h> | ||||
#include <libzfs.h> | #include <libzfs.h> | ||||
/* Keep in sync with zfsboot.c. */ | /* Keep in sync with zfsboot.c. */ | ||||
#define MAX_COMMAND_LEN 512 | #define MAX_COMMAND_LEN 512 | ||||
int | |||||
install_bootonce(libzfs_handle_t *hdl, uint64_t pool_guid, nvlist_t *nv, | |||||
const char * const data) | |||||
{ | |||||
nvlist_t **child; | |||||
uint_t children = 0; | |||||
uint64_t guid; | |||||
int rv; | |||||
(void) nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, | |||||
&children); | |||||
for (int c = 0; c < children; c++) { | |||||
rv = install_bootonce(hdl, pool_guid, child[c], data); | |||||
yuripv: Shouldn't this be `+=` as otherwise we'll return the status for the last child only? | |||||
} | |||||
if (children > 0) | |||||
return (rv); | |||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) != 0) { | |||||
perror("can't get vdev guid"); | |||||
return (1); | |||||
} | |||||
if (zpool_nextboot(hdl, pool_guid, guid, data) != 0) { | |||||
perror("ZFS_IOC_NEXTBOOT failed"); | |||||
return (1); | |||||
} | |||||
return (0); | |||||
} | |||||
int main(int argc, const char * const *argv) | int main(int argc, const char * const *argv) | ||||
{ | { | ||||
char buf[32]; | char buf[32], *name; | ||||
libzfs_handle_t *hdl; | libzfs_handle_t *hdl; | ||||
zpool_handle_t *zphdl; | |||||
uint64_t pool_guid; | uint64_t pool_guid; | ||||
uint64_t vdev_guid; | nvlist_t *nv, *config; | ||||
int zfs_fd; | int rv; | ||||
int len; | int len; | ||||
if (argc != 2) { | if (argc != 2) { | ||||
fprintf(stderr, "usage: zfsbootcfg <boot.config(5) options>\n"); | fprintf(stderr, "usage: zfsbootcfg <boot.config(5) options>\n"); | ||||
return (1); | return (1); | ||||
} | } | ||||
len = strlen(argv[1]); | len = strlen(argv[1]); | ||||
if (len >= MAX_COMMAND_LEN) { | if (len >= MAX_COMMAND_LEN) { | ||||
fprintf(stderr, "options string is too long\n"); | fprintf(stderr, "options string is too long\n"); | ||||
return (1); | return (1); | ||||
} | } | ||||
if (kenv(KENV_GET, "vfs.zfs.boot.primary_pool", buf, sizeof(buf)) <= 0) { | if (kenv(KENV_GET, "vfs.root.mountfrom", buf, sizeof(buf)) <= 0) { | ||||
perror("can't get vfs.zfs.boot.primary_pool"); | perror("can't get vfs.root.mountfrom"); | ||||
return (1); | return (1); | ||||
} | } | ||||
pool_guid = strtoumax(buf, NULL, 10); | |||||
if (pool_guid == 0) { | if (strncmp(buf, "zfs:", 4) == 0) { | ||||
perror("can't parse vfs.zfs.boot.primary_pool"); | name = strchr(buf + 4, '/'); | ||||
if (name != NULL) | |||||
*name = '\0'; | |||||
name = buf + 4; | |||||
} else { | |||||
perror("not a zfs root"); | |||||
return (1); | return (1); | ||||
} | } | ||||
if (kenv(KENV_GET, "vfs.zfs.boot.primary_vdev", buf, sizeof(buf)) <= 0) { | if ((hdl = libzfs_init()) == NULL) { | ||||
perror("can't get vfs.zfs.boot.primary_vdev"); | (void) fprintf(stderr, "internal error: failed to " | ||||
"initialize ZFS library\n"); | |||||
return (1); | return (1); | ||||
} | } | ||||
vdev_guid = strtoumax(buf, NULL, 10); | |||||
if (vdev_guid == 0) { | zphdl = zpool_open(hdl, name); | ||||
perror("can't parse vfs.zfs.boot.primary_vdev"); | if (zphdl == NULL) { | ||||
perror("can't open pool"); | |||||
libzfs_fini(hdl); | |||||
return (1); | return (1); | ||||
} | } | ||||
if ((hdl = libzfs_init()) == NULL) { | pool_guid = zpool_get_prop_int(zphdl, ZPOOL_PROP_GUID, NULL); | ||||
(void) fprintf(stderr, "internal error: failed to " | |||||
"initialize ZFS library\n"); | config = zpool_get_config(zphdl, NULL); | ||||
if (config == NULL) { | |||||
perror("can't get pool config"); | |||||
zpool_close(zphdl); | |||||
libzfs_fini(hdl); | |||||
return (1); | return (1); | ||||
} | } | ||||
if (zpool_nextboot(hdl, pool_guid, vdev_guid, argv[1]) != 0) { | if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nv) != 0) { | ||||
perror("ZFS_IOC_NEXTBOOT failed"); | perror("failed to get vdev tree"); | ||||
zpool_close(zphdl); | |||||
libzfs_fini(hdl); | libzfs_fini(hdl); | ||||
return (1); | return (1); | ||||
} | } | ||||
rv = install_bootonce(hdl, pool_guid, nv, argv[1]); | |||||
zpool_close(zphdl); | |||||
libzfs_fini(hdl); | libzfs_fini(hdl); | ||||
if (rv == 0) | |||||
printf("zfs next boot options are successfully written\n"); | printf("zfs next boot options are successfully written\n"); | ||||
return (0); | return (rv); | ||||
} | } |
Shouldn't this be += as otherwise we'll return the status for the last child only?