diff --git a/include/sys/zfs_sysfs.h b/include/sys/zfs_sysfs.h index 912ef234f8..d1cb2ef432 100644 --- a/include/sys/zfs_sysfs.h +++ b/include/sys/zfs_sysfs.h @@ -25,6 +25,10 @@ #ifndef _SYS_ZFS_SYSFS_H #define _SYS_ZFS_SYSFS_H extern __attribute__((visibility("default"))) +struct zfs_mod_supported_features; +struct zfs_mod_supported_features *zfs_mod_list_supported(const char *scope); +void zfs_mod_list_supported_free(struct zfs_mod_supported_features *); + #ifdef _KERNEL void zfs_sysfs_init(void); @@ -35,7 +39,8 @@ void zfs_sysfs_fini(void); #define zfs_sysfs_init() #define zfs_sysfs_fini() -_SYS_ZFS_SYSFS_H boolean_t zfs_mod_supported(const char *, const char *); +_SYS_ZFS_SYSFS_H boolean_t zfs_mod_supported(const char *, const char *, + const struct zfs_mod_supported_features *); #endif #define ZFS_SYSFS_POOL_PROPERTIES "properties.pool" diff --git a/include/zfs_prop.h b/include/zfs_prop.h index 8014c757aa..c7363f7015 100644 --- a/include/zfs_prop.h +++ b/include/zfs_prop.h @@ -28,6 +28,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -111,15 +112,19 @@ _ZFS_PROP_H zprop_desc_t *vdev_prop_get_table(void); */ _ZFS_PROP_H void zprop_register_impl(int, const char *, zprop_type_t, uint64_t, const char *, zprop_attr_t, int, const char *, const char *, - boolean_t, boolean_t, const zprop_index_t *); + boolean_t, boolean_t, const zprop_index_t *, + const struct zfs_mod_supported_features *); _ZFS_PROP_H void zprop_register_string(int, const char *, const char *, - zprop_attr_t attr, int, const char *, const char *); + zprop_attr_t attr, int, const char *, const char *, + const struct zfs_mod_supported_features *); _ZFS_PROP_H void zprop_register_number(int, const char *, uint64_t, - zprop_attr_t, int, const char *, const char *); + zprop_attr_t, int, const char *, const char *, + const struct zfs_mod_supported_features *); _ZFS_PROP_H void zprop_register_index(int, const char *, uint64_t, zprop_attr_t, - int, const char *, const char *, const zprop_index_t *); + int, const char *, const char *, const zprop_index_t *, + const struct zfs_mod_supported_features *); _ZFS_PROP_H void zprop_register_hidden(int, const char *, zprop_type_t, - zprop_attr_t, int, const char *); + zprop_attr_t, int, const char *, const struct zfs_mod_supported_features *); /* * Common routines for zfs and zpool property management diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi index 08767c3814..ce26c5ee06 100644 --- a/lib/libzfs/libzfs.abi +++ b/lib/libzfs/libzfs.abi @@ -1947,8 +1947,18 @@ + + + + + + + + + + @@ -1978,6 +1988,7 @@ + @@ -2793,6 +2804,7 @@ + @@ -2803,6 +2815,7 @@ + @@ -2813,6 +2826,7 @@ + @@ -2824,6 +2838,7 @@ + @@ -2833,6 +2848,7 @@ + diff --git a/module/zcommon/zfeature_common.c b/module/zcommon/zfeature_common.c index 8d84c6d151..c7278fa007 100644 --- a/module/zcommon/zfeature_common.c +++ b/module/zcommon/zfeature_common.c @@ -32,6 +32,8 @@ #ifndef _KERNEL #include #include +#include +#include #include #endif #include @@ -164,30 +166,109 @@ deps_contains_feature(const spa_feature_t *deps, const spa_feature_t feature) return (B_FALSE); } +#define STRCMP ((int(*)(const void *, const void *))&strcmp) +struct zfs_mod_supported_features { + void *tree; + boolean_t all_features; +}; + +struct zfs_mod_supported_features * +zfs_mod_list_supported(const char *scope) +{ +#if defined(__FreeBSD__) || defined(_KERNEL) || defined(LIB_ZPOOL_BUILD) + (void) scope; + return (NULL); +#else + struct zfs_mod_supported_features *ret = calloc(1, sizeof (*ret)); + if (ret == NULL) + return (NULL); + + DIR *sysfs_dir = NULL; + char path[128]; + + if (snprintf(path, sizeof (path), "%s/%s", + ZFS_SYSFS_DIR, scope) < sizeof (path)) + sysfs_dir = opendir(path); + if (sysfs_dir == NULL && errno == ENOENT) { + if (snprintf(path, sizeof (path), "%s/%s", + ZFS_SYSFS_ALT_DIR, scope) < sizeof (path)) + sysfs_dir = opendir(path); + } + if (sysfs_dir == NULL) { + ret->all_features = errno == ENOENT && + (access(ZFS_SYSFS_DIR, F_OK) == 0 || + access(ZFS_SYSFS_ALT_DIR, F_OK) == 0); + return (ret); + } + + struct dirent *node; + while ((node = readdir(sysfs_dir)) != NULL) { + if (strcmp(node->d_name, ".") == 0 || + strcmp(node->d_name, "..") == 0) + continue; + + char *name = strdup(node->d_name); + if (name == NULL) { + goto nomem; + } + + if (tsearch(name, &ret->tree, STRCMP) == NULL) { + /* + * Don't bother checking for duplicate entries: + * we're iterating a single directory. + */ + free(name); + goto nomem; + } + } + +end: + closedir(sysfs_dir); + return (ret); + +nomem: + zfs_mod_list_supported_free(ret); + ret = NULL; + goto end; +#endif +} + +void +zfs_mod_list_supported_free(struct zfs_mod_supported_features *list) +{ +#if !defined(__FreeBSD__) && !defined(_KERNEL) && !defined(LIB_ZPOOL_BUILD) + if (list) { + tdestroy(list->tree, free); + free(list); + } +#else + (void) list; +#endif +} + #if !defined(_KERNEL) && !defined(LIB_ZPOOL_BUILD) static boolean_t zfs_mod_supported_impl(const char *scope, const char *name, const char *sysfs) { - boolean_t supported = B_FALSE; - char *path; - - int len = asprintf(&path, "%s%s%s%s%s", sysfs, - scope == NULL ? "" : "/", scope == NULL ? "" : scope, - name == NULL ? "" : "/", name == NULL ? "" : name); - if (len > 0) { - struct stat64 statbuf; - supported = !!(stat64(path, &statbuf) == 0); - free(path); - } - - return (supported); + char path[128]; + if (snprintf(path, sizeof (path), "%s%s%s%s%s", sysfs, + scope == NULL ? "" : "/", scope ?: "", + name == NULL ? "" : "/", name ?: "") < sizeof (path)) + return (access(path, F_OK) == 0); + else + return (B_FALSE); } boolean_t -zfs_mod_supported(const char *scope, const char *name) +zfs_mod_supported(const char *scope, const char *name, + const struct zfs_mod_supported_features *sfeatures) { boolean_t supported; + if (sfeatures != NULL) + return (sfeatures->all_features || + tfind(name, &sfeatures->tree, STRCMP)); + /* * Check both the primary and alternate sysfs locations to determine * if the required functionality is supported. @@ -202,10 +283,10 @@ zfs_mod_supported(const char *scope, const char *name) * scope directory does not exist. */ if (supported == B_FALSE) { - struct stat64 statbuf; - if ((stat64(ZFS_SYSFS_DIR, &statbuf) == 0) && - !zfs_mod_supported_impl(scope, NULL, ZFS_SYSFS_DIR) && - !zfs_mod_supported_impl(scope, NULL, ZFS_SYSFS_ALT_DIR)) { + if ((access(ZFS_SYSFS_DIR, F_OK) == 0 && + !zfs_mod_supported_impl(scope, NULL, ZFS_SYSFS_DIR)) || + (access(ZFS_SYSFS_ALT_DIR, F_OK) == 0 && + !zfs_mod_supported_impl(scope, NULL, ZFS_SYSFS_ALT_DIR))) { supported = B_TRUE; } } @@ -215,7 +296,8 @@ zfs_mod_supported(const char *scope, const char *name) #endif static boolean_t -zfs_mod_supported_feature(const char *name) +zfs_mod_supported_feature(const char *name, + const struct zfs_mod_supported_features *sfeatures) { /* * The zfs module spa_feature_table[], whether in-kernel or in @@ -229,17 +311,18 @@ zfs_mod_supported_feature(const char *name) */ #if defined(_KERNEL) || defined(LIB_ZPOOL_BUILD) || defined(__FreeBSD__) - (void) name; + (void) name, (void) sfeatures; return (B_TRUE); #else - return (zfs_mod_supported(ZFS_SYSFS_POOL_FEATURES, name)); + return (zfs_mod_supported(ZFS_SYSFS_POOL_FEATURES, name, sfeatures)); #endif } static void zfeature_register(spa_feature_t fid, const char *guid, const char *name, const char *desc, zfeature_flags_t flags, zfeature_type_t type, - const spa_feature_t *deps) + const spa_feature_t *deps, + const struct zfs_mod_supported_features *sfeatures) { zfeature_info_t *feature = &spa_feature_table[fid]; static spa_feature_t nodeps[] = { SPA_FEATURE_NONE }; @@ -264,7 +347,8 @@ zfeature_register(spa_feature_t fid, const char *guid, const char *name, feature->fi_flags = flags; feature->fi_type = type; feature->fi_depends = deps; - feature->fi_zfs_mod_supported = zfs_mod_supported_feature(guid); + feature->fi_zfs_mod_supported = + zfs_mod_supported_feature(guid, sfeatures); } /* @@ -283,318 +367,335 @@ zfeature_register(spa_feature_t fid, const char *guid, const char *name, void zpool_feature_init(void) { + struct zfs_mod_supported_features *sfeatures = + zfs_mod_list_supported(ZFS_SYSFS_POOL_FEATURES); + zfeature_register(SPA_FEATURE_ASYNC_DESTROY, "com.delphix:async_destroy", "async_destroy", "Destroy filesystems asynchronously.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); zfeature_register(SPA_FEATURE_EMPTY_BPOBJ, "com.delphix:empty_bpobj", "empty_bpobj", "Snapshots use less space.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); zfeature_register(SPA_FEATURE_LZ4_COMPRESS, "org.illumos:lz4_compress", "lz4_compress", "LZ4 compression algorithm support.", - ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); zfeature_register(SPA_FEATURE_MULTI_VDEV_CRASH_DUMP, "com.joyent:multi_vdev_crash_dump", "multi_vdev_crash_dump", "Crash dumps to multiple vdev pools.", - 0, ZFEATURE_TYPE_BOOLEAN, NULL); + 0, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures); zfeature_register(SPA_FEATURE_SPACEMAP_HISTOGRAM, "com.delphix:spacemap_histogram", "spacemap_histogram", "Spacemaps maintain space histograms.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); zfeature_register(SPA_FEATURE_ENABLED_TXG, "com.delphix:enabled_txg", "enabled_txg", "Record txg at which a feature is enabled", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); { - static const spa_feature_t hole_birth_deps[] = { - SPA_FEATURE_ENABLED_TXG, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_HOLE_BIRTH, - "com.delphix:hole_birth", "hole_birth", - "Retain hole birth txg for more precise zfs send", - ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, - ZFEATURE_TYPE_BOOLEAN, hole_birth_deps); + static const spa_feature_t hole_birth_deps[] = { + SPA_FEATURE_ENABLED_TXG, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_HOLE_BIRTH, + "com.delphix:hole_birth", "hole_birth", + "Retain hole birth txg for more precise zfs send", + ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, + ZFEATURE_TYPE_BOOLEAN, hole_birth_deps, sfeatures); } zfeature_register(SPA_FEATURE_POOL_CHECKPOINT, "com.delphix:zpool_checkpoint", "zpool_checkpoint", "Pool state can be checkpointed, allowing rewind later.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); zfeature_register(SPA_FEATURE_SPACEMAP_V2, "com.delphix:spacemap_v2", "spacemap_v2", "Space maps representing large segments are more efficient.", ZFEATURE_FLAG_READONLY_COMPAT | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, - ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures); zfeature_register(SPA_FEATURE_EXTENSIBLE_DATASET, "com.delphix:extensible_dataset", "extensible_dataset", "Enhanced dataset functionality, used by other features.", - 0, ZFEATURE_TYPE_BOOLEAN, NULL); + 0, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures); { - static const spa_feature_t bookmarks_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; + static const spa_feature_t bookmarks_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; - zfeature_register(SPA_FEATURE_BOOKMARKS, - "com.delphix:bookmarks", "bookmarks", - "\"zfs bookmark\" command", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, - bookmarks_deps); + zfeature_register(SPA_FEATURE_BOOKMARKS, + "com.delphix:bookmarks", "bookmarks", + "\"zfs bookmark\" command", + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, + bookmarks_deps, sfeatures); } { - static const spa_feature_t filesystem_limits_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_FS_SS_LIMIT, - "com.joyent:filesystem_limits", "filesystem_limits", - "Filesystem and snapshot limits.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, - filesystem_limits_deps); + static const spa_feature_t filesystem_limits_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_FS_SS_LIMIT, + "com.joyent:filesystem_limits", "filesystem_limits", + "Filesystem and snapshot limits.", + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, + filesystem_limits_deps, sfeatures); } zfeature_register(SPA_FEATURE_EMBEDDED_DATA, "com.delphix:embedded_data", "embedded_data", "Blocks which compress very well use even less space.", ZFEATURE_FLAG_MOS | ZFEATURE_FLAG_ACTIVATE_ON_ENABLE, - ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures); { - static const spa_feature_t livelist_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_LIVELIST, - "com.delphix:livelist", "livelist", - "Improved clone deletion performance.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, - livelist_deps); + static const spa_feature_t livelist_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_LIVELIST, + "com.delphix:livelist", "livelist", + "Improved clone deletion performance.", + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, + livelist_deps, sfeatures); } { - static const spa_feature_t log_spacemap_deps[] = { - SPA_FEATURE_SPACEMAP_V2, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_LOG_SPACEMAP, - "com.delphix:log_spacemap", "log_spacemap", - "Log metaslab changes on a single spacemap and " - "flush them periodically.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, - log_spacemap_deps); + static const spa_feature_t log_spacemap_deps[] = { + SPA_FEATURE_SPACEMAP_V2, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_LOG_SPACEMAP, + "com.delphix:log_spacemap", "log_spacemap", + "Log metaslab changes on a single spacemap and " + "flush them periodically.", + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, + log_spacemap_deps, sfeatures); } { - static const spa_feature_t large_blocks_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_LARGE_BLOCKS, - "org.open-zfs:large_blocks", "large_blocks", - "Support for blocks larger than 128KB.", - ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, - large_blocks_deps); + static const spa_feature_t large_blocks_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_LARGE_BLOCKS, + "org.open-zfs:large_blocks", "large_blocks", + "Support for blocks larger than 128KB.", + ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, + large_blocks_deps, sfeatures); } { - static const spa_feature_t large_dnode_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_LARGE_DNODE, - "org.zfsonlinux:large_dnode", "large_dnode", - "Variable on-disk size of dnodes.", - ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, - large_dnode_deps); + static const spa_feature_t large_dnode_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_LARGE_DNODE, + "org.zfsonlinux:large_dnode", "large_dnode", + "Variable on-disk size of dnodes.", + ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, + large_dnode_deps, sfeatures); } { - static const spa_feature_t sha512_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_SHA512, - "org.illumos:sha512", "sha512", - "SHA-512/256 hash algorithm.", - ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, - sha512_deps); + static const spa_feature_t sha512_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_SHA512, + "org.illumos:sha512", "sha512", + "SHA-512/256 hash algorithm.", + ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, + sha512_deps, sfeatures); } { - static const spa_feature_t skein_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_SKEIN, - "org.illumos:skein", "skein", - "Skein hash algorithm.", - ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, - skein_deps); + static const spa_feature_t skein_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_SKEIN, + "org.illumos:skein", "skein", + "Skein hash algorithm.", + ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, + skein_deps, sfeatures); } { - static const spa_feature_t edonr_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_EDONR, - "org.illumos:edonr", "edonr", - "Edon-R hash algorithm.", - ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, - edonr_deps); + static const spa_feature_t edonr_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_EDONR, + "org.illumos:edonr", "edonr", + "Edon-R hash algorithm.", + ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, + edonr_deps, sfeatures); } { - static const spa_feature_t redact_books_deps[] = { - SPA_FEATURE_BOOKMARK_V2, - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_BOOKMARKS, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_REDACTION_BOOKMARKS, - "com.delphix:redaction_bookmarks", "redaction_bookmarks", - "Support for bookmarks which store redaction lists for zfs " - "redacted send/recv.", 0, ZFEATURE_TYPE_BOOLEAN, - redact_books_deps); + static const spa_feature_t redact_books_deps[] = { + SPA_FEATURE_BOOKMARK_V2, + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_BOOKMARKS, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_REDACTION_BOOKMARKS, + "com.delphix:redaction_bookmarks", "redaction_bookmarks", + "Support for bookmarks which store redaction lists for zfs " + "redacted send/recv.", 0, ZFEATURE_TYPE_BOOLEAN, + redact_books_deps, sfeatures); } { - static const spa_feature_t redact_datasets_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_REDACTED_DATASETS, - "com.delphix:redacted_datasets", "redacted_datasets", "Support for " - "redacted datasets, produced by receiving a redacted zfs send " - "stream.", ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_UINT64_ARRAY, - redact_datasets_deps); + static const spa_feature_t redact_datasets_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_REDACTED_DATASETS, + "com.delphix:redacted_datasets", "redacted_datasets", + "Support for redacted datasets, produced by receiving " + "a redacted zfs send stream.", + ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_UINT64_ARRAY, + redact_datasets_deps, sfeatures); } { - static const spa_feature_t bookmark_written_deps[] = { - SPA_FEATURE_BOOKMARK_V2, - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_BOOKMARKS, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_BOOKMARK_WRITTEN, - "com.delphix:bookmark_written", "bookmark_written", - "Additional accounting, enabling the written# property" - "(space written since a bookmark), and estimates of send stream " - "sizes for incrementals from bookmarks.", - 0, ZFEATURE_TYPE_BOOLEAN, bookmark_written_deps); + static const spa_feature_t bookmark_written_deps[] = { + SPA_FEATURE_BOOKMARK_V2, + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_BOOKMARKS, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_BOOKMARK_WRITTEN, + "com.delphix:bookmark_written", "bookmark_written", + "Additional accounting, enabling the written# " + "property (space written since a bookmark), " + "and estimates of send stream sizes for incrementals from " + "bookmarks.", + 0, ZFEATURE_TYPE_BOOLEAN, bookmark_written_deps, sfeatures); } zfeature_register(SPA_FEATURE_DEVICE_REMOVAL, "com.delphix:device_removal", "device_removal", "Top-level vdevs can be removed, reducing logical pool size.", - ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures); { - static const spa_feature_t obsolete_counts_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_DEVICE_REMOVAL, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_OBSOLETE_COUNTS, - "com.delphix:obsolete_counts", "obsolete_counts", - "Reduce memory used by removed devices when their blocks are " - "freed or remapped.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, - obsolete_counts_deps); + static const spa_feature_t obsolete_counts_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_DEVICE_REMOVAL, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_OBSOLETE_COUNTS, + "com.delphix:obsolete_counts", "obsolete_counts", + "Reduce memory used by removed devices when their blocks " + "are freed or remapped.", + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, + obsolete_counts_deps, sfeatures); } { - static const spa_feature_t userobj_accounting_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_USEROBJ_ACCOUNTING, - "org.zfsonlinux:userobj_accounting", "userobj_accounting", - "User/Group object accounting.", - ZFEATURE_FLAG_READONLY_COMPAT | ZFEATURE_FLAG_PER_DATASET, - ZFEATURE_TYPE_BOOLEAN, userobj_accounting_deps); + static const spa_feature_t userobj_accounting_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_USEROBJ_ACCOUNTING, + "org.zfsonlinux:userobj_accounting", "userobj_accounting", + "User/Group object accounting.", + ZFEATURE_FLAG_READONLY_COMPAT | ZFEATURE_FLAG_PER_DATASET, + ZFEATURE_TYPE_BOOLEAN, userobj_accounting_deps, sfeatures); } { - static const spa_feature_t bookmark_v2_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_BOOKMARKS, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_BOOKMARK_V2, - "com.datto:bookmark_v2", "bookmark_v2", - "Support for larger bookmarks", - 0, ZFEATURE_TYPE_BOOLEAN, bookmark_v2_deps); + static const spa_feature_t bookmark_v2_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_BOOKMARKS, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_BOOKMARK_V2, + "com.datto:bookmark_v2", "bookmark_v2", + "Support for larger bookmarks", + 0, ZFEATURE_TYPE_BOOLEAN, bookmark_v2_deps, sfeatures); } { - static const spa_feature_t encryption_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_BOOKMARK_V2, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_ENCRYPTION, - "com.datto:encryption", "encryption", - "Support for dataset level encryption", - ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, - encryption_deps); + static const spa_feature_t encryption_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_BOOKMARK_V2, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_ENCRYPTION, + "com.datto:encryption", "encryption", + "Support for dataset level encryption", + ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, + encryption_deps, sfeatures); } { - static const spa_feature_t project_quota_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_PROJECT_QUOTA, - "org.zfsonlinux:project_quota", "project_quota", - "space/object accounting based on project ID.", - ZFEATURE_FLAG_READONLY_COMPAT | ZFEATURE_FLAG_PER_DATASET, - ZFEATURE_TYPE_BOOLEAN, project_quota_deps); + static const spa_feature_t project_quota_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_PROJECT_QUOTA, + "org.zfsonlinux:project_quota", "project_quota", + "space/object accounting based on project ID.", + ZFEATURE_FLAG_READONLY_COMPAT | ZFEATURE_FLAG_PER_DATASET, + ZFEATURE_TYPE_BOOLEAN, project_quota_deps, sfeatures); } zfeature_register(SPA_FEATURE_ALLOCATION_CLASSES, "org.zfsonlinux:allocation_classes", "allocation_classes", "Support for separate allocation classes.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); zfeature_register(SPA_FEATURE_RESILVER_DEFER, "com.datto:resilver_defer", "resilver_defer", "Support for deferring new resilvers when one is already running.", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); zfeature_register(SPA_FEATURE_DEVICE_REBUILD, "org.openzfs:device_rebuild", "device_rebuild", "Support for sequential mirror/dRAID device rebuilds", - ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); { - static const spa_feature_t zstd_deps[] = { - SPA_FEATURE_EXTENSIBLE_DATASET, - SPA_FEATURE_NONE - }; - zfeature_register(SPA_FEATURE_ZSTD_COMPRESS, - "org.freebsd:zstd_compress", "zstd_compress", - "zstd compression algorithm support.", - ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, zstd_deps); + static const spa_feature_t zstd_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_ZSTD_COMPRESS, + "org.freebsd:zstd_compress", "zstd_compress", + "zstd compression algorithm support.", + ZFEATURE_FLAG_PER_DATASET, ZFEATURE_TYPE_BOOLEAN, zstd_deps, + sfeatures); } zfeature_register(SPA_FEATURE_DRAID, "org.openzfs:draid", "draid", "Support for distributed spare RAID", - ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL); + ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures); + + zfs_mod_list_supported_free(sfeatures); } #if defined(_KERNEL) diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index 592ba8bc32..800885ee64 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -377,44 +377,47 @@ zfs_prop_init(void) { NULL } }; + struct zfs_mod_supported_features *sfeatures = + zfs_mod_list_supported(ZFS_SYSFS_DATASET_PROPERTIES); + /* inherit index properties */ zprop_register_index(ZFS_PROP_REDUNDANT_METADATA, "redundant_metadata", ZFS_REDUNDANT_METADATA_ALL, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "all | most", "REDUND_MD", - redundant_metadata_table); + redundant_metadata_table, sfeatures); zprop_register_index(ZFS_PROP_SYNC, "sync", ZFS_SYNC_STANDARD, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "standard | always | disabled", "SYNC", - sync_table); + sync_table, sfeatures); zprop_register_index(ZFS_PROP_CHECKSUM, "checksum", ZIO_CHECKSUM_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off | fletcher2 | fletcher4 | sha256 | sha512 | skein" " | edonr", - "CHECKSUM", checksum_table); + "CHECKSUM", checksum_table, sfeatures); zprop_register_index(ZFS_PROP_DEDUP, "dedup", ZIO_CHECKSUM_OFF, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off | verify | sha256[,verify] | sha512[,verify] | " "skein[,verify] | edonr,verify", - "DEDUP", dedup_table); + "DEDUP", dedup_table, sfeatures); zprop_register_index(ZFS_PROP_COMPRESSION, "compression", ZIO_COMPRESS_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off | lzjb | gzip | gzip-[1-9] | zle | lz4 | " "zstd | zstd-[1-19] | " "zstd-fast | zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]", - "COMPRESS", compress_table); + "COMPRESS", compress_table, sfeatures); zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, - "hidden | visible", "SNAPDIR", snapdir_table); + "hidden | visible", "SNAPDIR", snapdir_table, sfeatures); zprop_register_index(ZFS_PROP_SNAPDEV, "snapdev", ZFS_SNAPDEV_HIDDEN, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "hidden | visible", "SNAPDEV", snapdev_table); + "hidden | visible", "SNAPDEV", snapdev_table, sfeatures); zprop_register_index(ZFS_PROP_ACLMODE, "aclmode", ZFS_ACL_DISCARD, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, "discard | groupmask | passthrough | restricted", "ACLMODE", - acl_mode_table); + acl_mode_table, sfeatures); zprop_register_index(ZFS_PROP_ACLTYPE, "acltype", #ifdef __linux__ /* Linux doesn't natively support ZFS's NFSv4-style ACLs. */ @@ -423,270 +426,288 @@ zfs_prop_init(void) ZFS_ACLTYPE_NFSV4, #endif PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, - "off | nfsv4 | posix", "ACLTYPE", acltype_table); + "off | nfsv4 | posix", "ACLTYPE", acltype_table, sfeatures); zprop_register_index(ZFS_PROP_ACLINHERIT, "aclinherit", ZFS_ACL_RESTRICTED, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, "discard | noallow | restricted | passthrough | passthrough-x", - "ACLINHERIT", acl_inherit_table); + "ACLINHERIT", acl_inherit_table, sfeatures); zprop_register_index(ZFS_PROP_COPIES, "copies", 1, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "1 | 2 | 3", "COPIES", copies_table); + "1 | 2 | 3", "COPIES", copies_table, sfeatures); zprop_register_index(ZFS_PROP_PRIMARYCACHE, "primarycache", ZFS_CACHE_ALL, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, - "all | none | metadata", "PRIMARYCACHE", cache_table); + "all | none | metadata", "PRIMARYCACHE", cache_table, sfeatures); zprop_register_index(ZFS_PROP_SECONDARYCACHE, "secondarycache", ZFS_CACHE_ALL, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, - "all | none | metadata", "SECONDARYCACHE", cache_table); + "all | none | metadata", "SECONDARYCACHE", cache_table, sfeatures); zprop_register_index(ZFS_PROP_LOGBIAS, "logbias", ZFS_LOGBIAS_LATENCY, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "latency | throughput", "LOGBIAS", logbias_table); + "latency | throughput", "LOGBIAS", logbias_table, sfeatures); zprop_register_index(ZFS_PROP_XATTR, "xattr", ZFS_XATTR_DIR, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, - "on | off | dir | sa", "XATTR", xattr_table); + "on | off | dir | sa", "XATTR", xattr_table, sfeatures); zprop_register_index(ZFS_PROP_DNODESIZE, "dnodesize", ZFS_DNSIZE_LEGACY, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, - "legacy | auto | 1k | 2k | 4k | 8k | 16k", "DNSIZE", dnsize_table); + "legacy | auto | 1k | 2k | 4k | 8k | 16k", "DNSIZE", dnsize_table, + sfeatures); zprop_register_index(ZFS_PROP_VOLMODE, "volmode", ZFS_VOLMODE_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "default | full | geom | dev | none", "VOLMODE", volmode_table); + "default | full | geom | dev | none", "VOLMODE", volmode_table, + sfeatures); /* inherit index (boolean) properties */ zprop_register_index(ZFS_PROP_ATIME, "atime", 1, PROP_INHERIT, - ZFS_TYPE_FILESYSTEM, "on | off", "ATIME", boolean_table); + ZFS_TYPE_FILESYSTEM, "on | off", "ATIME", boolean_table, sfeatures); zprop_register_index(ZFS_PROP_RELATIME, "relatime", 0, PROP_INHERIT, - ZFS_TYPE_FILESYSTEM, "on | off", "RELATIME", boolean_table); + ZFS_TYPE_FILESYSTEM, "on | off", "RELATIME", boolean_table, + sfeatures); zprop_register_index(ZFS_PROP_DEVICES, "devices", 1, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "DEVICES", - boolean_table); + boolean_table, sfeatures); zprop_register_index(ZFS_PROP_EXEC, "exec", 1, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "EXEC", - boolean_table); + boolean_table, sfeatures); zprop_register_index(ZFS_PROP_SETUID, "setuid", 1, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "SETUID", - boolean_table); + boolean_table, sfeatures); zprop_register_index(ZFS_PROP_READONLY, "readonly", 0, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off", "RDONLY", - boolean_table); + boolean_table, sfeatures); #ifdef __FreeBSD__ zprop_register_index(ZFS_PROP_ZONED, "jailed", 0, PROP_INHERIT, - ZFS_TYPE_FILESYSTEM, "on | off", "JAILED", boolean_table); + ZFS_TYPE_FILESYSTEM, "on | off", "JAILED", boolean_table, + sfeatures); #else zprop_register_index(ZFS_PROP_ZONED, "zoned", 0, PROP_INHERIT, - ZFS_TYPE_FILESYSTEM, "on | off", "ZONED", boolean_table); + ZFS_TYPE_FILESYSTEM, "on | off", "ZONED", boolean_table, sfeatures); #endif zprop_register_index(ZFS_PROP_VSCAN, "vscan", 0, PROP_INHERIT, - ZFS_TYPE_FILESYSTEM, "on | off", "VSCAN", boolean_table); + ZFS_TYPE_FILESYSTEM, "on | off", "VSCAN", boolean_table, sfeatures); zprop_register_index(ZFS_PROP_NBMAND, "nbmand", 0, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "NBMAND", - boolean_table); + boolean_table, sfeatures); zprop_register_index(ZFS_PROP_OVERLAY, "overlay", 1, PROP_INHERIT, - ZFS_TYPE_FILESYSTEM, "on | off", "OVERLAY", boolean_table); + ZFS_TYPE_FILESYSTEM, "on | off", "OVERLAY", boolean_table, + sfeatures); /* default index properties */ zprop_register_index(ZFS_PROP_VERSION, "version", 0, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, - "1 | 2 | 3 | 4 | 5 | current", "VERSION", version_table); + "1 | 2 | 3 | 4 | 5 | current", "VERSION", version_table, sfeatures); zprop_register_index(ZFS_PROP_CANMOUNT, "canmount", ZFS_CANMOUNT_ON, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM, "on | off | noauto", - "CANMOUNT", canmount_table); + "CANMOUNT", canmount_table, sfeatures); /* readonly index properties */ zprop_register_index(ZFS_PROP_MOUNTED, "mounted", 0, PROP_READONLY, - ZFS_TYPE_FILESYSTEM, "yes | no", "MOUNTED", boolean_table); + ZFS_TYPE_FILESYSTEM, "yes | no", "MOUNTED", boolean_table, + sfeatures); zprop_register_index(ZFS_PROP_DEFER_DESTROY, "defer_destroy", 0, PROP_READONLY, ZFS_TYPE_SNAPSHOT, "yes | no", "DEFER_DESTROY", - boolean_table); + boolean_table, sfeatures); zprop_register_index(ZFS_PROP_KEYSTATUS, "keystatus", ZFS_KEYSTATUS_NONE, PROP_READONLY, ZFS_TYPE_DATASET, "none | unavailable | available", - "KEYSTATUS", keystatus_table); + "KEYSTATUS", keystatus_table, sfeatures); /* set once index properties */ zprop_register_index(ZFS_PROP_NORMALIZE, "normalization", 0, PROP_ONETIME, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "none | formC | formD | formKC | formKD", "NORMALIZATION", - normalize_table); + normalize_table, sfeatures); zprop_register_index(ZFS_PROP_CASE, "casesensitivity", ZFS_CASE_SENSITIVE, PROP_ONETIME, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, - "sensitive | insensitive | mixed", "CASE", case_table); + "sensitive | insensitive | mixed", "CASE", case_table, sfeatures); zprop_register_index(ZFS_PROP_KEYFORMAT, "keyformat", ZFS_KEYFORMAT_NONE, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "none | raw | hex | passphrase", "KEYFORMAT", keyformat_table); + "none | raw | hex | passphrase", "KEYFORMAT", keyformat_table, + sfeatures); zprop_register_index(ZFS_PROP_ENCRYPTION, "encryption", ZIO_CRYPT_DEFAULT, PROP_ONETIME, ZFS_TYPE_DATASET, "on | off | aes-128-ccm | aes-192-ccm | aes-256-ccm | " "aes-128-gcm | aes-192-gcm | aes-256-gcm", "ENCRYPTION", - crypto_table); + crypto_table, sfeatures); /* set once index (boolean) properties */ zprop_register_index(ZFS_PROP_UTF8ONLY, "utf8only", 0, PROP_ONETIME, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, - "on | off", "UTF8ONLY", boolean_table); + "on | off", "UTF8ONLY", boolean_table, sfeatures); /* string properties */ zprop_register_string(ZFS_PROP_ORIGIN, "origin", NULL, PROP_READONLY, - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", "ORIGIN"); + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", "ORIGIN", + sfeatures); zprop_register_string(ZFS_PROP_CLONES, "clones", NULL, PROP_READONLY, - ZFS_TYPE_SNAPSHOT, "[,...]", "CLONES"); + ZFS_TYPE_SNAPSHOT, "[,...]", "CLONES", sfeatures); zprop_register_string(ZFS_PROP_MOUNTPOINT, "mountpoint", "/", PROP_INHERIT, ZFS_TYPE_FILESYSTEM, " | legacy | none", - "MOUNTPOINT"); + "MOUNTPOINT", sfeatures); zprop_register_string(ZFS_PROP_SHARENFS, "sharenfs", "off", PROP_INHERIT, ZFS_TYPE_FILESYSTEM, "on | off | NFS share options", - "SHARENFS"); + "SHARENFS", sfeatures); zprop_register_string(ZFS_PROP_TYPE, "type", NULL, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, - "filesystem | volume | snapshot | bookmark", "TYPE"); + "filesystem | volume | snapshot | bookmark", "TYPE", sfeatures); zprop_register_string(ZFS_PROP_SHARESMB, "sharesmb", "off", PROP_INHERIT, ZFS_TYPE_FILESYSTEM, - "on | off | SMB share options", "SHARESMB"); + "on | off | SMB share options", "SHARESMB", sfeatures); zprop_register_string(ZFS_PROP_MLSLABEL, "mlslabel", ZFS_MLSLABEL_DEFAULT, PROP_INHERIT, ZFS_TYPE_DATASET, - "", "MLSLABEL"); + "", "MLSLABEL", sfeatures); zprop_register_string(ZFS_PROP_SELINUX_CONTEXT, "context", "none", PROP_DEFAULT, ZFS_TYPE_DATASET, "", - "CONTEXT"); + "CONTEXT", sfeatures); zprop_register_string(ZFS_PROP_SELINUX_FSCONTEXT, "fscontext", "none", PROP_DEFAULT, ZFS_TYPE_DATASET, "", - "FSCONTEXT"); + "FSCONTEXT", sfeatures); zprop_register_string(ZFS_PROP_SELINUX_DEFCONTEXT, "defcontext", "none", PROP_DEFAULT, ZFS_TYPE_DATASET, "", - "DEFCONTEXT"); + "DEFCONTEXT", sfeatures); zprop_register_string(ZFS_PROP_SELINUX_ROOTCONTEXT, "rootcontext", "none", PROP_DEFAULT, ZFS_TYPE_DATASET, "", - "ROOTCONTEXT"); + "ROOTCONTEXT", sfeatures); zprop_register_string(ZFS_PROP_RECEIVE_RESUME_TOKEN, "receive_resume_token", NULL, PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "", "RESUMETOK"); + "", "RESUMETOK", sfeatures); zprop_register_string(ZFS_PROP_ENCRYPTION_ROOT, "encryptionroot", NULL, PROP_READONLY, ZFS_TYPE_DATASET, "", - "ENCROOT"); + "ENCROOT", sfeatures); zprop_register_string(ZFS_PROP_KEYLOCATION, "keylocation", "none", PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "prompt | | | ", "KEYLOCATION"); + "prompt | | | ", "KEYLOCATION", + sfeatures); zprop_register_string(ZFS_PROP_REDACT_SNAPS, "redact_snaps", NULL, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "[,...]", - "RSNAPS"); + "RSNAPS", sfeatures); /* readonly number properties */ zprop_register_number(ZFS_PROP_USED, "used", 0, PROP_READONLY, - ZFS_TYPE_DATASET, "", "USED"); + ZFS_TYPE_DATASET, "", "USED", sfeatures); zprop_register_number(ZFS_PROP_AVAILABLE, "available", 0, PROP_READONLY, - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", "AVAIL"); + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", "AVAIL", + sfeatures); zprop_register_number(ZFS_PROP_REFERENCED, "referenced", 0, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "", - "REFER"); + "REFER", sfeatures); zprop_register_number(ZFS_PROP_COMPRESSRATIO, "compressratio", 0, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, - "<1.00x or higher if compressed>", "RATIO"); + "<1.00x or higher if compressed>", "RATIO", sfeatures); zprop_register_number(ZFS_PROP_REFRATIO, "refcompressratio", 0, PROP_READONLY, ZFS_TYPE_DATASET, - "<1.00x or higher if compressed>", "REFRATIO"); + "<1.00x or higher if compressed>", "REFRATIO", sfeatures); zprop_register_number(ZFS_PROP_VOLBLOCKSIZE, "volblocksize", ZVOL_DEFAULT_BLOCKSIZE, PROP_ONETIME, - ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK"); + ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK", sfeatures); zprop_register_number(ZFS_PROP_USEDSNAP, "usedbysnapshots", 0, PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", - "USEDSNAP"); + "USEDSNAP", sfeatures); zprop_register_number(ZFS_PROP_USEDDS, "usedbydataset", 0, PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", - "USEDDS"); + "USEDDS", sfeatures); zprop_register_number(ZFS_PROP_USEDCHILD, "usedbychildren", 0, PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", - "USEDCHILD"); + "USEDCHILD", sfeatures); zprop_register_number(ZFS_PROP_USEDREFRESERV, "usedbyrefreservation", 0, PROP_READONLY, - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", "USEDREFRESERV"); + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", "USEDREFRESERV", + sfeatures); zprop_register_number(ZFS_PROP_USERREFS, "userrefs", 0, PROP_READONLY, - ZFS_TYPE_SNAPSHOT, "", "USERREFS"); + ZFS_TYPE_SNAPSHOT, "", "USERREFS", sfeatures); zprop_register_number(ZFS_PROP_WRITTEN, "written", 0, PROP_READONLY, - ZFS_TYPE_DATASET, "", "WRITTEN"); + ZFS_TYPE_DATASET, "", "WRITTEN", sfeatures); zprop_register_number(ZFS_PROP_LOGICALUSED, "logicalused", 0, PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "", - "LUSED"); + "LUSED", sfeatures); zprop_register_number(ZFS_PROP_LOGICALREFERENCED, "logicalreferenced", 0, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "", - "LREFER"); + "LREFER", sfeatures); zprop_register_number(ZFS_PROP_FILESYSTEM_COUNT, "filesystem_count", UINT64_MAX, PROP_READONLY, ZFS_TYPE_FILESYSTEM, - "", "FSCOUNT"); + "", "FSCOUNT", sfeatures); zprop_register_number(ZFS_PROP_SNAPSHOT_COUNT, "snapshot_count", UINT64_MAX, PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "", "SSCOUNT"); + "", "SSCOUNT", sfeatures); zprop_register_number(ZFS_PROP_GUID, "guid", 0, PROP_READONLY, - ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "", "GUID"); + ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "", "GUID", + sfeatures); zprop_register_number(ZFS_PROP_CREATETXG, "createtxg", 0, PROP_READONLY, - ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "", "CREATETXG"); + ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "", "CREATETXG", + sfeatures); zprop_register_number(ZFS_PROP_PBKDF2_ITERS, "pbkdf2iters", 0, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "", "PBKDF2ITERS"); + "", "PBKDF2ITERS", sfeatures); zprop_register_number(ZFS_PROP_OBJSETID, "objsetid", 0, - PROP_READONLY, ZFS_TYPE_DATASET, "", "OBJSETID"); + PROP_READONLY, ZFS_TYPE_DATASET, "", "OBJSETID", sfeatures); /* default number properties */ zprop_register_number(ZFS_PROP_QUOTA, "quota", 0, PROP_DEFAULT, - ZFS_TYPE_FILESYSTEM, " | none", "QUOTA"); + ZFS_TYPE_FILESYSTEM, " | none", "QUOTA", sfeatures); zprop_register_number(ZFS_PROP_RESERVATION, "reservation", 0, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - " | none", "RESERV"); + " | none", "RESERV", sfeatures); zprop_register_number(ZFS_PROP_VOLSIZE, "volsize", 0, PROP_DEFAULT, - ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, "", "VOLSIZE"); + ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, "", "VOLSIZE", + sfeatures); zprop_register_number(ZFS_PROP_REFQUOTA, "refquota", 0, PROP_DEFAULT, - ZFS_TYPE_FILESYSTEM, " | none", "REFQUOTA"); + ZFS_TYPE_FILESYSTEM, " | none", "REFQUOTA", sfeatures); zprop_register_number(ZFS_PROP_REFRESERVATION, "refreservation", 0, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - " | none", "REFRESERV"); + " | none", "REFRESERV", sfeatures); zprop_register_number(ZFS_PROP_FILESYSTEM_LIMIT, "filesystem_limit", UINT64_MAX, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM, - " | none", "FSLIMIT"); + " | none", "FSLIMIT", sfeatures); zprop_register_number(ZFS_PROP_SNAPSHOT_LIMIT, "snapshot_limit", UINT64_MAX, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - " | none", "SSLIMIT"); + " | none", "SSLIMIT", sfeatures); /* inherit number properties */ zprop_register_number(ZFS_PROP_RECORDSIZE, "recordsize", SPA_OLD_MAXBLOCKSIZE, PROP_INHERIT, - ZFS_TYPE_FILESYSTEM, "512 to 1M, power of 2", "RECSIZE"); + ZFS_TYPE_FILESYSTEM, "512 to 1M, power of 2", "RECSIZE", sfeatures); zprop_register_number(ZFS_PROP_SPECIAL_SMALL_BLOCKS, "special_small_blocks", 0, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, - "zero or 512 to 1M, power of 2", "SPECIAL_SMALL_BLOCKS"); + "zero or 512 to 1M, power of 2", "SPECIAL_SMALL_BLOCKS", sfeatures); /* hidden properties */ zprop_register_hidden(ZFS_PROP_NUMCLONES, "numclones", PROP_TYPE_NUMBER, - PROP_READONLY, ZFS_TYPE_SNAPSHOT, "NUMCLONES"); + PROP_READONLY, ZFS_TYPE_SNAPSHOT, "NUMCLONES", sfeatures); zprop_register_hidden(ZFS_PROP_NAME, "name", PROP_TYPE_STRING, - PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "NAME"); + PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "NAME", + sfeatures); zprop_register_hidden(ZFS_PROP_ISCSIOPTIONS, "iscsioptions", - PROP_TYPE_STRING, PROP_INHERIT, ZFS_TYPE_VOLUME, "ISCSIOPTIONS"); + PROP_TYPE_STRING, PROP_INHERIT, ZFS_TYPE_VOLUME, "ISCSIOPTIONS", + sfeatures); zprop_register_hidden(ZFS_PROP_STMF_SHAREINFO, "stmf_sbd_lu", PROP_TYPE_STRING, PROP_INHERIT, ZFS_TYPE_VOLUME, - "STMF_SBD_LU"); + "STMF_SBD_LU", sfeatures); zprop_register_hidden(ZFS_PROP_USERACCOUNTING, "useraccounting", PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_DATASET, - "USERACCOUNTING"); + "USERACCOUNTING", sfeatures); zprop_register_hidden(ZFS_PROP_UNIQUE, "unique", PROP_TYPE_NUMBER, - PROP_READONLY, ZFS_TYPE_DATASET, "UNIQUE"); + PROP_READONLY, ZFS_TYPE_DATASET, "UNIQUE", sfeatures); zprop_register_hidden(ZFS_PROP_INCONSISTENT, "inconsistent", - PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_DATASET, "INCONSISTENT"); + PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_DATASET, "INCONSISTENT", + sfeatures); zprop_register_hidden(ZFS_PROP_IVSET_GUID, "ivsetguid", PROP_TYPE_NUMBER, PROP_READONLY, - ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "IVSETGUID"); + ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "IVSETGUID", sfeatures); zprop_register_hidden(ZFS_PROP_PREV_SNAP, "prevsnap", PROP_TYPE_STRING, - PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "PREVSNAP"); + PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "PREVSNAP", + sfeatures); zprop_register_hidden(ZFS_PROP_PBKDF2_SALT, "pbkdf2salt", PROP_TYPE_NUMBER, PROP_ONETIME_DEFAULT, - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "PBKDF2SALT"); + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "PBKDF2SALT", sfeatures); zprop_register_hidden(ZFS_PROP_KEY_GUID, "keyguid", PROP_TYPE_NUMBER, - PROP_READONLY, ZFS_TYPE_DATASET, "KEYGUID"); + PROP_READONLY, ZFS_TYPE_DATASET, "KEYGUID", sfeatures); zprop_register_hidden(ZFS_PROP_REDACTED, "redacted", PROP_TYPE_NUMBER, - PROP_READONLY, ZFS_TYPE_DATASET, "REDACTED"); + PROP_READONLY, ZFS_TYPE_DATASET, "REDACTED", sfeatures); /* * Properties that are obsolete and not used. These are retained so @@ -694,12 +715,14 @@ zfs_prop_init(void) * have NULL pointers in the zfs_prop_table[]. */ zprop_register_hidden(ZFS_PROP_REMAPTXG, "remaptxg", PROP_TYPE_NUMBER, - PROP_READONLY, ZFS_TYPE_DATASET, "REMAPTXG"); + PROP_READONLY, ZFS_TYPE_DATASET, "REMAPTXG", sfeatures); /* oddball properties */ zprop_register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0, NULL, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, - "", "CREATION", B_FALSE, B_TRUE, NULL); + "", "CREATION", B_FALSE, B_TRUE, NULL, sfeatures); + + zfs_mod_list_supported_free(sfeatures); } boolean_t diff --git a/module/zcommon/zpool_prop.c b/module/zcommon/zpool_prop.c index bfe4ef9adc..44bfe4add2 100644 --- a/module/zcommon/zpool_prop.c +++ b/module/zcommon/zpool_prop.c @@ -65,90 +65,105 @@ zpool_prop_init(void) { NULL } }; + struct zfs_mod_supported_features *sfeatures = + zfs_mod_list_supported(ZFS_SYSFS_POOL_PROPERTIES); + /* string properties */ zprop_register_string(ZPOOL_PROP_ALTROOT, "altroot", NULL, PROP_DEFAULT, - ZFS_TYPE_POOL, "", "ALTROOT"); + ZFS_TYPE_POOL, "", "ALTROOT", sfeatures); zprop_register_string(ZPOOL_PROP_BOOTFS, "bootfs", NULL, PROP_DEFAULT, - ZFS_TYPE_POOL, "", "BOOTFS"); + ZFS_TYPE_POOL, "", "BOOTFS", sfeatures); zprop_register_string(ZPOOL_PROP_CACHEFILE, "cachefile", NULL, - PROP_DEFAULT, ZFS_TYPE_POOL, " | none", "CACHEFILE"); + PROP_DEFAULT, ZFS_TYPE_POOL, " | none", "CACHEFILE", + sfeatures); zprop_register_string(ZPOOL_PROP_COMMENT, "comment", NULL, - PROP_DEFAULT, ZFS_TYPE_POOL, "", "COMMENT"); + PROP_DEFAULT, ZFS_TYPE_POOL, "", "COMMENT", + sfeatures); zprop_register_string(ZPOOL_PROP_COMPATIBILITY, "compatibility", "off", PROP_DEFAULT, ZFS_TYPE_POOL, - " | off | legacy", "COMPATIBILITY"); + " | off | legacy", "COMPATIBILITY", sfeatures); /* readonly number properties */ zprop_register_number(ZPOOL_PROP_SIZE, "size", 0, PROP_READONLY, - ZFS_TYPE_POOL, "", "SIZE"); + ZFS_TYPE_POOL, "", "SIZE", sfeatures); zprop_register_number(ZPOOL_PROP_FREE, "free", 0, PROP_READONLY, - ZFS_TYPE_POOL, "", "FREE"); + ZFS_TYPE_POOL, "", "FREE", sfeatures); zprop_register_number(ZPOOL_PROP_FREEING, "freeing", 0, PROP_READONLY, - ZFS_TYPE_POOL, "", "FREEING"); + ZFS_TYPE_POOL, "", "FREEING", sfeatures); zprop_register_number(ZPOOL_PROP_CHECKPOINT, "checkpoint", 0, - PROP_READONLY, ZFS_TYPE_POOL, "", "CKPOINT"); + PROP_READONLY, ZFS_TYPE_POOL, "", "CKPOINT", sfeatures); zprop_register_number(ZPOOL_PROP_LEAKED, "leaked", 0, PROP_READONLY, - ZFS_TYPE_POOL, "", "LEAKED"); + ZFS_TYPE_POOL, "", "LEAKED", sfeatures); zprop_register_number(ZPOOL_PROP_ALLOCATED, "allocated", 0, - PROP_READONLY, ZFS_TYPE_POOL, "", "ALLOC"); + PROP_READONLY, ZFS_TYPE_POOL, "", "ALLOC", sfeatures); zprop_register_number(ZPOOL_PROP_EXPANDSZ, "expandsize", 0, - PROP_READONLY, ZFS_TYPE_POOL, "", "EXPANDSZ"); + PROP_READONLY, ZFS_TYPE_POOL, "", "EXPANDSZ", sfeatures); zprop_register_number(ZPOOL_PROP_FRAGMENTATION, "fragmentation", 0, - PROP_READONLY, ZFS_TYPE_POOL, "", "FRAG"); + PROP_READONLY, ZFS_TYPE_POOL, "", "FRAG", sfeatures); zprop_register_number(ZPOOL_PROP_CAPACITY, "capacity", 0, PROP_READONLY, - ZFS_TYPE_POOL, "", "CAP"); + ZFS_TYPE_POOL, "", "CAP", sfeatures); zprop_register_number(ZPOOL_PROP_GUID, "guid", 0, PROP_READONLY, - ZFS_TYPE_POOL, "", "GUID"); + ZFS_TYPE_POOL, "", "GUID", sfeatures); zprop_register_number(ZPOOL_PROP_LOAD_GUID, "load_guid", 0, - PROP_READONLY, ZFS_TYPE_POOL, "", "LOAD_GUID"); + PROP_READONLY, ZFS_TYPE_POOL, "", "LOAD_GUID", + sfeatures); zprop_register_number(ZPOOL_PROP_HEALTH, "health", 0, PROP_READONLY, - ZFS_TYPE_POOL, "", "HEALTH"); + ZFS_TYPE_POOL, "", "HEALTH", sfeatures); zprop_register_number(ZPOOL_PROP_DEDUPRATIO, "dedupratio", 0, PROP_READONLY, ZFS_TYPE_POOL, "<1.00x or higher if deduped>", - "DEDUP"); + "DEDUP", sfeatures); /* default number properties */ zprop_register_number(ZPOOL_PROP_VERSION, "version", SPA_VERSION, - PROP_DEFAULT, ZFS_TYPE_POOL, "", "VERSION"); + PROP_DEFAULT, ZFS_TYPE_POOL, "", "VERSION", sfeatures); zprop_register_number(ZPOOL_PROP_ASHIFT, "ashift", 0, PROP_DEFAULT, - ZFS_TYPE_POOL, "", "ASHIFT"); + ZFS_TYPE_POOL, "", "ASHIFT", sfeatures); /* default index (boolean) properties */ zprop_register_index(ZPOOL_PROP_DELEGATION, "delegation", 1, PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "DELEGATION", - boolean_table); + boolean_table, sfeatures); zprop_register_index(ZPOOL_PROP_AUTOREPLACE, "autoreplace", 0, - PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "REPLACE", boolean_table); + PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "REPLACE", boolean_table, + sfeatures); zprop_register_index(ZPOOL_PROP_LISTSNAPS, "listsnapshots", 0, PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "LISTSNAPS", - boolean_table); + boolean_table, sfeatures); zprop_register_index(ZPOOL_PROP_AUTOEXPAND, "autoexpand", 0, - PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "EXPAND", boolean_table); + PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "EXPAND", boolean_table, + sfeatures); zprop_register_index(ZPOOL_PROP_READONLY, "readonly", 0, - PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "RDONLY", boolean_table); + PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "RDONLY", boolean_table, + sfeatures); zprop_register_index(ZPOOL_PROP_MULTIHOST, "multihost", 0, PROP_DEFAULT, ZFS_TYPE_POOL, "on | off", "MULTIHOST", - boolean_table); + boolean_table, sfeatures); /* default index properties */ zprop_register_index(ZPOOL_PROP_FAILUREMODE, "failmode", ZIO_FAILURE_MODE_WAIT, PROP_DEFAULT, ZFS_TYPE_POOL, - "wait | continue | panic", "FAILMODE", failuremode_table); + "wait | continue | panic", "FAILMODE", failuremode_table, + sfeatures); zprop_register_index(ZPOOL_PROP_AUTOTRIM, "autotrim", SPA_AUTOTRIM_DEFAULT, PROP_DEFAULT, ZFS_TYPE_POOL, - "on | off", "AUTOTRIM", boolean_table); + "on | off", "AUTOTRIM", boolean_table, sfeatures); /* hidden properties */ zprop_register_hidden(ZPOOL_PROP_NAME, "name", PROP_TYPE_STRING, - PROP_READONLY, ZFS_TYPE_POOL, "NAME"); + PROP_READONLY, ZFS_TYPE_POOL, "NAME", sfeatures); zprop_register_hidden(ZPOOL_PROP_MAXBLOCKSIZE, "maxblocksize", - PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_POOL, "MAXBLOCKSIZE"); + PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_POOL, "MAXBLOCKSIZE", + sfeatures); zprop_register_hidden(ZPOOL_PROP_TNAME, "tname", PROP_TYPE_STRING, - PROP_ONETIME, ZFS_TYPE_POOL, "TNAME"); + PROP_ONETIME, ZFS_TYPE_POOL, "TNAME", sfeatures); zprop_register_hidden(ZPOOL_PROP_MAXDNODESIZE, "maxdnodesize", - PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_POOL, "MAXDNODESIZE"); + PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_POOL, "MAXDNODESIZE", + sfeatures); zprop_register_hidden(ZPOOL_PROP_DEDUPDITTO, "dedupditto", - PROP_TYPE_NUMBER, PROP_DEFAULT, ZFS_TYPE_POOL, "DEDUPDITTO"); + PROP_TYPE_NUMBER, PROP_DEFAULT, ZFS_TYPE_POOL, "DEDUPDITTO", + sfeatures); + + zfs_mod_list_supported_free(sfeatures); } /* @@ -283,102 +298,110 @@ vdev_prop_init(void) { NULL } }; + struct zfs_mod_supported_features *sfeatures = + zfs_mod_list_supported(ZFS_SYSFS_VDEV_PROPERTIES); + /* string properties */ zprop_register_string(VDEV_PROP_COMMENT, "comment", NULL, - PROP_DEFAULT, ZFS_TYPE_VDEV, "", "COMMENT"); + PROP_DEFAULT, ZFS_TYPE_VDEV, "", "COMMENT", + sfeatures); zprop_register_string(VDEV_PROP_PATH, "path", NULL, - PROP_DEFAULT, ZFS_TYPE_VDEV, "", "PATH"); + PROP_DEFAULT, ZFS_TYPE_VDEV, "", "PATH", sfeatures); zprop_register_string(VDEV_PROP_DEVID, "devid", NULL, - PROP_READONLY, ZFS_TYPE_VDEV, "", "DEVID"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "DEVID", sfeatures); zprop_register_string(VDEV_PROP_PHYS_PATH, "physpath", NULL, - PROP_READONLY, ZFS_TYPE_VDEV, "", "PHYSPATH"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "PHYSPATH", sfeatures); zprop_register_string(VDEV_PROP_ENC_PATH, "encpath", NULL, - PROP_READONLY, ZFS_TYPE_VDEV, "", "ENCPATH"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "ENCPATH", sfeatures); zprop_register_string(VDEV_PROP_FRU, "fru", NULL, - PROP_READONLY, ZFS_TYPE_VDEV, "", "FRU"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "FRU", sfeatures); zprop_register_string(VDEV_PROP_PARENT, "parent", NULL, - PROP_READONLY, ZFS_TYPE_VDEV, "", "PARENT"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "PARENT", sfeatures); zprop_register_string(VDEV_PROP_CHILDREN, "children", NULL, - PROP_READONLY, ZFS_TYPE_VDEV, "", "CHILDREN"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "CHILDREN", + sfeatures); /* readonly number properties */ zprop_register_number(VDEV_PROP_SIZE, "size", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "SIZE"); + ZFS_TYPE_VDEV, "", "SIZE", sfeatures); zprop_register_number(VDEV_PROP_FREE, "free", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "FREE"); + ZFS_TYPE_VDEV, "", "FREE", sfeatures); zprop_register_number(VDEV_PROP_ALLOCATED, "allocated", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "ALLOC"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "ALLOC", sfeatures); zprop_register_number(VDEV_PROP_EXPANDSZ, "expandsize", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "EXPANDSZ"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "EXPANDSZ", sfeatures); zprop_register_number(VDEV_PROP_FRAGMENTATION, "fragmentation", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "FRAG"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "FRAG", sfeatures); zprop_register_number(VDEV_PROP_CAPACITY, "capacity", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "CAP"); + ZFS_TYPE_VDEV, "", "CAP", sfeatures); zprop_register_number(VDEV_PROP_GUID, "guid", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "GUID"); + ZFS_TYPE_VDEV, "", "GUID", sfeatures); zprop_register_number(VDEV_PROP_STATE, "state", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "STATE"); + ZFS_TYPE_VDEV, "", "STATE", sfeatures); zprop_register_number(VDEV_PROP_BOOTSIZE, "bootsize", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "BOOTSIZE"); + ZFS_TYPE_VDEV, "", "BOOTSIZE", sfeatures); zprop_register_number(VDEV_PROP_ASIZE, "asize", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "ASIZE"); + ZFS_TYPE_VDEV, "", "ASIZE", sfeatures); zprop_register_number(VDEV_PROP_PSIZE, "psize", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "PSIZE"); + ZFS_TYPE_VDEV, "", "PSIZE", sfeatures); zprop_register_number(VDEV_PROP_ASHIFT, "ashift", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "ASHIFT"); + ZFS_TYPE_VDEV, "", "ASHIFT", sfeatures); zprop_register_number(VDEV_PROP_PARITY, "parity", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "", "PARITY"); + ZFS_TYPE_VDEV, "", "PARITY", sfeatures); zprop_register_number(VDEV_PROP_NUMCHILDREN, "numchildren", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "NUMCHILD"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "NUMCHILD", + sfeatures); zprop_register_number(VDEV_PROP_READ_ERRORS, "read_errors", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "RDERR"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "RDERR", sfeatures); zprop_register_number(VDEV_PROP_WRITE_ERRORS, "write_errors", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "WRERR"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "WRERR", sfeatures); zprop_register_number(VDEV_PROP_CHECKSUM_ERRORS, "checksum_errors", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "CKERR"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "CKERR", sfeatures); zprop_register_number(VDEV_PROP_INITIALIZE_ERRORS, "initialize_errors", 0, PROP_READONLY, ZFS_TYPE_VDEV, "", - "INITERR"); + "INITERR", sfeatures); zprop_register_number(VDEV_PROP_OPS_NULL, "null_ops", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "NULLOP"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "NULLOP", sfeatures); zprop_register_number(VDEV_PROP_OPS_READ, "read_ops", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "READOP"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "READOP", sfeatures); zprop_register_number(VDEV_PROP_OPS_WRITE, "write_ops", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "WRITEOP"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "WRITEOP", sfeatures); zprop_register_number(VDEV_PROP_OPS_FREE, "free_ops", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "FREEOP"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "FREEOP", sfeatures); zprop_register_number(VDEV_PROP_OPS_CLAIM, "claim_ops", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "CLAIMOP"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "CLAIMOP", sfeatures); zprop_register_number(VDEV_PROP_OPS_TRIM, "trim_ops", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "TRIMOP"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "TRIMOP", sfeatures); zprop_register_number(VDEV_PROP_BYTES_NULL, "null_bytes", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "NULLBYTE"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "NULLBYTE", sfeatures); zprop_register_number(VDEV_PROP_BYTES_READ, "read_bytes", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "READBYTE"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "READBYTE", sfeatures); zprop_register_number(VDEV_PROP_BYTES_WRITE, "write_bytes", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "WRITEBYTE"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "WRITEBYTE", sfeatures); zprop_register_number(VDEV_PROP_BYTES_FREE, "free_bytes", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "FREEBYTE"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "FREEBYTE", sfeatures); zprop_register_number(VDEV_PROP_BYTES_CLAIM, "claim_bytes", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "CLAIMBYTE"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "CLAIMBYTE", sfeatures); zprop_register_number(VDEV_PROP_BYTES_TRIM, "trim_bytes", 0, - PROP_READONLY, ZFS_TYPE_VDEV, "", "TRIMBYTE"); + PROP_READONLY, ZFS_TYPE_VDEV, "", "TRIMBYTE", sfeatures); /* default numeric properties */ /* default index (boolean) properties */ zprop_register_index(VDEV_PROP_REMOVING, "removing", 0, PROP_READONLY, ZFS_TYPE_VDEV, "on | off", "REMOVING", - boolean_table); + boolean_table, sfeatures); zprop_register_index(VDEV_PROP_ALLOCATING, "allocating", 1, PROP_DEFAULT, ZFS_TYPE_VDEV, "on | off", "ALLOCATING", - boolean_na_table); + boolean_na_table, sfeatures); /* default index properties */ /* hidden properties */ zprop_register_hidden(VDEV_PROP_NAME, "name", PROP_TYPE_STRING, - PROP_READONLY, ZFS_TYPE_VDEV, "NAME"); + PROP_READONLY, ZFS_TYPE_VDEV, "NAME", sfeatures); + + zfs_mod_list_supported_free(sfeatures); } /* diff --git a/module/zcommon/zprop_common.c b/module/zcommon/zprop_common.c index 17a48361f9..428af57419 100644 --- a/module/zcommon/zprop_common.c +++ b/module/zcommon/zprop_common.c @@ -71,7 +71,8 @@ zprop_get_numprops(zfs_type_t type) } static boolean_t -zfs_mod_supported_prop(const char *name, zfs_type_t type) +zfs_mod_supported_prop(const char *name, zfs_type_t type, + const struct zfs_mod_supported_features *sfeatures) { /* * The zfs module spa_feature_table[], whether in-kernel or in libzpool, @@ -86,7 +87,8 @@ zfs_mod_supported_prop(const char *name, zfs_type_t type) #else return (zfs_mod_supported(type == ZFS_TYPE_POOL ? ZFS_SYSFS_POOL_PROPERTIES : (type == ZFS_TYPE_VDEV ? - ZFS_SYSFS_VDEV_PROPERTIES : ZFS_SYSFS_DATASET_PROPERTIES), name)); + ZFS_SYSFS_VDEV_PROPERTIES : ZFS_SYSFS_DATASET_PROPERTIES), + name, sfeatures)); #endif } @@ -94,7 +96,8 @@ void zprop_register_impl(int prop, const char *name, zprop_type_t type, uint64_t numdefault, const char *strdefault, zprop_attr_t attr, int objset_types, const char *values, const char *colname, - boolean_t rightalign, boolean_t visible, const zprop_index_t *idx_tbl) + boolean_t rightalign, boolean_t visible, const zprop_index_t *idx_tbl, + const struct zfs_mod_supported_features *sfeatures) { zprop_desc_t *prop_tbl = zprop_get_proptable(objset_types); zprop_desc_t *pd; @@ -116,7 +119,8 @@ zprop_register_impl(int prop, const char *name, zprop_type_t type, pd->pd_colname = colname; pd->pd_rightalign = rightalign; pd->pd_visible = visible; - pd->pd_zfs_mod_supported = zfs_mod_supported_prop(name, objset_types); + pd->pd_zfs_mod_supported = + zfs_mod_supported_prop(name, objset_types, sfeatures); pd->pd_table = idx_tbl; pd->pd_table_size = 0; while (idx_tbl && (idx_tbl++)->pi_name != NULL) @@ -126,38 +130,40 @@ zprop_register_impl(int prop, const char *name, zprop_type_t type, void zprop_register_string(int prop, const char *name, const char *def, zprop_attr_t attr, int objset_types, const char *values, - const char *colname) + const char *colname, const struct zfs_mod_supported_features *sfeatures) { zprop_register_impl(prop, name, PROP_TYPE_STRING, 0, def, attr, - objset_types, values, colname, B_FALSE, B_TRUE, NULL); + objset_types, values, colname, B_FALSE, B_TRUE, NULL, sfeatures); } void zprop_register_number(int prop, const char *name, uint64_t def, zprop_attr_t attr, int objset_types, const char *values, - const char *colname) + const char *colname, const struct zfs_mod_supported_features *sfeatures) { zprop_register_impl(prop, name, PROP_TYPE_NUMBER, def, NULL, attr, - objset_types, values, colname, B_TRUE, B_TRUE, NULL); + objset_types, values, colname, B_TRUE, B_TRUE, NULL, sfeatures); } void zprop_register_index(int prop, const char *name, uint64_t def, zprop_attr_t attr, int objset_types, const char *values, - const char *colname, const zprop_index_t *idx_tbl) + const char *colname, const zprop_index_t *idx_tbl, + const struct zfs_mod_supported_features *sfeatures) { zprop_register_impl(prop, name, PROP_TYPE_INDEX, def, NULL, attr, - objset_types, values, colname, B_FALSE, B_TRUE, idx_tbl); + objset_types, values, colname, B_FALSE, B_TRUE, idx_tbl, sfeatures); } void zprop_register_hidden(int prop, const char *name, zprop_type_t type, - zprop_attr_t attr, int objset_types, const char *colname) + zprop_attr_t attr, int objset_types, const char *colname, + const struct zfs_mod_supported_features *sfeatures) { zprop_register_impl(prop, name, type, 0, NULL, attr, objset_types, NULL, colname, - type == PROP_TYPE_NUMBER, B_FALSE, NULL); + type == PROP_TYPE_NUMBER, B_FALSE, NULL, sfeatures); }