From e8bcb693d6a19962291e4429f2dc4ce60693bef7 Mon Sep 17 00:00:00 2001 From: Don Brady Date: Sun, 2 Sep 2018 15:09:53 -0400 Subject: Add zfs module feature and property info to sysfs This extends our sysfs '/sys/module/zfs' entry to include feature and property attributes. The primary consumer of this information is user processes, like the zfs CLI, that need to know what the current loaded ZFS module supports. The libzfs binary will consult this information when instantiating the zfs and zpool property tables and the pool features table. This introduces 4 kernel objects (dirs) into '/sys/module/zfs' with corresponding attributes (files): features.runtime features.pool properties.dataset properties.pool Reviewed-by: Matthew Ahrens Reviewed-by: Tony Hutter Reviewed-by: Brian Behlendorf Signed-off-by: Don Brady Closes #7706 --- module/zcommon/zfeature_common.c | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'module/zcommon/zfeature_common.c') diff --git a/module/zcommon/zfeature_common.c b/module/zcommon/zfeature_common.c index f5c98933c..e2b0fd511 100644 --- a/module/zcommon/zfeature_common.c +++ b/module/zcommon/zfeature_common.c @@ -29,11 +29,13 @@ #ifndef _KERNEL #include #include +#include #endif #include #include #include #include +#include #include "zfeature_common.h" /* @@ -100,11 +102,30 @@ zfeature_is_supported(const char *guid) return (B_FALSE); } +int +zfeature_lookup_guid(const char *guid, spa_feature_t *res) +{ + for (spa_feature_t i = 0; i < SPA_FEATURES; i++) { + zfeature_info_t *feature = &spa_feature_table[i]; + if (!feature->fi_zfs_mod_supported) + continue; + if (strcmp(guid, feature->fi_guid) == 0) { + if (res != NULL) + *res = i; + return (0); + } + } + + return (ENOENT); +} + int zfeature_lookup_name(const char *name, spa_feature_t *res) { for (spa_feature_t i = 0; i < SPA_FEATURES; i++) { zfeature_info_t *feature = &spa_feature_table[i]; + if (!feature->fi_zfs_mod_supported) + continue; if (strcmp(name, feature->fi_uname) == 0) { if (res != NULL) *res = i; @@ -137,6 +158,34 @@ deps_contains_feature(const spa_feature_t *deps, const spa_feature_t feature) return (B_FALSE); } +static boolean_t +zfs_mod_supported_feature(const char *name) +{ + /* + * The zfs module spa_feature_table[], whether in-kernel or in + * libzpool, always supports all the features. libzfs needs to + * query the running module, via sysfs, to determine which + * features are supported. + */ +#if defined(_KERNEL) || defined(LIB_ZPOOL_BUILD) + return (B_TRUE); +#else + struct stat64 statbuf; + char *path; + boolean_t supported = B_FALSE; + int len; + + len = asprintf(&path, "%s/%s/%s", ZFS_SYSFS_DIR, + ZFS_SYSFS_POOL_FEATURES, name); + + if (len > 0) { + supported = !!(stat64(path, &statbuf) == 0); + free(path); + } + return (supported); +#endif +} + static void zfeature_register(spa_feature_t fid, const char *guid, const char *name, const char *desc, zfeature_flags_t flags, const spa_feature_t *deps) @@ -163,6 +212,7 @@ zfeature_register(spa_feature_t fid, const char *guid, const char *name, feature->fi_desc = desc; feature->fi_flags = flags; feature->fi_depends = deps; + feature->fi_zfs_mod_supported = zfs_mod_supported_feature(guid); } void @@ -361,6 +411,7 @@ zpool_feature_init(void) } #if defined(_KERNEL) +EXPORT_SYMBOL(zfeature_lookup_guid); EXPORT_SYMBOL(zfeature_lookup_name); EXPORT_SYMBOL(zfeature_is_supported); EXPORT_SYMBOL(zfeature_is_valid_guid); -- cgit v1.2.3