Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c37511b8 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcache: Fix/revamp tracepoints



The tracepoints were reworked to be more sensible, and fixed a null
pointer deref in one of the tracepoints.

Converted some of the pr_debug()s to tracepoints - this is partly a
performance optimization; it used to be that with DEBUG or
CONFIG_DYNAMIC_DEBUG pr_debug() was an empty macro; but at some point it
was changed to an empty inline function.

Some of the pr_debug() statements had rather expensive function calls as
part of the arguments, so this code was getting run unnecessarily even
on non debug kernels - in some fast paths, too.

Signed-off-by: default avatarKent Overstreet <koverstreet@google.com>
parent 57943511
Loading
Loading
Loading
Loading
+3 −7
Original line number Original line Diff line number Diff line
@@ -65,6 +65,7 @@


#include <linux/kthread.h>
#include <linux/kthread.h>
#include <linux/random.h>
#include <linux/random.h>
#include <trace/events/bcache.h>


#define MAX_IN_FLIGHT_DISCARDS		8U
#define MAX_IN_FLIGHT_DISCARDS		8U


@@ -351,10 +352,7 @@ static void invalidate_buckets(struct cache *ca)
		break;
		break;
	}
	}


	pr_debug("free %zu/%zu free_inc %zu/%zu unused %zu/%zu",
	trace_bcache_alloc_invalidate(ca);
		 fifo_used(&ca->free), ca->free.size,
		 fifo_used(&ca->free_inc), ca->free_inc.size,
		 fifo_used(&ca->unused), ca->unused.size);
}
}


#define allocator_wait(ca, cond)					\
#define allocator_wait(ca, cond)					\
@@ -473,9 +471,7 @@ long bch_bucket_alloc(struct cache *ca, unsigned watermark, struct closure *cl)
		return r;
		return r;
	}
	}


	pr_debug("alloc failure: blocked %i free %zu free_inc %zu unused %zu",
	trace_bcache_alloc_fail(ca);
		 atomic_read(&ca->set->prio_blocked), fifo_used(&ca->free),
		 fifo_used(&ca->free_inc), fifo_used(&ca->unused));


	if (cl) {
	if (cl) {
		closure_wait(&ca->set->bucket_wait, cl);
		closure_wait(&ca->set->bucket_wait, cl);
+0 −20
Original line number Original line Diff line number Diff line
@@ -178,7 +178,6 @@
#define pr_fmt(fmt) "bcache: %s() " fmt "\n", __func__
#define pr_fmt(fmt) "bcache: %s() " fmt "\n", __func__


#include <linux/bio.h>
#include <linux/bio.h>
#include <linux/blktrace_api.h>
#include <linux/kobject.h>
#include <linux/kobject.h>
#include <linux/list.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/mutex.h>
@@ -901,8 +900,6 @@ static inline unsigned local_clock_us(void)
	return local_clock() >> 10;
	return local_clock() >> 10;
}
}


#define MAX_BSETS		4U

#define BTREE_PRIO		USHRT_MAX
#define BTREE_PRIO		USHRT_MAX
#define INITIAL_PRIO		32768
#define INITIAL_PRIO		32768


@@ -1107,23 +1104,6 @@ static inline void __bkey_put(struct cache_set *c, struct bkey *k)
		atomic_dec_bug(&PTR_BUCKET(c, k, i)->pin);
		atomic_dec_bug(&PTR_BUCKET(c, k, i)->pin);
}
}


/* Blktrace macros */

