Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+19 -11
+9 -4
drivers/md/bcache/extents.c
··· 474 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 479 char buf[80]; 481 480 482 481 if (!KEY_SIZE(k)) ··· 484 485 if (KEY_SIZE(k) > KEY_OFFSET(k)) 485 486 goto bad; 486 487 487 - if (__ptr_invalid(b->c, k)) 488 + if (__ptr_invalid(c, k)) 488 489 goto bad; 489 490 490 491 return false; 491 492 bad: 492 493 bch_extent_to_text(buf, sizeof(buf), k); 493 - cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k)); 494 + cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k)); 494 495 return true; 496 + } 497 + 498 + static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k) 499 + { 500 + struct btree *b = container_of(bk, struct btree, keys); 501 + return __bch_extent_invalid(b->c, k); 495 502 } 496 503 497 504 static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
+1
drivers/md/bcache/extents.h
··· 9 9 10 10 void bch_extent_to_text(char *, size_t, const struct bkey *); 11 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 14 #endif /* _BCACHE_EXTENTS_H */
+9 -7
drivers/md/bcache/journal.c
··· 7 7 #include "bcache.h" 8 8 #include "btree.h" 9 9 #include "debug.h" 10 + #include "extents.h" 10 11 11 12 #include <trace/events/bcache.h> 12 13 ··· 292 291 293 292 for (k = i->j.start; 294 293 k < bset_bkey_last(&i->j); 295 - k = bkey_next(k)) { 296 - unsigned j; 294 + k = bkey_next(k)) 295 + if (!__bch_extent_invalid(c, k)) { 296 + unsigned j; 297 297 298 - for (j = 0; j < KEY_PTRS(k); j++) 299 - if (ptr_available(c, k, j)) 300 - atomic_inc(&PTR_BUCKET(c, k, j)->pin); 298 + for (j = 0; j < KEY_PTRS(k); j++) 299 + if (ptr_available(c, k, j)) 300 + atomic_inc(&PTR_BUCKET(c, k, j)->pin); 301 301 302 - bch_initial_mark_key(c, 0, k); 303 - } 302 + bch_initial_mark_key(c, 0, k); 303 + } 304 304 } 305 305 } 306 306