summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2016-12-05 15:52:27 -0200
committerRenato Botelho <renato@netgate.com>2016-12-05 15:52:27 -0200
commitec84a59afa973e7e021ba2ae8ecae4cb6ba37b1d (patch)
treed7d40ac77bda3d6fc35814a1a6484eb324b3c7df /sbin
parentca825f0a56d174ca9d3478d87cdca9f318a50cc6 (diff)
parent356fbc072920d7e71c42b310d6bfa2d1a3d36f9f (diff)
downloadFreeBSD-src-ec84a59afa973e7e021ba2ae8ecae4cb6ba37b1d.zip
FreeBSD-src-ec84a59afa973e7e021ba2ae8ecae4cb6ba37b1d.tar.gz
Merge remote-tracking branch 'origin/stable/11' into devel-11
Diffstat (limited to 'sbin')
-rw-r--r--sbin/Makefile1
-rw-r--r--sbin/dhclient/dispatch.c4
-rw-r--r--sbin/etherswitchcfg/etherswitchcfg.c6
-rw-r--r--sbin/ipfw/ipfw2.c13
-rw-r--r--sbin/ipfw/ipfw2.h9
-rw-r--r--sbin/ipfw/ipv6.c23
-rw-r--r--sbin/swapon/swapon.88
-rw-r--r--sbin/swapon/swapon.c4
-rw-r--r--sbin/umount/umount.c24
-rw-r--r--sbin/zfsbootcfg/Makefile27
-rw-r--r--sbin/zfsbootcfg/zfsbootcfg.8112
-rw-r--r--sbin/zfsbootcfg/zfsbootcfg.c98
12 files changed, 293 insertions, 36 deletions
diff --git a/sbin/Makefile b/sbin/Makefile
index affca8e..4826bc0 100644
--- a/sbin/Makefile
+++ b/sbin/Makefile
@@ -87,6 +87,7 @@ SUBDIR.${MK_PF}+= pfctl
SUBDIR.${MK_PF}+= pflogd
SUBDIR.${MK_QUOTAS}+= quotacheck
SUBDIR.${MK_ROUTED}+= routed
+SUBDIR.${MK_ZFS}+= zfsbootcfg
SUBDIR.${MK_TESTS}+= tests
diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c
index 3ee0cf6..3317ceb 100644
--- a/sbin/dhclient/dispatch.c
+++ b/sbin/dhclient/dispatch.c
@@ -105,8 +105,8 @@ discover_interfaces(struct interface_info *iface)
if (foo.sin_addr.s_addr == htonl(INADDR_LOOPBACK))
continue;
if (!iface->ifp) {
- int len = IFNAMSIZ + ifa->ifa_addr->sa_len;
- if ((tif = malloc(len)) == NULL)
+ if ((tif = calloc(1, sizeof(struct ifreq)))
+ == NULL)
error("no space to remember ifp");
strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ);
memcpy(&tif->ifr_addr, ifa->ifa_addr,
diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c
index f7f117a..0ab110b 100644
--- a/sbin/etherswitchcfg/etherswitchcfg.c
+++ b/sbin/etherswitchcfg/etherswitchcfg.c
@@ -274,7 +274,8 @@ set_vlangroup_vid(struct cfg *cfg, char *argv[])
{
int v;
etherswitch_vlangroup_t vg;
-
+
+ memset(&vg, 0, sizeof(vg));
v = strtol(argv[1], NULL, 0);
if (v < 0 || v > IEEE802DOT1Q_VID_MAX)
errx(EX_USAGE, "vlan must be between 0 and %d", IEEE802DOT1Q_VID_MAX);
@@ -293,8 +294,9 @@ set_vlangroup_members(struct cfg *cfg, char *argv[])
int member, untagged;
char *c, *d;
int v;
-
+
member = untagged = 0;
+ memset(&vg, 0, sizeof(vg));
if (strcmp(argv[1], "none") != 0) {
for (c=argv[1]; *c; c=d) {
v = strtol(c, &d, 0);
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 42b020a..6a69a43 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -2883,8 +2883,9 @@ pack_table(struct tidx *tstate, char *name)
return (pack_object(tstate, name, IPFW_TLV_TBL_NAME));
}
-static void
-fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate)
+void
+fill_table(struct _ipfw_insn *cmd, char *av, uint8_t opcode,
+ struct tidx *tstate)
{
uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
uint16_t uidx;
@@ -3543,7 +3544,7 @@ add_src(ipfw_insn *cmd, char *av, u_char proto, int cblen, struct tidx *tstate)
if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 ||
inet_pton(AF_INET6, host, &a) == 1)
- ret = add_srcip6(cmd, av, cblen);
+ ret = add_srcip6(cmd, av, cblen, tstate);
/* XXX: should check for IPv4, not !IPv6 */
if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 ||
inet_pton(AF_INET6, host, &a) != 1))
@@ -3574,7 +3575,7 @@ add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen, struct tidx *tstate)
if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 ||
inet_pton(AF_INET6, host, &a) == 1)
- ret = add_dstip6(cmd, av, cblen);
+ ret = add_dstip6(cmd, av, cblen, tstate);
/* XXX: should check for IPv4, not !IPv6 */
if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 ||
inet_pton(AF_INET6, host, &a) != 1))
@@ -4578,14 +4579,14 @@ read_options:
case TOK_SRCIP6:
NEED1("missing source IP6");
- if (add_srcip6(cmd, *av, cblen)) {
+ if (add_srcip6(cmd, *av, cblen, tstate)) {
av++;
}
break;
case TOK_DSTIP6:
NEED1("missing destination IP6");
- if (add_dstip6(cmd, *av, cblen)) {
+ if (add_dstip6(cmd, *av, cblen, tstate)) {
av++;
}
break;
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index b7f8c0b..c89a1c5 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -363,8 +363,11 @@ void print_flow6id(struct buf_pr *bp, struct _ipfw_insn_u32 *cmd);
void print_icmp6types(struct buf_pr *bp, struct _ipfw_insn_u32 *cmd);
void print_ext6hdr(struct buf_pr *bp, struct _ipfw_insn *cmd );
-struct _ipfw_insn *add_srcip6(struct _ipfw_insn *cmd, char *av, int cblen);
-struct _ipfw_insn *add_dstip6(struct _ipfw_insn *cmd, char *av, int cblen);
+struct tidx;
+struct _ipfw_insn *add_srcip6(struct _ipfw_insn *cmd, char *av, int cblen,
+ struct tidx *tstate);
+struct _ipfw_insn *add_dstip6(struct _ipfw_insn *cmd, char *av, int cblen,
+ struct tidx *tstate);
void fill_flow6(struct _ipfw_insn_u32 *cmd, char *av, int cblen);
void fill_unreach6_code(u_short *codep, char *str);
@@ -373,6 +376,8 @@ int fill_ext6hdr(struct _ipfw_insn *cmd, char *av);
/* ipfw2.c */
void bp_flush(struct buf_pr *b);
+void fill_table(struct _ipfw_insn *cmd, char *av, uint8_t opcode,
+ struct tidx *tstate);
/* tables.c */
struct _ipfw_obj_ctlv;
diff --git a/sbin/ipfw/ipv6.c b/sbin/ipfw/ipv6.c
index 6d884ee..f6b858d 100644
--- a/sbin/ipfw/ipv6.c
+++ b/sbin/ipfw/ipv6.c
@@ -334,7 +334,7 @@ lookup_host6 (char *host, struct in6_addr *ip6addr)
* Return 1 on success, 0 on failure.
*/
static int
-fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen)
+fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen, struct tidx *tstate)
{
int len = 0;
struct in6_addr *d = &(cmd->addr6);
@@ -360,18 +360,7 @@ fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen)
}
if (strncmp(av, "table(", 6) == 0) {
- char *p = strchr(av + 6, ',');
- uint32_t *dm = ((ipfw_insn_u32 *)cmd)->d;
-
- if (p)
- *p++ = '\0';
- cmd->o.opcode = O_IP_DST_LOOKUP;
- cmd->o.arg1 = strtoul(av + 6, NULL, 0);
- if (p) {
- cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
- dm[0] = strtoul(p, NULL, 0);
- } else
- cmd->o.len |= F_INSN_SIZE(ipfw_insn);
+ fill_table(&cmd->o, av, O_IP_DST_LOOKUP, tstate);
return (1);
}
@@ -492,10 +481,10 @@ fill_flow6( ipfw_insn_u32 *cmd, char *av, int cblen)
}
ipfw_insn *
-add_srcip6(ipfw_insn *cmd, char *av, int cblen)
+add_srcip6(ipfw_insn *cmd, char *av, int cblen, struct tidx *tstate)
{
- fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen);
+ fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen, tstate);
if (cmd->opcode == O_IP_DST_SET) /* set */
cmd->opcode = O_IP_SRC_SET;
else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */
@@ -514,10 +503,10 @@ add_srcip6(ipfw_insn *cmd, char *av, int cblen)
}
ipfw_insn *
-add_dstip6(ipfw_insn *cmd, char *av, int cblen)
+add_dstip6(ipfw_insn *cmd, char *av, int cblen, struct tidx *tstate)
{
- fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen);
+ fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen, tstate);
if (cmd->opcode == O_IP_DST_SET) /* set */
;
else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */
diff --git a/sbin/swapon/swapon.8 b/sbin/swapon/swapon.8
index c4286d7..51bee68 100644
--- a/sbin/swapon/swapon.8
+++ b/sbin/swapon/swapon.8
@@ -28,7 +28,7 @@
.\" @(#)swapon.8 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd November 22, 2013
+.Dd October 21, 2016
.Dt SWAPON 8
.Os
.Sh NAME
@@ -96,15 +96,13 @@ option is used, all swap devices in
.Pa /etc/fstab
will be removed, unless their
.Dq noauto
-or
-.Dq late
option is also set.
If the
.Fl L
option is specified,
-swap devices with the
+only swap devices with the
.Dq late
-option will be removed as well as ones with no option.
+option will be removed.
If the
.Fl q
option is used,
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index e34cfcf..052fbc7 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -176,6 +176,10 @@ main(int argc, char **argv)
strstr(fsp->fs_mntops, "late") &&
late == 0)
continue;
+ if (which_prog == SWAPOFF &&
+ strstr(fsp->fs_mntops, "late") == NULL &&
+ late != 0)
+ continue;
swfile = swap_on_off(fsp->fs_spec, 1,
fsp->fs_mntops);
if (swfile == NULL) {
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c
index 20b7804..e6ece31 100644
--- a/sbin/umount/umount.c
+++ b/sbin/umount/umount.c
@@ -49,6 +49,7 @@ static const char rcsid[] =
#include <netdb.h>
#include <rpc/rpc.h>
#include <rpcsvc/mount.h>
+#include <nfs/nfssvc.h>
#include <ctype.h>
#include <err.h>
@@ -323,6 +324,9 @@ umountfs(struct statfs *sfs)
CLIENT *clp;
char *nfsdirname, *orignfsdirname;
char *hostp, *delimp;
+ char buf[1024];
+ struct nfscl_dumpmntopts dumpmntopts;
+ const char *proto_ptr = NULL;
ai = NULL;
do_rpc = 0;
@@ -361,8 +365,24 @@ umountfs(struct statfs *sfs)
* mount from mntfromname that is still mounted.
*/
if (getmntentry(sfs->f_mntfromname, NULL, NULL,
- CHECKUNIQUE) != NULL)
+ CHECKUNIQUE) != NULL) {
do_rpc = 1;
+ proto_ptr = "udp";
+ /*
+ * Try and find out whether this NFS mount is NFSv4 and
+ * what protocol is being used. If this fails, the
+ * default is NFSv2,3 and use UDP for the Unmount RPC.
+ */
+ dumpmntopts.ndmnt_fname = sfs->f_mntonname;
+ dumpmntopts.ndmnt_buf = buf;
+ dumpmntopts.ndmnt_blen = sizeof(buf);
+ if (nfssvc(NFSSVC_DUMPMNTOPTS, &dumpmntopts) >= 0) {
+ if (strstr(buf, "nfsv4,") != NULL)
+ do_rpc = 0;
+ else if (strstr(buf, ",tcp,") != NULL)
+ proto_ptr = "tcp";
+ }
+ }
}
if (!namematch(ai)) {
@@ -400,7 +420,7 @@ umountfs(struct statfs *sfs)
* has been unmounted.
*/
if (ai != NULL && !(fflag & MNT_FORCE) && do_rpc) {
- clp = clnt_create(hostp, MOUNTPROG, MOUNTVERS3, "udp");
+ clp = clnt_create(hostp, MOUNTPROG, MOUNTVERS3, proto_ptr);
if (clp == NULL) {
warnx("%s: %s", hostp,
clnt_spcreateerror("MOUNTPROG"));
diff --git a/sbin/zfsbootcfg/Makefile b/sbin/zfsbootcfg/Makefile
new file mode 100644
index 0000000..d485d8d
--- /dev/null
+++ b/sbin/zfsbootcfg/Makefile
@@ -0,0 +1,27 @@
+# @(#)Makefile 8.4 (Berkeley) 6/22/95
+# $FreeBSD$
+
+PROG= zfsbootcfg
+WARNS?= 1
+MAN= zfsbootcfg.8
+
+LIBADD+=zfs
+LIBADD+=nvpair
+LIBADD+=umem
+LIBADD+=uutil
+LIBADD+=geom
+
+CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include
+CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/lib/libumem
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs_core/common
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzpool/common
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libnvpair
+CFLAGS+= -I${SRCTOP}/sys/cddl/compat/opensolaris
+CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
+CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/head
+
+CFLAGS+= -DNEED_SOLARIS_BOOLEAN
+
+.include <bsd.prog.mk>
diff --git a/sbin/zfsbootcfg/zfsbootcfg.8 b/sbin/zfsbootcfg/zfsbootcfg.8
new file mode 100644
index 0000000..aa6201d
--- /dev/null
+++ b/sbin/zfsbootcfg/zfsbootcfg.8
@@ -0,0 +1,112 @@
+.\" Copyright (c) 2016 Andriy Gapon
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 12, 2016
+.Dt ZFSBOOTCFG 8
+.Os
+.Sh NAME
+.Nm zfsbootcfg
+.Nd "specify zfsboot options for the next boot"
+.Sh SYNOPSIS
+.Nm
+.Ao Ar options Ac
+.Sh DESCRIPTION
+.Nm
+is used to set
+.Xr boot.config 5 Ns -style
+options to be used by
+.Xr zfsboot 8
+or
+.Xr gptzfsboot 8
+the next time the machine is booted.
+Once
+.Xr zfsboot 8
+or
+.Xr gptzfsboot 8
+reads the information, it is deleted.
+If booting fails, the machine automatically reverts to the previous
+boot configuration.
+The information is stored in a special reserved area of a ZFS pool.
+.Xr zfsboot 8
+or
+.Xr gptzfsboot 8
+read the boot option information from the first disk found in the first
+ZFS pool found.
+.Sh ENVIRONMENT
+.Bl -tag -width vfs.zfs.boot.primary_pool -compact
+.It Ev vfs.zfs.boot.primary_pool
+The
+.Xr kenv 1
+variable that identifies a pool for which the options are written.
+.It Ev vfs.zfs.boot.primary_vdev
+The
+.Xr kenv 1
+variable that identifies a disk within the pool where the options
+are written.
+.El
+.Sh EXAMPLES
+Try to boot to a new
+.Em boot environment
+without changing the
+.Cm bootfs
+property of a pool:
+.Pp
+.Dl "zfsbootcfg ""zfs:tank/ROOT/newbe:""
+.Pp
+To clear the boot options:
+.Pp
+.Dl "zfsbootcfg """"
+.Sh SEE ALSO
+.Xr boot.config 5 ,
+.Xr gptzfsboot 8 ,
+.Xr zfsboot 8
+.Sh HISTORY
+.Nm
+appeared in
+.Fx 12.0 .
+.Sh AUTHORS
+This manual page was written by
+.An Andriy Gapon Aq Mt avg@FreeBSD.org .
+.Sh CAVEATS
+At the moment,
+.Nm
+uses the
+.Ev vfs.zfs.boot.primary_pool
+and
+.Ev vfs.zfs.boot.primary_vdev
+.Xr kenv 1
+variables to determine a ZFS pool and a disk in it where the options
+are to be stored.
+The variables are set by the ZFS boot chain, so there is an assumption
+that the same boot disk is going to be used for the next reboot.
+There is no
+.Nm
+option to specify a different pool or a different disk.
+.Pp
+.Nm
+should be extended to install new
+.Xr zfsboot 8
+blocks in a ZFS pool.
diff --git a/sbin/zfsbootcfg/zfsbootcfg.c b/sbin/zfsbootcfg/zfsbootcfg.c
new file mode 100644
index 0000000..096f1a4
--- /dev/null
+++ b/sbin/zfsbootcfg/zfsbootcfg.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2016 Andriy Gapon <avg@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <kenv.h>
+
+#include <libzfs.h>
+
+/* Keep in sync with zfsboot.c. */
+#define MAX_COMMAND_LEN 512
+
+int main(int argc, const char * const *argv)
+{
+ char buf[32];
+ libzfs_handle_t *hdl;
+ uint64_t pool_guid;
+ uint64_t vdev_guid;
+ int zfs_fd;
+ int len;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: zfsbootcfg <boot.config(5) options>\n");
+ return (1);
+ }
+
+ len = strlen(argv[1]);
+ if (len >= MAX_COMMAND_LEN) {
+ fprintf(stderr, "options string is too long\n");
+ return (1);
+ }
+
+ if (kenv(KENV_GET, "vfs.zfs.boot.primary_pool", buf, sizeof(buf)) <= 0) {
+ perror("can't get vfs.zfs.boot.primary_pool");
+ return (1);
+ }
+ pool_guid = strtoumax(buf, NULL, 10);
+ if (pool_guid == 0) {
+ perror("can't parse vfs.zfs.boot.primary_pool");
+ return (1);
+ }
+
+ if (kenv(KENV_GET, "vfs.zfs.boot.primary_vdev", buf, sizeof(buf)) <= 0) {
+ perror("can't get vfs.zfs.boot.primary_vdev");
+ return (1);
+ }
+ vdev_guid = strtoumax(buf, NULL, 10);
+ if (vdev_guid == 0) {
+ perror("can't parse vfs.zfs.boot.primary_vdev");
+ return (1);
+ }
+
+ if ((hdl = libzfs_init()) == NULL) {
+ (void) fprintf(stderr, "internal error: failed to "
+ "initialize ZFS library\n");
+ return (1);
+ }
+
+ if (zpool_nextboot(hdl, pool_guid, vdev_guid, argv[1]) != 0) {
+ perror("ZFS_IOC_NEXTBOOT failed");
+ libzfs_fini(hdl);
+ return (1);
+ }
+
+ libzfs_fini(hdl);
+ printf("zfs next boot options are successfully written\n");
+ return (0);
+}
OpenPOWER on IntegriCloud