e4db37fb69
When setting bool values via sysfs interface, e.g. writeback_metadata, if writing 1 into writeback_metadata file, dc->writeback_metadata is set to 1, but if writing 2 into the file, dc->writeback_metadata is 0. This is misleading, a better result should be 1 for all non-zero input value. It is because dc->writeback_metadata is a bit-field variable, and current code simply use d_strtoul() to convert a string into integer and takes the lowest bit value. To fix such error, we need a routine to convert the input string into unsigned integer, and set target variable to 1 if the converted integer is non-zero. This patch introduces a new macro called sysfs_strtoul_bool(), it can be used to convert input string into bool value, we can use it to set bool value for bit-field vairables. Signed-off-by: Coly Li <colyli@suse.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
129 lines
3.2 KiB
C
129 lines
3.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _BCACHE_SYSFS_H_
|
|
#define _BCACHE_SYSFS_H_
|
|
|
|
#define KTYPE(type) \
|
|
struct kobj_type type ## _ktype = { \
|
|
.release = type ## _release, \
|
|
.sysfs_ops = &((const struct sysfs_ops) { \
|
|
.show = type ## _show, \
|
|
.store = type ## _store \
|
|
}), \
|
|
.default_attrs = type ## _files \
|
|
}
|
|
|
|
#define SHOW(fn) \
|
|
static ssize_t fn ## _show(struct kobject *kobj, struct attribute *attr,\
|
|
char *buf) \
|
|
|
|
#define STORE(fn) \
|
|
static ssize_t fn ## _store(struct kobject *kobj, struct attribute *attr,\
|
|
const char *buf, size_t size) \
|
|
|
|
#define SHOW_LOCKED(fn) \
|
|
SHOW(fn) \
|
|
{ \
|
|
ssize_t ret; \
|
|
mutex_lock(&bch_register_lock); \
|
|
ret = __ ## fn ## _show(kobj, attr, buf); \
|
|
mutex_unlock(&bch_register_lock); \
|
|
return ret; \
|
|
}
|
|
|
|
#define STORE_LOCKED(fn) \
|
|
STORE(fn) \
|
|
{ \
|
|
ssize_t ret; \
|
|
mutex_lock(&bch_register_lock); \
|
|
ret = __ ## fn ## _store(kobj, attr, buf, size); \
|
|
mutex_unlock(&bch_register_lock); \
|
|
return ret; \
|
|
}
|
|
|
|
#define __sysfs_attribute(_name, _mode) \
|
|
static struct attribute sysfs_##_name = \
|
|
{ .name = #_name, .mode = _mode }
|
|
|
|
#define write_attribute(n) __sysfs_attribute(n, 0200)
|
|
#define read_attribute(n) __sysfs_attribute(n, 0444)
|
|
#define rw_attribute(n) __sysfs_attribute(n, 0644)
|
|
|
|
#define sysfs_printf(file, fmt, ...) \
|
|
do { \
|
|
if (attr == &sysfs_ ## file) \
|
|
return snprintf(buf, PAGE_SIZE, fmt "\n", __VA_ARGS__); \
|
|
} while (0)
|
|
|
|
#define sysfs_print(file, var) \
|
|
do { \
|
|
if (attr == &sysfs_ ## file) \
|
|
return snprint(buf, PAGE_SIZE, var); \
|
|
} while (0)
|
|
|
|
#define sysfs_hprint(file, val) \
|
|
do { \
|
|
if (attr == &sysfs_ ## file) { \
|
|
ssize_t ret = bch_hprint(buf, val); \
|
|
strcat(buf, "\n"); \
|
|
return ret + 1; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define var_printf(_var, fmt) sysfs_printf(_var, fmt, var(_var))
|
|
#define var_print(_var) sysfs_print(_var, var(_var))
|
|
#define var_hprint(_var) sysfs_hprint(_var, var(_var))
|
|
|
|
#define sysfs_strtoul(file, var) \
|
|
do { \
|
|
if (attr == &sysfs_ ## file) \
|
|
return strtoul_safe(buf, var) ?: (ssize_t) size; \
|
|
} while (0)
|
|
|
|
#define sysfs_strtoul_bool(file, var) \
|
|
do { \
|
|
if (attr == &sysfs_ ## file) { \
|
|
unsigned long v = strtoul_or_return(buf); \
|
|
\
|
|
var = v ? 1 : 0; \
|
|
return size; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define sysfs_strtoul_clamp(file, var, min, max) \
|
|
do { \
|
|
if (attr == &sysfs_ ## file) { \
|
|
unsigned long v = 0; \
|
|
ssize_t ret; \
|
|
ret = strtoul_safe_clamp(buf, v, min, max); \
|
|
if (!ret) { \
|
|
var = v; \
|
|
return size; \
|
|
} \
|
|
return ret; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define strtoul_or_return(cp) \
|
|
({ \
|
|
unsigned long _v; \
|
|
int _r = kstrtoul(cp, 10, &_v); \
|
|
if (_r) \
|
|
return _r; \
|
|
_v; \
|
|
})
|
|
|
|
#define strtoi_h_or_return(cp, v) \
|
|
do { \
|
|
int _r = strtoi_h(cp, &v); \
|
|
if (_r) \
|
|
return _r; \
|
|
} while (0)
|
|
|
|
#define sysfs_hatoi(file, var) \
|
|
do { \
|
|
if (attr == &sysfs_ ## file) \
|
|
return strtoi_h(buf, &var) ?: (ssize_t) size; \
|
|
} while (0)
|
|
|
|
#endif /* _BCACHE_SYSFS_H_ */
|