#define blktrace_msg(c, fmt, ...)					\
do {									\
	struct request_queue *q = bdev_get_queue(c->bdev);		\
	if (q)								\
		blk_add_trace_msg(q, fmt, ##__VA_ARGS__);		\
} while (0)

#define blktrace_msg_all(s, fmt, ...)					\
do {									\
	struct cache *_c;						\
	unsigned i;							\
	for_each_cache(_c, (s), i)					\
		blktrace_msg(_c, fmt, ##__VA_ARGS__);			\
} while (0)

static inline void cached_dev_put(struct cached_dev *dc)
static inline void cached_dev_put(struct cached_dev *dc)
{
{
	if (atomic_dec_and_test(&dc->count))
	if (atomic_dec_and_test(&dc->count))
+4 −0
Original line number Original line Diff line number Diff line
#ifndef _BCACHE_BSET_H
#ifndef _BCACHE_BSET_H
#define _BCACHE_BSET_H
#define _BCACHE_BSET_H


#include <linux/slab.h>

/*
/*
 * BKEYS:
 * BKEYS:
 *
 *
@@ -142,6 +144,8 @@


/* Btree key comparison/iteration */
/* Btree key comparison/iteration */


#define MAX_BSETS		4U

struct btree_iter {
struct btree_iter {
	size_t size, used;
	size_t size, used;
	struct btree_iter_set {
	struct btree_iter_set {
+24 −23
Original line number Original line Diff line number Diff line
@@ -223,8 +223,9 @@ void bch_btree_node_read(struct btree *b)
	struct closure cl;
	struct closure cl;
	struct bio *bio;
	struct bio *bio;


	trace_bcache_btree_read(b);

	closure_init_stack(&cl);
	closure_init_stack(&cl);
	pr_debug("%s", pbtree(b));


	bio = bch_bbio_alloc(b->c);
	bio = bch_bbio_alloc(b->c);
	bio->bi_rw	= REQ_META|READ_SYNC;
	bio->bi_rw	= REQ_META|READ_SYNC;
@@ -234,7 +235,6 @@ void bch_btree_node_read(struct btree *b)


	bch_bio_map(bio, b->sets[0].data);
	bch_bio_map(bio, b->sets[0].data);


	trace_bcache_btree_read(bio);
	bch_submit_bbio(bio, b->c, &b->key, 0);
	bch_submit_bbio(bio, b->c, &b->key, 0);
	closure_sync(&cl);
	closure_sync(&cl);


@@ -343,7 +343,6 @@ static void do_btree_node_write(struct btree *b)
			memcpy(page_address(bv->bv_page),
			memcpy(page_address(bv->bv_page),
			       base + j * PAGE_SIZE, PAGE_SIZE);
			       base + j * PAGE_SIZE, PAGE_SIZE);


		trace_bcache_btree_write(b->bio);
		bch_submit_bbio(b->bio, b->c, &k.key, 0);
		bch_submit_bbio(b->bio, b->c, &k.key, 0);


		continue_at(cl, btree_node_write_done, NULL);
		continue_at(cl, btree_node_write_done, NULL);
@@ -351,7 +350,6 @@ static void do_btree_node_write(struct btree *b)
		b->bio->bi_vcnt = 0;
		b->bio->bi_vcnt = 0;
		bch_bio_map(b->bio, i);
		bch_bio_map(b->bio, i);


		trace_bcache_btree_write(b->bio);
		bch_submit_bbio(b->bio, b->c, &k.key, 0);
		bch_submit_bbio(b->bio, b->c, &k.key, 0);


		closure_sync(cl);
		closure_sync(cl);
@@ -363,10 +361,13 @@ void bch_btree_node_write(struct btree *b, struct closure *parent)
{
{
	struct bset *i = b->sets[b->nsets].data;
	struct bset *i = b->sets[b->nsets].data;


	trace_bcache_btree_write(b);

	BUG_ON(current->bio_list);
	BUG_ON(current->bio_list);
	BUG_ON(b->written >= btree_blocks(b));
	BUG_ON(b->written >= btree_blocks(b));
	BUG_ON(b->written && !i->keys);
	BUG_ON(b->written && !i->keys);
	BUG_ON(b->sets->data->seq != i->seq);
	BUG_ON(b->sets->data->seq != i->seq);
	bch_check_key_order(b, i);


	cancel_delayed_work(&b->work);
	cancel_delayed_work(&b->work);


@@ -376,12 +377,8 @@ void bch_btree_node_write(struct btree *b, struct closure *parent)
	clear_bit(BTREE_NODE_dirty,	 &b->flags);
	clear_bit(BTREE_NODE_dirty,	 &b->flags);
	change_bit(BTREE_NODE_write_idx, &b->flags);
	change_bit(BTREE_NODE_write_idx, &b->flags);


	bch_check_key_order(b, i);

	do_btree_node_write(b);
	do_btree_node_write(b);


	pr_debug("%s block %i keys %i", pbtree(b), b->written, i->keys);

	b->written += set_blocks(i, b->c);
	b->written += set_blocks(i, b->c);
	atomic_long_add(set_blocks(i, b->c) * b->c->sb.block_size,
	atomic_long_add(set_blocks(i, b->c) * b->c->sb.block_size,
			&PTR_CACHE(b->c, &b->key, 0)->btree_sectors_written);
			&PTR_CACHE(b->c, &b->key, 0)->btree_sectors_written);
@@ -752,6 +749,8 @@ static struct btree *mca_cannibalize(struct cache_set *c, struct bkey *k,
	int ret = -ENOMEM;
	int ret = -ENOMEM;
	struct btree *i;
	struct btree *i;


	trace_bcache_btree_cache_cannibalize(c);

	if (!cl)
	if (!cl)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);


@@ -770,7 +769,6 @@ static struct btree *mca_cannibalize(struct cache_set *c, struct bkey *k,
		return ERR_PTR(-EAGAIN);
		return ERR_PTR(-EAGAIN);
	}
	}


	/* XXX: tracepoint */
	c->try_harder = cl;
	c->try_harder = cl;
	c->try_harder_start = local_clock();
	c->try_harder_start = local_clock();
retry:
retry:
@@ -956,13 +954,14 @@ static void btree_node_free(struct btree *b, struct btree_op *op)
{
{
	unsigned i;
	unsigned i;


	trace_bcache_btree_node_free(b);

	/*
	/*
	 * The BUG_ON() in btree_node_get() implies that we must have a write
	 * The BUG_ON() in btree_node_get() implies that we must have a write
	 * lock on parent to free or even invalidate a node
	 * lock on parent to free or even invalidate a node
	 */
	 */
	BUG_ON(op->lock <= b->level);
	BUG_ON(op->lock <= b->level);
	BUG_ON(b == b->c->root);
	BUG_ON(b == b->c->root);
	pr_debug("bucket %s", pbtree(b));


	if (btree_node_dirty(b))
	if (btree_node_dirty(b))
		btree_complete_write(b, btree_current_write(b));
		btree_complete_write(b, btree_current_write(b));
@@ -1012,12 +1011,16 @@ struct btree *bch_btree_node_alloc(struct cache_set *c, int level,
	bch_bset_init_next(b);
	bch_bset_init_next(b);


	mutex_unlock(&c->bucket_lock);
	mutex_unlock(&c->bucket_lock);

	trace_bcache_btree_node_alloc(b);
	return b;
	return b;
err_free:
err_free:
	bch_bucket_free(c, &k.key);
	bch_bucket_free(c, &k.key);
	__bkey_put(c, &k.key);
	__bkey_put(c, &k.key);
err:
err:
	mutex_unlock(&c->bucket_lock);
	mutex_unlock(&c->bucket_lock);

	trace_bcache_btree_node_alloc_fail(b);
	return b;
	return b;
}
}


@@ -1254,7 +1257,7 @@ static void btree_gc_coalesce(struct btree *b, struct btree_op *op,
	btree_node_free(r->b, op);
	btree_node_free(r->b, op);
	up_write(&r->b->lock);
	up_write(&r->b->lock);


	pr_debug("coalesced %u nodes", nodes);
	trace_bcache_btree_gc_coalesce(nodes);


	gc->nodes--;
	gc->nodes--;
	nodes--;
	nodes--;
@@ -1479,8 +1482,7 @@ static void bch_btree_gc(struct closure *cl)
	struct btree_op op;
	struct btree_op op;
	uint64_t start_time = local_clock();
	uint64_t start_time = local_clock();


	trace_bcache_gc_start(c->sb.set_uuid);
	trace_bcache_gc_start(c);
	blktrace_msg_all(c, "Starting gc");


	memset(&stats, 0, sizeof(struct gc_stat));
	memset(&stats, 0, sizeof(struct gc_stat));
	closure_init_stack(&writes);
	closure_init_stack(&writes);
@@ -1496,9 +1498,7 @@ static void bch_btree_gc(struct closure *cl)
	closure_sync(&writes);
	closure_sync(&writes);


	if (ret) {
	if (ret) {
		blktrace_msg_all(c, "Stopped gc");
		pr_warn("gc failed!");
		pr_warn("gc failed!");

		continue_at(cl, bch_btree_gc, bch_gc_wq);
		continue_at(cl, bch_btree_gc, bch_gc_wq);
	}
	}


@@ -1519,8 +1519,7 @@ static void bch_btree_gc(struct closure *cl)
	stats.in_use	= (c->nbuckets - available) * 100 / c->nbuckets;
	stats.in_use	= (c->nbuckets - available) * 100 / c->nbuckets;
	memcpy(&c->gc_stats, &stats, sizeof(struct gc_stat));
	memcpy(&c->gc_stats, &stats, sizeof(struct gc_stat));


	blktrace_msg_all(c, "Finished gc");
	trace_bcache_gc_end(c);
	trace_bcache_gc_end(c->sb.set_uuid);


	continue_at(cl, bch_moving_gc, bch_gc_wq);
	continue_at(cl, bch_moving_gc, bch_gc_wq);
}
}
@@ -1901,12 +1900,11 @@ static int btree_split(struct btree *b, struct btree_op *op)


	split = set_blocks(n1->sets[0].data, n1->c) > (btree_blocks(b) * 4) / 5;
	split = set_blocks(n1->sets[0].data, n1->c) > (btree_blocks(b) * 4) / 5;


	pr_debug("%ssplitting at %s keys %i", split ? "" : "not ",
		 pbtree(b), n1->sets[0].data->keys);

	if (split) {
	if (split) {
		unsigned keys = 0;
		unsigned keys = 0;


		trace_bcache_btree_node_split(b, n1->sets[0].data->keys);

		n2 = bch_btree_node_alloc(b->c, b->level, &op->cl);
		n2 = bch_btree_node_alloc(b->c, b->level, &op->cl);
		if (IS_ERR(n2))
		if (IS_ERR(n2))
			goto err_free1;
			goto err_free1;
@@ -1941,8 +1939,11 @@ static int btree_split(struct btree *b, struct btree_op *op)
		bch_keylist_add(&op->keys, &n2->key);
		bch_keylist_add(&op->keys, &n2->key);
		bch_btree_node_write(n2, &op->cl);
		bch_btree_node_write(n2, &op->cl);
		rw_unlock(true, n2);
		rw_unlock(true, n2);
	} else
	} else {
		trace_bcache_btree_node_compact(b, n1->sets[0].data->keys);

		bch_btree_insert_keys(n1, op);
		bch_btree_insert_keys(n1, op);
	}


	bch_keylist_add(&op->keys, &n1->key);
	bch_keylist_add(&op->keys, &n1->key);
	bch_btree_node_write(n1, &op->cl);
	bch_btree_node_write(n1, &op->cl);
@@ -2117,6 +2118,8 @@ void bch_btree_set_root(struct btree *b)
{
{
	unsigned i;
	unsigned i;


	trace_bcache_btree_set_root(b);

	BUG_ON(!b->written);
	BUG_ON(!b->written);


	for (i = 0; i < KEY_PTRS(&b->key); i++)
	for (i = 0; i < KEY_PTRS(&b->key); i++)
@@ -2130,7 +2133,6 @@ void bch_btree_set_root(struct btree *b)
	__bkey_put(b->c, &b->key);
	__bkey_put(b->c, &b->key);


	bch_journal_meta(b->c, NULL);
	bch_journal_meta(b->c, NULL);
	pr_debug("%s for %pf", pbtree(b), __builtin_return_address(0));
}
}


/* Cache lookup */
/* Cache lookup */
@@ -2216,7 +2218,6 @@ static int submit_partial_cache_hit(struct btree *b, struct btree_op *op,
		n->bi_end_io	= bch_cache_read_endio;
		n->bi_end_io	= bch_cache_read_endio;
		n->bi_private	= &s->cl;
		n->bi_private	= &s->cl;


		trace_bcache_cache_hit(n);
		__bch_submit_bbio(n, b->c);
		__bch_submit_bbio(n, b->c);
	}
	}


+2 −0
Original line number Original line Diff line number Diff line
@@ -9,6 +9,8 @@
#include "bset.h"
#include "bset.h"
#include "debug.h"
#include "debug.h"


#include <linux/blkdev.h>

static void bch_bi_idx_hack_endio(struct bio *bio, int error)
static void bch_bi_idx_hack_endio(struct bio *bio, int error)
{
{
	struct bio *p = bio->bi_private;
	struct bio *p = bio->bi_private;
Loading