#include <linux/blkdev.h>
#include <linux/sort.h>
+#include "util.h"
+
+#define SYSFS_OPS(type) \
+struct sysfs_ops type ## _sysfs_ops = { \
+ .show = type ## _show, \
+ .store = type ## _store \
+}
+
+#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 __sysfs_attribute(_name, _mode) \
+ static struct attribute sysfs_##_name = \
+ { .name = #_name, .mode = _mode }
+
+#define write_attribute(n) __sysfs_attribute(n, S_IWUSR)
+#define read_attribute(n) __sysfs_attribute(n, S_IRUGO)
+#define rw_attribute(n) __sysfs_attribute(n, S_IRUGO|S_IWUSR)
+
+#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 = bch2_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_clamp(file, var, min, max) \
+do { \
+ if (attr == &sysfs_ ## file) \
+ return strtoul_safe_clamp(buf, var, min, max) \
+ ?: (ssize_t) size; \
+} while (0)
+
+#define strtoul_or_return(cp) \
+({ \
+ unsigned long _v; \
+ int _r = kstrtoul(cp, 10, &_v); \
+ if (_r) \
+ return _r; \
+ _v; \
+})
+
+#define strtoul_restrict_or_return(cp, min, max) \
+({ \
+ unsigned long __v = 0; \
+ int _r = strtoul_safe_restrict(cp, __v, min, max); \
+ if (_r) \
+ return _r; \
+ __v; \
+})
+
+#define strtoi_h_or_return(cp) \
+({ \
+ u64 _v; \
+ int _r = strtoi_h(cp, &_v); \
+ if (_r) \
+ return _r; \
+ _v; \
+})
+
+#define sysfs_hatoi(file, var) \
+do { \
+ if (attr == &sysfs_ ## file) \
+ return strtoi_h(buf, &var) ?: (ssize_t) size; \
+} while (0)
+
write_attribute(trigger_btree_coalesce);
write_attribute(trigger_gc);
write_attribute(prune_cache);
return size;
}
+SYSFS_OPS(bch2_fs);
-static struct attribute *bch2_fs_files[] = {
+struct attribute *bch2_fs_files[] = {
&sysfs_journal_write_delay_ms,
&sysfs_journal_reclaim_delay_ms,
&sysfs_journal_entry_size_max,
&sysfs_journal_flush,
NULL
};
-KTYPE(bch2_fs);
/* internal dir - just a wrapper */
struct bch_fs *c = container_of(kobj, struct bch_fs, internal);
return bch2_fs_store(&c->kobj, attr, buf, size);
}
+SYSFS_OPS(bch2_fs_internal);
-static void bch2_fs_internal_release(struct kobject *k)
-{
-}
-
-static struct attribute *bch2_fs_internal_files[] = {
+struct attribute *bch2_fs_internal_files[] = {
&sysfs_journal_debug,
&sysfs_alloc_debug,
NULL
};
-KTYPE(bch2_fs_internal);
/* options */
return size;
}
+SYSFS_OPS(bch2_fs_opts_dir);
-static void bch2_fs_opts_dir_release(struct kobject *k)
-{
-}
-
-static struct attribute *bch2_fs_opts_dir_files[] = {
+struct attribute *bch2_fs_opts_dir_files[] = {
#define BCH_OPT(_name, ...) \
&sysfs_opt_##_name,
NULL
};
-KTYPE(bch2_fs_opts_dir);
/* time stats */
return size;
}
+SYSFS_OPS(bch2_fs_time_stats);
-static void bch2_fs_time_stats_release(struct kobject *k)
-{
-}
-
-static struct attribute *bch2_fs_time_stats_files[] = {
+struct attribute *bch2_fs_time_stats_files[] = {
#define BCH_TIME_STAT(name, frequency_units, duration_units) \
sysfs_time_stats_attribute_list(name, frequency_units, duration_units)
BCH_TIME_STATS()
NULL
};
-KTYPE(bch2_fs_time_stats);
typedef unsigned (bucket_map_fn)(struct bch_dev *, struct bucket *, void *);
return size;
}
+SYSFS_OPS(bch2_dev);
-static struct attribute *bch2_dev_files[] = {
+struct attribute *bch2_dev_files[] = {
&sysfs_uuid,
&sysfs_bucket_size,
&sysfs_bucket_size_bytes,
sysfs_pd_controller_files(copy_gc),
NULL
};
-KTYPE(bch2_dev);