diff options
author | Kent Overstreet <kmo@daterainc.com> | 2014-04-10 20:58:49 -0400 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2014-08-04 18:23:02 -0400 |
commit | 9aa61a992acceeec0d1de2cd99938421498659d5 (patch) | |
tree | d414fdba809e0193f0d19d5ea80180ef96f3a23e | |
parent | 5b1016e62f74c53e0330403025954c8d95384c03 (diff) |
bcache: Fix a journal replay bug
journal replay wansn't validating pointers with bch_extent_invalid() before
derefing, fixed
Signed-off-by: Kent Overstreet <kmo@daterainc.com>
-rw-r--r-- | drivers/md/bcache/extents.c | 13 | ||||
-rw-r--r-- | drivers/md/bcache/extents.h | 1 | ||||
-rw-r--r-- | drivers/md/bcache/journal.c | 16 |
3 files changed, 19 insertions, 11 deletions
diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c index 3a0de4cf9771..243de0bf15cd 100644 --- a/drivers/md/bcache/extents.c +++ b/drivers/md/bcache/extents.c | |||
@@ -474,9 +474,8 @@ out: | |||
474 | return false; | 474 | return false; |
475 | } | 475 | } |
476 | 476 | ||
477 | static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k) | 477 | bool __bch_extent_invalid(struct cache_set *c, const struct bkey *k) |
478 | { | 478 | { |
479 | struct btree *b = container_of(bk, struct btree, keys); | ||
480 | char buf[80]; | 479 | char buf[80]; |
481 | 480 | ||
482 | if (!KEY_SIZE(k)) | 481 | if (!KEY_SIZE(k)) |
@@ -485,16 +484,22 @@ static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k) | |||
485 | if (KEY_SIZE(k) > KEY_OFFSET(k)) | 484 | if (KEY_SIZE(k) > KEY_OFFSET(k)) |
486 | goto bad; | 485 | goto bad; |
487 | 486 | ||
488 | if (__ptr_invalid(b->c, k)) | 487 | if (__ptr_invalid(c, k)) |
489 | goto bad; | 488 | goto bad; |
490 | 489 | ||
491 | return false; | 490 | return false; |
492 | bad: | 491 | bad: |
493 | bch_extent_to_text(buf, sizeof(buf), k); | 492 | bch_extent_to_text(buf, sizeof(buf), k); |
494 | cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k)); | 493 | cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k)); |
495 | return true; | 494 | return true; |
496 | } | 495 | } |
497 | 496 | ||
497 | static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k) | ||
498 | { | ||
499 | struct btree *b = container_of(bk, struct btree, keys); | ||
500 | return __bch_extent_invalid(b->c, k); | ||
501 | } | ||
502 | |||
498 | static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k, | 503 | static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k, |
499 | unsigned ptr) | 504 | unsigned ptr) |
500 | { | 505 | { |
diff --git a/drivers/md/bcache/extents.h b/drivers/md/bcache/extents.h index e4e23409782d..e2ed54054e7a 100644 --- a/drivers/md/bcache/extents.h +++ b/drivers/md/bcache/extents.h | |||
@@ -9,5 +9,6 @@ struct cache_set; | |||
9 | 9 | ||
10 | void bch_extent_to_text(char *, size_t, const struct bkey *); | 10 | void bch_extent_to_text(char *, size_t, const struct bkey *); |
11 | bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *); | 11 | bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *); |
12 | bool __bch_extent_invalid(struct cache_set *, const struct bkey *); | ||
12 | 13 | ||
13 | #endif /* _BCACHE_EXTENTS_H */ | 14 | #endif /* _BCACHE_EXTENTS_H */ |
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index 59e82021b5bb..363b88131f01 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "bcache.h" | 7 | #include "bcache.h" |
8 | #include "btree.h" | 8 | #include "btree.h" |
9 | #include "debug.h" | 9 | #include "debug.h" |
10 | #include "extents.h" | ||
10 | 11 | ||
11 | #include <trace/events/bcache.h> | 12 | #include <trace/events/bcache.h> |
12 | 13 | ||
@@ -291,15 +292,16 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list) | |||
291 | 292 | ||
292 | for (k = i->j.start; | 293 | for (k = i->j.start; |
293 | k < bset_bkey_last(&i->j); | 294 | k < bset_bkey_last(&i->j); |
294 | k = bkey_next(k)) { | 295 | k = bkey_next(k)) |
295 | unsigned j; | 296 | if (!__bch_extent_invalid(c, k)) { |
297 | unsigned j; | ||
296 | 298 | ||
297 | for (j = 0; j < KEY_PTRS(k); j++) | 299 | for (j = 0; j < KEY_PTRS(k); j++) |
298 | if (ptr_available(c, k, j)) | 300 | if (ptr_available(c, k, j)) |
299 | atomic_inc(&PTR_BUCKET(c, k, j)->pin); | 301 | atomic_inc(&PTR_BUCKET(c, k, j)->pin); |
300 | 302 | ||
301 | bch_initial_mark_key(c, 0, k); | 303 | bch_initial_mark_key(c, 0, k); |
302 | } | 304 | } |
303 | } | 305 | } |
304 | } | 306 | } |
305 | 307 | ||