summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorPaul Dagnelie <pcd@delphix.com>2020-08-07 19:50:55 +0300
committerToomas Soome <tsoome@me.com>2020-11-13 19:03:14 +0200
commitc4ecba8aa5f13f00c2439c06af2aa1198771ee66 (patch)
treeb744c31c8360cd150451bce1ca2f34f291ab1f43 /usr/src
parent1a2acdcd3ce765904dbf2bfc511e92d68022d100 (diff)
downloadillumos-gate-c4ecba8aa5f13f00c2439c06af2aa1198771ee66.tar.gz
13025 Port OpenZFS: Add support for boot environment data to be stored in the label
Reviewed-by: Pavel Zakharov <pavel.zakharov@delphix.com> Reviewed-by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Toomas Soome <tsoome@me.com> Reviewed by: C Fraire <cfraire@me.com> Reviewed by: Andy Fiddaman <andy@omniosce.org> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/zinject/translate.c4
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h2
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c40
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers2
-rw-r--r--usr/src/lib/libzfs_core/common/libzfs_core.c24
-rw-r--r--usr/src/lib/libzfs_core/common/libzfs_core.h4
-rw-r--r--usr/src/lib/libzfs_core/common/mapfile-vers7
-rw-r--r--usr/src/test/zfs-tests/cmd/libzfs_input_check/libzfs_input_check.c221
-rw-r--r--usr/src/uts/common/fs/zfs/sys/vdev.h4
-rw-r--r--usr/src/uts/common/fs/zfs/sys/vdev_impl.h27
-rw-r--r--usr/src/uts/common/fs/zfs/vdev.c2
-rw-r--r--usr/src/uts/common/fs/zfs/vdev_label.c156
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c62
-rw-r--r--usr/src/uts/common/sys/fs/zfs.h22
14 files changed, 467 insertions, 110 deletions
diff --git a/usr/src/cmd/zinject/translate.c b/usr/src/cmd/zinject/translate.c
index 546009ab88..32cff30e16 100644
--- a/usr/src/cmd/zinject/translate.c
+++ b/usr/src/cmd/zinject/translate.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2020 by Delphix. All rights reserved.
*/
#include <libzfs.h>
@@ -407,7 +407,7 @@ translate_device(const char *pool, const char *device, err_type_t label_type,
record->zi_end = record->zi_start + VDEV_PAD_SIZE - 1;
break;
case TYPE_LABEL_PAD2:
- record->zi_start = offsetof(vdev_label_t, vl_pad2);
+ record->zi_start = offsetof(vdev_label_t, vl_be);
record->zi_end = record->zi_start + VDEV_PAD_SIZE - 1;
break;
}
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index edfe2454e5..c798bd15ca 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -821,6 +821,8 @@ extern int zpool_in_use(libzfs_handle_t *, int, pool_state_t *, char **,
* Label manipulation.
*/
extern int zpool_clear_label(int);
+extern int zpool_set_bootenv(zpool_handle_t *, const char *);
+extern int zpool_get_bootenv(zpool_handle_t *, char *, size_t, off_t);
/* is this zvol valid for use as a dump device? */
extern int zvol_check_dump_config(char *);
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index d2b4b54294..c751b95484 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
* Copyright 2019 Joyent, Inc.
* Copyright 2016 Nexenta Systems, Inc.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
@@ -396,7 +396,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
* Assuming bootfs is a valid dataset name.
*/
static boolean_t
-bootfs_name_valid(const char *pool, char *bootfs)
+bootfs_name_valid(const char *pool, const char *bootfs)
{
int len = strlen(pool);
if (bootfs[0] == '\0')
@@ -4410,6 +4410,42 @@ zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
free(mntpnt);
}
+int
+zpool_set_bootenv(zpool_handle_t *zhp, const char *envmap)
+{
+ int error = lzc_set_bootenv(zhp->zpool_name, envmap);
+ if (error != 0) {
+ (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
+ dgettext(TEXT_DOMAIN,
+ "error setting bootenv in pool '%s'"), zhp->zpool_name);
+ }
+
+ return (error);
+}
+
+int
+zpool_get_bootenv(zpool_handle_t *zhp, char *outbuf, size_t size, off_t offset)
+{
+ nvlist_t *nvl;
+ int error = lzc_get_bootenv(zhp->zpool_name, &nvl);
+ if (error != 0) {
+ (void) zpool_standard_error_fmt(zhp->zpool_hdl, error,
+ dgettext(TEXT_DOMAIN,
+ "error getting bootenv in pool '%s'"), zhp->zpool_name);
+ return (-1);
+ }
+ char *envmap = fnvlist_lookup_string(nvl, "envmap");
+ if (offset >= strlen(envmap)) {
+ fnvlist_free(nvl);
+ return (0);
+ }
+
+ strlcpy(outbuf, envmap + offset, size);
+ int bytes = MIN(strlen(envmap + offset), size);
+ fnvlist_free(nvl);
+ return (bytes);
+}
+
/*
* Read the EFI label from the config, if a label does not exist then
* pass back the error to the caller. If the caller has passed a non-NULL
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index 49fc94a536..0083c052df 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -202,6 +202,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zpool_find_vdev;
zpool_find_vdev_by_physpath;
zpool_fru_set;
+ zpool_get_bootenv;
zpool_get_config;
zpool_get_errlog;
zpool_get_features;
@@ -241,6 +242,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zpool_reguid;
zpool_reopen;
zpool_scan;
+ zpool_set_bootenv;
zpool_set_prop;
zpool_skip_pool;
zpool_state_to_name;
diff --git a/usr/src/lib/libzfs_core/common/libzfs_core.c b/usr/src/lib/libzfs_core/common/libzfs_core.c
index 82d992f469..8b094fbd6a 100644
--- a/usr/src/lib/libzfs_core/common/libzfs_core.c
+++ b/usr/src/lib/libzfs_core/common/libzfs_core.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2020 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 RackTop Systems.
@@ -1354,3 +1354,25 @@ lzc_change_key(const char *fsname, uint64_t crypt_cmd, nvlist_t *props,
nvlist_free(ioc_args);
return (error);
}
+
+/*
+ * Set the bootenv contents for the given pool.
+ */
+int
+lzc_set_bootenv(const char *pool, const char *env)
+{
+ nvlist_t *args = fnvlist_alloc();
+ fnvlist_add_string(args, "envmap", env);
+ int error = lzc_ioctl(ZFS_IOC_SET_BOOTENV, pool, args, NULL);
+ fnvlist_free(args);
+ return (error);
+}
+
+/*
+ * Get the contents of the bootenv of the given pool.
+ */
+int
+lzc_get_bootenv(const char *pool, nvlist_t **outnvl)
+{
+ return (lzc_ioctl(ZFS_IOC_GET_BOOTENV, pool, NULL, outnvl));
+}
diff --git a/usr/src/lib/libzfs_core/common/libzfs_core.h b/usr/src/lib/libzfs_core/common/libzfs_core.h
index 9b7721e7eb..f5a04b0762 100644
--- a/usr/src/lib/libzfs_core/common/libzfs_core.h
+++ b/usr/src/lib/libzfs_core/common/libzfs_core.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2020 by Delphix. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 RackTop Systems.
* Copyright (c) 2017 Datto Inc.
@@ -118,6 +118,8 @@ int lzc_channel_program_nosync(const char *, const char *, uint64_t,
int lzc_pool_checkpoint(const char *);
int lzc_pool_checkpoint_discard(const char *);
+int lzc_set_bootenv(const char *, const char *);
+int lzc_get_bootenv(const char *, nvlist_t **);
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libzfs_core/common/mapfile-vers b/usr/src/lib/libzfs_core/common/mapfile-vers
index 98516b66cc..bc4bc3631d 100644
--- a/usr/src/lib/libzfs_core/common/mapfile-vers
+++ b/usr/src/lib/libzfs_core/common/mapfile-vers
@@ -38,6 +38,13 @@
$mapfile_version 2
+SYMBOL_VERSION ILLUMOS_0.8 {
+ global:
+
+ lzc_get_bootenv;
+ lzc_set_bootenv;
+} ILLUMOS_0.7;
+
SYMBOL_VERSION ILLUMOS_0.7 {
global:
diff --git a/usr/src/test/zfs-tests/cmd/libzfs_input_check/libzfs_input_check.c b/usr/src/test/zfs-tests/cmd/libzfs_input_check/libzfs_input_check.c
index b469a96982..c65c6f2938 100644
--- a/usr/src/test/zfs-tests/cmd/libzfs_input_check/libzfs_input_check.c
+++ b/usr/src/test/zfs-tests/cmd/libzfs_input_check/libzfs_input_check.c
@@ -108,6 +108,9 @@ static unsigned ioc_skip[] = {
ZFS_IOC_EVENTS_NEXT,
ZFS_IOC_EVENTS_CLEAR,
ZFS_IOC_EVENTS_SEEK,
+ ZFS_IOC_NEXTBOOT,
+ ZFS_IOC_JAIL,
+ ZFS_IOC_UNJAIL,
#else
/* This is still a legacy ioctl in illumos */
ZFS_IOC_POOL_REOPEN,
@@ -706,6 +709,24 @@ zfs_destroy(const char *dataset)
}
static void
+test_get_bootenv(const char *pool)
+{
+ IOC_INPUT_TEST(ZFS_IOC_GET_BOOTENV, pool, NULL, NULL, 0);
+}
+
+static void
+test_set_bootenv(const char *pool)
+{
+ nvlist_t *required = fnvlist_alloc();
+
+ fnvlist_add_string(required, "envmap", "test");
+
+ IOC_INPUT_TEST(ZFS_IOC_SET_BOOTENV, pool, required, NULL, 0);
+
+ nvlist_free(required);
+}
+
+static void
zfs_ioc_input_tests(const char *pool)
{
char filepath[] = "/tmp/ioc_test_file_XXXXXX";
@@ -789,6 +810,9 @@ zfs_ioc_input_tests(const char *pool)
test_vdev_initialize(pool);
test_vdev_trim(pool);
+ test_set_bootenv(pool);
+ test_get_bootenv(pool);
+
/*
* cleanup
*/
@@ -834,9 +858,12 @@ zfs_ioc_input_tests(const char *pool)
}
enum zfs_ioc_ref {
+#ifdef __FreeBSD__
+ ZFS_IOC_BASE = 0,
+#else
ZFS_IOC_BASE = ('Z' << 8),
- LINUX_IOC_BASE = ('Z' << 8) + 0x80,
- FREEBSD_IOC_BASE = ('Z' << 8) + 0xC0,
+#endif
+ ZFS_IOC_PLATFORM_BASE = ZFS_IOC_BASE + 0x80,
};
/*
@@ -846,100 +873,114 @@ enum zfs_ioc_ref {
boolean_t
validate_ioc_values(void)
{
- return (
- ZFS_IOC_BASE + 0 == ZFS_IOC_POOL_CREATE &&
- ZFS_IOC_BASE + 1 == ZFS_IOC_POOL_DESTROY &&
- ZFS_IOC_BASE + 2 == ZFS_IOC_POOL_IMPORT &&
- ZFS_IOC_BASE + 3 == ZFS_IOC_POOL_EXPORT &&
- ZFS_IOC_BASE + 4 == ZFS_IOC_POOL_CONFIGS &&
- ZFS_IOC_BASE + 5 == ZFS_IOC_POOL_STATS &&
- ZFS_IOC_BASE + 6 == ZFS_IOC_POOL_TRYIMPORT &&
- ZFS_IOC_BASE + 7 == ZFS_IOC_POOL_SCAN &&
- ZFS_IOC_BASE + 8 == ZFS_IOC_POOL_FREEZE &&
- ZFS_IOC_BASE + 9 == ZFS_IOC_POOL_UPGRADE &&
- ZFS_IOC_BASE + 10 == ZFS_IOC_POOL_GET_HISTORY &&
- ZFS_IOC_BASE + 11 == ZFS_IOC_VDEV_ADD &&
- ZFS_IOC_BASE + 12 == ZFS_IOC_VDEV_REMOVE &&
- ZFS_IOC_BASE + 13 == ZFS_IOC_VDEV_SET_STATE &&
- ZFS_IOC_BASE + 14 == ZFS_IOC_VDEV_ATTACH &&
- ZFS_IOC_BASE + 15 == ZFS_IOC_VDEV_DETACH &&
- ZFS_IOC_BASE + 16 == ZFS_IOC_VDEV_SETPATH &&
- ZFS_IOC_BASE + 17 == ZFS_IOC_VDEV_SETFRU &&
- ZFS_IOC_BASE + 18 == ZFS_IOC_OBJSET_STATS &&
- ZFS_IOC_BASE + 19 == ZFS_IOC_OBJSET_ZPLPROPS &&
- ZFS_IOC_BASE + 20 == ZFS_IOC_DATASET_LIST_NEXT &&
- ZFS_IOC_BASE + 21 == ZFS_IOC_SNAPSHOT_LIST_NEXT &&
- ZFS_IOC_BASE + 22 == ZFS_IOC_SET_PROP &&
- ZFS_IOC_BASE + 23 == ZFS_IOC_CREATE &&
- ZFS_IOC_BASE + 24 == ZFS_IOC_DESTROY &&
- ZFS_IOC_BASE + 25 == ZFS_IOC_ROLLBACK &&
- ZFS_IOC_BASE + 26 == ZFS_IOC_RENAME &&
- ZFS_IOC_BASE + 27 == ZFS_IOC_RECV &&
- ZFS_IOC_BASE + 28 == ZFS_IOC_SEND &&
- ZFS_IOC_BASE + 29 == ZFS_IOC_INJECT_FAULT &&
- ZFS_IOC_BASE + 30 == ZFS_IOC_CLEAR_FAULT &&
- ZFS_IOC_BASE + 31 == ZFS_IOC_INJECT_LIST_NEXT &&
- ZFS_IOC_BASE + 32 == ZFS_IOC_ERROR_LOG &&
- ZFS_IOC_BASE + 33 == ZFS_IOC_CLEAR &&
- ZFS_IOC_BASE + 34 == ZFS_IOC_PROMOTE &&
- ZFS_IOC_BASE + 35 == ZFS_IOC_SNAPSHOT &&
- ZFS_IOC_BASE + 36 == ZFS_IOC_DSOBJ_TO_DSNAME &&
- ZFS_IOC_BASE + 37 == ZFS_IOC_OBJ_TO_PATH &&
- ZFS_IOC_BASE + 38 == ZFS_IOC_POOL_SET_PROPS &&
- ZFS_IOC_BASE + 39 == ZFS_IOC_POOL_GET_PROPS &&
- ZFS_IOC_BASE + 40 == ZFS_IOC_SET_FSACL &&
- ZFS_IOC_BASE + 41 == ZFS_IOC_GET_FSACL &&
- ZFS_IOC_BASE + 42 == ZFS_IOC_SHARE &&
- ZFS_IOC_BASE + 43 == ZFS_IOC_INHERIT_PROP &&
- ZFS_IOC_BASE + 44 == ZFS_IOC_SMB_ACL &&
- ZFS_IOC_BASE + 45 == ZFS_IOC_USERSPACE_ONE &&
- ZFS_IOC_BASE + 46 == ZFS_IOC_USERSPACE_MANY &&
- ZFS_IOC_BASE + 47 == ZFS_IOC_USERSPACE_UPGRADE &&
- ZFS_IOC_BASE + 48 == ZFS_IOC_HOLD &&
- ZFS_IOC_BASE + 49 == ZFS_IOC_RELEASE &&
- ZFS_IOC_BASE + 50 == ZFS_IOC_GET_HOLDS &&
- ZFS_IOC_BASE + 51 == ZFS_IOC_OBJSET_RECVD_PROPS &&
- ZFS_IOC_BASE + 52 == ZFS_IOC_VDEV_SPLIT &&
- ZFS_IOC_BASE + 53 == ZFS_IOC_NEXT_OBJ &&
- ZFS_IOC_BASE + 54 == ZFS_IOC_DIFF &&
- ZFS_IOC_BASE + 55 == ZFS_IOC_TMP_SNAPSHOT &&
- ZFS_IOC_BASE + 56 == ZFS_IOC_OBJ_TO_STATS &&
- ZFS_IOC_BASE + 57 == ZFS_IOC_SPACE_WRITTEN &&
- ZFS_IOC_BASE + 58 == ZFS_IOC_SPACE_SNAPS &&
- ZFS_IOC_BASE + 59 == ZFS_IOC_DESTROY_SNAPS &&
- ZFS_IOC_BASE + 60 == ZFS_IOC_POOL_REGUID &&
- ZFS_IOC_BASE + 61 == ZFS_IOC_POOL_REOPEN &&
- ZFS_IOC_BASE + 62 == ZFS_IOC_SEND_PROGRESS &&
- ZFS_IOC_BASE + 63 == ZFS_IOC_LOG_HISTORY &&
- ZFS_IOC_BASE + 64 == ZFS_IOC_SEND_NEW &&
- ZFS_IOC_BASE + 65 == ZFS_IOC_SEND_SPACE &&
- ZFS_IOC_BASE + 66 == ZFS_IOC_CLONE &&
- ZFS_IOC_BASE + 67 == ZFS_IOC_BOOKMARK &&
- ZFS_IOC_BASE + 68 == ZFS_IOC_GET_BOOKMARKS &&
- ZFS_IOC_BASE + 69 == ZFS_IOC_DESTROY_BOOKMARKS &&
+ boolean_t result = B_TRUE;
+
+#define CHECK(expr) do { \
+ if (!(expr)) { \
+ result = B_FALSE; \
+ fprintf(stderr, "(%s) === FALSE\n", #expr); \
+ } \
+} while (0)
+
+ CHECK(ZFS_IOC_BASE + 0 == ZFS_IOC_POOL_CREATE);
+ CHECK(ZFS_IOC_BASE + 1 == ZFS_IOC_POOL_DESTROY);
+ CHECK(ZFS_IOC_BASE + 2 == ZFS_IOC_POOL_IMPORT);
+ CHECK(ZFS_IOC_BASE + 3 == ZFS_IOC_POOL_EXPORT);
+ CHECK(ZFS_IOC_BASE + 4 == ZFS_IOC_POOL_CONFIGS);
+ CHECK(ZFS_IOC_BASE + 5 == ZFS_IOC_POOL_STATS);
+ CHECK(ZFS_IOC_BASE + 6 == ZFS_IOC_POOL_TRYIMPORT);
+ CHECK(ZFS_IOC_BASE + 7 == ZFS_IOC_POOL_SCAN);
+ CHECK(ZFS_IOC_BASE + 8 == ZFS_IOC_POOL_FREEZE);
+ CHECK(ZFS_IOC_BASE + 9 == ZFS_IOC_POOL_UPGRADE);
+ CHECK(ZFS_IOC_BASE + 10 == ZFS_IOC_POOL_GET_HISTORY);
+ CHECK(ZFS_IOC_BASE + 11 == ZFS_IOC_VDEV_ADD);
+ CHECK(ZFS_IOC_BASE + 12 == ZFS_IOC_VDEV_REMOVE);
+ CHECK(ZFS_IOC_BASE + 13 == ZFS_IOC_VDEV_SET_STATE);
+ CHECK(ZFS_IOC_BASE + 14 == ZFS_IOC_VDEV_ATTACH);
+ CHECK(ZFS_IOC_BASE + 15 == ZFS_IOC_VDEV_DETACH);
+ CHECK(ZFS_IOC_BASE + 16 == ZFS_IOC_VDEV_SETPATH);
+ CHECK(ZFS_IOC_BASE + 17 == ZFS_IOC_VDEV_SETFRU);
+ CHECK(ZFS_IOC_BASE + 18 == ZFS_IOC_OBJSET_STATS);
+ CHECK(ZFS_IOC_BASE + 19 == ZFS_IOC_OBJSET_ZPLPROPS);
+ CHECK(ZFS_IOC_BASE + 20 == ZFS_IOC_DATASET_LIST_NEXT);
+ CHECK(ZFS_IOC_BASE + 21 == ZFS_IOC_SNAPSHOT_LIST_NEXT);
+ CHECK(ZFS_IOC_BASE + 22 == ZFS_IOC_SET_PROP);
+ CHECK(ZFS_IOC_BASE + 23 == ZFS_IOC_CREATE);
+ CHECK(ZFS_IOC_BASE + 24 == ZFS_IOC_DESTROY);
+ CHECK(ZFS_IOC_BASE + 25 == ZFS_IOC_ROLLBACK);
+ CHECK(ZFS_IOC_BASE + 26 == ZFS_IOC_RENAME);
+ CHECK(ZFS_IOC_BASE + 27 == ZFS_IOC_RECV);
+ CHECK(ZFS_IOC_BASE + 28 == ZFS_IOC_SEND);
+ CHECK(ZFS_IOC_BASE + 29 == ZFS_IOC_INJECT_FAULT);
+ CHECK(ZFS_IOC_BASE + 30 == ZFS_IOC_CLEAR_FAULT);
+ CHECK(ZFS_IOC_BASE + 31 == ZFS_IOC_INJECT_LIST_NEXT);
+ CHECK(ZFS_IOC_BASE + 32 == ZFS_IOC_ERROR_LOG);
+ CHECK(ZFS_IOC_BASE + 33 == ZFS_IOC_CLEAR);
+ CHECK(ZFS_IOC_BASE + 34 == ZFS_IOC_PROMOTE);
+ CHECK(ZFS_IOC_BASE + 35 == ZFS_IOC_SNAPSHOT);
+ CHECK(ZFS_IOC_BASE + 36 == ZFS_IOC_DSOBJ_TO_DSNAME);
+ CHECK(ZFS_IOC_BASE + 37 == ZFS_IOC_OBJ_TO_PATH);
+ CHECK(ZFS_IOC_BASE + 38 == ZFS_IOC_POOL_SET_PROPS);
+ CHECK(ZFS_IOC_BASE + 39 == ZFS_IOC_POOL_GET_PROPS);
+ CHECK(ZFS_IOC_BASE + 40 == ZFS_IOC_SET_FSACL);
+ CHECK(ZFS_IOC_BASE + 41 == ZFS_IOC_GET_FSACL);
+ CHECK(ZFS_IOC_BASE + 42 == ZFS_IOC_SHARE);
+ CHECK(ZFS_IOC_BASE + 43 == ZFS_IOC_INHERIT_PROP);
+ CHECK(ZFS_IOC_BASE + 44 == ZFS_IOC_SMB_ACL);
+ CHECK(ZFS_IOC_BASE + 45 == ZFS_IOC_USERSPACE_ONE);
+ CHECK(ZFS_IOC_BASE + 46 == ZFS_IOC_USERSPACE_MANY);
+ CHECK(ZFS_IOC_BASE + 47 == ZFS_IOC_USERSPACE_UPGRADE);
+ CHECK(ZFS_IOC_BASE + 48 == ZFS_IOC_HOLD);
+ CHECK(ZFS_IOC_BASE + 49 == ZFS_IOC_RELEASE);
+ CHECK(ZFS_IOC_BASE + 50 == ZFS_IOC_GET_HOLDS);
+ CHECK(ZFS_IOC_BASE + 51 == ZFS_IOC_OBJSET_RECVD_PROPS);
+ CHECK(ZFS_IOC_BASE + 52 == ZFS_IOC_VDEV_SPLIT);
+ CHECK(ZFS_IOC_BASE + 53 == ZFS_IOC_NEXT_OBJ);
+ CHECK(ZFS_IOC_BASE + 54 == ZFS_IOC_DIFF);
+ CHECK(ZFS_IOC_BASE + 55 == ZFS_IOC_TMP_SNAPSHOT);
+ CHECK(ZFS_IOC_BASE + 56 == ZFS_IOC_OBJ_TO_STATS);
+ CHECK(ZFS_IOC_BASE + 57 == ZFS_IOC_SPACE_WRITTEN);
+ CHECK(ZFS_IOC_BASE + 58 == ZFS_IOC_SPACE_SNAPS);
+ CHECK(ZFS_IOC_BASE + 59 == ZFS_IOC_DESTROY_SNAPS);
+ CHECK(ZFS_IOC_BASE + 60 == ZFS_IOC_POOL_REGUID);
+ CHECK(ZFS_IOC_BASE + 61 == ZFS_IOC_POOL_REOPEN);
+ CHECK(ZFS_IOC_BASE + 62 == ZFS_IOC_SEND_PROGRESS);
+ CHECK(ZFS_IOC_BASE + 63 == ZFS_IOC_LOG_HISTORY);
+ CHECK(ZFS_IOC_BASE + 64 == ZFS_IOC_SEND_NEW);
+ CHECK(ZFS_IOC_BASE + 65 == ZFS_IOC_SEND_SPACE);
+ CHECK(ZFS_IOC_BASE + 66 == ZFS_IOC_CLONE);
+ CHECK(ZFS_IOC_BASE + 67 == ZFS_IOC_BOOKMARK);
+ CHECK(ZFS_IOC_BASE + 68 == ZFS_IOC_GET_BOOKMARKS);
+ CHECK(ZFS_IOC_BASE + 69 == ZFS_IOC_DESTROY_BOOKMARKS);
#ifndef __sun
- ZFS_IOC_BASE + 71 == ZFS_IOC_RECV_NEW &&
+ CHECK(ZFS_IOC_BASE + 71 == ZFS_IOC_RECV_NEW);
#endif
- ZFS_IOC_BASE + 70 == ZFS_IOC_POOL_SYNC &&
- ZFS_IOC_BASE + 71 == ZFS_IOC_CHANNEL_PROGRAM &&
- ZFS_IOC_BASE + 72 == ZFS_IOC_LOAD_KEY &&
- ZFS_IOC_BASE + 73 == ZFS_IOC_UNLOAD_KEY &&
- ZFS_IOC_BASE + 74 == ZFS_IOC_CHANGE_KEY &&
- ZFS_IOC_BASE + 75 == ZFS_IOC_REMAP &&
- ZFS_IOC_BASE + 76 == ZFS_IOC_POOL_CHECKPOINT &&
+ CHECK(ZFS_IOC_BASE + 70 == ZFS_IOC_POOL_SYNC);
+ CHECK(ZFS_IOC_BASE + 71 == ZFS_IOC_CHANNEL_PROGRAM);
+ CHECK(ZFS_IOC_BASE + 72 == ZFS_IOC_LOAD_KEY);
+ CHECK(ZFS_IOC_BASE + 73 == ZFS_IOC_UNLOAD_KEY);
+ CHECK(ZFS_IOC_BASE + 74 == ZFS_IOC_CHANGE_KEY);
+ CHECK(ZFS_IOC_BASE + 75 == ZFS_IOC_REMAP);
+ CHECK(ZFS_IOC_BASE + 76 == ZFS_IOC_POOL_CHECKPOINT);
#ifndef __sun
- ZFS_IOC_BASE + 78 == ZFS_IOC_POOL_DISCARD_CHECKPOINT &&
- LINUX_IOC_BASE + 1 == ZFS_IOC_EVENTS_NEXT &&
- LINUX_IOC_BASE + 2 == ZFS_IOC_EVENTS_CLEAR &&
- LINUX_IOC_BASE + 3 == ZFS_IOC_EVENTS_SEEK);
+ CHECK(ZFS_IOC_BASE + 78 == ZFS_IOC_POOL_DISCARD_CHECKPOINT);
+ CHECK(ZFS_IOC_PLATFORM_BASE + 1 == ZFS_IOC_EVENTS_NEXT);
+ CHECK(ZFS_IOC_PLATFORM_BASE + 2 == ZFS_IOC_EVENTS_CLEAR);
+ CHECK(ZFS_IOC_PLATFORM_BASE + 3 == ZFS_IOC_EVENTS_SEEK);
#else
- ZFS_IOC_BASE + 77 == ZFS_IOC_POOL_DISCARD_CHECKPOINT &&
- ZFS_IOC_BASE + 78 == ZFS_IOC_POOL_INITIALIZE &&
- ZFS_IOC_BASE + 79 == ZFS_IOC_POOL_TRIM &&
- ZFS_IOC_BASE + 80 == ZFS_IOC_REDACT &&
- ZFS_IOC_BASE + 81 == ZFS_IOC_GET_BOOKMARK_PROPS);
+ CHECK(ZFS_IOC_BASE + 77 == ZFS_IOC_POOL_DISCARD_CHECKPOINT);
+ CHECK(ZFS_IOC_BASE + 78 == ZFS_IOC_POOL_INITIALIZE);
+ CHECK(ZFS_IOC_BASE + 79 == ZFS_IOC_POOL_TRIM);
+ CHECK(ZFS_IOC_BASE + 80 == ZFS_IOC_REDACT);
+ CHECK(ZFS_IOC_BASE + 81 == ZFS_IOC_GET_BOOKMARK_PROPS);
#endif
+ CHECK(ZFS_IOC_PLATFORM_BASE + 7 == ZFS_IOC_SET_BOOTENV);
+ CHECK(ZFS_IOC_PLATFORM_BASE + 8 == ZFS_IOC_GET_BOOTENV);
+
+#undef CHECK
+
+ return (result);
}
int
diff --git a/usr/src/uts/common/fs/zfs/sys/vdev.h b/usr/src/uts/common/fs/zfs/sys/vdev.h
index b8c2ee5c9e..5ac2f2520d 100644
--- a/usr/src/uts/common/fs/zfs/sys/vdev.h
+++ b/usr/src/uts/common/fs/zfs/sys/vdev.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2019, Datto Inc. All rights reserved.
*/
@@ -180,6 +180,8 @@ extern void vdev_uberblock_load(vdev_t *, struct uberblock *, nvlist_t **);
extern void vdev_config_generate_stats(vdev_t *vd, nvlist_t *nv);
extern void vdev_label_write(zio_t *zio, vdev_t *vd, int l, abd_t *buf, uint64_t
offset, uint64_t size, zio_done_func_t *done, void *private, int flags);
+extern int vdev_label_read_bootenv(vdev_t *, nvlist_t *);
+extern int vdev_label_write_bootenv(vdev_t *, char *);
typedef enum {
VDEV_LABEL_CREATE, /* create/add a new device */
diff --git a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h
index 3004872de7..153bd71e5d 100644
--- a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h
+++ b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h
@@ -20,8 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
- * Copyright (c) 2011, 2019 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
* Copyright 2019 Joyent, Inc.
* Copyright 2020 Joshua M. Clulow <josh@sysmgr.org>
@@ -411,7 +410,7 @@ struct vdev {
#define VDEV_RAIDZ_MAXPARITY 3
#define VDEV_PAD_SIZE (8 << 10)
-/* 2 padding areas (vl_pad1 and vl_pad2) to skip */
+/* 2 padding areas (vl_pad1 and vl_be) to skip */
#define VDEV_SKIP_SIZE VDEV_PAD_SIZE * 2
#define VDEV_PHYS_SIZE (112 << 10)
#define VDEV_UBERBLOCK_RING (128 << 10)
@@ -438,9 +437,29 @@ typedef struct vdev_phys {
zio_eck_t vp_zbt;
} vdev_phys_t;
+typedef enum vbe_vers {
+ /* The bootenv file is stored as ascii text in the envblock */
+ VB_RAW = 0,
+
+ /*
+ * The bootenv file is converted to an nvlist and then packed into the
+ * envblock.
+ */
+ VB_NVLIST = 1
+} vbe_vers_t;
+
+typedef struct vdev_boot_envblock {
+ uint64_t vbe_version;
+ char vbe_bootenv[VDEV_PAD_SIZE - sizeof (uint64_t) -
+ sizeof (zio_eck_t)];
+ zio_eck_t vbe_zbt;
+} vdev_boot_envblock_t;
+
+CTASSERT(sizeof (vdev_boot_envblock_t) == VDEV_PAD_SIZE);
+
typedef struct vdev_label {
char vl_pad1[VDEV_PAD_SIZE]; /* 8K */
- char vl_pad2[VDEV_PAD_SIZE]; /* 8K */
+ vdev_boot_envblock_t vl_be; /* 8K */
vdev_phys_t vl_vdev_phys; /* 112K */
char vl_uberblock[VDEV_UBERBLOCK_RING]; /* 128K */
} vdev_label_t; /* 256K total */
diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c
index 37c93f60cc..99ad0cd27d 100644
--- a/usr/src/uts/common/fs/zfs/vdev.c
+++ b/usr/src/uts/common/fs/zfs/vdev.c
@@ -1469,7 +1469,7 @@ vdev_probe(vdev_t *vd, zio_t *zio)
for (int l = 1; l < VDEV_LABELS; l++) {
zio_nowait(zio_read_phys(pio, vd,
vdev_label_offset(vd->vdev_psize, l,
- offsetof(vdev_label_t, vl_pad2)), VDEV_PAD_SIZE,
+ offsetof(vdev_label_t, vl_be)), VDEV_PAD_SIZE,
abd_alloc_for_io(VDEV_PAD_SIZE, B_TRUE),
ZIO_CHECKSUM_OFF, vdev_probe_done, vps,
ZIO_PRIORITY_SYNC_READ, vps->vps_flags, B_TRUE));
diff --git a/usr/src/uts/common/fs/zfs/vdev_label.c b/usr/src/uts/common/fs/zfs/vdev_label.c
index 6235b06f17..25fe79667d 100644
--- a/usr/src/uts/common/fs/zfs/vdev_label.c
+++ b/usr/src/uts/common/fs/zfs/vdev_label.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2020 by Delphix. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
* Copyright 2020 Joyent, Inc.
*/
@@ -940,7 +940,7 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
nvlist_t *label;
vdev_phys_t *vp;
abd_t *vp_abd;
- abd_t *pad2;
+ abd_t *bootenv;
uberblock_t *ub;
abd_t *ub_abd;
zio_t *zio;
@@ -1101,8 +1101,8 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
ub->ub_txg = 0;
/* Initialize the 2nd padding area. */
- pad2 = abd_alloc_for_io(VDEV_PAD_SIZE, B_TRUE);
- abd_zero(pad2, VDEV_PAD_SIZE);
+ bootenv = abd_alloc_for_io(VDEV_PAD_SIZE, B_TRUE);
+ abd_zero(bootenv, VDEV_PAD_SIZE);
/*
* Write everything in parallel.
@@ -1121,8 +1121,8 @@ retry:
* Zero out the 2nd padding area where it might have
* left over data from previous filesystem format.
*/
- vdev_label_write(zio, vd, l, pad2,
- offsetof(vdev_label_t, vl_pad2),
+ vdev_label_write(zio, vd, l, bootenv,
+ offsetof(vdev_label_t, vl_be),
VDEV_PAD_SIZE, NULL, NULL, flags);
vdev_label_write(zio, vd, l, ub_abd,
@@ -1138,7 +1138,7 @@ retry:
}
nvlist_free(label);
- abd_free(pad2);
+ abd_free(bootenv);
abd_free(ub_abd);
abd_free(vp_abd);
@@ -1162,6 +1162,148 @@ retry:
}
/*
+ * Done callback for vdev_label_read_bootenv_impl. If this is the first
+ * callback to finish, store our abd in the callback pointer. Otherwise, we
+ * just free our abd and return.
+ */
+static void
+vdev_label_read_bootenv_done(zio_t *zio)
+{
+ zio_t *rio = zio->io_private;
+ abd_t **cbp = rio->io_private;
+
+ ASSERT3U(zio->io_size, ==, VDEV_PAD_SIZE);
+
+ if (zio->io_error == 0) {
+ mutex_enter(&rio->io_lock);
+ if (*cbp == NULL) {
+ /* Will free this buffer in vdev_label_read_bootenv. */
+ *cbp = zio->io_abd;
+ } else {
+ abd_free(zio->io_abd);
+ }
+ mutex_exit(&rio->io_lock);
+ } else {
+ abd_free(zio->io_abd);
+ }
+}
+
+static void
+vdev_label_read_bootenv_impl(zio_t *zio, vdev_t *vd, int flags)
+{
+ for (int c = 0; c < vd->vdev_children; c++)
+ vdev_label_read_bootenv_impl(zio, vd->vdev_child[c], flags);
+
+ /*
+ * We just use the first label that has a correct checksum; the
+ * bootloader should have rewritten them all to be the same on boot,
+ * and any changes we made since boot have been the same across all
+ * labels.
+ *
+ * While grub supports writing to all four labels, other bootloaders
+ * don't, so we only use the first two labels to store boot
+ * information.
+ */
+ if (vd->vdev_ops->vdev_op_leaf && vdev_readable(vd)) {
+ for (int l = 0; l < VDEV_LABELS / 2; l++) {
+ vdev_label_read(zio, vd, l,
+ abd_alloc_linear(VDEV_PAD_SIZE, B_FALSE),
+ offsetof(vdev_label_t, vl_be), VDEV_PAD_SIZE,
+ vdev_label_read_bootenv_done, zio, flags);
+ }
+ }
+}
+
+int
+vdev_label_read_bootenv(vdev_t *rvd, nvlist_t *command)
+{
+ spa_t *spa = rvd->vdev_spa;
+ abd_t *abd = NULL;
+ int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL |
+ ZIO_FLAG_SPECULATIVE | ZIO_FLAG_TRYHARD;
+
+ ASSERT(command);
+ ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL);
+
+ zio_t *zio = zio_root(spa, NULL, &abd, flags);
+ vdev_label_read_bootenv_impl(zio, rvd, flags);
+ int err = zio_wait(zio);
+
+ if (abd != NULL) {
+ vdev_boot_envblock_t *vbe = abd_to_buf(abd);
+ if (vbe->vbe_version != VB_RAW) {
+ abd_free(abd);
+ return (SET_ERROR(ENOTSUP));
+ }
+ vbe->vbe_bootenv[sizeof (vbe->vbe_bootenv) - 1] = '\0';
+ fnvlist_add_string(command, "envmap", vbe->vbe_bootenv);
+ /* abd was allocated in vdev_label_read_bootenv_impl() */
+ abd_free(abd);
+ /* If we managed to read any successfully, return success. */
+ return (0);
+ }
+ return (err);
+}
+
+int
+vdev_label_write_bootenv(vdev_t *vd, char *envmap)
+{
+ zio_t *zio;
+ spa_t *spa = vd->vdev_spa;
+ vdev_boot_envblock_t *bootenv;
+ int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL;
+ int error = ENXIO;
+
+ if (strlen(envmap) >= sizeof (bootenv->vbe_bootenv)) {
+ return (SET_ERROR(E2BIG));
+ }
+
+ ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL);
+
+ for (int c = 0; c < vd->vdev_children; c++) {
+ int child_err = vdev_label_write_bootenv(vd->vdev_child[c],
+ envmap);
+ /*
+ * As long as any of the disks managed to write all of their
+ * labels successfully, return success.
+ */
+ if (child_err == 0)
+ error = child_err;
+ }
+
+ if (!vd->vdev_ops->vdev_op_leaf || vdev_is_dead(vd) ||
+ !vdev_writeable(vd)) {
+ return (error);
+ }
+ ASSERT3U(sizeof (*bootenv), ==, VDEV_PAD_SIZE);
+ abd_t *abd = abd_alloc_for_io(VDEV_PAD_SIZE, B_TRUE);
+ abd_zero(abd, VDEV_PAD_SIZE);
+ bootenv = abd_borrow_buf_copy(abd, VDEV_PAD_SIZE);
+
+ char *buf = bootenv->vbe_bootenv;
+ (void) strlcpy(buf, envmap, sizeof (bootenv->vbe_bootenv));
+ bootenv->vbe_version = VB_RAW;
+ abd_return_buf_copy(abd, bootenv, VDEV_PAD_SIZE);
+
+retry:
+ zio = zio_root(spa, NULL, NULL, flags);
+ for (int l = 0; l < VDEV_LABELS / 2; l++) {
+ vdev_label_write(zio, vd, l, abd,
+ offsetof(vdev_label_t, vl_be),
+ VDEV_PAD_SIZE, NULL, NULL, flags);
+ }
+
+ error = zio_wait(zio);
+ if (error != 0 && !(flags & ZIO_FLAG_TRYHARD)) {
+ flags |= ZIO_FLAG_TRYHARD;
+ goto retry;
+ }
+
+ abd_free(abd);
+ return (error);
+}
+
+/*
* ==========================================================================
* uberblock load/sync
* ==========================================================================
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index 68d9f3a011..f1ea6ce778 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -3570,6 +3570,58 @@ zfs_ioc_log_history(const char *unused, nvlist_t *innvl, nvlist_t *outnvl)
}
/*
+ * This ioctl is used to set the bootenv configuration on the current
+ * pool. This configuration is stored in the second padding area of the label,
+ * and it is used by the GRUB bootloader used on Linux to store the contents
+ * of the grubenv file. The file is stored as raw ASCII, and is protected by
+ * an embedded checksum. By default, GRUB will check if the boot filesystem
+ * supports storing the environment data in a special location, and if so,
+ * will invoke filesystem specific logic to retrieve it. This can be overridden
+ * by a variable, should the user so desire.
+ */
+/* ARGSUSED */
+static const zfs_ioc_key_t zfs_keys_set_bootenv[] = {
+ {"envmap", DATA_TYPE_STRING, 0},
+};
+
+static int
+zfs_ioc_set_bootenv(const char *name, nvlist_t *innvl, nvlist_t *outnvl)
+{
+ char *envmap;
+ int error;
+ spa_t *spa;
+
+ envmap = fnvlist_lookup_string(innvl, "envmap");
+ if ((error = spa_open(name, &spa, FTAG)) != 0)
+ return (error);
+ spa_vdev_state_enter(spa, SCL_ALL);
+ error = vdev_label_write_bootenv(spa->spa_root_vdev, envmap);
+ (void) spa_vdev_state_exit(spa, NULL, 0);
+ spa_close(spa, FTAG);
+ return (error);
+}
+
+static const zfs_ioc_key_t zfs_keys_get_bootenv[] = {
+ /* no nvl keys */
+};
+
+/* ARGSUSED */
+static int
+zfs_ioc_get_bootenv(const char *name, nvlist_t *innvl, nvlist_t *outnvl)
+{
+ spa_t *spa;
+ int error;
+
+ if ((error = spa_open(name, &spa, FTAG)) != 0)
+ return (error);
+ spa_vdev_state_enter(spa, SCL_ALL);
+ error = vdev_label_read_bootenv(spa->spa_root_vdev, outnvl);
+ (void) spa_vdev_state_exit(spa, NULL, 0);
+ spa_close(spa, FTAG);
+ return (error);
+}
+
+/*
* The dp_config_rwlock must not be held when calling this, because the
* unmount may need to write out data.
*
@@ -6761,6 +6813,16 @@ zfs_ioctl_init(void)
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE,
zfs_keys_pool_trim, ARRAY_SIZE(zfs_keys_pool_trim));
+ zfs_ioctl_register("set_bootenv", ZFS_IOC_SET_BOOTENV,
+ zfs_ioc_set_bootenv, zfs_secpolicy_config, POOL_NAME,
+ POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_TRUE,
+ zfs_keys_set_bootenv, ARRAY_SIZE(zfs_keys_set_bootenv));
+
+ zfs_ioctl_register("get_bootenv", ZFS_IOC_GET_BOOTENV,
+ zfs_ioc_get_bootenv, zfs_secpolicy_none, POOL_NAME,
+ POOL_CHECK_SUSPENDED, B_FALSE, B_TRUE,
+ zfs_keys_get_bootenv, ARRAY_SIZE(zfs_keys_get_bootenv));
+
/* IOCTLS that use the legacy function signature */
zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
diff --git a/usr/src/uts/common/sys/fs/zfs.h b/usr/src/uts/common/sys/fs/zfs.h
index 819905a8d9..ede7640eb3 100644
--- a/usr/src/uts/common/sys/fs/zfs.h
+++ b/usr/src/uts/common/sys/fs/zfs.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2020 Joyent, Inc.
@@ -1173,7 +1173,14 @@ typedef struct ddt_histogram {
* /dev/zfs ioctl numbers.
*/
typedef enum zfs_ioc {
+ /*
+ * Core features - 81/128 numbers reserved.
+ */
+#ifdef __FreeBSD__
+ ZFS_IOC_FIRST = 0,
+#else
ZFS_IOC_FIRST = ('Z' << 8),
+#endif
ZFS_IOC = ZFS_IOC_FIRST,
ZFS_IOC_POOL_CREATE = ZFS_IOC_FIRST, /* 0x5a00 */
ZFS_IOC_POOL_DESTROY, /* 0x5a01 */
@@ -1257,6 +1264,19 @@ typedef enum zfs_ioc {
ZFS_IOC_POOL_TRIM, /* 0x5a50 */
ZFS_IOC_REDACT, /* 0x5a51 */
ZFS_IOC_GET_BOOKMARK_PROPS, /* 0x5a52 */
+
+ /*
+ * Per-platform (Optional) - 8/128 numbers reserved.
+ */
+ ZFS_IOC_PLATFORM = ZFS_IOC_FIRST + 0x80,
+ ZFS_IOC_EVENTS_NEXT, /* 0x81 (Linux) */
+ ZFS_IOC_EVENTS_CLEAR, /* 0x82 (Linux) */
+ ZFS_IOC_EVENTS_SEEK, /* 0x83 (Linux) */
+ ZFS_IOC_NEXTBOOT, /* 0x84 (FreeBSD) */
+ ZFS_IOC_JAIL, /* 0x85 (FreeBSD) */
+ ZFS_IOC_UNJAIL, /* 0x86 (FreeBSD) */
+ ZFS_IOC_SET_BOOTENV, /* 0x87 (Linux) */
+ ZFS_IOC_GET_BOOTENV, /* 0x88 (Linux) */
ZFS_IOC_LAST
} zfs_ioc_t;