diff options
-rw-r--r-- | drivers/md/bcache/bcache.h | 50 | ||||
-rw-r--r-- | drivers/md/bcache/bset.c | 17 | ||||
-rw-r--r-- | drivers/md/bcache/bset.h | 20 | ||||
-rw-r--r-- | drivers/md/bcache/btree_cache.c | 13 | ||||
-rw-r--r-- | drivers/md/bcache/btree_gc.c | 10 | ||||
-rw-r--r-- | drivers/md/bcache/btree_iter.c | 4 | ||||
-rw-r--r-- | drivers/md/bcache/btree_update.c | 5 | ||||
-rw-r--r-- | drivers/md/bcache/debug.c | 5 | ||||
-rw-r--r-- | drivers/md/bcache/debug.h | 37 | ||||
-rw-r--r-- | drivers/md/bcache/io.c | 9 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 7 | ||||
-rw-r--r-- | drivers/md/bcache/sysfs.c | 65 |
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); |