Commit 9aa61a99 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcache: Fix a journal replay bug



journal replay wansn't validating pointers with bch_extent_invalid() before
derefing, fixed

Signed-off-by: default avatarKent Overstreet <kmo@daterainc.com>
parent 5b1016e6
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -474,9 +474,8 @@ out:
	return false;
}

static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
bool __bch_extent_invalid(struct cache_set *c, const struct bkey *k)
{
	struct btree *b = container_of(bk, struct btree, keys);
	char buf[80];

	if (!KEY_SIZE(k))
@@ -485,16 +484,22 @@ static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
	if (KEY_SIZE(k) > KEY_OFFSET(k))
		goto bad;

	if (__ptr_invalid(b->c, k))
	if (__ptr_invalid(c, k))
		goto bad;

	return false;
bad:
	bch_extent_to_text(buf, sizeof(buf), k);
	cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k));
	cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k));
	return true;
}

static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
{
	struct btree *b = container_of(bk, struct btree, keys);
	return __bch_extent_invalid(b->c, k);
}

static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
				     unsigned ptr)
{
+1 −0
Original line number Diff line number Diff line
@@ -9,5 +9,6 @@ struct cache_set;

void bch_extent_to_text(char *, size_t, const struct bkey *);
bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *);
bool __bch_extent_invalid(struct cache_set *, const struct bkey *);

#endif /* _BCACHE_EXTENTS_H */
+9 −7
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include "bcache.h"
#include "btree.h"
#include "debug.h"
#include "extents.h"

#include <trace/events/bcache.h>

@@ -291,7 +292,8 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list)

		for (k = i->j.start;
		     k < bset_bkey_last(&i->j);
		     k = bkey_next(k)) {
		     k = bkey_next(k))
			if (!__bch_extent_invalid(c, k)) {
				unsigned j;

				for (j = 0; j < KEY_PTRS(k); j++)