Blame view

drivers/md/bcache/sysfs.c 21.7 KB
cafe56359   Kent Overstreet   bcache: A block l...
1
2
3
4
5
6
7
8
9
10
11
  /*
   * bcache sysfs interfaces
   *
   * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com>
   * Copyright 2012 Google, Inc.
   */
  
  #include "bcache.h"
  #include "sysfs.h"
  #include "btree.h"
  #include "request.h"
279afbad4   Kent Overstreet   bcache: Track dir...
12
  #include "writeback.h"
cafe56359   Kent Overstreet   bcache: A block l...
13

c37511b86   Kent Overstreet   bcache: Fix/revam...
14
  #include <linux/blkdev.h>
cafe56359   Kent Overstreet   bcache: A block l...
15
16
17
18
19
20
21
22
  #include <linux/sort.h>
  
  static const char * const cache_replacement_policies[] = {
  	"lru",
  	"fifo",
  	"random",
  	NULL
  };
77c320eb4   Kent Overstreet   bcache: Add on er...
23
24
25
26
27
  static const char * const error_actions[] = {
  	"unregister",
  	"panic",
  	NULL
  };
cafe56359   Kent Overstreet   bcache: A block l...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  write_attribute(attach);
  write_attribute(detach);
  write_attribute(unregister);
  write_attribute(stop);
  write_attribute(clear_stats);
  write_attribute(trigger_gc);
  write_attribute(prune_cache);
  write_attribute(flash_vol_create);
  
  read_attribute(bucket_size);
  read_attribute(block_size);
  read_attribute(nbuckets);
  read_attribute(tree_depth);
  read_attribute(root_usage_percent);
  read_attribute(priority_stats);
  read_attribute(btree_cache_size);
  read_attribute(btree_cache_max_chain);
  read_attribute(cache_available_percent);
  read_attribute(written);
  read_attribute(btree_written);
  read_attribute(metadata_written);
  read_attribute(active_journal_entries);
  
  sysfs_time_stats_attribute(btree_gc,	sec, ms);
  sysfs_time_stats_attribute(btree_split, sec, us);
  sysfs_time_stats_attribute(btree_sort,	ms,  us);
  sysfs_time_stats_attribute(btree_read,	ms,  us);
cafe56359   Kent Overstreet   bcache: A block l...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  
  read_attribute(btree_nodes);
  read_attribute(btree_used_percent);
  read_attribute(average_key_size);
  read_attribute(dirty_data);
  read_attribute(bset_tree_stats);
  
  read_attribute(state);
  read_attribute(cache_read_races);
  read_attribute(writeback_keys_done);
  read_attribute(writeback_keys_failed);
  read_attribute(io_errors);
  read_attribute(congested);
  rw_attribute(congested_read_threshold_us);
  rw_attribute(congested_write_threshold_us);
  
  rw_attribute(sequential_cutoff);
cafe56359   Kent Overstreet   bcache: A block l...
72
73
74
75
76
77
78
79
80
81
82
  rw_attribute(data_csum);
  rw_attribute(cache_mode);
  rw_attribute(writeback_metadata);
  rw_attribute(writeback_running);
  rw_attribute(writeback_percent);
  rw_attribute(writeback_delay);
  rw_attribute(writeback_rate);
  
  rw_attribute(writeback_rate_update_seconds);
  rw_attribute(writeback_rate_d_term);
  rw_attribute(writeback_rate_p_term_inverse);
cafe56359   Kent Overstreet   bcache: A block l...
83
  read_attribute(writeback_rate_debug);
72c270612   Kent Overstreet   bcache: Write out...
84
85
  read_attribute(stripe_size);
  read_attribute(partial_stripes_expensive);
cafe56359   Kent Overstreet   bcache: A block l...
86
87
88
89
90
91
  rw_attribute(synchronous);
  rw_attribute(journal_delay_ms);
  rw_attribute(discard);
  rw_attribute(running);
  rw_attribute(label);
  rw_attribute(readahead);
77c320eb4   Kent Overstreet   bcache: Add on er...
92
  rw_attribute(errors);
cafe56359   Kent Overstreet   bcache: A block l...
93
94
95
  rw_attribute(io_error_limit);
  rw_attribute(io_error_halflife);
  rw_attribute(verify);
5ceaaad70   Kent Overstreet   bcache: Bypass to...
96
  rw_attribute(bypass_torture_test);
cafe56359   Kent Overstreet   bcache: A block l...
97
98
  rw_attribute(key_merging_disabled);
  rw_attribute(gc_always_rewrite);
280481d06   Kent Overstreet   bcache: Debug cod...
99
  rw_attribute(expensive_debug_checks);
