aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-11-11 22:03:54 -0500
committerKent Overstreet <kmo@daterainc.com>2014-01-08 16:05:13 -0500
commit59158fde429fb5d18064e2734b3dd5e6048affbd (patch)
tree1cc4d34e0ba1523155dad7b8726b5249d050cc34
parenta85e968e66a175c86d0410719ea84a5bd0f1d070 (diff)
bcache: Add bch_btree_keys_u64s_remaining()
Helper function to explicitly check how much space is free in a btree node Signed-off-by: Kent Overstreet <kmo@daterainc.com>
-rw-r--r--drivers/md/bcache/bset.h15
-rw-r--r--drivers/md/bcache/btree.c28
-rw-r--r--include/uapi/linux/bcache.h1
3 files changed, 31 insertions, 13 deletions
diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h
index 87da828477f3..4fc40fd719de 100644
--- a/drivers/md/bcache/bset.h
+++ b/drivers/md/bcache/bset.h
@@ -260,6 +260,21 @@ static inline bool btree_keys_expensive_checks(struct btree_keys *b)
260#define set_blocks(i, block_bytes) \ 260#define set_blocks(i, block_bytes) \
261 __set_blocks(i, (i)->keys, block_bytes) 261 __set_blocks(i, (i)->keys, block_bytes)
262 262
263static inline size_t bch_btree_keys_u64s_remaining(struct btree_keys *b)
264{
265 struct bset_tree *t = bset_tree_last(b);
266
267 BUG_ON((PAGE_SIZE << b->page_order) <
268 (bset_byte_offset(b, t->data) + set_bytes(t->data)));
269
270 if (!b->last_set_unwritten)
271 return 0;
272
273 return ((PAGE_SIZE << b->page_order) -
274 (bset_byte_offset(b, t->data) + set_bytes(t->data))) /
275 sizeof(u64);
276}
277
263static inline struct bset *bset_next_set(struct btree_keys *b, 278static inline struct bset *bset_next_set(struct btree_keys *b,
264 unsigned block_bytes) 279 unsigned block_bytes)
265{ 280{
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 5d7dee8bb850..2c90003ff4ce 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -179,14 +179,6 @@ static inline struct bset *write_block(struct btree *b)
179 return ((void *) btree_bset_first(b)) + b->written * block_bytes(b->c); 179 return ((void *) btree_bset_first(b)) + b->written * block_bytes(b->c);
180} 180}
181 181
182static inline bool should_split(struct btree *b)
183{
184 struct bset *i = write_block(b);
185 return b->written >= btree_blocks(b) ||
186 (b->written + __set_blocks(i, i->keys + 15, block_bytes(b->c))
187 > btree_blocks(b));
188}
189
190/* Btree key manipulation */ 182/* Btree key manipulation */
191 183
192void bkey_put(struct cache_set *c, struct bkey *k) 184void bkey_put(struct cache_set *c, struct bkey *k)
@@ -2026,6 +2018,19 @@ merged:
2026 return true; 2018 return true;
2027} 2019}
2028 2020
2021static size_t insert_u64s_remaining(struct btree *b)
2022{
2023 ssize_t ret = bch_btree_keys_u64s_remaining(&b->keys);
2024
2025 /*
2026 * Might land in the middle of an existing extent and have to split it
2027 */
2028 if (b->keys.ops->is_extents)
2029 ret -= KEY_MAX_U64S;
2030
2031 return max(ret, 0L);
2032}
2033
2029static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op, 2034static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op,
2030 struct keylist *insert_keys, 2035 struct keylist *insert_keys,
2031 struct bkey *replace_key) 2036 struct bkey *replace_key)
@@ -2034,12 +2039,9 @@ static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op,
2034 int oldsize = bch_count_data(b); 2039 int oldsize = bch_count_data(b);
2035 2040
2036 while (!bch_keylist_empty(insert_keys)) { 2041 while (!bch_keylist_empty(insert_keys)) {
2037 struct bset *i = write_block(b);
2038 struct bkey *k = insert_keys->keys; 2042 struct bkey *k = insert_keys->keys;
2039 2043
2040 if (b->written + 2044 if (bkey_u64s(k) > insert_u64s_remaining(b))
2041 __set_blocks(i, i->keys + bkey_u64s(k),
2042 block_bytes(b->c)) > btree_blocks(b))
2043 break; 2045 break;
2044 2046
2045 if (bkey_cmp(k, &b->key) <= 0) { 2047 if (bkey_cmp(k, &b->key) <= 0) {
@@ -2203,7 +2205,7 @@ static int bch_btree_insert_node(struct btree *b, struct btree_op *op,
2203{ 2205{
2204 BUG_ON(b->level && replace_key); 2206 BUG_ON(b->level && replace_key);
2205 2207
2206 if (should_split(b)) { 2208 if (bch_keylist_nkeys(insert_keys) > insert_u64s_remaining(b)) {
2207 if (current->bio_list) { 2209 if (current->bio_list) {
2208 op->lock = b->c->root->level + 1; 2210 op->lock = b->c->root->level + 1;
2209 return -EAGAIN; 2211 return -EAGAIN;
diff --git a/include/uapi/linux/bcache.h b/include/uapi/linux/bcache.h
index ae66311be82f..22b6ad31c706 100644
--- a/include/uapi/linux/bcache.h
+++ b/include/uapi/linux/bcache.h
@@ -39,6 +39,7 @@ static inline void SET_##name(struct bkey *k, unsigned i, __u64 v) \
39} 39}
40 40
41#define KEY_SIZE_BITS 16 41#define KEY_SIZE_BITS 16
42#define KEY_MAX_U64S 8
42 43
43KEY_FIELD(KEY_PTRS, high, 60, 3) 44KEY_FIELD(KEY_PTRS, high, 60, 3)
44KEY_FIELD(HEADER_SIZE, high, 58, 2) 45KEY_FIELD(HEADER_SIZE, high, 58, 2)