1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BCACHE_SYSFS_H_
3 #define _BCACHE_SYSFS_H_
4 
5 #define KTYPE(type)							\
6 struct kobj_type type ## _ktype = {					\
7 	.release	= type ## _release,				\
8 	.sysfs_ops	= &((const struct sysfs_ops) {			\
9 		.show	= type ## _show,				\
10 		.store	= type ## _store				\
11 	}),								\
12 	.default_groups	= type ## _groups				\
13 }
14 
15 #define SHOW(fn)							\
16 static ssize_t fn ## _show(struct kobject *kobj, struct attribute *attr,\
17 			   char *buf)					\
18 
19 #define STORE(fn)							\
20 static ssize_t fn ## _store(struct kobject *kobj, struct attribute *attr,\
21 			    const char *buf, size_t size)		\
22 
23 #define SHOW_LOCKED(fn)							\
24 SHOW(fn)								\
25 {									\
26 	ssize_t ret;							\
27 	mutex_lock(&bch_register_lock);					\
28 	ret = __ ## fn ## _show(kobj, attr, buf);			\
29 	mutex_unlock(&bch_register_lock);				\
30 	return ret;							\
31 }
32 
33 #define STORE_LOCKED(fn)						\
34 STORE(fn)								\
35 {									\
36 	ssize_t ret;							\
37 	mutex_lock(&bch_register_lock);					\
38 	ret = __ ## fn ## _store(kobj, attr, buf, size);		\
39 	mutex_unlock(&bch_register_lock);				\
40 	return ret;							\
41 }
42 
43 #define __sysfs_attribute(_name, _mode)					\
44 	static struct attribute sysfs_##_name =				\
45 		{ .name = #_name, .mode = _mode }
46 
47 #define write_attribute(n)	__sysfs_attribute(n, 0200)
48 #define read_attribute(n)	__sysfs_attribute(n, 0444)
49 #define rw_attribute(n)		__sysfs_attribute(n, 0644)
50 
51 #define sysfs_printf(file, fmt, ...)					\
52 do {									\
53 	if (attr == &sysfs_ ## file)					\
54 		return sysfs_emit(buf, fmt "\n", __VA_ARGS__);	\
55 } while (0)
56 
57 #define sysfs_print(file, var)						\
58 do {									\
59 	if (attr == &sysfs_ ## file)					\
60 		return sysfs_emit(buf,						\
61 				__builtin_types_compatible_p(typeof(var), int)		\
62 					 ? "%i\n" :				\
63 				__builtin_types_compatible_p(typeof(var), unsigned int)	\
64 					 ? "%u\n" :				\
65 				__builtin_types_compatible_p(typeof(var), long)		\
66 					 ? "%li\n" :			\
67 				__builtin_types_compatible_p(typeof(var), unsigned long)\
68 					 ? "%lu\n" :			\
69 				__builtin_types_compatible_p(typeof(var), int64_t)	\
70 					 ? "%lli\n" :			\
71 				__builtin_types_compatible_p(typeof(var), uint64_t)	\
72 					 ? "%llu\n" :			\
73 				__builtin_types_compatible_p(typeof(var), const char *)	\
74 					 ? "%s\n" : "%i\n", var);	\
75 } while (0)
76 
77 #define sysfs_hprint(file, val)						\
78 do {									\
79 	if (attr == &sysfs_ ## file) {					\
80 		ssize_t ret = bch_hprint(buf, val);			\
81 		strcat(buf, "\n");					\
82 		return ret + 1;						\
83 	}								\
84 } while (0)
85 
86 #define var_printf(_var, fmt)	sysfs_printf(_var, fmt, var(_var))
87 #define var_print(_var)		sysfs_print(_var, var(_var))
88 #define var_hprint(_var)	sysfs_hprint(_var, var(_var))
89 
90 #define sysfs_strtoul(file, var)					\
91 do {									\
92 	if (attr == &sysfs_ ## file)					\
93 		return strtoul_safe(buf, var) ?: (ssize_t) size;	\
94 } while (0)
95 
96 #define sysfs_strtoul_bool(file, var)					\
97 do {									\
98 	if (attr == &sysfs_ ## file) {					\
99 		unsigned long v = strtoul_or_return(buf);		\
100 									\
101 		var = v ? 1 : 0;					\
102 		return size;						\
103 	}								\
104 } while (0)
105 
106 #define sysfs_strtoul_clamp(file, var, min, max)			\
107 do {									\
108 	if (attr == &sysfs_ ## file) {					\
109 		unsigned long v = 0;					\
110 		ssize_t ret;						\
111 		ret = strtoul_safe_clamp(buf, v, min, max);		\
112 		if (!ret) {						\
113 			var = v;					\
114 			return size;					\
115 		}							\
116 		return ret;						\
117 	}								\
118 } while (0)
119 
120 #define strtoul_or_return(cp)						\
121 ({									\
122 	unsigned long _v;						\
123 	int _r = kstrtoul(cp, 10, &_v);					\
124 	if (_r)								\
125 		return _r;						\
126 	_v;								\
127 })
128 
129 #define strtoi_h_or_return(cp, v)					\
130 do {									\
131 	int _r = strtoi_h(cp, &v);					\
132 	if (_r)								\
133 		return _r;						\
134 } while (0)
135 
136 #define sysfs_hatoi(file, var)						\
137 do {									\
138 	if (attr == &sysfs_ ## file)					\
139 		return strtoi_h(buf, &var) ?: (ssize_t) size;		\
140 } while (0)
141 
142 #endif  /* _BCACHE_SYSFS_H_ */
143