aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2015-11-29 21:47:01 -0500
committerJens Axboe <axboe@fb.com>2015-12-30 22:23:16 -0500
commit627ccd20b4ad3ba836472468208e2ac4dfadbf03 (patch)
treea784e113c005e53ba3d86f27c3f9a0c59bd55de6
parent8d16ce540c94c9d366eb36fc91b7154d92d6397b (diff)
bcache: Change refill_dirty() to always scan entire disk if necessary
Previously, it would only scan the entire disk if it was starting from the very start of the disk - i.e. if the previous scan got to the end. This was broken by refill_full_stripes(), which updates last_scanned so that refill_dirty was never triggering the searched_from_start path. But if we change refill_dirty() to always scan the entire disk if necessary, regardless of what last_scanned was, the code gets cleaner and we fix that bug too. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--drivers/md/bcache/writeback.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index b23f88d9f18c..b9346cd9cda1 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -323,6 +323,10 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
323 323
324static bool dirty_pred(struct keybuf *buf, struct bkey *k) 324static bool dirty_pred(struct keybuf *buf, struct bkey *k)
325{ 325{
326 struct cached_dev *dc = container_of(buf, struct cached_dev, writeback_keys);
327
328 BUG_ON(KEY_INODE(k) != dc->disk.id);
329
326 return KEY_DIRTY(k); 330 return KEY_DIRTY(k);
327} 331}
328 332
@@ -372,11 +376,24 @@ next:
372 } 376 }
373} 377}
374 378
379/*
380 * Returns true if we scanned the entire disk
381 */
375static bool refill_dirty(struct cached_dev *dc) 382static bool refill_dirty(struct cached_dev *dc)
376{ 383{
377 struct keybuf *buf = &dc->writeback_keys; 384 struct keybuf *buf = &dc->writeback_keys;
385 struct bkey start = KEY(dc->disk.id, 0, 0);
378 struct bkey end = KEY(dc->disk.id, MAX_KEY_OFFSET, 0); 386 struct bkey end = KEY(dc->disk.id, MAX_KEY_OFFSET, 0);
379 bool searched_from_start = false; 387 struct bkey start_pos;
388
389 /*
390 * make sure keybuf pos is inside the range for this disk - at bringup
391 * we might not be attached yet so this disk's inode nr isn't
392 * initialized then
393 */
394 if (bkey_cmp(&buf->last_scanned, &start) < 0 ||
395 bkey_cmp(&buf->last_scanned, &end) > 0)
396 buf->last_scanned = start;
380 397
381 if (dc->partial_stripes_expensive) { 398 if (dc->partial_stripes_expensive) {
382 refill_full_stripes(dc); 399 refill_full_stripes(dc);
@@ -384,14 +401,20 @@ static bool refill_dirty(struct cached_dev *dc)
384 return false; 401 return false;
385 } 402 }
386 403
387 if (bkey_cmp(&buf->last_scanned, &end) >= 0) { 404 start_pos = buf->last_scanned;
388 buf->last_scanned = KEY(dc->disk.id, 0, 0);
389 searched_from_start = true;
390 }
391
392 bch_refill_keybuf(dc->disk.c, buf, &end, dirty_pred); 405 bch_refill_keybuf(dc->disk.c, buf, &end, dirty_pred);
393 406
394 return bkey_cmp(&buf->last_scanned, &end) >= 0 && searched_from_start; 407 if (bkey_cmp(&buf->last_scanned, &end) < 0)
408 return false;
409
410 /*
411 * If we get to the end start scanning again from the beginning, and
412 * only scan up to where we initially started scanning from:
413 */
414 buf->last_scanned = start;
415 bch_refill_keybuf(dc->disk.c, buf, &start_pos, dirty_pred);
416
417 return bkey_cmp(&buf->last_scanned, &start_pos) >= 0;
395} 418}
396 419
397static int bch_writeback_thread(void *arg) 420static int bch_writeback_thread(void *arg)