]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
bcache: Insert multiple keys at a time
authorKent Overstreet <kmo@daterainc.com>
Thu, 25 Jul 2013 00:22:44 +0000 (17:22 -0700)
committerKent Overstreet <kmo@daterainc.com>
Wed, 11 Sep 2013 01:41:23 +0000 (18:41 -0700)
We'll often end up with a list of adjacent keys to insert -
because bch_data_insert() may have to fragment the data it writes.

Originally, to simplify things and avoid having to deal with corner
cases bch_btree_insert() would pass keys from this list one at a time to
btree_insert_recurse() - mainly because the list of keys might span leaf
nodes, so it was easier this way.

With the btree_insert_node() refactoring, it's now a lot easier to just
pass down the whole list and have btree_insert_recurse() iterate over
leaf nodes until it's done.

Signed-off-by: Kent Overstreet <kmo@daterainc.com>
drivers/md/bcache/btree.c

index b094c1d89ed61f0cf3da1f5e3a80972e5c890a6a..a2f77bb85d6e1b1007af3e0c08fe86d145e10953 100644 (file)
@@ -1846,10 +1846,14 @@ static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op,
        BUG_ON(!insert_lock(op, b));
 
        while (!bch_keylist_empty(insert_keys)) {
+               struct bset *i = write_block(b);
                struct bkey *k = insert_keys->bottom;
 
-               if (b->level ||
-                   bkey_cmp(k, &b->key) <= 0) {
+               if (b->written + __set_blocks(i, i->keys + bkey_u64s(k), b->c)
+                   > btree_blocks(b))
+                       break;
+
+               if (bkey_cmp(k, &b->key) <= 0) {
                        bkey_put(b->c, k, b->level);
 
                        ret |= btree_insert_key(b, op, k);
@@ -1876,6 +1880,8 @@ static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op,
                }
        }
 
+       BUG_ON(!bch_keylist_empty(insert_keys) && b->level);
+
        BUG_ON(bch_count_data(b) < oldsize);
        return ret;
 }
@@ -2061,6 +2067,8 @@ static int bch_btree_insert_node(struct btree *b, struct btree_op *op,
                                                  &split_keys);
                                insert_keys = &split_keys;
                                b = parent;
+                               if (!ret)
+                                       ret = -EINTR;
                        }
                } else {
                        BUG_ON(write_block(b) != b->sets[b->nsets].data);
@@ -2079,6 +2087,9 @@ static int bch_btree_insert_node(struct btree *b, struct btree_op *op,
 
 static int bch_btree_insert_recurse(struct btree *b, struct btree_op *op)
 {
+       if (bch_keylist_empty(&op->keys))
+               return 0;
+
        if (b->level) {
                struct bkey *insert = op->keys.bottom;
                struct bkey *k = bch_next_recurse_key(b, &START_KEY(insert));
@@ -2100,7 +2111,6 @@ static int bch_btree_insert_recurse(struct btree *b, struct btree_op *op)
 int bch_btree_insert(struct btree_op *op, struct cache_set *c)
 {
        int ret = 0;
-       struct keylist stack_keys;
 
        /*
         * Don't want to block with the btree locked unless we have to,
@@ -2109,17 +2119,9 @@ int bch_btree_insert(struct btree_op *op, struct cache_set *c)
        clear_closure_blocking(&op->cl);
 
        BUG_ON(bch_keylist_empty(&op->keys));
-       bch_keylist_copy(&stack_keys, &op->keys);
-       bch_keylist_init(&op->keys);
-
-       while (!bch_keylist_empty(&stack_keys) ||
-              !bch_keylist_empty(&op->keys)) {
-               if (bch_keylist_empty(&op->keys)) {
-                       bch_keylist_add(&op->keys,
-                                       bch_keylist_pop(&stack_keys));
-                       op->lock = 0;
-               }
 
+       while (!bch_keylist_empty(&op->keys)) {
+               op->lock = 0;
                ret = btree_root(insert_recurse, c, op);
 
                if (ret == -EAGAIN) {
@@ -2131,14 +2133,11 @@ int bch_btree_insert(struct btree_op *op, struct cache_set *c)
                        pr_err("error %i trying to insert key for %s",
                               ret, op_type(op));
 
-                       while ((k = bch_keylist_pop(&stack_keys) ?:
-                                   bch_keylist_pop(&op->keys)))
+                       while ((k = bch_keylist_pop(&op->keys)))
                                bkey_put(c, k, 0);
                }
        }
 
-       bch_keylist_free(&stack_keys);
-
        if (op->journal)
                atomic_dec_bug(op->journal);
        op->journal = NULL;