diff options
author | Andriy Gapon <avg@FreeBSD.org> | 2016-10-29 14:09:32 +0000 |
---|---|---|
committer | Andriy Gapon <avg@FreeBSD.org> | 2016-10-29 14:09:32 +0000 |
commit | 97371ba2a9bd423f6a8742e06dc2b7c68b7cf5d2 (patch) | |
tree | a542dc12a8746152e8972c9868e11cb4a8eb88a3 /sbin | |
parent | 6eeff7a7b2f22e5363f5a3a6f595352111eba7eb (diff) | |
download | src-97371ba2a9bd423f6a8742e06dc2b7c68b7cf5d2.tar.gz src-97371ba2a9bd423f6a8742e06dc2b7c68b7cf5d2.zip |
zfsbootcfg: a simple tool to set next boot (one time) options for zfsboot
(gpt)zfsboot will read one-time boot directives from a special ZFS pool
area. The area was previously described as "Boot Block Header", but
currently it is know as Pad2, marked as reserved and is zeroed out on
pool creation. The new code interprets data in this area, if any, using
the same format as boot.config. The area is immediately wiped out.
Failure to parse the directives results in a reboot right after the
cleanup. Otherwise the boot sequence proceeds as usual.
zfsbootcfg writes zfsboot arguments specified on its command line to the
Pad2 area of a disk identified by vfs.zfs.boot.primary_pool and
vfs.zfs.boot.primary_vdev kenv variables that are set by loader during
boot. Please see the manual page for more.
Thanks to all who reviewed, contributed and made suggestions! There are
many potential improvements to the feature, please see the review for
details.
Reviewed by: wblock (docs)
Discussed with: jhb, tsoome
MFC after: 3 weeks
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D7612
Notes
Notes:
svn path=/head/; revision=308089
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/Makefile | 1 | ||||
-rw-r--r-- | sbin/zfsbootcfg/Makefile | 27 | ||||
-rw-r--r-- | sbin/zfsbootcfg/zfsbootcfg.8 | 112 | ||||
-rw-r--r-- | sbin/zfsbootcfg/zfsbootcfg.c | 98 |
4 files changed, 238 insertions, 0 deletions
diff --git a/sbin/Makefile b/sbin/Makefile index affca8e19d91..4826bc09b26d 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/zfsbootcfg/Makefile b/sbin/zfsbootcfg/Makefile new file mode 100644 index 000000000000..d485d8dad8dc --- /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 000000000000..aa6201da15fd --- /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 000000000000..096f1a4697e6 --- /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); +} |