diff options
-rw-r--r-- | drivers/md/bcache/bcache.h | 27 | ||||
-rw-r--r-- | drivers/md/bcache/bset.c | 10 | ||||
-rw-r--r-- | drivers/md/bcache/bset.h | 5 | ||||
-rw-r--r-- | drivers/md/bcache/journal.c | 32 | ||||
-rw-r--r-- | drivers/md/bcache/journal_types.h | 10 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 21 | ||||
-rw-r--r-- | drivers/md/bcache/super.h | 1 | ||||
-rw-r--r-- | drivers/md/bcache/sysfs.c | 77 | ||||
-rw-r--r-- | drivers/md/bcache/util.c | 9 | ||||
-rw-r--r-- | drivers/md/bcache/util.h | 1 |
10 files changed, 125 insertions, 68 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 0a7cdb39a632..8d1b0c0a8491 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -245,6 +245,20 @@ #define BCH_DEBUG_PARAMS() BCH_DEBUG_PARAMS_ALWAYS() #endif +/* name, frequency_units, duration_units */ +#define BCH_TIME_STATS() \ + BCH_TIME_STAT(mca_alloc, sec, us) \ + BCH_TIME_STAT(mca_scan, sec, ms) \ + BCH_TIME_STAT(btree_gc, sec, ms) \ + BCH_TIME_STAT(btree_coalesce, sec, ms) \ + BCH_TIME_STAT(btree_split, sec, us) \ + BCH_TIME_STAT(btree_sort, ms, us) \ + BCH_TIME_STAT(btree_read, ms, us) \ + BCH_TIME_STAT(journal_write, us, us) \ + BCH_TIME_STAT(journal_delay, ms, us) \ + BCH_TIME_STAT(journal_full, sec, ms) \ + BCH_TIME_STAT(journal_flush_seq, us, us) + #include "alloc_types.h" #include "blockdev_types.h" #include "buckets_types.h" @@ -447,6 +461,7 @@ struct cache_set { struct list_head list; struct kobject kobj; struct kobject internal; + struct kobject time_stats; struct completion *stop_completion; unsigned long flags; @@ -675,13 +690,6 @@ struct cache_set { unsigned congested_read_threshold_us; unsigned congested_write_threshold_us; - struct time_stats mca_alloc_time; - struct time_stats mca_scan_time; - struct time_stats btree_gc_time; - struct time_stats btree_coalesce_time; - struct time_stats btree_split_time; - struct time_stats btree_read_time; - struct cache_accounting accounting; atomic_long_t cache_read_races; atomic_long_t writeback_keys_done; @@ -709,6 +717,11 @@ struct cache_set { #define BCH_DEBUG_PARAM(name, description) bool name; BCH_DEBUG_PARAMS_ALL() #undef BCH_DEBUG_PARAM + +#define BCH_TIME_STAT(name, frequency_units, duration_units) \ + struct time_stats name##_time; + BCH_TIME_STATS() +#undef BCH_TIME_STAT }; static inline unsigned bucket_pages(const struct cache *ca) diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c index 6fb437d192f4..0e6ce0f7e103 100644 --- a/drivers/md/bcache/bset.c +++ b/drivers/md/bcache/bset.c @@ -1468,12 +1468,12 @@ void bch_bset_sort_state_free(struct bset_sort_state *state) mempool_exit(&state->pool); } -int bch_bset_sort_state_init(struct bset_sort_state *state, unsigned page_order) +int bch_bset_sort_state_init(struct bset_sort_state *state, unsigned page_order, + struct time_stats *time) { - spin_lock_init(&state->time.lock); - state->page_order = page_order; state->crit_factor = int_sqrt(1 << page_order); + state->time = time; if (mempool_init_page_pool(&state->pool, 1, page_order)) return -ENOMEM; @@ -1647,7 +1647,7 @@ struct btree_nr_keys bch_sort_bsets(struct bset *dst, struct btree_keys *b, nr = btree_mergesort_simple(b, dst, iter); if (!from) - bch_time_stats_update(&state->time, start_time); + bch_time_stats_update(state->time, start_time); return nr; } @@ -1678,7 +1678,7 @@ void bch_btree_sort_into(struct btree_keys *dst, BUG_ON(set_bytes(dst->set->data) > (PAGE_SIZE << dst->page_order)); - bch_time_stats_update(&state->time, start_time); + bch_time_stats_update(state->time, start_time); dst->nr = nr; dst->nsets = 0; diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h index ddb2af3e7a94..d1057600a3e1 100644 --- a/drivers/md/bcache/bset.h +++ b/drivers/md/bcache/bset.h @@ -603,7 +603,7 @@ struct bset_sort_state { unsigned page_order; unsigned crit_factor; - struct time_stats time; + struct time_stats *time; }; typedef struct btree_nr_keys (*btree_keys_sort_fn)(struct btree_keys *, @@ -611,7 +611,8 @@ typedef struct btree_nr_keys (*btree_keys_sort_fn)(struct btree_keys *, struct btree_node_iter *); void bch_bset_sort_state_free(struct bset_sort_state *); -int bch_bset_sort_state_init(struct bset_sort_state *, unsigned); +int bch_bset_sort_state_init(struct bset_sort_state *, unsigned, + struct time_stats *times); struct btree_nr_keys bch_sort_bsets(struct bset *, struct btree_keys *, unsigned, struct btree_node_iter *, diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index 51b5515277e0..e432ee534ac7 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -1371,6 +1371,8 @@ static void journal_write_done(struct closure *cl) j->last_seq_ondisk = w->data->last_seq; + __bch_time_stats_update(j->write_time, j->write_start_time); + clear_bit(JOURNAL_IO_IN_FLIGHT, &j->flags); closure_wake_up(&w->wait); @@ -1507,7 +1509,7 @@ static void journal_write_locked(struct closure *cl) closure_return_with_destructor(cl, journal_write_done); } -static bool __journal_write(struct journal *j) +static bool __journal_write(struct journal *j, bool need_write_just_set) __releases(j->lock) { struct cache_set *c = container_of(j, struct cache_set, journal); @@ -1528,7 +1530,12 @@ static bool __journal_write(struct journal *j) !journal_entry_close(j)) goto nowrite; + if (!need_write_just_set && + test_bit(JOURNAL_NEED_WRITE, &flags)) + __bch_time_stats_update(j->delay_time, j->need_write_time); + set_bit(JOURNAL_IO_IN_FLIGHT, &j->flags); + j->write_start_time = local_clock(); __set_current_state(TASK_RUNNING); closure_call(&j->io, journal_write_locked, NULL, &c->cl); @@ -1540,14 +1547,20 @@ nowrite: static bool journal_try_write(struct journal *j) { - set_bit(JOURNAL_NEED_WRITE, &j->flags); - return __journal_write(j); + bool set_need_write = false; + + if (!test_and_set_bit(JOURNAL_NEED_WRITE, &j->flags)) { + j->need_write_time = local_clock(); + set_need_write = true; + } + + return __journal_write(j, set_need_write); } static void journal_unlock(struct journal *j) { if (test_bit(JOURNAL_NEED_WRITE, &j->flags)) - __journal_write(j); + __journal_write(j, false); else spin_unlock(&j->lock); } @@ -1750,7 +1763,7 @@ int bch_journal_res_get(struct journal *j, struct journal_res *res, u64s_max, &start_time))); if (start_time) - bch_time_stats_update(&j->full_time, start_time); + bch_time_stats_update(j->full_time, start_time); if (ret < 0) return ret; @@ -1768,10 +1781,13 @@ void bch_journal_flush_seq_async(struct journal *j, u64 seq, struct closure *par if (seq == j->seq) { BUG_ON(!test_bit(JOURNAL_DIRTY, &j->flags)); - set_bit(JOURNAL_NEED_WRITE, &j->flags); + if (parent && !closure_wait(&journal_cur_write(j)->wait, parent)) BUG(); + + journal_try_write(j); + return; } else if (seq + 1 == j->seq && test_bit(JOURNAL_IO_IN_FLIGHT, &j->flags)) { if (parent && @@ -1785,11 +1801,14 @@ void bch_journal_flush_seq_async(struct journal *j, u64 seq, struct closure *par int bch_journal_flush_seq(struct journal *j, u64 seq) { struct closure cl; + u64 start_time = local_clock(); closure_init_stack(&cl); bch_journal_flush_seq_async(j, seq, &cl); closure_sync(&cl); + bch_time_stats_update(j->flush_seq_time, start_time); + return bch_journal_error(j); } @@ -1877,7 +1896,6 @@ int bch_journal_alloc(struct journal *j) INIT_WORK(&j->reclaim_work, journal_reclaim_work); mutex_init(&j->blacklist_lock); INIT_LIST_HEAD(&j->seq_blacklist); - spin_lock_init(&j->full_time.lock); lockdep_init_map(&j->res_map, "journal res", &res_key, 0); diff --git a/drivers/md/bcache/journal_types.h b/drivers/md/bcache/journal_types.h index b526ef470e02..4a23b18052f2 100644 --- a/drivers/md/bcache/journal_types.h +++ b/drivers/md/bcache/journal_types.h @@ -158,7 +158,15 @@ struct journal { u64 prio_buckets[MAX_CACHES_PER_SET]; unsigned nr_prio_buckets; - struct time_stats full_time; + + u64 need_write_time; + u64 write_start_time; + + struct time_stats *write_time; + struct time_stats *delay_time; + struct time_stats *full_time; + struct time_stats *flush_seq_time; + #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map res_map; #endif diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index b9f7b3f36ee5..03f6d7891cf1 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -924,6 +924,7 @@ static void cache_set_flush(struct closure *cl) bch_cache_accounting_destroy(&c->accounting); + kobject_put(&c->time_stats); kobject_put(&c->internal); closure_return(cl); @@ -1003,6 +1004,7 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, c->kobj.kset = bcache_kset; kobject_init(&c->kobj, &bch_cache_set_ktype); kobject_init(&c->internal, &bch_cache_set_internal_ktype); + kobject_init(&c->time_stats, &bch_cache_set_time_stats_ktype); bch_cache_accounting_init(&c->accounting, &c->cl); @@ -1028,12 +1030,10 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, mutex_init(&c->gc_scan_keylist_lock); INIT_LIST_HEAD(&c->gc_scan_keylists); - spin_lock_init(&c->mca_alloc_time.lock); - spin_lock_init(&c->mca_scan_time.lock); - spin_lock_init(&c->btree_gc_time.lock); - spin_lock_init(&c->btree_coalesce_time.lock); - spin_lock_init(&c->btree_split_time.lock); - spin_lock_init(&c->btree_read_time.lock); +#define BCH_TIME_STAT(name, frequency_units, duration_units) \ + spin_lock_init(&c->name##_time.lock); + BCH_TIME_STATS() +#undef BCH_TIME_STAT bch_open_buckets_init(c); bch_tiering_init_cache_set(c); @@ -1074,6 +1074,11 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, c->foreground_target_percent = 20; c->sector_reserve_percent = 20; + c->journal.write_time = &c->journal_write_time; + c->journal.delay_time = &c->journal_delay_time; + c->journal.full_time = &c->journal_full_time; + c->journal.flush_seq_time = &c->journal_flush_seq_time; + mutex_init(&c->uevent_lock); iter_size = (btree_blocks(c) + 1) * @@ -1103,7 +1108,8 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, bch_io_clock_init(&c->io_clock[WRITE]) || bch_journal_alloc(&c->journal) || bch_btree_cache_alloc(c) || - bch_bset_sort_state_init(&c->sort, ilog2(btree_pages(c)))) + bch_bset_sort_state_init(&c->sort, ilog2(btree_pages(c)), + &c->btree_sort_time)) goto err; for_each_possible_cpu(cpu) { @@ -1144,6 +1150,7 @@ static int bch_cache_set_online(struct cache_set *c) if (kobject_add(&c->kobj, NULL, "%pU", c->sb.user_uuid.b) || kobject_add(&c->internal, &c->kobj, "internal") || + kobject_add(&c->time_stats, &c->kobj, "time_stats") || bch_cache_accounting_add_kobjs(&c->accounting, &c->kobj)) return -1; diff --git a/drivers/md/bcache/super.h b/drivers/md/bcache/super.h index df6489d99f72..5c5bfac42bd1 100644 --- a/drivers/md/bcache/super.h +++ b/drivers/md/bcache/super.h @@ -184,6 +184,7 @@ extern wait_queue_head_t unregister_wait; extern struct kobj_type bch_cache_set_ktype; extern struct kobj_type bch_cache_set_internal_ktype; +extern struct kobj_type bch_cache_set_time_stats_ktype; extern struct kobj_type bch_cache_ktype; #endif /* _BCACHE_SUPER_H */ diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c index 493e14d61491..9698ea3d2a9f 100644 --- a/drivers/md/bcache/sysfs.c +++ b/drivers/md/bcache/sysfs.c @@ -83,15 +83,6 @@ read_attribute(journal_debug); write_attribute(journal_flush); read_attribute(internal_uuid); -sysfs_time_stats_attribute(mca_alloc, sec, us); -sysfs_time_stats_attribute(mca_scan, sec, ms); -sysfs_time_stats_attribute(btree_gc, sec, ms); -sysfs_time_stats_attribute(btree_coalesce, 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); -sysfs_time_stats_attribute(journal_full, sec, ms); - read_attribute(btree_gc_running); read_attribute(btree_nodes); @@ -174,6 +165,11 @@ read_attribute(tier); BCH_DEBUG_PARAMS() #undef BCH_DEBUG_PARAM +#define BCH_TIME_STAT(name, frequency_units, duration_units) \ + sysfs_time_stats_attribute(name, frequency_units, duration_units); + BCH_TIME_STATS() +#undef BCH_TIME_STAT + static struct attribute sysfs_state_rw = { .name = "state", .mode = S_IRUGO|S_IWUSR @@ -604,16 +600,6 @@ SHOW(bch_cache_set) sysfs_print(btree_gc_running, c->gc_pos.phase != GC_PHASE_DONE); - sysfs_print_time_stats(&c->mca_alloc_time, mca_alloc, sec, us); - sysfs_print_time_stats(&c->mca_scan_time, mca_scan, sec, ms); - sysfs_print_time_stats(&c->btree_gc_time, btree_gc, sec, ms); - sysfs_print_time_stats(&c->btree_coalesce_time, - btree_coalesce, sec, ms); - sysfs_print_time_stats(&c->btree_split_time, btree_split, sec, us); - sysfs_print_time_stats(&c->sort.time, btree_sort, ms, us); - sysfs_print_time_stats(&c->btree_read_time, btree_read, ms, us); - sysfs_print_time_stats(&c->journal.full_time, journal_full, sec, ms); - #if 0 /* XXX: reimplement */ sysfs_print(btree_used_percent, bch_btree_used(c)); @@ -683,6 +669,12 @@ SHOW(bch_cache_set) BCH_DEBUG_PARAMS() #undef BCH_DEBUG_PARAM +#define BCH_TIME_STAT(name, frequency_units, duration_units) \ + sysfs_print_time_stats(&c->name##_time, name, \ + frequency_units, duration_units); + BCH_TIME_STATS() +#undef BCH_TIME_STAT + if (!test_bit(CACHE_SET_RUNNING, &c->flags)) return -EPERM; @@ -751,14 +743,10 @@ STORE(__bch_cache_set) return size; } - sysfs_clear_time_stats(&c->mca_alloc_time, mca_alloc); - sysfs_clear_time_stats(&c->mca_scan_time, mca_scan); - sysfs_clear_time_stats(&c->btree_gc_time, btree_gc); - sysfs_clear_time_stats(&c->btree_coalesce_time, btree_coalesce); - sysfs_clear_time_stats(&c->btree_split_time, btree_split); - sysfs_clear_time_stats(&c->sort.time, btree_sort); - sysfs_clear_time_stats(&c->btree_read_time, btree_read); - sysfs_clear_time_stats(&c->journal.full_time, journal_full); +#define BCH_TIME_STAT(name, frequency_units, duration_units) \ + sysfs_clear_time_stats(&c->name##_time, name); + BCH_TIME_STATS() +#undef BCH_TIME_STAT sysfs_strtoul(journal_delay_ms, c->journal.delay_ms); sysfs_strtoul(foreground_write_ratelimit_enabled, @@ -956,15 +944,6 @@ static struct attribute *bch_cache_set_internal_files[] = { &sysfs_alloc_debug, - sysfs_time_stats_attribute_list(mca_alloc, sec, us) - sysfs_time_stats_attribute_list(mca_scan, sec, ms) - sysfs_time_stats_attribute_list(btree_gc, sec, ms) - sysfs_time_stats_attribute_list(btree_coalesce, 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) - sysfs_time_stats_attribute_list(journal_full, sec, ms) - &sysfs_btree_gc_running, &sysfs_btree_nodes, @@ -992,6 +971,32 @@ static struct attribute *bch_cache_set_internal_files[] = { }; KTYPE(bch_cache_set_internal); +SHOW(bch_cache_set_time_stats) +{ + struct cache_set *c = container_of(kobj, struct cache_set, time_stats); + return bch_cache_set_show(&c->kobj, attr, buf); +} + +STORE(bch_cache_set_time_stats) +{ + struct cache_set *c = container_of(kobj, struct cache_set, time_stats); + return bch_cache_set_store(&c->kobj, attr, buf, size); +} + +static void bch_cache_set_time_stats_release(struct kobject *k) +{ +} + +static struct attribute *bch_cache_set_time_stats_files[] = { +#define BCH_TIME_STAT(name, frequency_units, duration_units) \ + sysfs_time_stats_attribute_list(name, frequency_units, duration_units) + BCH_TIME_STATS() +#undef BCH_TIME_STAT + + NULL +}; +KTYPE(bch_cache_set_time_stats); + typedef unsigned (bucket_map_fn)(struct cache *, struct bucket *, void *); static unsigned bucket_priority_fn(struct cache *ca, struct bucket *g, diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c index 65de7f96d5b6..b0ae1a4c6a7a 100644 --- a/drivers/md/bcache/util.c +++ b/drivers/md/bcache/util.c @@ -160,12 +160,10 @@ void bch_time_stats_clear(struct time_stats *stats) spin_unlock(&stats->lock); } -void bch_time_stats_update(struct time_stats *stats, u64 start_time) +void __bch_time_stats_update(struct time_stats *stats, u64 start_time) { u64 now, duration, last; - spin_lock(&stats->lock); - stats->count++; now = local_clock(); @@ -192,7 +190,12 @@ void bch_time_stats_update(struct time_stats *stats, u64 start_time) } stats->last = now ?: 1; +} +void bch_time_stats_update(struct time_stats *stats, u64 start_time) +{ + spin_lock(&stats->lock); + __bch_time_stats_update(stats, start_time); spin_unlock(&stats->lock); } diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h index fd2934692f05..4e341575f651 100644 --- a/drivers/md/bcache/util.h +++ b/drivers/md/bcache/util.h @@ -303,6 +303,7 @@ struct time_stats { }; void bch_time_stats_clear(struct time_stats *stats); +void __bch_time_stats_update(struct time_stats *stats, u64 time); void bch_time_stats_update(struct time_stats *stats, u64 time); static inline unsigned local_clock_us(void) |