diff options
Diffstat (limited to 'module/zcommon/zfeature_common.c')
-rw-r--r-- | module/zcommon/zfeature_common.c | 51 |
1 files changed, 51 insertions, 0 deletions
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 <errno.h> #include <string.h> +#include <sys/stat.h> #endif #include <sys/debug.h> #include <sys/fs/zfs.h> #include <sys/inttypes.h> #include <sys/types.h> +#include <sys/zfs_sysfs.h> #include "zfeature_common.h" /* @@ -101,10 +103,29 @@ zfeature_is_supported(const char *guid) } 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); |