brintos

brintos / linux-shallow public Read only

0
0
Text · 20.6 KiB · 03e59f8 Raw
894 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * bcache sysfs interfaces4 *5 * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>6 * Copyright 2012 Google, Inc.7 */8 9#ifndef NO_BCACHEFS_SYSFS10 11#include "bcachefs.h"12#include "alloc_background.h"13#include "alloc_foreground.h"14#include "sysfs.h"15#include "btree_cache.h"16#include "btree_io.h"17#include "btree_iter.h"18#include "btree_key_cache.h"19#include "btree_update.h"20#include "btree_update_interior.h"21#include "btree_gc.h"22#include "buckets.h"23#include "clock.h"24#include "compress.h"25#include "disk_accounting.h"26#include "disk_groups.h"27#include "ec.h"28#include "inode.h"29#include "journal.h"30#include "journal_reclaim.h"31#include "keylist.h"32#include "move.h"33#include "movinggc.h"34#include "nocow_locking.h"35#include "opts.h"36#include "rebalance.h"37#include "replicas.h"38#include "super-io.h"39#include "tests.h"40 41#include <linux/blkdev.h>42#include <linux/sort.h>43#include <linux/sched/clock.h>44 45#include "util.h"46 47#define SYSFS_OPS(type)							\48const struct sysfs_ops type ## _sysfs_ops = {				\49	.show	= type ## _show,					\50	.store	= type ## _store					\51}52 53#define SHOW(fn)							\54static ssize_t fn ## _to_text(struct printbuf *,			\55			      struct kobject *, struct attribute *);	\56									\57static ssize_t fn ## _show(struct kobject *kobj, struct attribute *attr,\58			   char *buf)					\59{									\60	struct printbuf out = PRINTBUF;					\61	ssize_t ret = fn ## _to_text(&out, kobj, attr);			\62									\63	if (out.pos && out.buf[out.pos - 1] != '\n')			\64		prt_newline(&out);					\65									\66	if (!ret && out.allocation_failure)				\67		ret = -ENOMEM;						\68									\69	if (!ret) {							\70		ret = min_t(size_t, out.pos, PAGE_SIZE - 1);		\71		memcpy(buf, out.buf, ret);				\72	}								\73	printbuf_exit(&out);						\74	return bch2_err_class(ret);					\75}									\76									\77static ssize_t fn ## _to_text(struct printbuf *out, struct kobject *kobj,\78			      struct attribute *attr)79 80#define STORE(fn)							\81static ssize_t fn ## _store_inner(struct kobject *, struct attribute *,\82			    const char *, size_t);			\83									\84static ssize_t fn ## _store(struct kobject *kobj, struct attribute *attr,\85			    const char *buf, size_t size)		\86{									\87	return bch2_err_class(fn##_store_inner(kobj, attr, buf, size));	\88}									\89									\90static ssize_t fn ## _store_inner(struct kobject *kobj, struct attribute *attr,\91				  const char *buf, size_t size)92 93#define __sysfs_attribute(_name, _mode)					\94	static struct attribute sysfs_##_name =				\95		{ .name = #_name, .mode = _mode }96 97#define write_attribute(n)	__sysfs_attribute(n, 0200)98#define read_attribute(n)	__sysfs_attribute(n, 0444)99#define rw_attribute(n)		__sysfs_attribute(n, 0644)100 101#define sysfs_printf(file, fmt, ...)					\102do {									\103	if (attr == &sysfs_ ## file)					\104		prt_printf(out, fmt "\n", __VA_ARGS__);			\105} while (0)106 107#define sysfs_print(file, var)						\108do {									\109	if (attr == &sysfs_ ## file)					\110		snprint(out, var);					\111} while (0)112 113#define sysfs_hprint(file, val)						\114do {									\115	if (attr == &sysfs_ ## file)					\116		prt_human_readable_s64(out, val);			\117} while (0)118 119#define sysfs_strtoul(file, var)					\120do {									\121	if (attr == &sysfs_ ## file)					\122		return strtoul_safe(buf, var) ?: (ssize_t) size;	\123} while (0)124 125#define sysfs_strtoul_clamp(file, var, min, max)			\126do {									\127	if (attr == &sysfs_ ## file)					\128		return strtoul_safe_clamp(buf, var, min, max)		\129			?: (ssize_t) size;				\130} while (0)131 132#define strtoul_or_return(cp)						\133({									\134	unsigned long _v;						\135	int _r = kstrtoul(cp, 10, &_v);					\136	if (_r)								\137		return _r;						\138	_v;								\139})140 141write_attribute(trigger_gc);142write_attribute(trigger_discards);143write_attribute(trigger_invalidates);144write_attribute(trigger_journal_flush);145write_attribute(trigger_journal_writes);146write_attribute(trigger_btree_cache_shrink);147write_attribute(trigger_btree_key_cache_shrink);148write_attribute(trigger_freelist_wakeup);149rw_attribute(gc_gens_pos);150 151read_attribute(uuid);152read_attribute(minor);153read_attribute(flags);154read_attribute(bucket_size);155read_attribute(first_bucket);156read_attribute(nbuckets);157rw_attribute(durability);158read_attribute(io_done);159read_attribute(io_errors);160write_attribute(io_errors_reset);161 162read_attribute(io_latency_read);163read_attribute(io_latency_write);164read_attribute(io_latency_stats_read);165read_attribute(io_latency_stats_write);166read_attribute(congested);167 168read_attribute(btree_write_stats);169 170read_attribute(btree_cache_size);171read_attribute(compression_stats);172read_attribute(journal_debug);173read_attribute(btree_cache);174read_attribute(btree_key_cache);175read_attribute(btree_reserve_cache);176read_attribute(stripes_heap);177read_attribute(open_buckets);178read_attribute(open_buckets_partial);179read_attribute(write_points);180read_attribute(nocow_lock_table);181 182#ifdef BCH_WRITE_REF_DEBUG183read_attribute(write_refs);184 185static const char * const bch2_write_refs[] = {186#define x(n)	#n,187	BCH_WRITE_REFS()188#undef x189	NULL190};191 192static void bch2_write_refs_to_text(struct printbuf *out, struct bch_fs *c)193{194	bch2_printbuf_tabstop_push(out, 24);195 196	for (unsigned i = 0; i < ARRAY_SIZE(c->writes); i++)197		prt_printf(out, "%s\t%li\n", bch2_write_refs[i], atomic_long_read(&c->writes[i]));198}199#endif200 201read_attribute(internal_uuid);202read_attribute(disk_groups);203 204read_attribute(has_data);205read_attribute(alloc_debug);206read_attribute(accounting);207read_attribute(usage_base);208 209#define x(t, n, ...) read_attribute(t);210BCH_PERSISTENT_COUNTERS()211#undef x212 213rw_attribute(discard);214rw_attribute(label);215 216rw_attribute(copy_gc_enabled);217read_attribute(copy_gc_wait);218 219rw_attribute(rebalance_enabled);220sysfs_pd_controller_attribute(rebalance);221read_attribute(rebalance_status);222 223read_attribute(new_stripes);224 225read_attribute(io_timers_read);226read_attribute(io_timers_write);227 228read_attribute(moving_ctxts);229 230#ifdef CONFIG_BCACHEFS_TESTS231write_attribute(perf_test);232#endif /* CONFIG_BCACHEFS_TESTS */233 234#define x(_name)						\235	static struct attribute sysfs_time_stat_##_name =		\236		{ .name = #_name, .mode = 0644 };237	BCH_TIME_STATS()238#undef x239 240static struct attribute sysfs_state_rw = {241	.name = "state",242	.mode =  0444,243};244 245static size_t bch2_btree_cache_size(struct bch_fs *c)246{247	struct btree_cache *bc = &c->btree_cache;248	size_t ret = 0;249	struct btree *b;250 251	mutex_lock(&bc->lock);252	list_for_each_entry(b, &bc->live[0].list, list)253		ret += btree_buf_bytes(b);254	list_for_each_entry(b, &bc->live[1].list, list)255		ret += btree_buf_bytes(b);256	list_for_each_entry(b, &bc->freeable, list)257		ret += btree_buf_bytes(b);258	mutex_unlock(&bc->lock);259	return ret;260}261 262static int bch2_compression_stats_to_text(struct printbuf *out, struct bch_fs *c)263{264	prt_str(out, "type");265	printbuf_tabstop_push(out, 12);266	printbuf_tabstop_push(out, 16);267	printbuf_tabstop_push(out, 16);268	printbuf_tabstop_push(out, 24);269	prt_printf(out, "type\tcompressed\runcompressed\raverage extent size\r\n");270 271	for (unsigned i = 1; i < BCH_COMPRESSION_TYPE_NR; i++) {272		struct disk_accounting_pos a = {273			.type			= BCH_DISK_ACCOUNTING_compression,274			.compression.type	= i,275		};276		struct bpos p = disk_accounting_pos_to_bpos(&a);277		u64 v[3];278		bch2_accounting_mem_read(c, p, v, ARRAY_SIZE(v));279 280		u64 nr_extents			= v[0];281		u64 sectors_uncompressed	= v[1];282		u64 sectors_compressed		= v[2];283 284		bch2_prt_compression_type(out, i);285		prt_tab(out);286 287		prt_human_readable_u64(out, sectors_compressed << 9);288		prt_tab_rjust(out);289 290		prt_human_readable_u64(out, sectors_uncompressed << 9);291		prt_tab_rjust(out);292 293		prt_human_readable_u64(out, nr_extents294				       ? div64_u64(sectors_uncompressed << 9, nr_extents)295				       : 0);296		prt_tab_rjust(out);297		prt_newline(out);298	}299 300	return 0;301}302 303static void bch2_gc_gens_pos_to_text(struct printbuf *out, struct bch_fs *c)304{305	prt_printf(out, "%s: ", bch2_btree_id_str(c->gc_gens_btree));306	bch2_bpos_to_text(out, c->gc_gens_pos);307	prt_printf(out, "\n");308}309 310static void bch2_fs_usage_base_to_text(struct printbuf *out, struct bch_fs *c)311{312	struct bch_fs_usage_base b = {};313 314	acc_u64s_percpu(&b.hidden, &c->usage->hidden, sizeof(b) / sizeof(u64));315 316	prt_printf(out, "hidden:\t\t%llu\n",	b.hidden);317	prt_printf(out, "btree:\t\t%llu\n",	b.btree);318	prt_printf(out, "data:\t\t%llu\n",	b.data);319	prt_printf(out, "cached:\t%llu\n",	b.cached);320	prt_printf(out, "reserved:\t\t%llu\n",	b.reserved);321	prt_printf(out, "nr_inodes:\t%llu\n",	b.nr_inodes);322}323 324SHOW(bch2_fs)325{326	struct bch_fs *c = container_of(kobj, struct bch_fs, kobj);327 328	sysfs_print(minor,			c->minor);329	sysfs_printf(internal_uuid, "%pU",	c->sb.uuid.b);330 331	if (attr == &sysfs_flags)332		prt_bitflags(out, bch2_fs_flag_strs, c->flags);333 334	sysfs_hprint(btree_cache_size,		bch2_btree_cache_size(c));335 336	if (attr == &sysfs_btree_write_stats)337		bch2_btree_write_stats_to_text(out, c);338 339	if (attr == &sysfs_gc_gens_pos)340		bch2_gc_gens_pos_to_text(out, c);341 342	sysfs_printf(copy_gc_enabled, "%i", c->copy_gc_enabled);343 344	sysfs_printf(rebalance_enabled,		"%i", c->rebalance.enabled);345	sysfs_pd_controller_show(rebalance,	&c->rebalance.pd); /* XXX */346 347	if (attr == &sysfs_copy_gc_wait)348		bch2_copygc_wait_to_text(out, c);349 350	if (attr == &sysfs_rebalance_status)351		bch2_rebalance_status_to_text(out, c);352 353	/* Debugging: */354 355	if (attr == &sysfs_journal_debug)356		bch2_journal_debug_to_text(out, &c->journal);357 358	if (attr == &sysfs_btree_cache)359		bch2_btree_cache_to_text(out, &c->btree_cache);360 361	if (attr == &sysfs_btree_key_cache)362		bch2_btree_key_cache_to_text(out, &c->btree_key_cache);363 364	if (attr == &sysfs_btree_reserve_cache)365		bch2_btree_reserve_cache_to_text(out, c);366 367	if (attr == &sysfs_stripes_heap)368		bch2_stripes_heap_to_text(out, c);369 370	if (attr == &sysfs_open_buckets)371		bch2_open_buckets_to_text(out, c, NULL);372 373	if (attr == &sysfs_open_buckets_partial)374		bch2_open_buckets_partial_to_text(out, c);375 376	if (attr == &sysfs_write_points)377		bch2_write_points_to_text(out, c);378 379	if (attr == &sysfs_compression_stats)380		bch2_compression_stats_to_text(out, c);381 382	if (attr == &sysfs_new_stripes)383		bch2_new_stripes_to_text(out, c);384 385	if (attr == &sysfs_io_timers_read)386		bch2_io_timers_to_text(out, &c->io_clock[READ]);387 388	if (attr == &sysfs_io_timers_write)389		bch2_io_timers_to_text(out, &c->io_clock[WRITE]);390 391	if (attr == &sysfs_moving_ctxts)392		bch2_fs_moving_ctxts_to_text(out, c);393 394#ifdef BCH_WRITE_REF_DEBUG395	if (attr == &sysfs_write_refs)396		bch2_write_refs_to_text(out, c);397#endif398 399	if (attr == &sysfs_nocow_lock_table)400		bch2_nocow_locks_to_text(out, &c->nocow_locks);401 402	if (attr == &sysfs_disk_groups)403		bch2_disk_groups_to_text(out, c);404 405	if (attr == &sysfs_alloc_debug)406		bch2_fs_alloc_debug_to_text(out, c);407 408	if (attr == &sysfs_accounting)409		bch2_fs_accounting_to_text(out, c);410 411	if (attr == &sysfs_usage_base)412		bch2_fs_usage_base_to_text(out, c);413 414	return 0;415}416 417STORE(bch2_fs)418{419	struct bch_fs *c = container_of(kobj, struct bch_fs, kobj);420 421	if (attr == &sysfs_copy_gc_enabled) {422		ssize_t ret = strtoul_safe(buf, c->copy_gc_enabled)423			?: (ssize_t) size;424 425		if (c->copygc_thread)426			wake_up_process(c->copygc_thread);427		return ret;428	}429 430	if (attr == &sysfs_rebalance_enabled) {431		ssize_t ret = strtoul_safe(buf, c->rebalance.enabled)432			?: (ssize_t) size;433 434		rebalance_wakeup(c);435		return ret;436	}437 438	sysfs_pd_controller_store(rebalance,	&c->rebalance.pd);439 440	/* Debugging: */441 442	if (!test_bit(BCH_FS_started, &c->flags))443		return -EPERM;444 445	/* Debugging: */446 447	if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_sysfs))448		return -EROFS;449 450	if (attr == &sysfs_trigger_btree_cache_shrink) {451		struct btree_cache *bc = &c->btree_cache;452		struct shrink_control sc;453 454		sc.gfp_mask = GFP_KERNEL;455		sc.nr_to_scan = strtoul_or_return(buf);456		bc->live[0].shrink->scan_objects(bc->live[0].shrink, &sc);457	}458 459	if (attr == &sysfs_trigger_btree_key_cache_shrink) {460		struct shrink_control sc;461 462		sc.gfp_mask = GFP_KERNEL;463		sc.nr_to_scan = strtoul_or_return(buf);464		c->btree_key_cache.shrink->scan_objects(c->btree_key_cache.shrink, &sc);465	}466 467	if (attr == &sysfs_trigger_gc)468		bch2_gc_gens(c);469 470	if (attr == &sysfs_trigger_discards)471		bch2_do_discards(c);472 473	if (attr == &sysfs_trigger_invalidates)474		bch2_do_invalidates(c);475 476	if (attr == &sysfs_trigger_journal_flush) {477		bch2_journal_flush_all_pins(&c->journal);478		bch2_journal_meta(&c->journal);479	}480 481	if (attr == &sysfs_trigger_journal_writes)482		bch2_journal_do_writes(&c->journal);483 484	if (attr == &sysfs_trigger_freelist_wakeup)485		closure_wake_up(&c->freelist_wait);486 487#ifdef CONFIG_BCACHEFS_TESTS488	if (attr == &sysfs_perf_test) {489		char *tmp = kstrdup(buf, GFP_KERNEL), *p = tmp;490		char *test		= strsep(&p, " \t\n");491		char *nr_str		= strsep(&p, " \t\n");492		char *threads_str	= strsep(&p, " \t\n");493		unsigned threads;494		u64 nr;495		int ret = -EINVAL;496 497		if (threads_str &&498		    !(ret = kstrtouint(threads_str, 10, &threads)) &&499		    !(ret = bch2_strtoull_h(nr_str, &nr)))500			ret = bch2_btree_perf_test(c, test, nr, threads);501		kfree(tmp);502 503		if (ret)504			size = ret;505	}506#endif507	bch2_write_ref_put(c, BCH_WRITE_REF_sysfs);508	return size;509}510SYSFS_OPS(bch2_fs);511 512struct attribute *bch2_fs_files[] = {513	&sysfs_minor,514	&sysfs_btree_cache_size,515	&sysfs_btree_write_stats,516 517	&sysfs_rebalance_status,518 519	&sysfs_compression_stats,520 521#ifdef CONFIG_BCACHEFS_TESTS522	&sysfs_perf_test,523#endif524	NULL525};526 527/* counters dir */528 529SHOW(bch2_fs_counters)530{531	struct bch_fs *c = container_of(kobj, struct bch_fs, counters_kobj);532	u64 counter = 0;533	u64 counter_since_mount = 0;534 535	printbuf_tabstop_push(out, 32);536 537	#define x(t, ...) \538		if (attr == &sysfs_##t) {					\539			counter             = percpu_u64_get(&c->counters[BCH_COUNTER_##t]);\540			counter_since_mount = counter - c->counters_on_mount[BCH_COUNTER_##t];\541			prt_printf(out, "since mount:\t");			\542			prt_human_readable_u64(out, counter_since_mount);	\543			prt_newline(out);					\544										\545			prt_printf(out, "since filesystem creation:\t");	\546			prt_human_readable_u64(out, counter);			\547			prt_newline(out);					\548		}549	BCH_PERSISTENT_COUNTERS()550	#undef x551	return 0;552}553 554STORE(bch2_fs_counters) {555	return 0;556}557 558SYSFS_OPS(bch2_fs_counters);559 560struct attribute *bch2_fs_counters_files[] = {561#define x(t, ...) \562	&sysfs_##t,563	BCH_PERSISTENT_COUNTERS()564#undef x565	NULL566};567/* internal dir - just a wrapper */568 569SHOW(bch2_fs_internal)570{571	struct bch_fs *c = container_of(kobj, struct bch_fs, internal);572 573	return bch2_fs_to_text(out, &c->kobj, attr);574}575 576STORE(bch2_fs_internal)577{578	struct bch_fs *c = container_of(kobj, struct bch_fs, internal);579 580	return bch2_fs_store(&c->kobj, attr, buf, size);581}582SYSFS_OPS(bch2_fs_internal);583 584struct attribute *bch2_fs_internal_files[] = {585	&sysfs_flags,586	&sysfs_journal_debug,587	&sysfs_btree_cache,588	&sysfs_btree_key_cache,589	&sysfs_btree_reserve_cache,590	&sysfs_new_stripes,591	&sysfs_stripes_heap,592	&sysfs_open_buckets,593	&sysfs_open_buckets_partial,594	&sysfs_write_points,595#ifdef BCH_WRITE_REF_DEBUG596	&sysfs_write_refs,597#endif598	&sysfs_nocow_lock_table,599	&sysfs_io_timers_read,600	&sysfs_io_timers_write,601 602	&sysfs_trigger_gc,603	&sysfs_trigger_discards,604	&sysfs_trigger_invalidates,605	&sysfs_trigger_journal_flush,606	&sysfs_trigger_journal_writes,607	&sysfs_trigger_btree_cache_shrink,608	&sysfs_trigger_btree_key_cache_shrink,609	&sysfs_trigger_freelist_wakeup,610 611	&sysfs_gc_gens_pos,612 613	&sysfs_copy_gc_enabled,614	&sysfs_copy_gc_wait,615 616	&sysfs_rebalance_enabled,617	sysfs_pd_controller_files(rebalance),618 619	&sysfs_moving_ctxts,620 621	&sysfs_internal_uuid,622 623	&sysfs_disk_groups,624	&sysfs_alloc_debug,625	&sysfs_accounting,626	&sysfs_usage_base,627	NULL628};629 630/* options */631 632SHOW(bch2_fs_opts_dir)633{634	struct bch_fs *c = container_of(kobj, struct bch_fs, opts_dir);635	const struct bch_option *opt = container_of(attr, struct bch_option, attr);636	int id = opt - bch2_opt_table;637	u64 v = bch2_opt_get_by_id(&c->opts, id);638 639	bch2_opt_to_text(out, c, c->disk_sb.sb, opt, v, OPT_SHOW_FULL_LIST);640	prt_char(out, '\n');641 642	return 0;643}644 645STORE(bch2_fs_opts_dir)646{647	struct bch_fs *c = container_of(kobj, struct bch_fs, opts_dir);648	const struct bch_option *opt = container_of(attr, struct bch_option, attr);649	int ret, id = opt - bch2_opt_table;650	char *tmp;651	u64 v;652 653	/*654	 * We don't need to take c->writes for correctness, but it eliminates an655	 * unsightly error message in the dmesg log when we're RO:656	 */657	if (unlikely(!bch2_write_ref_tryget(c, BCH_WRITE_REF_sysfs)))658		return -EROFS;659 660	tmp = kstrdup(buf, GFP_KERNEL);661	if (!tmp) {662		ret = -ENOMEM;663		goto err;664	}665 666	ret = bch2_opt_parse(c, opt, strim(tmp), &v, NULL);667	kfree(tmp);668 669	if (ret < 0)670		goto err;671 672	ret = bch2_opt_check_may_set(c, id, v);673	if (ret < 0)674		goto err;675 676	bch2_opt_set_sb(c, NULL, opt, v);677	bch2_opt_set_by_id(&c->opts, id, v);678 679	if (v &&680	    (id == Opt_background_target ||681	     id == Opt_background_compression ||682	     (id == Opt_compression && !c->opts.background_compression)))683		bch2_set_rebalance_needs_scan(c, 0);684 685	ret = size;686err:687	bch2_write_ref_put(c, BCH_WRITE_REF_sysfs);688	return ret;689}690SYSFS_OPS(bch2_fs_opts_dir);691 692struct attribute *bch2_fs_opts_dir_files[] = { NULL };693 694int bch2_opts_create_sysfs_files(struct kobject *kobj)695{696	const struct bch_option *i;697	int ret;698 699	for (i = bch2_opt_table;700	     i < bch2_opt_table + bch2_opts_nr;701	     i++) {702		if (!(i->flags & OPT_FS))703			continue;704 705		ret = sysfs_create_file(kobj, &i->attr);706		if (ret)707			return ret;708	}709 710	return 0;711}712 713/* time stats */714 715SHOW(bch2_fs_time_stats)716{717	struct bch_fs *c = container_of(kobj, struct bch_fs, time_stats);718 719#define x(name)								\720	if (attr == &sysfs_time_stat_##name)				\721		bch2_time_stats_to_text(out, &c->times[BCH_TIME_##name]);722	BCH_TIME_STATS()723#undef x724 725	return 0;726}727 728STORE(bch2_fs_time_stats)729{730	struct bch_fs *c = container_of(kobj, struct bch_fs, time_stats);731 732#define x(name)								\733	if (attr == &sysfs_time_stat_##name)				\734		bch2_time_stats_reset(&c->times[BCH_TIME_##name]);735	BCH_TIME_STATS()736#undef x737	return size;738}739SYSFS_OPS(bch2_fs_time_stats);740 741struct attribute *bch2_fs_time_stats_files[] = {742#define x(name)						\743	&sysfs_time_stat_##name,744	BCH_TIME_STATS()745#undef x746	NULL747};748 749static const char * const bch2_rw[] = {750	"read",751	"write",752	NULL753};754 755static void dev_io_done_to_text(struct printbuf *out, struct bch_dev *ca)756{757	int rw, i;758 759	for (rw = 0; rw < 2; rw++) {760		prt_printf(out, "%s:\n", bch2_rw[rw]);761 762		for (i = 1; i < BCH_DATA_NR; i++)763			prt_printf(out, "%-12s:%12llu\n",764			       bch2_data_type_str(i),765			       percpu_u64_get(&ca->io_done->sectors[rw][i]) << 9);766	}767}768 769SHOW(bch2_dev)770{771	struct bch_dev *ca = container_of(kobj, struct bch_dev, kobj);772	struct bch_fs *c = ca->fs;773 774	sysfs_printf(uuid,		"%pU\n", ca->uuid.b);775 776	sysfs_print(bucket_size,	bucket_bytes(ca));777	sysfs_print(first_bucket,	ca->mi.first_bucket);778	sysfs_print(nbuckets,		ca->mi.nbuckets);779	sysfs_print(durability,		ca->mi.durability);780	sysfs_print(discard,		ca->mi.discard);781 782	if (attr == &sysfs_label) {783		if (ca->mi.group)784			bch2_disk_path_to_text(out, c, ca->mi.group - 1);785		prt_char(out, '\n');786	}787 788	if (attr == &sysfs_has_data) {789		prt_bitflags(out, __bch2_data_types, bch2_dev_has_data(c, ca));790		prt_char(out, '\n');791	}792 793	if (attr == &sysfs_state_rw) {794		prt_string_option(out, bch2_member_states, ca->mi.state);795		prt_char(out, '\n');796	}797 798	if (attr == &sysfs_io_done)799		dev_io_done_to_text(out, ca);800 801	if (attr == &sysfs_io_errors)802		bch2_dev_io_errors_to_text(out, ca);803 804	sysfs_print(io_latency_read,		atomic64_read(&ca->cur_latency[READ]));805	sysfs_print(io_latency_write,		atomic64_read(&ca->cur_latency[WRITE]));806 807	if (attr == &sysfs_io_latency_stats_read)808		bch2_time_stats_to_text(out, &ca->io_latency[READ].stats);809 810	if (attr == &sysfs_io_latency_stats_write)811		bch2_time_stats_to_text(out, &ca->io_latency[WRITE].stats);812 813	sysfs_printf(congested,			"%u%%",814		     clamp(atomic_read(&ca->congested), 0, CONGESTED_MAX)815		     * 100 / CONGESTED_MAX);816 817	if (attr == &sysfs_alloc_debug)818		bch2_dev_alloc_debug_to_text(out, ca);819 820	if (attr == &sysfs_open_buckets)821		bch2_open_buckets_to_text(out, c, ca);822 823	return 0;824}825 826STORE(bch2_dev)827{828	struct bch_dev *ca = container_of(kobj, struct bch_dev, kobj);829	struct bch_fs *c = ca->fs;830 831	if (attr == &sysfs_discard) {832		bool v = strtoul_or_return(buf);833 834		bch2_opt_set_sb(c, ca, bch2_opt_table + Opt_discard, v);835	}836 837	if (attr == &sysfs_durability) {838		u64 v = strtoul_or_return(buf);839 840		bch2_opt_set_sb(c, ca, bch2_opt_table + Opt_durability, v);841	}842 843	if (attr == &sysfs_label) {844		char *tmp;845		int ret;846 847		tmp = kstrdup(buf, GFP_KERNEL);848		if (!tmp)849			return -ENOMEM;850 851		ret = bch2_dev_group_set(c, ca, strim(tmp));852		kfree(tmp);853		if (ret)854			return ret;855	}856 857	if (attr == &sysfs_io_errors_reset)858		bch2_dev_errors_reset(ca);859 860	return size;861}862SYSFS_OPS(bch2_dev);863 864struct attribute *bch2_dev_files[] = {865	&sysfs_uuid,866	&sysfs_bucket_size,867	&sysfs_first_bucket,868	&sysfs_nbuckets,869	&sysfs_durability,870 871	/* settings: */872	&sysfs_discard,873	&sysfs_state_rw,874	&sysfs_label,875 876	&sysfs_has_data,877	&sysfs_io_done,878	&sysfs_io_errors,879	&sysfs_io_errors_reset,880 881	&sysfs_io_latency_read,882	&sysfs_io_latency_write,883	&sysfs_io_latency_stats_read,884	&sysfs_io_latency_stats_write,885	&sysfs_congested,886 887	/* debug: */888	&sysfs_alloc_debug,889	&sysfs_open_buckets,890	NULL891};892 893#endif  /* _BCACHEFS_SYSFS_H_ */894