#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"
/*
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;
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)
feature->fi_desc = desc;
feature->fi_flags = flags;
feature->fi_depends = deps;
+ feature->fi_zfs_mod_supported = zfs_mod_supported_feature(guid);
}
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);