summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/md/bcache/bcache.h50
-rw-r--r--drivers/md/bcache/bset.c17
-rw-r--r--drivers/md/bcache/bset.h20
-rw-r--r--drivers/md/bcache/btree_cache.c13
-rw-r--r--drivers/md/bcache/btree_gc.c10
-rw-r--r--drivers/md/bcache/btree_iter.c4
-rw-r--r--drivers/md/bcache/btree_update.c5
-rw-r--r--drivers/md/bcache/debug.c5
-rw-r--r--drivers/md/bcache/debug.h37
-rw-r--r--drivers/md/bcache/io.c9
-rw-r--r--drivers/md/bcache/super.c7
-rw-r--r--drivers/md/bcache/sysfs.c65
12 files changed, 140 insertions, 102 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 256fc8966eb4..d2c99c1f42e7 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -207,6 +207,44 @@
#define bch_meta_write_fault(name) \
dynamic_fault("bcache:meta:write:" name)
+/* Parameters that are useful for debugging, but should always be compiled in: */
+#define BCH_DEBUG_PARAMS_ALWAYS() \
+ BCH_DEBUG_PARAM(key_merging_disabled, \
+ "Disables merging of extents") \
+ BCH_DEBUG_PARAM(btree_gc_always_rewrite, \
+ "Causes mark and sweep to compact and rewrite every " \
+ "btree node it traverses") \
+ BCH_DEBUG_PARAM(btree_gc_rewrite_disabled, \
+ "Disables rewriting of btree nodes during mark and sweep")\
+ BCH_DEBUG_PARAM(btree_gc_coalesce_disabled, \
+ "Disables coalescing of btree nodes") \
+ BCH_DEBUG_PARAM(btree_shrinker_disabled, \
+ "Disables the shrinker callback for the btree node cache")
+
+/* Parameters that should only be compiled in in debug mode: */
+#define BCH_DEBUG_PARAMS_DEBUG() \
+ BCH_DEBUG_PARAM(expensive_debug_checks, \
+ "Enables various runtime debugging checks that " \
+ "significantly affect performance") \
+ BCH_DEBUG_PARAM(debug_check_bkeys, \
+ "Run bkey_debugcheck (primarily checking GC/allocation "\
+ "information) when iterating over keys") \
+ BCH_DEBUG_PARAM(version_stress_test, \
+ "Assigns random version numbers to newly written " \
+ "extents, to test overlapping extent cases") \
+ BCH_DEBUG_PARAM(verify_btree_ondisk, \
+ "Reread btree nodes at various points to verify the " \
+ "mergesort in the read path against modifications " \
+ "done in memory") \
+
+#define BCH_DEBUG_PARAMS_ALL() BCH_DEBUG_PARAMS_ALWAYS() BCH_DEBUG_PARAMS_DEBUG()
+
+#ifdef CONFIG_BCACHE_DEBUG
+#define BCH_DEBUG_PARAMS() BCH_DEBUG_PARAMS_ALL()
+#else
+#define BCH_DEBUG_PARAMS() BCH_DEBUG_PARAMS_ALWAYS()
+#endif
+
#include "alloc_types.h"
#include "blockdev_types.h"
#include "buckets_types.h"
@@ -648,14 +686,6 @@ struct cache_set {
unsigned error_limit;
unsigned error_decay;
- bool expensive_debug_checks;
- unsigned version_stress_test:1;
- unsigned verify:1;
- unsigned key_merging_disabled:1;
- unsigned gc_always_rewrite:1;
- unsigned gc_rewrite_disabled:1;
- unsigned gc_coalesce_disabled:1;
- unsigned shrinker_disabled:1;
unsigned foreground_write_ratelimit_enabled:1;
unsigned copy_gc_enabled:1;
unsigned tiering_enabled:1;
@@ -671,6 +701,10 @@ struct cache_set {
* below this percentage
*/
unsigned sector_reserve_percent;
+
+#define BCH_DEBUG_PARAM(name, description) bool name;
+ BCH_DEBUG_PARAMS_ALL()
+#undef BCH_DEBUG_PARAM
};
static inline unsigned bucket_pages(const struct cache *ca)
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 00a21e8bc30d..6fb437d192f4 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -99,9 +99,6 @@ s64 __bch_count_data(struct btree_keys *b)
struct bkey_tup k;
u64 ret = 0;
- if (!btree_keys_expensive_checks(b))
- return -1;
-
if (b->ops->is_extents)
for_each_btree_node_key_unpack(b, &k, &iter)
ret += k.k.size;
@@ -109,24 +106,12 @@ s64 __bch_count_data(struct btree_keys *b)
return ret;
}
-void __bch_count_data_verify(struct btree_keys *b, int oldsize)
-{
- if (oldsize != -1) {
- int newsize = __bch_count_data(b);
-
- BUG_ON(newsize != -1 && newsize < oldsize);
- }
-}
-
-void bch_verify_btree_nr_keys(struct btree_keys *b)
+void __bch_verify_btree_nr_keys(struct btree_keys *b)
{
struct btree_node_iter iter;
struct bkey_packed *k;
unsigned u64s = 0, packed = 0, unpacked = 0;
- if (!btree_keys_expensive_checks(b))
- return;
-
for_each_btree_node_key(b, k, &iter) {
u64s += k->u64s;
if (bkey_packed(k))
diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h
index 3ba3fc44d63e..ddb2af3e7a94 100644
--- a/drivers/md/bcache/bset.h
+++ b/drivers/md/bcache/bset.h
@@ -274,10 +274,12 @@ struct btree_keys {
#endif
};
+extern bool bch_expensive_debug_checks;
+
static inline bool btree_keys_expensive_checks(struct btree_keys *b)
{
#ifdef CONFIG_BCACHE_DEBUG
- return *b->expensive_debug_checks;
+ return bch_expensive_debug_checks || *b->expensive_debug_checks;
#else
return false;
#endif
@@ -641,7 +643,7 @@ s64 __bch_count_data(struct btree_keys *);
void __bch_count_data_verify(struct btree_keys *, int);
void bch_dump_bucket(struct btree_keys *);
void bch_btree_node_iter_verify(struct btree_node_iter *, struct btree_keys *);
-void bch_verify_btree_nr_keys(struct btree_keys *);
+void __bch_verify_btree_nr_keys(struct btree_keys *);
#else
@@ -650,21 +652,27 @@ static inline void __bch_count_data_verify(struct btree_keys *b, int oldsize ) {
static inline void bch_dump_bucket(struct btree_keys *b) {}
static inline void bch_btree_node_iter_verify(struct btree_node_iter *iter,
struct btree_keys *b) {}
-static inline void bch_verify_btree_nr_keys(struct btree_keys *b) {}
+static inline void __bch_verify_btree_nr_keys(struct btree_keys *b) {}
#endif
void bch_dump_bset(struct btree_keys *, struct bset *, unsigned);
-static inline int bch_count_data(struct btree_keys *b)
+static inline s64 bch_count_data(struct btree_keys *b)
{
return btree_keys_expensive_checks(b) ? __bch_count_data(b) : -1;
}
-static inline void bch_count_data_verify(struct btree_keys *b, int oldsize)
+static inline void bch_count_data_verify(struct btree_keys *b, s64 oldsize)
+{
+ if (btree_keys_expensive_checks(b))
+ BUG_ON(oldsize != -1 && __bch_count_data(b) < oldsize);
+}
+
+static inline void bch_verify_btree_nr_keys(struct btree_keys *b)
{
if (btree_keys_expensive_checks(b))
- __bch_count_data_verify(b, oldsize);
+ __bch_verify_btree_nr_keys(b);
}
#endif
diff --git a/drivers/md/bcache/btree_cache.c b/drivers/md/bcache/btree_cache.c
index 56eab3e0b424..d78591ed03c0 100644
--- a/drivers/md/bcache/btree_cache.c
+++ b/drivers/md/bcache/btree_cache.c
@@ -4,6 +4,7 @@
#include "btree_io.h"
#include "btree_iter.h"
#include "btree_locking.h"
+#include "debug.h"
#include "extents.h"
#include <trace/events/bcache.h>
@@ -230,7 +231,7 @@ static unsigned long bch_mca_scan(struct shrinker *shrink,
u64 start_time = local_clock();
- if (c->shrinker_disabled)
+ if (btree_shrinker_disabled(c))
return SHRINK_STOP;
if (c->btree_cache_alloc_lock)
@@ -324,7 +325,7 @@ static unsigned long bch_mca_count(struct shrinker *shrink,
struct cache_set *c = container_of(shrink, struct cache_set,
btree_cache_shrink);
- if (c->shrinker_disabled)
+ if (btree_shrinker_disabled(c))
return 0;
if (c->btree_cache_alloc_lock)
@@ -403,10 +404,14 @@ int bch_btree_cache_alloc(struct cache_set *c)
c->verify_ondisk = (void *)
__get_free_pages(GFP_KERNEL, ilog2(btree_pages(c)));
+ if (!c->verify_ondisk)
+ return -ENOMEM;
c->verify_data = mca_bucket_alloc(c, GFP_KERNEL);
- if (c->verify_data)
- list_del_init(&c->verify_data->list);
+ if (!c->verify_data)
+ return -ENOMEM;
+
+ list_del_init(&c->verify_data->list);
#endif
c->btree_cache_shrink.count_objects = bch_mca_count;
diff --git a/drivers/md/bcache/btree_gc.c b/drivers/md/bcache/btree_gc.c
index 512804d48ad5..85c778dc4d80 100644
--- a/drivers/md/bcache/btree_gc.c
+++ b/drivers/md/bcache/btree_gc.c
@@ -152,14 +152,14 @@ bool btree_gc_mark_node(struct cache_set *c, struct btree *b)
bch_btree_key_recalc_oldest_gen(c, k));
}
- if (c->gc_rewrite_disabled)
+ if (btree_gc_rewrite_disabled(c))
return false;
if (stale > 10)
return true;
}
- if (c->gc_always_rewrite)
+ if (btree_gc_always_rewrite(c))
return true;
return false;
@@ -433,9 +433,6 @@ static void bch_coalesce_nodes(struct btree *old_nodes[GC_MERGE_NODES],
struct bkey_format new_format;
int ret;
- if (c->gc_coalesce_disabled)
- return;
-
memset(new_nodes, 0, sizeof(new_nodes));
bch_keylist_init(&keylist, NULL, 0);
@@ -693,6 +690,9 @@ static void bch_coalesce(struct cache_set *c)
u64 start_time = local_clock();
enum btree_id id;
+ if (btree_gc_coalesce_disabled(c))
+ return;
+
if (test_bit(CACHE_SET_GC_FAILURE, &c->flags))
return;
diff --git a/drivers/md/bcache/btree_iter.c b/drivers/md/bcache/btree_iter.c
index 2187846894f8..113cb8cd54de 100644
--- a/drivers/md/bcache/btree_iter.c
+++ b/drivers/md/bcache/btree_iter.c
@@ -215,7 +215,7 @@ static inline struct bkey_s_c __btree_iter_peek_all(struct btree_iter *iter)
bkey_disassemble(&iter->tup, f, k);
ret = bkey_tup_to_s_c(&iter->tup);
- if (expensive_debug_checks(iter->c))
+ if (debug_check_bkeys(iter->c))
bkey_debugcheck(iter->c, iter->nodes[iter->level], ret);
return ret;
@@ -235,7 +235,7 @@ static inline struct bkey_s_c __btree_iter_peek(struct btree_iter *iter)
bkey_disassemble(&iter->tup, f, k);
ret = bkey_tup_to_s_c(&iter->tup);
- if (expensive_debug_checks(iter->c))
+ if (debug_check_bkeys(iter->c))
bkey_debugcheck(iter->c, iter->nodes[iter->level], ret);
return ret;
diff --git a/drivers/md/bcache/btree_update.c b/drivers/md/bcache/btree_update.c
index 43de87a12172..f924191ee53e 100644
--- a/drivers/md/bcache/btree_update.c
+++ b/drivers/md/bcache/btree_update.c
@@ -705,7 +705,7 @@ static bool btree_insert_key(struct btree_iter *iter, struct btree *b,
struct bkey_i *insert = bch_keylist_front(insert_keys), *orig = insert;
BKEY_PADDED(key) temp;
struct bpos done;
- s64 newsize, oldsize = bch_count_data(&b->keys);
+ s64 oldsize = bch_count_data(&b->keys);
bool do_insert;
BUG_ON(bkey_deleted(&insert->k) && bkey_val_u64s(&insert->k));
@@ -741,8 +741,7 @@ static bool btree_insert_key(struct btree_iter *iter, struct btree *b,
if (dequeue)
bch_keylist_dequeue(insert_keys);
- newsize = bch_count_data(&b->keys);
- BUG_ON(newsize != -1 && newsize < oldsize);
+ bch_count_data_verify(&b->keys, oldsize);
trace_bcache_btree_insert_key(b, insert, replace != NULL, do_insert);
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 015d0d7fbae3..bdd7f641c163 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -35,7 +35,7 @@ static void btree_verify_endio(struct bio *bio)
closure_put(cl);
}
-void bch_btree_verify(struct cache_set *c, struct btree *b)
+void __bch_btree_verify(struct cache_set *c, struct btree *b)
{
struct btree *v = c->verify_data;
struct btree_node *n_ondisk, *n_sorted, *n_inmemory;
@@ -44,9 +44,6 @@ void bch_btree_verify(struct cache_set *c, struct btree *b)
struct bio *bio;
struct closure cl;
- if (!c->verify || !c->verify_ondisk)
- return;
-
closure_init_stack(&cl);
down(&b->io_mutex);
diff --git a/drivers/md/bcache/debug.h b/drivers/md/bcache/debug.h
index b3cbb0bd9cd3..ad7c79a1e5ba 100644
--- a/drivers/md/bcache/debug.h
+++ b/drivers/md/bcache/debug.h
@@ -1,33 +1,58 @@
#ifndef _BCACHE_DEBUG_H
#define _BCACHE_DEBUG_H
+#include "bcache.h"
+
struct bio;
struct btree;
struct cached_dev;
struct cache_set;
+#define BCH_DEBUG_PARAM(name, description) extern bool bch_##name;
+BCH_DEBUG_PARAMS()
+#undef BCH_DEBUG_PARAM
+
+#define BCH_DEBUG_PARAM(name, description) \
+ static inline bool name(struct cache_set *c) \
+ { return bch_##name || c->name; }
+BCH_DEBUG_PARAMS_ALWAYS()
+#undef BCH_DEBUG_PARAM
+
#ifdef CONFIG_BCACHE_DEBUG
-void bch_btree_verify(struct cache_set *, struct btree *);
+#define BCH_DEBUG_PARAM(name, description) \
+ static inline bool name(struct cache_set *c) \
+ { return bch_##name || c->name; }
+BCH_DEBUG_PARAMS_DEBUG()
+#undef BCH_DEBUG_PARAM
+
+void __bch_btree_verify(struct cache_set *, struct btree *);
void bch_data_verify(struct cached_dev *, struct bio *);
void bch_verify_inode_refs(struct cache_set *);
-#define expensive_debug_checks(c) ((c)->expensive_debug_checks)
-#define key_merging_disabled(c) ((c)->key_merging_disabled)
#define bypass_torture_test(d) ((d)->bypass_torture_test)
#else /* DEBUG */
-static inline void bch_btree_verify(struct cache_set *c, struct btree *b) {}
+#define BCH_DEBUG_PARAM(name, description) \
+ static inline bool name(struct cache_set *c) { return false; }
+BCH_DEBUG_PARAMS_DEBUG()
+#undef BCH_DEBUG_PARAM
+
+static inline void __bch_btree_verify(struct cache_set *c, struct btree *b) {}
static inline void bch_data_verify(struct cached_dev *dc, struct bio *bio) {}
static inline void bch_verify_inode_refs(struct cache_set *c) {}
-#define expensive_debug_checks(c) 0
-#define key_merging_disabled(c) 0
#define bypass_torture_test(d) 0
#endif
+static inline void bch_btree_verify(struct cache_set *c, struct btree *b)
+{
+ if (verify_btree_ondisk(c))
+ __bch_btree_verify(c, b);
+}
+
#ifdef CONFIG_DEBUG_FS
void bch_debug_exit_cache_set(struct cache_set *);
void bch_debug_init_cache_set(struct cache_set *);
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 363ee6c6f231..9bf6766a90a1 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -210,15 +210,6 @@ void bch_bbio_endio(struct bbio *bio)
/* Writes */
-static inline bool version_stress_test(struct cache_set *c)
-{
-#ifdef CONFIG_BCACHE_DEBUG
- return c->version_stress_test;
-#else
- return false;
-#endif
-}
-
static u32 checksum_bio(struct bio *bio, unsigned type)
{
struct bio_vec bv;
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index d711f186bd50..fc76ec9737f4 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -2390,5 +2390,12 @@ err:
return -ENOMEM;
}
+#define BCH_DEBUG_PARAM(name, description) \
+ bool bch_##name; \
+ module_param_named(name, bch_##name, bool, 0644); \
+ MODULE_PARM_DESC(name, description);
+BCH_DEBUG_PARAMS()
+#undef BCH_DEBUG_PARAM
+
module_exit(bcache_exit);
module_init(bcache_init);
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index 4e91b7916065..62c94fd46768 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -93,9 +93,6 @@ sysfs_time_stats_attribute(btree_read, ms, us);
sysfs_time_stats_attribute(journal_full, sec, ms);
read_attribute(btree_gc_running);
-rw_attribute(btree_gc_always_rewrite);
-rw_attribute(btree_gc_rewrite_disabled);
-rw_attribute(btree_gc_coalesce_disabled);
read_attribute(btree_nodes);
read_attribute(btree_used_percent);
@@ -145,12 +142,8 @@ rw_attribute(io_error_limit);
rw_attribute(io_error_halflife);
rw_attribute(verify);
rw_attribute(bypass_torture_test);
-rw_attribute(key_merging_disabled);
-rw_attribute(expensive_debug_checks);
-rw_attribute(version_stress_test);
rw_attribute(cache_replacement_policy);
rw_attribute(checksum_type);
-rw_attribute(btree_shrinker_disabled);
rw_attribute(foreground_write_ratelimit_enabled);
rw_attribute(copy_gc_enabled);
@@ -178,6 +171,10 @@ rw_attribute(data_replicas_want);
read_attribute(data_replicas_have);
read_attribute(tier);
+#define BCH_DEBUG_PARAM(name, description) rw_attribute(name);
+ BCH_DEBUG_PARAMS()
+#undef BCH_DEBUG_PARAM
+
static struct attribute sysfs_state_rw = {
.name = "state",
.mode = S_IRUGO|S_IWUSR
@@ -664,18 +661,6 @@ SHOW(bch_cache_set)
sysfs_print(congested_write_threshold_us,
c->congested_write_threshold_us);
- if (attr == &sysfs_journal_debug)
- return bch_journal_print_debug(&c->journal, buf);
-
- sysfs_printf(verify, "%i", c->verify);
- sysfs_printf(key_merging_disabled, "%i", c->key_merging_disabled);
- sysfs_printf(expensive_debug_checks,
- "%i", c->expensive_debug_checks);
- sysfs_printf(version_stress_test, "%i", c->version_stress_test);
- sysfs_printf(btree_gc_always_rewrite, "%i", c->gc_always_rewrite);
- sysfs_printf(btree_gc_rewrite_disabled, "%i", c->gc_rewrite_disabled);
- sysfs_printf(btree_gc_coalesce_disabled, "%i", c->gc_coalesce_disabled);
- sysfs_printf(btree_shrinker_disabled, "%i", c->shrinker_disabled);
sysfs_printf(foreground_write_ratelimit_enabled, "%i",
c->foreground_write_ratelimit_enabled);
sysfs_printf(copy_gc_enabled, "%i", c->copy_gc_enabled);
@@ -701,6 +686,15 @@ SHOW(bch_cache_set)
sysfs_printf(data_replicas_have, "%llu",
CACHE_SET_DATA_REPLICAS_HAVE(&c->sb));
+ /* Debugging: */
+
+ if (attr == &sysfs_journal_debug)
+ return bch_journal_print_debug(&c->journal, buf);
+
+#define BCH_DEBUG_PARAM(name, description) sysfs_print(name, c->name);
+ BCH_DEBUG_PARAMS()
+#undef BCH_DEBUG_PARAM
+
if (!test_bit(CACHE_SET_RUNNING, &c->flags))
return -EPERM;
@@ -779,14 +773,6 @@ STORE(__bch_cache_set)
sysfs_clear_time_stats(&c->journal.full_time, journal_full);
sysfs_strtoul(journal_delay_ms, c->journal.delay_ms);
- sysfs_strtoul(verify, c->verify);
- sysfs_strtoul(key_merging_disabled, c->key_merging_disabled);
- sysfs_strtoul(expensive_debug_checks, c->expensive_debug_checks);
- sysfs_strtoul(version_stress_test, c->version_stress_test);
- sysfs_strtoul(btree_gc_always_rewrite, c->gc_always_rewrite);
- sysfs_strtoul(btree_gc_rewrite_disabled, c->gc_rewrite_disabled);
- sysfs_strtoul(btree_gc_coalesce_disabled, c->gc_coalesce_disabled);
- sysfs_strtoul(btree_shrinker_disabled, c->shrinker_disabled);
sysfs_strtoul(foreground_write_ratelimit_enabled,
c->foreground_write_ratelimit_enabled);
@@ -849,6 +835,12 @@ STORE(__bch_cache_set)
sysfs_strtoul(tiering_percent, c->tiering_percent);
sysfs_pd_controller_store(tiering, &c->tiering_pd);
+ /* Debugging: */
+
+#define BCH_DEBUG_PARAM(name, description) sysfs_strtoul(name, c->name);
+ BCH_DEBUG_PARAMS()
+#undef BCH_DEBUG_PARAM
+
if (!test_bit(CACHE_SET_RUNNING, &c->flags))
return -EPERM;
@@ -877,9 +869,10 @@ STORE(__bch_cache_set)
return r;
}
- if (attr == &sysfs_trigger_gc) {
+ /* Debugging: */
+
+ if (attr == &sysfs_trigger_gc)
bch_gc(c);
- }
if (attr == &sysfs_prune_cache) {
struct shrink_control sc;
@@ -996,16 +989,6 @@ static struct attribute *bch_cache_set_internal_files[] = {
&sysfs_trigger_gc,
&sysfs_prune_cache,
-#ifdef CONFIG_BCACHE_DEBUG
- &sysfs_verify,
- &sysfs_key_merging_disabled,
- &sysfs_expensive_debug_checks,
- &sysfs_version_stress_test,
-#endif
- &sysfs_btree_gc_always_rewrite,
- &sysfs_btree_gc_rewrite_disabled,
- &sysfs_btree_gc_coalesce_disabled,
- &sysfs_btree_shrinker_disabled,
&sysfs_foreground_write_ratelimit_enabled,
&sysfs_copy_gc_enabled,
&sysfs_tiering_enabled,
@@ -1013,6 +996,10 @@ static struct attribute *bch_cache_set_internal_files[] = {
sysfs_pd_controller_files(foreground_write),
&sysfs_internal_uuid,
+#define BCH_DEBUG_PARAM(name, description) &sysfs_##name,
+ BCH_DEBUG_PARAMS()
+#undef BCH_DEBUG_PARAM
+
NULL
};
KTYPE(bch_cache_set_internal);