aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-09-24 02:17:35 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-05 10:13:09 -0400
commitdf8b0d944cae63df86dba0edaa8fa8f5efaa7e03 (patch)
tree350da3f4b0ef9e6b05b07404f0b1df06c31b975e
parent7866bece346caecd88c53c6603e178ce4ebda87b (diff)
bcache: Fix for handling overlapping extents when reading in a btree node
commit 84786438ed17978d72eeced580ab757e4da8830b upstream. btree_sort_fixup() was overly clever, because it was trying to avoid pulling a key off the btree iterator in more than one place. This led to a really obscure bug where we'd break early from the loop in btree_sort_fixup() if the current key overlapped with keys in more than one older set, and the next key it overlapped with was zero size. Signed-off-by: Kent Overstreet <kmo@daterainc.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/md/bcache/bset.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index cb4578a327b9..14032e8c7731 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -918,28 +918,45 @@ struct bkey *bch_next_recurse_key(struct btree *b, struct bkey *search)
918 918
919/* Mergesort */ 919/* Mergesort */
920 920
921static void sort_key_next(struct btree_iter *iter,
922 struct btree_iter_set *i)
923{
924 i->k = bkey_next(i->k);
925
926 if (i->k == i->end)
927 *i = iter->data[--iter->used];
928}
929
921static void btree_sort_fixup(struct btree_iter *iter) 930static void btree_sort_fixup(struct btree_iter *iter)
922{ 931{
923 while (iter->used > 1) { 932 while (iter->used > 1) {
924 struct btree_iter_set *top = iter->data, *i = top + 1; 933 struct btree_iter_set *top = iter->data, *i = top + 1;
925 struct bkey *k;
926 934
927 if (iter->used > 2 && 935 if (iter->used > 2 &&
928 btree_iter_cmp(i[0], i[1])) 936 btree_iter_cmp(i[0], i[1]))
929 i++; 937 i++;
930 938
931 for (k = i->k; 939 if (bkey_cmp(top->k, &START_KEY(i->k)) <= 0)
932 k != i->end && bkey_cmp(top->k, &START_KEY(k)) > 0;
933 k = bkey_next(k))
934 if (top->k > i->k)
935 __bch_cut_front(top->k, k);
936 else if (KEY_SIZE(k))
937 bch_cut_back(&START_KEY(k), top->k);
938
939 if (top->k < i->k || k == i->k)
940 break; 940 break;
941 941
942 heap_sift(iter, i - top, btree_iter_cmp); 942 if (!KEY_SIZE(i->k)) {
943 sort_key_next(iter, i);
944 heap_sift(iter, i - top, btree_iter_cmp);
945 continue;
946 }
947
948 if (top->k > i->k) {
949 if (bkey_cmp(top->k, i->k) >= 0)
950 sort_key_next(iter, i);
951 else
952 bch_cut_front(top->k, i->k);
953
954 heap_sift(iter, i - top, btree_iter_cmp);
955 } else {
956 /* can't happen because of comparison func */
957 BUG_ON(!bkey_cmp(&START_KEY(top->k), &START_KEY(i->k)));
958 bch_cut_back(&START_KEY(i->k), top->k);
959 }
943 } 960 }
944} 961}
945 962