1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _BCACHE_SYSFS_H_
3#define _BCACHE_SYSFS_H_
4
5#define KTYPE(type)							\
6struct 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_attrs	= type ## _files				\
13}
14
15#define SHOW(fn)							\
16static ssize_t fn ## _show(struct kobject *kobj, struct attribute *attr,\
17			   char *buf)					\
18
19#define STORE(fn)							\
20static ssize_t fn ## _store(struct kobject *kobj, struct attribute *attr,\
21			    const char *buf, size_t size)		\
22
23#define SHOW_LOCKED(fn)							\
24SHOW(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)						\
34STORE(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, ...)					\
52do {									\
53	if (attr == &sysfs_ ## file)					\
54		return snprintf(buf, PAGE_SIZE, fmt "\n", __VA_ARGS__);	\
55} while (0)
56
57#define sysfs_print(file, var)						\
58do {									\
59	if (attr == &sysfs_ ## file)					\
60		return snprint(buf, PAGE_SIZE, var);			\
61} while (0)
62
63#define sysfs_hprint(file, val)						\
64do {									\
65	if (attr == &sysfs_ ## file) {					\
66		ssize_t ret = bch_hprint(buf, val);			\
67		strcat(buf, "\n");					\
68		return ret + 1;						\
69	}								\
70} while (0)
71
72#define var_printf(_var, fmt)	sysfs_printf(_var, fmt, var(_var))
73#define var_print(_var)		sysfs_print(_var, var(_var))
74#define var_hprint(_var)	sysfs_hprint(_var, var(_var))
75
76#define sysfs_strtoul(file, var)					\
77do {									\
78	if (attr == &sysfs_ ## file)					\
79		return strtoul_safe(buf, var) ?: (ssize_t) size;	\
80} while (0)
81
82#define sysfs_strtoul_bool(file, var)					\
83do {									\
84	if (attr == &sysfs_ ## file) {					\
85		unsigned long v = strtoul_or_return(buf);		\
86									\
87		var = v ? 1 : 0;					\
88		return size;						\
89	}								\
90} while (0)
91
92#define sysfs_strtoul_clamp(file, var, min, max)			\
93do {									\
94	if (attr == &sysfs_ ## file) {					\
95		unsigned long v = 0;					\
96		ssize_t ret;						\
97		ret = strtoul_safe_clamp(buf, v, min, max);		\
98		if (!ret) {						\
99			var = v;					\
100			return size;					\
101		}							\
102		return ret;						\
103	}								\
104} while (0)
105
106#define strtoul_or_return(cp)						\
107({									\
108	unsigned long _v;						\
109	int _r = kstrtoul(cp, 10, &_v);					\
110	if (_r)								\
111		return _r;						\
112	_v;								\
113})
114
115#define strtoi_h_or_return(cp, v)					\
116do {									\
117	int _r = strtoi_h(cp, &v);					\
118	if (_r)								\
119		return _r;						\
120} while (0)
121
122#define sysfs_hatoi(file, var)						\
123do {									\
124	if (attr == &sysfs_ ## file)					\
125		return strtoi_h(buf, &var) ?: (ssize_t) size;		\
126} while (0)
127
128#endif  /* _BCACHE_SYSFS_H_ */
129