aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-12-20 20:22:05 -0500
committerKent Overstreet <kmo@daterainc.com>2014-01-08 16:05:12 -0500
commit65d45231b56efb3db51eb441e2c68f8252ecdd12 (patch)
treeb862e6fa72d076373c79841b555ef525d3b0f41b
parentee811287c9f241641899788cbfc9d70ed96ba3a5 (diff)
bcache: Abstract out stuff needed for sorting
Signed-off-by: Kent Overstreet <kmo@daterainc.com>
-rw-r--r--drivers/md/bcache/Makefile5
-rw-r--r--drivers/md/bcache/bset.c279
-rw-r--r--drivers/md/bcache/bset.h8
-rw-r--r--drivers/md/bcache/btree.c6
-rw-r--r--drivers/md/bcache/btree.h42
-rw-r--r--drivers/md/bcache/debug.c1
-rw-r--r--drivers/md/bcache/extents.c354
-rw-r--r--drivers/md/bcache/extents.h12
-rw-r--r--drivers/md/bcache/super.c5
9 files changed, 423 insertions, 289 deletions
diff --git a/drivers/md/bcache/Makefile b/drivers/md/bcache/Makefile
index 0e9c82523be6..c488b846f831 100644
--- a/drivers/md/bcache/Makefile
+++ b/drivers/md/bcache/Makefile
@@ -1,7 +1,8 @@
1 1
2obj-$(CONFIG_BCACHE) += bcache.o 2obj-$(CONFIG_BCACHE) += bcache.o
3 3
4bcache-y := alloc.o btree.o bset.o io.o journal.o writeback.o\ 4bcache-y := alloc.o bset.o btree.o closure.o debug.o extents.o\
5 movinggc.o request.o super.o sysfs.o debug.o util.o trace.o stats.o closure.o 5 io.o journal.o movinggc.o request.o stats.o super.o sysfs.o trace.o\
6 util.o writeback.o
6 7
7CFLAGS_request.o += -Iblock 8CFLAGS_request.o += -Iblock
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index e04e5908e29f..c2c42cbbe885 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -63,140 +63,6 @@ void bch_keylist_pop_front(struct keylist *l)
63 bch_keylist_bytes(l)); 63 bch_keylist_bytes(l));
64} 64}
65 65
66/* Pointer validation */
67
68static bool __ptr_invalid(struct cache_set *c, const struct bkey *k)
69{
70 unsigned i;
71
72 for (i = 0; i < KEY_PTRS(k); i++)
73 if (ptr_available(c, k, i)) {
74 struct cache *ca = PTR_CACHE(c, k, i);
75 size_t bucket = PTR_BUCKET_NR(c, k, i);
76 size_t r = bucket_remainder(c, PTR_OFFSET(k, i));
77
78 if (KEY_SIZE(k) + r > c->sb.bucket_size ||
79 bucket < ca->sb.first_bucket ||
80 bucket >= ca->sb.nbuckets)
81 return true;
82 }
83
84 return false;
85}
86
87bool bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k)
88{
89 char buf[80];
90
91 if (!KEY_PTRS(k) || !KEY_SIZE(k) || KEY_DIRTY(k))
92 goto bad;
93
94 if (__ptr_invalid(c, k))
95 goto bad;
96
97 return false;
98bad:
99 bch_bkey_to_text(buf, sizeof(buf), k);
100 cache_bug(c, "spotted btree ptr %s: %s", buf, bch_ptr_status(c, k));
101 return true;
102}
103
104bool bch_extent_ptr_invalid(struct cache_set *c, const struct bkey *k)
105{
106 char buf[80];
107
108 if (!KEY_SIZE(k))
109 return true;
110
111 if (KEY_SIZE(k) > KEY_OFFSET(k))
112 goto bad;
113
114 if (__ptr_invalid(c, k))
115 goto bad;
116
117 return false;
118bad:
119 bch_bkey_to_text(buf, sizeof(buf), k);
120 cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k));
121 return true;
122}
123
124static bool ptr_bad_expensive_checks(struct btree *b, const struct bkey *k,
125 unsigned ptr)
126{
127 struct bucket *g = PTR_BUCKET(b->c, k, ptr);
128 char buf[80];
129
130 if (mutex_trylock(&b->c->bucket_lock)) {
131 if (b->level) {
132 if (KEY_DIRTY(k) ||
133 g->prio != BTREE_PRIO ||
134 (b->c->gc_mark_valid &&
135 GC_MARK(g) != GC_MARK_METADATA))
136 goto err;
137
138 } else {
139 if (g->prio == BTREE_PRIO)
140 goto err;
141
142 if (KEY_DIRTY(k) &&
143 b->c->gc_mark_valid &&
144 GC_MARK(g) != GC_MARK_DIRTY)
145 goto err;
146 }
147 mutex_unlock(&b->c->bucket_lock);
148 }
149
150 return false;
151err:
152 mutex_unlock(&b->c->bucket_lock);
153 bch_bkey_to_text(buf, sizeof(buf), k);
154 btree_bug(b,
155"inconsistent pointer %s: bucket %zu pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i",
156 buf, PTR_BUCKET_NR(b->c, k, ptr), atomic_read(&g->pin),
157 g->prio, g->gen, g->last_gc, GC_MARK(g), g->gc_gen);
158 return true;
159}
160
161bool bch_ptr_bad(struct btree *b, const struct bkey *k)
162{
163 struct bucket *g;
164 unsigned i, stale;
165
166 if (!bkey_cmp(k, &ZERO_KEY) ||
167 !KEY_PTRS(k) ||
168 bch_ptr_invalid(b, k))
169 return true;
170
171 for (i = 0; i < KEY_PTRS(k); i++)
172 if (!ptr_available(b->c, k, i))
173 return true;
174
175 if (!expensive_debug_checks(b->c) && KEY_DIRTY(k))
176 return false;
177
178 for (i = 0; i < KEY_PTRS(k); i++) {
179 g = PTR_BUCKET(b->c, k, i);
180 stale = ptr_stale(b->c, k, i);
181
182 btree_bug_on(stale > 96, b,
183 "key too stale: %i, need_gc %u",
184 stale, b->c->need_gc);
185
186 btree_bug_on(stale && KEY_DIRTY(k) && KEY_SIZE(k),
187 b, "stale dirty pointer");
188
189 if (stale)
190 return true;
191
192 if (expensive_debug_checks(b->c) &&
193 ptr_bad_expensive_checks(b, k, i))
194 return true;
195 }
196
197 return false;
198}
199
200/* Key/pointer manipulation */ 66/* Key/pointer manipulation */
201 67
202void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src, 68void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src,
@@ -251,57 +117,6 @@ bool __bch_cut_back(const struct bkey *where, struct bkey *k)
251 return true; 117 return true;
252} 118}
253 119
254static uint64_t merge_chksums(struct bkey *l, struct bkey *r)
255{
256 return (l->ptr[KEY_PTRS(l)] + r->ptr[KEY_PTRS(r)]) &
257 ~((uint64_t)1 << 63);
258}
259
260/* Tries to merge l and r: l should be lower than r
261 * Returns true if we were able to merge. If we did merge, l will be the merged
262 * key, r will be untouched.
263 */
264bool bch_bkey_try_merge(struct btree *b, struct bkey *l, struct bkey *r)
265{
266 unsigned i;
267
268 if (key_merging_disabled(b->c))
269 return false;
270
271 if (KEY_PTRS(l) != KEY_PTRS(r) ||
272 KEY_DIRTY(l) != KEY_DIRTY(r) ||
273 bkey_cmp(l, &START_KEY(r)))
274 return false;
275
276 for (i = 0; i < KEY_PTRS(l); i++)
277 if (l->ptr[i] + PTR(0, KEY_SIZE(l), 0) != r->ptr[i] ||
278