From 0b8e4418b615eb6e46d409b3de61bfffe1000c68 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 3 Jan 2019 15:19:37 -0800 Subject: [PATCH] Add zfs module feature and property compatibility This change is required to ease the transition when upgrading from 0.7.x to 0.8.x. It allows 0.8.x user space utilities to remain compatible with 0.7.x and older kernel modules. Reviewed-by: Don Brady Signed-off-by: Brian Behlendorf Closes #8231 --- module/zcommon/zfeature_common.c | 36 ++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/module/zcommon/zfeature_common.c b/module/zcommon/zfeature_common.c index 40ce01b947..80f4a05628 100644 --- a/module/zcommon/zfeature_common.c +++ b/module/zcommon/zfeature_common.c @@ -163,25 +163,49 @@ deps_contains_feature(const spa_feature_t *deps, const spa_feature_t feature) static boolean_t zfs_mod_supported_impl(const char *scope, const char *name, const char *sysfs) { - struct stat64 statbuf; - char *path; boolean_t supported = B_FALSE; - int len; - - len = asprintf(&path, "%s/%s/%s", sysfs, scope, name); + 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); } boolean_t zfs_mod_supported(const char *scope, const char *name) { - return (zfs_mod_supported_impl(scope, name, ZFS_SYSFS_DIR) || + boolean_t supported; + + /* + * Check both the primary and alternate sysfs locations to determine + * if the required functionality is supported. + */ + supported = (zfs_mod_supported_impl(scope, name, ZFS_SYSFS_DIR) || zfs_mod_supported_impl(scope, name, ZFS_SYSFS_ALT_DIR)); + + /* + * For backwards compatibility with kernel modules that predate + * supported feature/property checking. Report the feature/property + * as supported if the kernel module is loaded but the requested + * 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)) { + supported = B_TRUE; + } + } + + return (supported); } #endif