]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zcommon/zfeature_common.c
Add zfs module feature and property info to sysfs
[mirror_zfs.git] / module / zcommon / zfeature_common.c
index f5c98933ccd7fdd9e49eeded6eb62a46eff09939..e2b0fd511a3cc8c20b4f30ef943810fafee0d29e 100644 (file)
 #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"
 
 /*
@@ -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);