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

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
...@@ -474,9 +474,8 @@ static bool bch_extent_insert_fixup(struct btree_keys *b, ...@@ -474,9 +474,8 @@ static bool bch_extent_insert_fixup(struct btree_keys *b,
return false; 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]; char buf[80];
if (!KEY_SIZE(k)) if (!KEY_SIZE(k))
...@@ -485,16 +484,22 @@ static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *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)) if (KEY_SIZE(k) > KEY_OFFSET(k))
goto bad; goto bad;
if (__ptr_invalid(b->c, k)) if (__ptr_invalid(c, k))
goto bad; goto bad;
return false; return false;
bad: bad:
bch_extent_to_text(buf, sizeof(buf), k); 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; 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, static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
unsigned ptr) unsigned ptr)
{ {
......
...@@ -9,5 +9,6 @@ struct cache_set; ...@@ -9,5 +9,6 @@ struct cache_set;
void bch_extent_to_text(char *, size_t, const struct bkey *); void bch_extent_to_text(char *, size_t, const struct bkey *);
bool __bch_btree_ptr_invalid(struct cache_set *, 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 */ #endif /* _BCACHE_EXTENTS_H */
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "bcache.h" #include "bcache.h"
#include "btree.h" #include "btree.h"
#include "debug.h" #include "debug.h"
#include "extents.h"
#include <trace/events/bcache.h> #include <trace/events/bcache.h>
...@@ -291,15 +292,16 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list) ...@@ -291,15 +292,16 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list)
for (k = i->j.start; for (k = i->j.start;
k < bset_bkey_last(&i->j); k < bset_bkey_last(&i->j);
k = bkey_next(k)) { k = bkey_next(k))
unsigned j; if (!__bch_extent_invalid(c, k)) {
unsigned j;
for (j = 0; j < KEY_PTRS(k); j++) for (j = 0; j < KEY_PTRS(k); j++)
if (ptr_available(c, k, j)) if (ptr_available(c, k, j))
atomic_inc(&PTR_BUCKET(c, k, j)->pin); atomic_inc(&PTR_BUCKET(c, k, j)->pin);
bch_initial_mark_key(c, 0, k); bch_initial_mark_key(c, 0, k);
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment