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) |
