summaryrefslogtreecommitdiff
path: root/include/linux/sysfs.h
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2026-04-19 18:28:57 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2026-04-19 18:28:57 -0700
commitf4b369c6fe0ceaba2da2daff8c9eb415f85926dd (patch)
tree30465d0a429b2c224685b5d8e804bf053c4d129a /include/linux/sysfs.h
parentff14dafde15c11403fac61367a34fea08926e9ee (diff)
parent2ca45e57ea027fffe3350ae5e21ad9cecb0dce74 (diff)
Merge branch 'next' into for-linus
Prepare input updates for 7.1 merge window.
Diffstat (limited to 'include/linux/sysfs.h')
-rw-r--r--include/linux/sysfs.h61
1 files changed, 42 insertions, 19 deletions
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 9a25a2911652..99b775f3ff46 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -58,6 +58,12 @@ do { \
#define sysfs_attr_init(attr) do {} while (0)
#endif
+#ifdef CONFIG_CFI
+#define __SYSFS_FUNCTION_ALTERNATIVE(MEMBERS...) struct { MEMBERS }
+#else
+#define __SYSFS_FUNCTION_ALTERNATIVE(MEMBERS...) union { MEMBERS }
+#endif
+
/**
* struct attribute_group - data structure used to declare an attribute group.
* @name: Optional: Attribute group name
@@ -98,14 +104,21 @@ do { \
*/
struct attribute_group {
const char *name;
- umode_t (*is_visible)(struct kobject *,
- struct attribute *, int);
+ __SYSFS_FUNCTION_ALTERNATIVE(
+ umode_t (*is_visible)(struct kobject *,
+ struct attribute *, int);
+ umode_t (*is_visible_const)(struct kobject *,
+ const struct attribute *, int);
+ );
umode_t (*is_bin_visible)(struct kobject *,
const struct bin_attribute *, int);
size_t (*bin_size)(struct kobject *,
const struct bin_attribute *,
int);
- struct attribute **attrs;
+ union {
+ struct attribute **attrs;
+ const struct attribute *const *attrs_const;
+ };
const struct bin_attribute *const *bin_attrs;
};
@@ -238,28 +251,20 @@ struct attribute_group {
.store = _store, \
}
-#define __ATTR_RO(_name) { \
- .attr = { .name = __stringify(_name), .mode = 0444 }, \
- .show = _name##_show, \
-}
-
#define __ATTR_RO_MODE(_name, _mode) { \
.attr = { .name = __stringify(_name), \
.mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \
.show = _name##_show, \
}
-#define __ATTR_RW_MODE(_name, _mode) { \
- .attr = { .name = __stringify(_name), \
- .mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \
- .show = _name##_show, \
- .store = _name##_store, \
-}
+#define __ATTR_RO(_name) \
+ __ATTR_RO_MODE(_name, 0444)
-#define __ATTR_WO(_name) { \
- .attr = { .name = __stringify(_name), .mode = 0200 }, \
- .store = _name##_store, \
-}
+#define __ATTR_RW_MODE(_name, _mode) \
+ __ATTR(_name, _mode, _name##_show, _name##_store)
+
+#define __ATTR_WO(_name) \
+ __ATTR(_name, 0200, NULL, _name##_store)
#define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store)
@@ -284,7 +289,12 @@ static const struct attribute_group *_name##_groups[] = { \
#define ATTRIBUTE_GROUPS(_name) \
static const struct attribute_group _name##_group = { \
- .attrs = _name##_attrs, \
+ .attrs = _Generic(_name##_attrs, \
+ struct attribute **: \
+ _name##_attrs, \
+ const struct attribute *const *: \
+ (void *)_name##_attrs \
+ ), \
}; \
__ATTRIBUTE_GROUPS(_name)
@@ -798,4 +808,17 @@ static inline void sysfs_put(struct kernfs_node *kn)
kernfs_put(kn);
}
+/* Permissions on a sysfs file: you didn't miss the 0 prefix did you? */
+#define VERIFY_OCTAL_PERMISSIONS(perms) \
+ (BUILD_BUG_ON_ZERO((perms) < 0) + \
+ BUILD_BUG_ON_ZERO((perms) > 0777) + \
+ /* USER_READABLE >= GROUP_READABLE >= OTHER_READABLE */ \
+ BUILD_BUG_ON_ZERO((((perms) >> 6) & 4) < (((perms) >> 3) & 4)) + \
+ BUILD_BUG_ON_ZERO((((perms) >> 3) & 4) < ((perms) & 4)) + \
+ /* USER_WRITABLE >= GROUP_WRITABLE */ \
+ BUILD_BUG_ON_ZERO((((perms) >> 6) & 2) < (((perms) >> 3) & 2)) + \
+ /* OTHER_WRITABLE? Generally considered a bad idea. */ \
+ BUILD_BUG_ON_ZERO((perms) & 2) + \
+ (perms))
+
#endif /* _SYSFS_H_ */