1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef _BCACHE_SYSFS_H_
3  #define _BCACHE_SYSFS_H_
4  
5  #define KTYPE(type)							\
6  const 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