diff options
author | Kent Overstreet <kmo@daterainc.com> | 2013-11-11 22:03:54 -0500 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2014-01-08 16:05:13 -0500 |
commit | 59158fde429fb5d18064e2734b3dd5e6048affbd (patch) | |
tree | 1cc4d34e0ba1523155dad7b8726b5249d050cc34 | |
parent | a85e968e66a175c86d0410719ea84a5bd0f1d070 (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.h | 15 | ||||
-rw-r--r-- | drivers/md/bcache/btree.c | 28 | ||||
-rw-r--r-- | include/uapi/linux/bcache.h | 1 |
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 | ||
263 | static 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 | |||
263 | static inline struct bset *bset_next_set(struct btree_keys *b, | 278 | static 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 | ||
182 | static 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 | ||
192 | void bkey_put(struct cache_set *c, struct bkey *k) | 184 | void bkey_put(struct cache_set *c, struct bkey *k) |
@@ -2026,6 +2018,19 @@ merged: | |||
2026 | return true; | 2018 | return true; |
2027 | } | 2019 | } |
2028 | 2020 | ||
2021 | static 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 | |||
2029 | static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op, | 2034 | static 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 | ||
43 | KEY_FIELD(KEY_PTRS, high, 60, 3) | 44 | KEY_FIELD(KEY_PTRS, high, 60, 3) |
44 | KEY_FIELD(HEADER_SIZE, high, 58, 2) | 45 | KEY_FIELD(HEADER_SIZE, high, 58, 2) |