cafe56359   Kent Overstreet   bcache: A block l...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  rw_attribute(cache_replacement_policy);
  rw_attribute(btree_shrinker_disabled);
  rw_attribute(copy_gc_enabled);
  rw_attribute(size);
  
  SHOW(__bch_cached_dev)
  {
  	struct cached_dev *dc = container_of(kobj, struct cached_dev,
  					     disk.kobj);
  	const char *states[] = { "no cache", "clean", "dirty", "inconsistent" };
  
  #define var(stat)		(dc->stat)
  
  	if (attr == &sysfs_cache_mode)
169ef1cf6   Kent Overstreet   bcache: Don't exp...
114
115
116
  		return bch_snprint_string_list(buf, PAGE_SIZE,
  					       bch_cache_modes + 1,
  					       BDEV_CACHE_MODE(&dc->sb));
cafe56359   Kent Overstreet   bcache: A block l...
117
118
119
  
  	sysfs_printf(data_csum,		"%i", dc->disk.data_csum);
  	var_printf(verify,		"%i");
5ceaaad70   Kent Overstreet   bcache: Bypass to...
120
  	var_printf(bypass_torture_test,	"%i");
cafe56359   Kent Overstreet   bcache: A block l...
121
122
123
124
  	var_printf(writeback_metadata,	"%i");
  	var_printf(writeback_running,	"%i");
  	var_print(writeback_delay);
  	var_print(writeback_percent);
16749c23c   Kent Overstreet   bcache: New write...
125
  	sysfs_hprint(writeback_rate,	dc->writeback_rate.rate << 9);
cafe56359   Kent Overstreet   bcache: A block l...
126
127
128
129
  
  	var_print(writeback_rate_update_seconds);
  	var_print(writeback_rate_d_term);
  	var_print(writeback_rate_p_term_inverse);
cafe56359   Kent Overstreet   bcache: A block l...
130
131
  
  	if (attr == &sysfs_writeback_rate_debug) {
16749c23c   Kent Overstreet   bcache: New write...
132
  		char rate[20];
cafe56359   Kent Overstreet   bcache: A block l...
133
  		char dirty[20];
cafe56359   Kent Overstreet   bcache: A block l...
134
  		char target[20];
16749c23c   Kent Overstreet   bcache: New write...
135
136
137
138
139
140
141
  		char proportional[20];
  		char derivative[20];
  		char change[20];
  		s64 next_io;
  
  		bch_hprint(rate,	dc->writeback_rate.rate << 9);
  		bch_hprint(dirty,	bcache_dev_sectors_dirty(&dc->disk) << 9);
169ef1cf6   Kent Overstreet   bcache: Don't exp...
142
  		bch_hprint(target,	dc->writeback_rate_target << 9);
16749c23c   Kent Overstreet   bcache: New write...
143
144
145
146
147
148
  		bch_hprint(proportional,dc->writeback_rate_proportional << 9);
  		bch_hprint(derivative,	dc->writeback_rate_derivative << 9);
  		bch_hprint(change,	dc->writeback_rate_change << 9);
  
  		next_io = div64_s64(dc->writeback_rate.next - local_clock(),
  				    NSEC_PER_MSEC);
cafe56359   Kent Overstreet   bcache: A block l...
149
150
  
  		return sprintf(buf,
16749c23c   Kent Overstreet   bcache: New write...
151
152
  			       "rate:\t\t%s/sec
  "
cafe56359   Kent Overstreet   bcache: A block l...
153
154
  			       "dirty:\t\t%s
  "
16749c23c   Kent Overstreet   bcache: New write...
155
156
157
158
  			       "target:\t\t%s
  "
  			       "proportional:\t%s
  "
cafe56359   Kent Overstreet   bcache: A block l...
159
160
  			       "derivative:\t%s
  "
16749c23c   Kent Overstreet   bcache: New write...
161
162
163
164
165
166
  			       "change:\t\t%s/sec
  "
  			       "next io:\t%llims
  ",
  			       rate, dirty, target, proportional,
  			       derivative, change, next_io);
cafe56359   Kent Overstreet   bcache: A block l...
167
168
169
  	}
  
  	sysfs_hprint(dirty_data,
279afbad4   Kent Overstreet   bcache: Track dir...
170
  		     bcache_dev_sectors_dirty(&dc->disk) << 9);
cafe56359   Kent Overstreet   bcache: A block l...
171

2d679fc75   Kent Overstreet   bcache: Stripe si...
172
  	sysfs_hprint(stripe_size,	dc->disk.stripe_size << 9);
72c270612   Kent Overstreet   bcache: Write out...
173
  	var_printf(partial_stripes_expensive,	"%u");
cafe56359   Kent Overstreet   bcache: A block l...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  	var_hprint(sequential_cutoff);
  	var_hprint(readahead);
  
  	sysfs_print(running,		atomic_read(&dc->running));
  	sysfs_print(state,		states[BDEV_STATE(&dc->sb)]);
  
  	if (attr == &sysfs_label) {
  		memcpy(buf, dc->sb.label, SB_LABEL_SIZE);
  		buf[SB_LABEL_SIZE + 1] = '\0';
  		strcat(buf, "
  ");
  		return strlen(buf);
  	}
  
  #undef var
  	return 0;
  }
  SHOW_LOCKED(bch_cached_dev)
  
  STORE(__cached_dev)
  {
  	struct cached_dev *dc = container_of(kobj, struct cached_dev,
  					     disk.kobj);
  	unsigned v = size;
  	struct cache_set *c;
ab9e14002   Gabriel de Perthuis   bcache: Send labe...
199
  	struct kobj_uevent_env *env;
cafe56359   Kent Overstreet   bcache: A block l...
200
201
  
  #define d_strtoul(var)		sysfs_strtoul(var, dc->var)
16749c23c   Kent Overstreet   bcache: New write...
202
  #define d_strtoul_nonzero(var)	sysfs_strtoul_clamp(var, dc->var, 1, INT_MAX)
cafe56359   Kent Overstreet   bcache: A block l...
203
204
205
206
  #define d_strtoi_h(var)		sysfs_hatoi(var, dc->var)
  
  	sysfs_strtoul(data_csum,	dc->disk.data_csum);
  	d_strtoul(verify);
5ceaaad70   Kent Overstreet   bcache: Bypass to...
207
  	d_strtoul(bypass_torture_test);
cafe56359   Kent Overstreet   bcache: A block l...
208
209
210
  	d_strtoul(writeback_metadata);
  	d_strtoul(writeback_running);
  	d_strtoul(writeback_delay);
16749c23c   Kent Overstreet   bcache: New write...
211

cafe56359   Kent Overstreet   bcache: A block l...
212
  	sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40);
16749c23c   Kent Overstreet   bcache: New write...
213
214
215
216
  	sysfs_strtoul_clamp(writeback_rate,
  			    dc->writeback_rate.rate, 1, INT_MAX);
  
  	d_strtoul_nonzero(writeback_rate_update_seconds);
cafe56359   Kent Overstreet   bcache: A block l...
217
  	d_strtoul(writeback_rate_d_term);
16749c23c   Kent Overstreet   bcache: New write...
218
  	d_strtoul_nonzero(writeback_rate_p_term_inverse);
cafe56359   Kent Overstreet   bcache: A block l...
219

cafe56359   Kent Overstreet   bcache: A block l...
220
221
222
223
224
225
226
227
228
229
230
  	d_strtoi_h(sequential_cutoff);
  	d_strtoi_h(readahead);
  
  	if (attr == &sysfs_clear_stats)
  		bch_cache_accounting_clear(&dc->accounting);
  
  	if (attr == &sysfs_running &&
  	    strtoul_or_return(buf))
  		bch_cached_dev_run(dc);
  
  	if (attr == &sysfs_cache_mode) {
169ef1cf6   Kent Overstreet   bcache: Don't exp...
231
  		ssize_t v = bch_read_string_list(buf, bch_cache_modes + 1);
cafe56359   Kent Overstreet   bcache: A block l...
232
233
234
235
236
237
238
239
240
241
242
  
  		if (v < 0)
  			return v;
  
  		if ((unsigned) v != BDEV_CACHE_MODE(&dc->sb)) {
  			SET_BDEV_CACHE_MODE(&dc->sb, v);
  			bch_write_bdev_super(dc, NULL);
  		}
  	}
  
  	if (attr == &sysfs_label) {
aee6f1cff   Gabriel de Perthuis   bcache: Strip end...
243
244
245
246
247
248
249
250
  		if (size > SB_LABEL_SIZE)
  			return -EINVAL;
  		memcpy(dc->sb.label, buf, size);
  		if (size < SB_LABEL_SIZE)
  			dc->sb.label[size] = '\0';
  		if (size && dc->sb.label[size - 1] == '
  ')
  			dc->sb.label[size - 1] = '\0';
cafe56359   Kent Overstreet   bcache: A block l...
251
252
253
254
255
256
  		bch_write_bdev_super(dc, NULL);
  		if (dc->disk.c) {
  			memcpy(dc->disk.c->uuids[dc->disk.id].label,
  			       buf, SB_LABEL_SIZE);
  			bch_uuid_write(dc->disk.c);
  		}
ab9e14002   Gabriel de Perthuis   bcache: Send labe...
257
  		env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
d2a65ce2a   Dan Carpenter   bcache: check for...
258
259
  		if (!env)
  			return -ENOMEM;
ab9e14002   Gabriel de Perthuis   bcache: Send labe...
260
261
262
263
264
265
  		add_uevent_var(env, "DRIVER=bcache");
  		add_uevent_var(env, "CACHED_UUID=%pU", dc->sb.uuid),
  		add_uevent_var(env, "CACHED_LABEL=%s", buf);
  		kobject_uevent_env(
  			&disk_to_dev(dc->disk.disk)->kobj, KOBJ_CHANGE, env->envp);
  		kfree(env);
cafe56359   Kent Overstreet   bcache: A block l...
266
267
268
  	}
  
  	if (attr == &sysfs_attach) {
169ef1cf6   Kent Overstreet   bcache: Don't exp...
269
  		if (bch_parse_uuid(buf, dc->sb.set_uuid) < 16)
cafe56359   Kent Overstreet   bcache: A block l...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  			return -EINVAL;
  
  		list_for_each_entry(c, &bch_cache_sets, list) {
  			v = bch_cached_dev_attach(dc, c);
  			if (!v)
  				return size;
  		}
  
  		pr_err("Can't attach %s: cache set not found", buf);
  		size = v;
  	}
  
  	if (attr == &sysfs_detach && dc->disk.c)
  		bch_cached_dev_detach(dc);
  
  	if (attr == &sysfs_stop)
  		bcache_device_stop(&dc->disk);
  
  	return size;
  }
  
  STORE(bch_cached_dev)
  {
  	struct cached_dev *dc = container_of(kobj, struct cached_dev,
  					     disk.kobj);
  
  	mutex_lock(&bch_register_lock);
  	size = __cached_dev_store(kobj, attr, buf, size);
  
  	if (attr == &sysfs_writeback_running)
  		bch_writeback_queue(dc);
  
  	if (attr == &sysfs_writeback_percent)
  		schedule_delayed_work(&dc->writeback_rate_update,
  				      dc->writeback_rate_update_seconds * HZ);
  
  	mutex_unlock(&bch_register_lock);
  	return size;
  }
  
  static struct attribute *bch_cached_dev_files[] = {
  	&sysfs_attach,
  	&sysfs_detach,
  	&sysfs_stop,
  #if 0
  	&sysfs_data_csum,
  #endif
  	&sysfs_cache_mode,
  	&sysfs_writeback_metadata,
  	&sysfs_writeback_running,
  	&sysfs_writeback_delay,
  	&sysfs_writeback_percent,
  	&sysfs_writeback_rate,
  	&sysfs_writeback_rate_update_seconds,
  	&sysfs_writeback_rate_d_term,
  	&sysfs_writeback_rate_p_term_inverse,
cafe56359   Kent Overstreet   bcache: A block l...
326
327
  	&sysfs_writeback_rate_debug,
  	&sysfs_dirty_data,
72c270612   Kent Overstreet   bcache: Write out...
328
329
  	&sysfs_stripe_size,
  	&sysfs_partial_stripes_expensive,
cafe56359   Kent Overstreet   bcache: A block l...
330
  	&sysfs_sequential_cutoff,
cafe56359   Kent Overstreet   bcache: A block l...
331
332
333
334
335
336
337
  	&sysfs_clear_stats,
  	&sysfs_running,
  	&sysfs_state,
  	&sysfs_label,
  	&sysfs_readahead,
  #ifdef CONFIG_BCACHE_DEBUG
  	&sysfs_verify,
5ceaaad70   Kent Overstreet   bcache: Bypass to...
338
  	&sysfs_bypass_torture_test,
cafe56359   Kent Overstreet   bcache: A block l...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  #endif
  	NULL
  };
  KTYPE(bch_cached_dev);
  
  SHOW(bch_flash_dev)
  {
  	struct bcache_device *d = container_of(kobj, struct bcache_device,
  					       kobj);
  	struct uuid_entry *u = &d->c->uuids[d->id];
  
  	sysfs_printf(data_csum,	"%i", d->data_csum);
  	sysfs_hprint(size,	u->sectors << 9);
  
  	if (attr == &sysfs_label) {
  		memcpy(buf, u->label, SB_LABEL_SIZE);
  		buf[SB_LABEL_SIZE + 1] = '\0';
  		strcat(buf, "
  ");
  		return strlen(buf);
  	}
  
  	return 0;
  }
  
  STORE(__bch_flash_dev)
  {
  	struct bcache_device *d = container_of(kobj, struct bcache_device,
  					       kobj);
  	struct uuid_entry *u = &d->c->uuids[d->id];
  
  	sysfs_strtoul(data_csum,	d->data_csum);
  
  	if (attr == &sysfs_size) {
  		uint64_t v;
  		strtoi_h_or_return(buf, v);
  
  		u->sectors = v >> 9;
  		bch_uuid_write(d->c);
  		set_capacity(d->disk, u->sectors);
  	}
  
  	if (attr == &sysfs_label) {
  		memcpy(u->label, buf, SB_LABEL_SIZE);
  		bch_uuid_write(d->c);
  	}
  
  	if (attr == &sysfs_unregister) {
c4d951ddb   Kent Overstreet   bcache: Fix sysfs...
387
  		set_bit(BCACHE_DEV_DETACHING, &d->flags);
cafe56359   Kent Overstreet   bcache: A block l...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  		bcache_device_stop(d);
  	}
  
  	return size;
  }
  STORE_LOCKED(bch_flash_dev)
  
  static struct attribute *bch_flash_dev_files[] = {
  	&sysfs_unregister,
  #if 0
  	&sysfs_data_csum,
  #endif
  	&sysfs_label,
  	&sysfs_size,
  	NULL
  };
  KTYPE(bch_flash_dev);
f67342dd3   Kent Overstreet   bcache: Refactor ...
405
406
407
408
409
  struct bset_stats_op {
  	struct btree_op op;
  	size_t nodes;
  	struct bset_stats stats;
  };
cb8511495   John Sheu   bcache: remove ne...
410
  static int bch_btree_bset_stats(struct btree_op *b_op, struct btree *b)
f67342dd3   Kent Overstreet   bcache: Refactor ...
411
412
413
414
415
416
417
418
  {
  	struct bset_stats_op *op = container_of(b_op, struct bset_stats_op, op);
  
  	op->nodes++;
  	bch_btree_keys_stats(&b->keys, &op->stats);
  
  	return MAP_CONTINUE;
  }
3572324af   Kent Overstreet   bcache: Minor fix...
419
  static int bch_bset_print_stats(struct cache_set *c, char *buf)
f67342dd3   Kent Overstreet   bcache: Refactor ...
420
421
422
423
424
425
  {
  	struct bset_stats_op op;
  	int ret;
  
  	memset(&op, 0, sizeof(op));
  	bch_btree_op_init(&op.op, -1);
cb8511495   John Sheu   bcache: remove ne...
426
  	ret = bch_btree_map_nodes(&op.op, c, &ZERO_KEY, bch_btree_bset_stats);
f67342dd3   Kent Overstreet   bcache: Refactor ...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  	if (ret < 0)
  		return ret;
  
  	return snprintf(buf, PAGE_SIZE,
  			"btree nodes:		%zu
  "
  			"written sets:		%zu
  "
  			"unwritten sets:		%zu
  "
  			"written key bytes:	%zu
  "
  			"unwritten key bytes:	%zu
  "
  			"floats:			%zu
  "
  			"failed:			%zu
  ",
  			op.nodes,
  			op.stats.sets_written, op.stats.sets_unwritten,
  			op.stats.bytes_written, op.stats.bytes_unwritten,
  			op.stats.floats, op.stats.failed);
  }
cb8511495   John Sheu   bcache: remove ne...
450
  static unsigned bch_root_usage(struct cache_set *c)
cafe56359   Kent Overstreet   bcache: A block l...
451
  {
cb8511495   John Sheu   bcache: remove ne...
452
453
454
455
  	unsigned bytes = 0;
  	struct bkey *k;
  	struct btree *b;
  	struct btree_iter iter;
cafe56359   Kent Overstreet   bcache: A block l...
456

cb8511495   John Sheu   bcache: remove ne...
457
  	goto lock_root;
cafe56359   Kent Overstreet   bcache: A block l...
458

cb8511495   John Sheu   bcache: remove ne...
459
460
  	do {
  		rw_unlock(false, b);
cafe56359   Kent Overstreet   bcache: A block l...
461
  lock_root:
cb8511495   John Sheu   bcache: remove ne...
462
463
464
  		b = c->root;
  		rw_lock(false, b, b->level);
  	} while (b != c->root);
cafe56359   Kent Overstreet   bcache: A block l...
465

cb8511495   John Sheu   bcache: remove ne...
466
467
  	for_each_key_filter(&b->keys, k, &iter, bch_ptr_bad)
  		bytes += bkey_bytes(k);
cafe56359   Kent Overstreet   bcache: A block l...
468

cb8511495   John Sheu   bcache: remove ne...
469
  	rw_unlock(false, b);
cafe56359   Kent Overstreet   bcache: A block l...
470

cb8511495   John Sheu   bcache: remove ne...
471
472
  	return (bytes * 100) / btree_bytes(c);
  }
cafe56359   Kent Overstreet   bcache: A block l...
473

cb8511495   John Sheu   bcache: remove ne...
474
475
476
477
  static size_t bch_cache_size(struct cache_set *c)
  {
  	size_t ret = 0;
  	struct btree *b;
cafe56359   Kent Overstreet   bcache: A block l...
478

cb8511495   John Sheu   bcache: remove ne...
479
480
481
  	mutex_lock(&c->bucket_lock);
  	list_for_each_entry(b, &c->btree_cache, list)
  		ret += 1 << (b->keys.page_order + PAGE_SHIFT);
cafe56359   Kent Overstreet   bcache: A block l...
482

cb8511495   John Sheu   bcache: remove ne...
483
484
485
  	mutex_unlock(&c->bucket_lock);
  	return ret;
  }
cafe56359   Kent Overstreet   bcache: A block l...
486

cb8511495   John Sheu   bcache: remove ne...
487
488
489
490
  static unsigned bch_cache_max_chain(struct cache_set *c)
  {
  	unsigned ret = 0;
  	struct hlist_head *h;
cafe56359   Kent Overstreet   bcache: A block l...
491

cb8511495   John Sheu   bcache: remove ne...
492
  	mutex_lock(&c->bucket_lock);
cafe56359   Kent Overstreet   bcache: A block l...
493

cb8511495   John Sheu   bcache: remove ne...
494
495
496
497
498
  	for (h = c->bucket_hash;
  	     h < c->bucket_hash + (1 << BUCKET_HASH_BITS);
  	     h++) {
  		unsigned i = 0;
  		struct hlist_node *p;
cafe56359   Kent Overstreet   bcache: A block l...
499

cb8511495   John Sheu   bcache: remove ne...
500
501
  		hlist_for_each(p, h)
  			i++;
cafe56359   Kent Overstreet   bcache: A block l...
502

cb8511495   John Sheu   bcache: remove ne...
503
  		ret = max(ret, i);
cafe56359   Kent Overstreet   bcache: A block l...
504
  	}
cb8511495   John Sheu   bcache: remove ne...
505
506
507
  	mutex_unlock(&c->bucket_lock);
  	return ret;
  }
cafe56359   Kent Overstreet   bcache: A block l...
508

cb8511495   John Sheu   bcache: remove ne...
509
510
511
512
513
  static unsigned bch_btree_used(struct cache_set *c)
  {
  	return div64_u64(c->gc_stats.key_bytes * 100,
  			 (c->gc_stats.nodes ?: 1) * btree_bytes(c));
  }
cafe56359   Kent Overstreet   bcache: A block l...
514

cb8511495   John Sheu   bcache: remove ne...
515
516
517
518
519
520
521
522
523
  static unsigned bch_average_key_size(struct cache_set *c)
  {
  	return c->gc_stats.nkeys
  		? div64_u64(c->gc_stats.data, c->gc_stats.nkeys)
  		: 0;
  }
  
  SHOW(__bch_cache_set)
  {
cafe56359   Kent Overstreet   bcache: A block l...
524
525
526
527
528
529
530
  	struct cache_set *c = container_of(kobj, struct cache_set, kobj);
  
  	sysfs_print(synchronous,		CACHE_SYNC(&c->sb));
  	sysfs_print(journal_delay_ms,		c->journal_delay_ms);
  	sysfs_hprint(bucket_size,		bucket_bytes(c));
  	sysfs_hprint(block_size,		block_bytes(c));
  	sysfs_print(tree_depth,			c->root->level);
cb8511495   John Sheu   bcache: remove ne...
531
  	sysfs_print(root_usage_percent,		bch_root_usage(c));
cafe56359   Kent Overstreet   bcache: A block l...
532

cb8511495   John Sheu   bcache: remove ne...
533
534
  	sysfs_hprint(btree_cache_size,		bch_cache_size(c));
  	sysfs_print(btree_cache_max_chain,	bch_cache_max_chain(c));
cafe56359   Kent Overstreet   bcache: A block l...
535
536
537
538
  	sysfs_print(cache_available_percent,	100 - c->gc_stats.in_use);
  
  	sysfs_print_time_stats(&c->btree_gc_time,	btree_gc, sec, ms);
  	sysfs_print_time_stats(&c->btree_split_time,	btree_split, sec, us);
67539e852   Kent Overstreet   bcache: Add struc...
539
  	sysfs_print_time_stats(&c->sort.time,		btree_sort, ms, us);
cafe56359   Kent Overstreet   bcache: A block l...
540
  	sysfs_print_time_stats(&c->btree_read_time,	btree_read, ms, us);
cafe56359   Kent Overstreet   bcache: A block l...
541

cb8511495   John Sheu   bcache: remove ne...
542
  	sysfs_print(btree_used_percent,	bch_btree_used(c));
cafe56359   Kent Overstreet   bcache: A block l...
543
  	sysfs_print(btree_nodes,	c->gc_stats.nodes);
cb8511495   John Sheu   bcache: remove ne...
544
  	sysfs_hprint(average_key_size,	bch_average_key_size(c));
cafe56359   Kent Overstreet   bcache: A block l...
545
546
547
548
549
550
551
552
  
  	sysfs_print(cache_read_races,
  		    atomic_long_read(&c->cache_read_races));
  
  	sysfs_print(writeback_keys_done,
  		    atomic_long_read(&c->writeback_keys_done));
  	sysfs_print(writeback_keys_failed,
  		    atomic_long_read(&c->writeback_keys_failed));
77c320eb4   Kent Overstreet   bcache: Add on er...
553
554
555
  	if (attr == &sysfs_errors)
  		return bch_snprint_string_list(buf, PAGE_SIZE, error_actions,
  					       c->on_error);
cafe56359   Kent Overstreet   bcache: A block l...
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  	/* See count_io_errors for why 88 */
  	sysfs_print(io_error_halflife,	c->error_decay * 88);
  	sysfs_print(io_error_limit,	c->error_limit >> IO_ERROR_SHIFT);
  
  	sysfs_hprint(congested,
  		     ((uint64_t) bch_get_congested(c)) << 9);
  	sysfs_print(congested_read_threshold_us,
  		    c->congested_read_threshold_us);
  	sysfs_print(congested_write_threshold_us,
  		    c->congested_write_threshold_us);
  
  	sysfs_print(active_journal_entries,	fifo_used(&c->journal.pin));
  	sysfs_printf(verify,			"%i", c->verify);
  	sysfs_printf(key_merging_disabled,	"%i", c->key_merging_disabled);
280481d06   Kent Overstreet   bcache: Debug cod...
570
571
  	sysfs_printf(expensive_debug_checks,
  		     "%i", c->expensive_debug_checks);
cafe56359   Kent Overstreet   bcache: A block l...
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
  	sysfs_printf(gc_always_rewrite,		"%i", c->gc_always_rewrite);
  	sysfs_printf(btree_shrinker_disabled,	"%i", c->shrinker_disabled);
  	sysfs_printf(copy_gc_enabled,		"%i", c->copy_gc_enabled);
  
  	if (attr == &sysfs_bset_tree_stats)
  		return bch_bset_print_stats(c, buf);
  
  	return 0;
  }
  SHOW_LOCKED(bch_cache_set)
  
  STORE(__bch_cache_set)
  {
  	struct cache_set *c = container_of(kobj, struct cache_set, kobj);
  
  	if (attr == &sysfs_unregister)
  		bch_cache_set_unregister(c);
  
  	if (attr == &sysfs_stop)
  		bch_cache_set_stop(c);
  
  	if (attr == &sysfs_synchronous) {
  		bool sync = strtoul_or_return(buf);
  
  		if (sync != CACHE_SYNC(&c->sb)) {
  			SET_CACHE_SYNC(&c->sb, sync);
  			bcache_write_super(c);
  		}
  	}
  
  	if (attr == &sysfs_flash_vol_create) {
  		int r;
  		uint64_t v;
  		strtoi_h_or_return(buf, v);
  
  		r = bch_flash_dev_create(c, v);
  		if (r)
  			return r;
  	}
  
  	if (attr == &sysfs_clear_stats) {
  		atomic_long_set(&c->writeback_keys_done,	0);
  		atomic_long_set(&c->writeback_keys_failed,	0);
  
  		memset(&c->gc_stats, 0, sizeof(struct gc_stat));
  		bch_cache_accounting_clear(&c->accounting);
  	}
  
  	if (attr == &sysfs_trigger_gc)
72a44517f   Kent Overstreet   bcache: Convert g...
621
  		wake_up_gc(c);
cafe56359   Kent Overstreet   bcache: A block l...
622
623
624
625
626
  
  	if (attr == &sysfs_prune_cache) {
  		struct shrink_control sc;
  		sc.gfp_mask = GFP_KERNEL;
  		sc.nr_to_scan = strtoul_or_return(buf);
7dc19d5af   Dave Chinner   drivers: convert ...
627
  		c->shrink.scan_objects(&c->shrink, &sc);
cafe56359   Kent Overstreet   bcache: A block l...
628
629
630
631
632
633
  	}
  
  	sysfs_strtoul(congested_read_threshold_us,
  		      c->congested_read_threshold_us);
  	sysfs_strtoul(congested_write_threshold_us,
  		      c->congested_write_threshold_us);
77c320eb4   Kent Overstreet   bcache: Add on er...
634
635
636
637
638
639
640
641
  	if (attr == &sysfs_errors) {
  		ssize_t v = bch_read_string_list(buf, error_actions);
  
  		if (v < 0)
  			return v;
  
  		c->on_error = v;
  	}
cafe56359   Kent Overstreet   bcache: A block l...
642
643
644
645
646
647
648
649
650
651
  	if (attr == &sysfs_io_error_limit)
  		c->error_limit = strtoul_or_return(buf) << IO_ERROR_SHIFT;
  
  	/* See count_io_errors() for why 88 */
  	if (attr == &sysfs_io_error_halflife)
  		c->error_decay = strtoul_or_return(buf) / 88;
  
  	sysfs_strtoul(journal_delay_ms,		c->journal_delay_ms);
  	sysfs_strtoul(verify,			c->verify);
  	sysfs_strtoul(key_merging_disabled,	c->key_merging_disabled);
280481d06   Kent Overstreet   bcache: Debug cod...
652
  	sysfs_strtoul(expensive_debug_checks,	c->expensive_debug_checks);
cafe56359   Kent Overstreet   bcache: A block l...
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  	sysfs_strtoul(gc_always_rewrite,	c->gc_always_rewrite);
  	sysfs_strtoul(btree_shrinker_disabled,	c->shrinker_disabled);
  	sysfs_strtoul(copy_gc_enabled,		c->copy_gc_enabled);
  
  	return size;
  }
  STORE_LOCKED(bch_cache_set)
  
  SHOW(bch_cache_set_internal)
  {
  	struct cache_set *c = container_of(kobj, struct cache_set, internal);
  	return bch_cache_set_show(&c->kobj, attr, buf);
  }
  
  STORE(bch_cache_set_internal)
  {
  	struct cache_set *c = container_of(kobj, struct cache_set, internal);
  	return bch_cache_set_store(&c->kobj, attr, buf, size);
  }
  
  static void bch_cache_set_internal_release(struct kobject *k)
  {
  }
  
  static struct attribute *bch_cache_set_files[] = {
  	&sysfs_unregister,
  	&sysfs_stop,
  	&sysfs_synchronous,
  	&sysfs_journal_delay_ms,
  	&sysfs_flash_vol_create,
  
  	&sysfs_bucket_size,
  	&sysfs_block_size,
  	&sysfs_tree_depth,
  	&sysfs_root_usage_percent,
  	&sysfs_btree_cache_size,
  	&sysfs_cache_available_percent,
  
  	&sysfs_average_key_size,
cafe56359   Kent Overstreet   bcache: A block l...
692

77c320eb4   Kent Overstreet   bcache: Add on er...
693
  	&sysfs_errors,
cafe56359   Kent Overstreet   bcache: A block l...
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
  	&sysfs_io_error_limit,
  	&sysfs_io_error_halflife,
  	&sysfs_congested,
  	&sysfs_congested_read_threshold_us,
  	&sysfs_congested_write_threshold_us,
  	&sysfs_clear_stats,
  	NULL
  };
  KTYPE(bch_cache_set);
  
  static struct attribute *bch_cache_set_internal_files[] = {
  	&sysfs_active_journal_entries,
  
  	sysfs_time_stats_attribute_list(btree_gc, sec, ms)
  	sysfs_time_stats_attribute_list(btree_split, sec, us)
  	sysfs_time_stats_attribute_list(btree_sort, ms, us)
  	sysfs_time_stats_attribute_list(btree_read, ms, us)
cafe56359   Kent Overstreet   bcache: A block l...
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
  
  	&sysfs_btree_nodes,
  	&sysfs_btree_used_percent,
  	&sysfs_btree_cache_max_chain,
  
  	&sysfs_bset_tree_stats,
  	&sysfs_cache_read_races,
  	&sysfs_writeback_keys_done,
  	&sysfs_writeback_keys_failed,
  
  	&sysfs_trigger_gc,
  	&sysfs_prune_cache,
  #ifdef CONFIG_BCACHE_DEBUG
  	&sysfs_verify,
  	&sysfs_key_merging_disabled,
280481d06   Kent Overstreet   bcache: Debug cod...
726
  	&sysfs_expensive_debug_checks,
cafe56359   Kent Overstreet   bcache: A block l...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
  #endif
  	&sysfs_gc_always_rewrite,
  	&sysfs_btree_shrinker_disabled,
  	&sysfs_copy_gc_enabled,
  	NULL
  };
  KTYPE(bch_cache_set_internal);
  
  SHOW(__bch_cache)
  {
  	struct cache *ca = container_of(kobj, struct cache, kobj);
  
  	sysfs_hprint(bucket_size,	bucket_bytes(ca));
  	sysfs_hprint(block_size,	block_bytes(ca));
  	sysfs_print(nbuckets,		ca->sb.nbuckets);
  	sysfs_print(discard,		ca->discard);
  	sysfs_hprint(written, atomic_long_read(&ca->sectors_written) << 9);
  	sysfs_hprint(btree_written,
  		     atomic_long_read(&ca->btree_sectors_written) << 9);
  	sysfs_hprint(metadata_written,
  		     (atomic_long_read(&ca->meta_sectors_written) +
  		      atomic_long_read(&ca->btree_sectors_written)) << 9);
  
  	sysfs_print(io_errors,
  		    atomic_read(&ca->io_errors) >> IO_ERROR_SHIFT);
cafe56359   Kent Overstreet   bcache: A block l...
752
  	if (attr == &sysfs_cache_replacement_policy)
169ef1cf6   Kent Overstreet   bcache: Don't exp...
753
754
755
  		return bch_snprint_string_list(buf, PAGE_SIZE,
  					       cache_replacement_policies,
  					       CACHE_REPLACEMENT(&ca->sb));
cafe56359   Kent Overstreet   bcache: A block l...
756
757
758
759
  
  	if (attr == &sysfs_priority_stats) {
  		int cmp(const void *l, const void *r)
  		{	return *((uint16_t *) r) - *((uint16_t *) l); }
157540205   Kent Overstreet   bcache: Improve p...
760
761
762
  		struct bucket *b;
  		size_t n = ca->sb.nbuckets, i;
  		size_t unused = 0, available = 0, dirty = 0, meta = 0;
cafe56359   Kent Overstreet   bcache: A block l...
763
  		uint64_t sum = 0;
bbc77aa7f   Kent Overstreet   bcache: fix a spu...
764
765
  		/* Compute 31 quantiles */
  		uint16_t q[31], *p, *cached;
cafe56359   Kent Overstreet   bcache: A block l...
766
767
768
769
770
771
772
  		ssize_t ret;
  
  		cached = p = vmalloc(ca->sb.nbuckets * sizeof(uint16_t));
  		if (!p)
  			return -ENOMEM;
  
  		mutex_lock(&ca->set->bucket_lock);
157540205   Kent Overstreet   bcache: Improve p...
773
774
775
776
777
778
779
780
781
782
  		for_each_bucket(b, ca) {
  			if (!GC_SECTORS_USED(b))
  				unused++;
  			if (GC_MARK(b) == GC_MARK_RECLAIMABLE)
  				available++;
  			if (GC_MARK(b) == GC_MARK_DIRTY)
  				dirty++;
  			if (GC_MARK(b) == GC_MARK_METADATA)
  				meta++;
  		}
cafe56359   Kent Overstreet   bcache: A block l...
783
784
785
786
787
788
789
790
791
792
793
794
795
796
  		for (i = ca->sb.first_bucket; i < n; i++)
  			p[i] = ca->buckets[i].prio;
  		mutex_unlock(&ca->set->bucket_lock);
  
  		sort(p, n, sizeof(uint16_t), cmp, NULL);
  
  		while (n &&
  		       !cached[n - 1])
  			--n;
  
  		unused = ca->sb.nbuckets - n;
  
  		while (cached < p + n &&
  		       *cached == BTREE_PRIO)
157540205   Kent Overstreet   bcache: Improve p...
797
  			cached++, n--;
cafe56359   Kent Overstreet   bcache: A block l...
798
799
800
801
802
803
  
  		for (i = 0; i < n; i++)
  			sum += INITIAL_PRIO - cached[i];
  
  		if (n)
  			do_div(sum, n);
bbc77aa7f   Kent Overstreet   bcache: fix a spu...
804
805
806
  		for (i = 0; i < ARRAY_SIZE(q); i++)
  			q[i] = INITIAL_PRIO - cached[n * (i + 1) /
  				(ARRAY_SIZE(q) + 1)];
cafe56359   Kent Overstreet   bcache: A block l...
807
808
  
  		vfree(p);
bbc77aa7f   Kent Overstreet   bcache: fix a spu...
809
810
811
  		ret = scnprintf(buf, PAGE_SIZE,
  				"Unused:		%zu%%
  "
157540205   Kent Overstreet   bcache: Improve p...
812
813
814
815
  				"Clean:		%zu%%
  "
  				"Dirty:		%zu%%
  "
bbc77aa7f   Kent Overstreet   bcache: fix a spu...
816
817
818
819
820
821
822
823
  				"Metadata:	%zu%%
  "
  				"Average:	%llu
  "
  				"Sectors per Q:	%zu
  "
  				"Quantiles:	[",
  				unused * 100 / (size_t) ca->sb.nbuckets,
157540205   Kent Overstreet   bcache: Improve p...
824
825
826
  				available * 100 / (size_t) ca->sb.nbuckets,
  				dirty * 100 / (size_t) ca->sb.nbuckets,
  				meta * 100 / (size_t) ca->sb.nbuckets, sum,
bbc77aa7f   Kent Overstreet   bcache: fix a spu...
827
828
829
830
831
832
833
834
835
  				n * ca->sb.bucket_size / (ARRAY_SIZE(q) + 1));
  
  		for (i = 0; i < ARRAY_SIZE(q); i++)
  			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
  					 "%u ", q[i]);
  		ret--;
  
  		ret += scnprintf(buf + ret, PAGE_SIZE - ret, "]
  ");
cafe56359   Kent Overstreet   bcache: A block l...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
  		return ret;
  	}
  
  	return 0;
  }
  SHOW_LOCKED(bch_cache)
  
  STORE(__bch_cache)
  {
  	struct cache *ca = container_of(kobj, struct cache, kobj);
  
  	if (attr == &sysfs_discard) {
  		bool v = strtoul_or_return(buf);
  
  		if (blk_queue_discard(bdev_get_queue(ca->bdev)))
  			ca->discard = v;
  
  		if (v != CACHE_DISCARD(&ca->sb)) {
  			SET_CACHE_DISCARD(&ca->sb, v);
  			bcache_write_super(ca->set);
  		}
  	}
  
  	if (attr == &sysfs_cache_replacement_policy) {
169ef1cf6   Kent Overstreet   bcache: Don't exp...
860
  		ssize_t v = bch_read_string_list(buf, cache_replacement_policies);
cafe56359   Kent Overstreet   bcache: A block l...
861
862
863
864
865
866
867
868
869
870
871
872
  
  		if (v < 0)
  			return v;
  
  		if ((unsigned) v != CACHE_REPLACEMENT(&ca->sb)) {
  			mutex_lock(&ca->set->bucket_lock);
  			SET_CACHE_REPLACEMENT(&ca->sb, v);
  			mutex_unlock(&ca->set->bucket_lock);
  
  			bcache_write_super(ca->set);
  		}
  	}
cafe56359   Kent Overstreet   bcache: A block l...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
  	if (attr == &sysfs_clear_stats) {
  		atomic_long_set(&ca->sectors_written, 0);
  		atomic_long_set(&ca->btree_sectors_written, 0);
  		atomic_long_set(&ca->meta_sectors_written, 0);
  		atomic_set(&ca->io_count, 0);
  		atomic_set(&ca->io_errors, 0);
  	}
  
  	return size;
  }
  STORE_LOCKED(bch_cache)
  
  static struct attribute *bch_cache_files[] = {
  	&sysfs_bucket_size,
  	&sysfs_block_size,
  	&sysfs_nbuckets,
  	&sysfs_priority_stats,
  	&sysfs_discard,
  	&sysfs_written,
  	&sysfs_btree_written,
  	&sysfs_metadata_written,
  	&sysfs_io_errors,
  	&sysfs_clear_stats,
cafe56359   Kent Overstreet   bcache: A block l...
896
897
898
899
  	&sysfs_cache_replacement_policy,
  	NULL
  };
  KTYPE(bch_cache);