summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2015-08-20 19:58:21 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:34:46 -0800
commitb11df900c708b7c06a349717e78da62f9d0bd68b (patch)
tree8b6e807a85675578a4259de2cfc2af1fdf433c7f
parent714818d1dac9758f017f34224466453f28f35d67 (diff)
bcache: Cleanup time_stats
-rw-r--r--drivers/md/bcache/bcache.h27
-rw-r--r--drivers/md/bcache/bset.c10
-rw-r--r--drivers/md/bcache/bset.h5
-rw-r--r--drivers/md/bcache/journal.c32
-rw-r--r--drivers/md/bcache/journal_types.h10
-rw-r--r--drivers/md/bcache/super.c21
-rw-r--r--drivers/md/bcache/super.h1
-rw-r--r--drivers/md/bcache/sysfs.c77
-rw-r--r--drivers/md/bcache/util.c9
-rw-r--r--drivers/md/bcache/util.h1
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)