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

Commit 72c27061 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcache: Write out full stripes



Now that we're tracking dirty data per stripe, we can add two
optimizations for raid5/6:

 * If a stripe is already dirty, force writes to that stripe to
   writeback mode - to help build up full stripes of dirty data

 * When flushing dirty data, preferentially write out full stripes first
   if there are any.

Signed-off-by: default avatarKent Overstreet <koverstreet@google.com>
parent 279afbad
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -387,8 +387,6 @@ struct keybuf_key {
typedef bool (keybuf_pred_fn)(struct keybuf *, struct bkey *);

struct keybuf {
	keybuf_pred_fn		*key_predicate;

	struct bkey		last_scanned;
	spinlock_t		lock;

@@ -532,6 +530,7 @@ struct cached_dev {
	unsigned		sequential_merge:1;
	unsigned		verify:1;

	unsigned		partial_stripes_expensive:1;
	unsigned		writeback_metadata:1;
	unsigned		writeback_running:1;
	unsigned char		writeback_percent;
+10 −9
Original line number Diff line number Diff line
@@ -2252,7 +2252,8 @@ static inline int keybuf_nonoverlapping_cmp(struct keybuf_key *l,
}

static int bch_btree_refill_keybuf(struct btree *b, struct btree_op *op,
				   struct keybuf *buf, struct bkey *end)
				   struct keybuf *buf, struct bkey *end,
				   keybuf_pred_fn *pred)
{
	struct btree_iter iter;
	bch_btree_iter_init(b, &iter, &buf->last_scanned);
@@ -2271,7 +2272,7 @@ static int bch_btree_refill_keybuf(struct btree *b, struct btree_op *op,
			if (bkey_cmp(&buf->last_scanned, end) >= 0)
				break;

			if (buf->key_predicate(buf, k)) {
			if (pred(buf, k)) {
				struct keybuf_key *w;

				spin_lock(&buf->lock);
@@ -2290,7 +2291,7 @@ static int bch_btree_refill_keybuf(struct btree *b, struct btree_op *op,
			if (!k)
				break;

			btree(refill_keybuf, k, b, op, buf, end);
			btree(refill_keybuf, k, b, op, buf, end, pred);
			/*
			 * Might get an error here, but can't really do anything
			 * and it'll get logged elsewhere. Just read what we
@@ -2308,7 +2309,7 @@ static int bch_btree_refill_keybuf(struct btree *b, struct btree_op *op,
}

void bch_refill_keybuf(struct cache_set *c, struct keybuf *buf,
			  struct bkey *end)
		       struct bkey *end, keybuf_pred_fn *pred)
{
	struct bkey start = buf->last_scanned;
	struct btree_op op;
@@ -2316,7 +2317,7 @@ void bch_refill_keybuf(struct cache_set *c, struct keybuf *buf,

	cond_resched();

	btree_root(refill_keybuf, c, &op, buf, end);
	btree_root(refill_keybuf, c, &op, buf, end, pred);
	closure_sync(&op.cl);

	pr_debug("found %s keys from %llu:%llu to %llu:%llu",
@@ -2402,7 +2403,8 @@ struct keybuf_key *bch_keybuf_next(struct keybuf *buf)

struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *c,
					     struct keybuf *buf,
					     struct bkey *end)
					     struct bkey *end,
					     keybuf_pred_fn *pred)
{
	struct keybuf_key *ret;

@@ -2416,15 +2418,14 @@ struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *c,
			break;
		}

		bch_refill_keybuf(c, buf, end);
		bch_refill_keybuf(c, buf, end, pred);
	}

	return ret;
}

void bch_keybuf_init(struct keybuf *buf, keybuf_pred_fn *fn)
void bch_keybuf_init(struct keybuf *buf)
{
	buf->key_predicate	= fn;
	buf->last_scanned	= MAX_KEY;
	buf->keys		= RB_ROOT;

+5 −4
Original line number Diff line number Diff line
@@ -391,13 +391,14 @@ void bch_moving_gc(struct closure *);
int bch_btree_check(struct cache_set *, struct btree_op *);
uint8_t __bch_btree_mark_key(struct cache_set *, int, struct bkey *);

void bch_keybuf_init(struct keybuf *, keybuf_pred_fn *);
void bch_refill_keybuf(struct cache_set *, struct keybuf *, struct bkey *);
void bch_keybuf_init(struct keybuf *);
void bch_refill_keybuf(struct cache_set *, struct keybuf *, struct bkey *,
		       keybuf_pred_fn *);
bool bch_keybuf_check_overlapping(struct keybuf *, struct bkey *,
				  struct bkey *);
void bch_keybuf_del(struct keybuf *, struct keybuf_key *);
struct keybuf_key *bch_keybuf_next(struct keybuf *);
struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *,
					  struct keybuf *, struct bkey *);
struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *, struct keybuf *,
					  struct bkey *, keybuf_pred_fn *);

#endif
+2 −2
Original line number Diff line number Diff line
@@ -357,7 +357,7 @@ static ssize_t bch_dump_read(struct file *file, char __user *buf,
		if (i->bytes)
			break;

		w = bch_keybuf_next_rescan(i->c, &i->keys, &MAX_KEY);
		w = bch_keybuf_next_rescan(i->c, &i->keys, &MAX_KEY, dump_pred);
		if (!w)
			break;

@@ -380,7 +380,7 @@ static int bch_dump_open(struct inode *inode, struct file *file)

	file->private_data = i;
	i->c = c;
	bch_keybuf_init(&i->keys, dump_pred);
	bch_keybuf_init(&i->keys);
	i->keys.last_scanned = KEY(0, 0, 0);

	return 0;
+3 −2
Original line number Diff line number Diff line
@@ -136,7 +136,8 @@ static void read_moving(struct closure *cl)
	/* XXX: if we error, background writeback could stall indefinitely */

	while (!test_bit(CACHE_SET_STOPPING, &c->flags)) {
		w = bch_keybuf_next_rescan(c, &c->moving_gc_keys, &MAX_KEY);
		w = bch_keybuf_next_rescan(c, &c->moving_gc_keys,
					   &MAX_KEY, moving_pred);
		if (!w)
			break;

@@ -248,5 +249,5 @@ void bch_moving_gc(struct closure *cl)

void bch_moving_init_cache_set(struct cache_set *c)
{
	bch_keybuf_init(&c->moving_gc_keys, moving_pred);
	bch_keybuf_init(&c->moving_gc_keys);
}
Loading