aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2014-03-17 18:13:26 -0400
committerKent Overstreet <kmo@daterainc.com>2014-03-18 15:22:33 -0400
commit487dded86ea065317aea121bec8f1816f2f235c9 (patch)
tree3d333832a9b133156985af197d1bd2952b033c6b
parent0bd143fd800055b1db756693289bbebdb93f2a73 (diff)
bcache: Fix another bug recovering from unclean shutdown
The on disk bucket gens are allowed to be out of date, when we reuse buckets that didn't have any live data in them. To deal with this, the initial gc has to update the bucket gen when we find a pointer gen newer than the bucket's gen. Unfortunately we weren't doing this for pointers in the journal that we're about to replay. Signed-off-by: Kent Overstreet <kmo@daterainc.com>
-rw-r--r--drivers/md/bcache/btree.c82
-rw-r--r--drivers/md/bcache/btree.h2
-rw-r--r--drivers/md/bcache/journal.c17
3 files changed, 36 insertions, 65 deletions
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 2d4a864865eb..5f587ce57e3a 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -1126,7 +1126,8 @@ static int btree_check_reserve(struct btree *b, struct btree_op *op)
1126 1126
1127/* Garbage collection */ 1127/* Garbage collection */
1128 1128
1129uint8_t __bch_btree_mark_key(struct cache_set *c, int level, struct bkey *k) 1129static uint8_t __bch_btree_mark_key(struct cache_set *c, int level,
1130 struct bkey *k)
1130{ 1131{
1131 uint8_t stale = 0; 1132 uint8_t stale = 0;
1132 unsigned i; 1133 unsigned i;
@@ -1177,6 +1178,26 @@ uint8_t __bch_btree_mark_key(struct cache_set *c, int level, struct bkey *k)
1177 1178
1178#define btree_mark_key(b, k) __bch_btree_mark_key(b->c, b->level, k) 1179#define btree_mark_key(b, k) __bch_btree_mark_key(b->c, b->level, k)
1179 1180
1181void bch_initial_mark_key(struct cache_set *c, int level, struct bkey *k)
1182{
1183 unsigned i;
1184
1185 for (i = 0; i < KEY_PTRS(k); i++)
1186 if (ptr_available(c, k, i) &&
1187 !ptr_stale(c, k, i)) {
1188 struct bucket *b = PTR_BUCKET(c, k, i);
1189
1190 b->gen = PTR_GEN(k, i);
1191
1192 if (level && bkey_cmp(k, &ZERO_KEY))
1193 b->prio = BTREE_PRIO;
1194 else if (!level && b->prio == BTREE_PRIO)
1195 b->prio = INITIAL_PRIO;
1196 }
1197
1198 __bch_btree_mark_key(c, level, k);
1199}
1200
1180static bool btree_gc_mark_node(struct btree *b, struct gc_stat *gc) 1201static bool btree_gc_mark_node(struct btree *b, struct gc_stat *gc)
1181{ 1202{
1182 uint8_t stale = 0; 1203 uint8_t stale = 0;
@@ -1511,6 +1532,8 @@ static int bch_btree_gc_root(struct btree *b, struct btree_op *op,
1511 } 1532 }
1512 } 1533 }
1513 1534
1535 __bch_btree_mark_key(b->c, b->level + 1, &b->key);
1536
1514 if (b->level) { 1537 if (b->level) {
1515 ret = btree_gc_recurse(b, op, writes, gc); 1538 ret = btree_gc_recurse(b, op, writes, gc);
1516 if (ret) 1539 if (ret)
@@ -1561,11 +1584,6 @@ size_t bch_btree_gc_finish(struct cache_set *c)
1561 c->gc_mark_valid = 1; 1584 c->gc_mark_valid = 1;
1562 c->need_gc = 0; 1585 c->need_gc = 0;
1563 1586
1564 if (c->root)
1565 for (i = 0; i < KEY_PTRS(&c->root->key); i++)
1566 SET_GC_MARK(PTR_BUCKET(c, &c->root->key, i),
1567 GC_MARK_METADATA);
1568
1569 for (i = 0; i < KEY_PTRS(&c->uuid_bucket); i++) 1587 for (i = 0; i < KEY_PTRS(&c->uuid_bucket); i++)
1570 SET_GC_MARK(PTR_BUCKET(c, &c->uuid_bucket, i), 1588 SET_GC_MARK(PTR_BUCKET(c, &c->uuid_bucket, i),
1571 GC_MARK_METADATA); 1589 GC_MARK_METADATA);
@@ -1705,36 +1723,16 @@ int bch_gc_thread_start(struct cache_set *c)
1705 1723
1706/* Initial partial gc */ 1724/* Initial partial gc */
1707 1725
1708static int bch_btree_check_recurse(struct btree *b, struct btree_op *op, 1726static int bch_btree_check_recurse(struct btree *b, struct btree_op *op)
1709 unsigned long **seen)
1710{ 1727{
1711 int ret = 0; 1728 int ret = 0;
1712 unsigned i;
1713 struct bkey *k, *p = NULL; 1729 struct bkey *k, *p = NULL;
1714 struct bucket *g;
1715 struct btree_iter iter; 1730 struct btree_iter iter;
1716 1731
1717 for_each_key_filter(&b->keys, k, &iter, bch_ptr_invalid) { 1732 for_each_key_filter(&b->keys, k, &iter, bch_ptr_invalid)
1718 for (i = 0; i < KEY_PTRS(k); i++) { 1733 bch_initial_mark_key(b->c, b->level, k);
1719 if (!ptr_available(b->c, k, i))
1720 continue;
1721
1722 g = PTR_BUCKET(b->c, k, i);
1723
1724 if (!__test_and_set_bit(PTR_BUCKET_NR(b->c, k, i),
1725 seen[PTR_DEV(k, i)]) ||
1726 !ptr_stale(b->c, k, i)) {
1727 g->gen = PTR_GEN(k, i);
1728
1729 if (b->level && bkey_cmp(k, &ZERO_KEY))
1730 g->prio = BTREE_PRIO;
1731 else if (!b->level && g->prio == BTREE_PRIO)
1732 g->prio = INITIAL_PRIO;
1733 }
1734 }
1735 1734
1736 btree_mark_key(b, k); 1735 bch_initial_mark_key(b->c, b->level + 1, &b->key);
1737 }
1738 1736
1739 if (b->level) { 1737 if (b->level) {
1740 bch_btree_iter_init(&b->keys, &iter, NULL); 1738 bch_btree_iter_init(&b->keys, &iter, NULL);
@@ -1746,40 +1744,22 @@ static int bch_btree_check_recurse(struct btree *b, struct btree_op *op,
1746 btree_node_prefetch(b->c, k, b->level - 1); 1744 btree_node_prefetch(b->c, k, b->level - 1);
1747 1745
1748 if (p) 1746 if (p)
1749 ret = btree(check_recurse, p, b, op, seen); 1747 ret = btree(check_recurse, p, b, op);
1750 1748
1751 p = k; 1749 p = k;
1752 } while (p && !ret); 1750 } while (p && !ret);
1753 } 1751 }
1754 1752
1755 return 0; 1753 return ret;
1756} 1754}
1757 1755
1758int bch_btree_check(struct cache_set *c) 1756int bch_btree_check(struct cache_set *c)
1759{ 1757{
1760 int ret = -ENOMEM;
1761 unsigned i;
1762 unsigned long *seen[MAX_CACHES_PER_SET];
1763 struct btree_op op; 1758 struct btree_op op;
1764 1759
1765 memset(seen, 0, sizeof(seen));
1766 bch_btree_op_init(&op, SHRT_MAX); 1760 bch_btree_op_init(&op, SHRT_MAX);
1767 1761
1768 for (i = 0; c->cache[i]; i++) { 1762 return btree_root(check_recurse, c, &op);
1769 size_t n = DIV_ROUND_UP(c->cache[i]->sb.nbuckets, 8);
1770 seen[i] = kmalloc(n, GFP_KERNEL);
1771 if (!seen[i])
1772 goto err;
1773
1774 /* Disables the seen array until prio_read() uses it too */
1775 memset(seen[i], 0xFF, n);
1776 }
1777
1778 ret = btree_root(check_recurse, c, &op, seen);
1779err:
1780 for (i = 0; i < MAX_CACHES_PER_SET; i++)
1781 kfree(seen[i]);
1782 return ret;
1783} 1763}
1784 1764
1785/* Btree insertion */ 1765/* Btree insertion */
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
index af065e97e55c..def9dc4a822f 100644
--- a/drivers/md/bcache/btree.h
+++ b/drivers/md/bcache/btree.h
@@ -251,7 +251,7 @@ int bch_gc_thread_start(struct cache_set *);
251size_t bch_btree_gc_finish(struct cache_set *); 251size_t bch_btree_gc_finish(struct cache_set *);
252void bch_moving_gc(struct cache_set *); 252void bch_moving_gc(struct cache_set *);
253int bch_btree_check(struct cache_set *); 253int bch_btree_check(struct cache_set *);
254uint8_t __bch_btree_mark_key(struct cache_set *, int, struct bkey *); 254void bch_initial_mark_key(struct cache_set *, int, struct bkey *);
255 255
256static inline void wake_up_gc(struct cache_set *c) 256static inline void wake_up_gc(struct cache_set *c)
257{ 257{
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 4152a9119896..cf8e0932aad2 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -293,21 +293,12 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list)
293 k < bset_bkey_last(&i->j); 293 k < bset_bkey_last(&i->j);
294 k = bkey_next(k)) { 294 k = bkey_next(k)) {
295 unsigned j; 295 unsigned j;
296 struct bucket *g;
297 296
298 for (j = 0; j < KEY_PTRS(k); j++) { 297 for (j = 0; j < KEY_PTRS(k); j++)
299 if (!ptr_available(c, k, j)) 298 if (ptr_available(c, k, j))
300 continue; 299 atomic_inc(&PTR_BUCKET(c, k, j)->pin);
301 300
302 g = PTR_BUCKET(c, k, j); 301 bch_initial_mark_key(c, 0, k);
303 atomic_inc(&g->pin);
304
305 if (g->prio == BTREE_PRIO &&
306 !ptr_stale(c, k, j))
307 g->prio = INITIAL_PRIO;
308 }
309
310 __bch_btree_mark_key(c, 0, k);
311 } 302 }
312 } 303 }
313} 304}