summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2015-05-28 23:46:24 -0700
committerKent Overstreet <kent.overstreet@gmail.com>2017-01-18 20:57:10 -0900
commit3759e8982de153c493d9a18db4b3212e253de3ac (patch)
tree35bdaabb1b54f4d40cf87a0b5c9ca01a7e0f30f2
parent758c5639d0f9961c6eeb0a3411f6687cbc430ab2 (diff)
bcache: Take inline_keys out of struct keylist
this is to make keylist_single smaller, and because we're gonna need explicit control over this soon
-rw-r--r--drivers/md/bcache/btree.c17
-rw-r--r--drivers/md/bcache/dirent.c2
-rw-r--r--drivers/md/bcache/gc.c2
-rw-r--r--drivers/md/bcache/io.c5
-rw-r--r--drivers/md/bcache/io.h1
-rw-r--r--drivers/md/bcache/keylist.c7
-rw-r--r--drivers/md/bcache/keylist.h18
-rw-r--r--drivers/md/bcache/keylist_types.h15
-rw-r--r--drivers/md/bcache/writeback.c12
-rw-r--r--drivers/md/bcache/xattr.c32
10 files changed, 62 insertions, 49 deletions
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 5c3b0c15aab9..8db2f8c62e3a 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -2313,6 +2313,13 @@ do_init_next: bch_btree_init_next(iter->c, b, iter);
struct btree_split_state {
struct closure stack_cl;
struct keylist parent_keys;
+ /*
+ * Enough room for btree_split's keys without realloc - btree node
+ * pointers never have crc/compression info, so we only need to acount
+ * for the pointers for three keys
+ */
+ u64 inline_keys[(BKEY_U64s +
+ BKEY_EXTENT_PTRS_MAX) * 3];
struct btree_reserve *reserve;
};
@@ -2492,9 +2499,9 @@ static void btree_split(struct btree *b, struct btree_iter *iter,
bch_btree_set_root(c, n3);
} else if (!parent) {
- BUG_ON(state->parent_keys.start_keys_p !=
- state->parent_keys.inline_keys);
- bch_keylist_init(&state->parent_keys);
+ bch_keylist_init(&state->parent_keys,
+ state->inline_keys,
+ ARRAY_SIZE(state->inline_keys));
/* Root filled up but didn't need to be split */
closure_sync(&state->stack_cl);
@@ -2611,7 +2618,9 @@ int bch_btree_insert_node(struct btree *b,
struct btree_split_state state;
closure_init_stack(&state.stack_cl);
- bch_keylist_init(&state.parent_keys);
+ bch_keylist_init(&state.parent_keys,
+ state.inline_keys,
+ ARRAY_SIZE(state.inline_keys));
state.reserve = reserve;
if (replace)
diff --git a/drivers/md/bcache/dirent.c b/drivers/md/bcache/dirent.c
index 999538c71391..9f780b0f4e59 100644
--- a/drivers/md/bcache/dirent.c
+++ b/drivers/md/bcache/dirent.c
@@ -144,7 +144,7 @@ static int __bch_dirent_create(struct cache_set *c, u64 dir_inum,
sizeof(u64));
int ret = -ENOENT;
- bch_keylist_init(&keys);
+ bch_keylist_init(&keys, NULL, 0);
if (bch_keylist_realloc(&keys, u64s))
return -ENOMEM;
diff --git a/drivers/md/bcache/gc.c b/drivers/md/bcache/gc.c
index fb335f89a68b..afdb8e92f8d2 100644
--- a/drivers/md/bcache/gc.c
+++ b/drivers/md/bcache/gc.c
@@ -368,7 +368,7 @@ static void bch_coalesce_nodes(struct btree *old_nodes[GC_MERGE_NODES],
return;
memset(new_nodes, 0, sizeof(new_nodes));
- bch_keylist_init(&keylist);
+ bch_keylist_init(&keylist, NULL, 0);
closure_init_stack(&cl);
/* Count keys that are not deleted */
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 1cebe3376576..c264e4361ce9 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -608,7 +608,6 @@ void bch_write(struct closure *cl)
op->insert_key.k.p.offset = bio_end_sector(op->bio);
op->insert_key.k.size = bio_sectors(op->bio);
- bch_keylist_init(&op->insert_keys);
bio_get(op->bio);
/* Don't call bch_next_delay() if rate is >= 1 GB/sec */
@@ -680,7 +679,9 @@ void bch_write_op_init(struct bch_write_op *op, struct cache_set *c,
op->wp = wp;
op->journal_seq = NULL;
- bch_keylist_init(&op->insert_keys);
+ bch_keylist_init(&op->insert_keys,
+ op->inline_keys,
+ ARRAY_SIZE(op->inline_keys));
bkey_reassemble(&op->insert_key, insert_key);
if (!bkey_val_u64s(&op->insert_key.k)) {
diff --git a/drivers/md/bcache/io.h b/drivers/md/bcache/io.h
index ef7122a591da..1d97fac2665c 100644
--- a/drivers/md/bcache/io.h
+++ b/drivers/md/bcache/io.h
@@ -59,6 +59,7 @@ struct bch_write_op {
struct keylist insert_keys;
BKEY_PADDED(insert_key);
struct bch_replace_info replace_info;
+ u64 inline_keys[BKEY_EXTENT_MAX_U64s * 2];
};
enum bch_write_flags {
diff --git a/drivers/md/bcache/keylist.c b/drivers/md/bcache/keylist.c
index f6f7eabf9b0f..94412518bc1a 100644
--- a/drivers/md/bcache/keylist.c
+++ b/drivers/md/bcache/keylist.c
@@ -13,7 +13,7 @@ int bch_keylist_realloc_max(struct keylist *l,
unsigned maxu64s)
{
size_t oldcap = bch_keylist_capacity(l);
- size_t newsize = oldcap + needu64s;
+ size_t newsize = max(oldcap, BKEY_EXTENT_MAX_U64s) + needu64s;
u64 *new_keys;
if (bch_keylist_fits(l, needu64s))
@@ -78,8 +78,9 @@ int bch_keylist_realloc_max(struct keylist *l,
l->bot_p = new_keys;
}
- if (l->start_keys_p != l->inline_keys)
+ if (l->has_buf)
kfree(l->start_keys_p);
+ l->has_buf = true;
l->start_keys_p = new_keys;
l->end_keys_p = new_keys + newsize;
@@ -129,7 +130,7 @@ void bch_scan_keylist_init(struct scan_keylist *kl,
mutex_init(&kl->lock);
kl->max_size = max_size;
- bch_keylist_init(&kl->list);
+ bch_keylist_init(&kl->list, NULL, 0);
/*
* Order of initialization is tricky, and this makes sure that
diff --git a/drivers/md/bcache/keylist.h b/drivers/md/bcache/keylist.h
index 6e2867cc9f83..5e760003cb0a 100644
--- a/drivers/md/bcache/keylist.h
+++ b/drivers/md/bcache/keylist.h
@@ -3,10 +3,12 @@
#include "keylist_types.h"
-static inline void bch_keylist_init(struct keylist *l)
+static inline void bch_keylist_init(struct keylist *l, u64 *inline_keys,
+ size_t nr_inline_u64s)
{
- l->bot_p = l->top_p = l->start_keys_p = l->inline_keys;
- l->end_keys_p = &l->inline_keys[KEYLIST_INLINE];
+ l->bot_p = l->top_p = l->start_keys_p = inline_keys;
+ l->end_keys_p = l->start_keys_p + nr_inline_u64s;
+ l->has_buf = false;
}
static inline size_t bch_keylist_capacity(struct keylist *l)
@@ -14,6 +16,11 @@ static inline size_t bch_keylist_capacity(struct keylist *l)
return l->end_keys_p - l->start_keys_p;
}
+/*
+ * XXX: why are we using BKEY_EXTENT_MAX_U64s here? keylists aren't used just
+ * for extents, this doesn't make any sense
+ */
+
static inline bool bch_keylist_fits(struct keylist *l, size_t u64s)
{
if (l->bot_p > l->top_p)
@@ -59,10 +66,9 @@ static inline bool bch_keylist_empty(struct keylist *l)
static inline void bch_keylist_free(struct keylist *l)
{
- if (l->start_keys_p != l->inline_keys) {
+ if (l->has_buf)
kfree(l->start_keys_p);
- bch_keylist_init(l);
- }
+ memset(l, 0, sizeof(*l));
}
/*
diff --git a/drivers/md/bcache/keylist_types.h b/drivers/md/bcache/keylist_types.h
index b48cc208472a..04cb866d36da 100644
--- a/drivers/md/bcache/keylist_types.h
+++ b/drivers/md/bcache/keylist_types.h
@@ -22,6 +22,8 @@
* full.
*/
+#define KEYLIST_MAX (1 << 18)
+
struct keylist {
/* This is a pointer to the LSB (inline_keys until realloc'd) */
union {
@@ -43,18 +45,7 @@ struct keylist {
struct bkey_i *end_keys;
u64 *end_keys_p;
};
- /* Enough room for btree_split's keys without realloc */
-#define KEYLIST_INLINE roundup_pow_of_two(BKEY_EXTENT_MAX_U64s * 3)
- /* Prevent key lists from growing too big */
- /*
- * This should always be big enough to allow btree_gc_coalesce and
- * btree_split to complete.
- * The current value is the (current) size of a bucket, so it
- * is far more than enough, as those two operations require only
- * a handful of keys.
- */
-#define KEYLIST_MAX (1 << 18)
- u64 inline_keys[KEYLIST_INLINE];
+ bool has_buf;
};
/*
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index 383745ef0c02..bd8ac8ea2d22 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -110,16 +110,14 @@ static void write_dirty_finish(struct closure *cl)
mempool_free(bv->bv_page, &dc->writeback_page_pool);
if (!io->error) {
+ BKEY_PADDED(k) tmp;
int ret;
- struct keylist keys;
- bch_keylist_init(&keys);
+ bkey_copy(&tmp.k, &io->replace.key);
+ SET_EXTENT_CACHED(&bkey_i_to_extent(&tmp.k)->v, true);
- bkey_copy(keys.top, &io->replace.key);
- SET_EXTENT_CACHED(&bkey_i_to_extent(keys.top)->v, true);
- bch_keylist_enqueue(&keys);
-
- ret = bch_btree_insert(dc->disk.c, BTREE_ID_EXTENTS, &keys,
+ ret = bch_btree_insert(dc->disk.c, BTREE_ID_EXTENTS,
+ &keylist_single(&tmp.k),
&io->replace, NULL, NULL, 0);
if (io->replace.successes == 0)
trace_bcache_writeback_collision(&io->replace.key.k);
diff --git a/drivers/md/bcache/xattr.c b/drivers/md/bcache/xattr.c
index 404796ff8163..2f9f176609bc 100644
--- a/drivers/md/bcache/xattr.c
+++ b/drivers/md/bcache/xattr.c
@@ -186,7 +186,6 @@ int bch_xattr_set(struct inode *inode, const char *name,
struct cache_set *c = inode->i_sb->s_fs_info;
struct btree_iter iter;
struct bkey_s_c k;
- struct keylist keys;
struct qstr qname = (struct qstr) QSTR_INIT((char *) name,
strlen(name));
int ret = -EINVAL;
@@ -226,9 +225,8 @@ int bch_xattr_set(struct inode *inode, const char *name,
break;
}
- bch_keylist_init(&keys);
-
if (value) {
+ struct keylist keys;
struct bkey_i_xattr *xattr;
unsigned u64s = BKEY_U64s +
DIV_ROUND_UP(sizeof(struct bch_xattr) +
@@ -240,6 +238,8 @@ int bch_xattr_set(struct inode *inode, const char *name,
break;
}
+ bch_keylist_init(&keys, NULL, 0);
+
if (bch_keylist_realloc(&keys, u64s)) {
ret = -ENOMEM;
break;
@@ -255,20 +255,26 @@ int bch_xattr_set(struct inode *inode, const char *name,
memcpy(xattr_val(&xattr->v), value, size);
BUG_ON(xattr_cmp(&xattr->v, type, &qname));
+
+ bch_keylist_enqueue(&keys);
+
+ ret = bch_btree_insert_at(&iter, &keys, NULL,
+ &ei->journal_seq,
+ insert_flags);
+ bch_keylist_free(&keys);
} else {
+ struct bkey_i whiteout;
/* removing */
- bkey_init(&keys.top->k);
- keys.top->k.type = BCH_XATTR_WHITEOUT;
- keys.top->k.p = k.k->p;
+ bkey_init(&whiteout.k);
+ whiteout.k.type = BCH_XATTR_WHITEOUT;
+ whiteout.k.p = k.k->p;
+
+ ret = bch_btree_insert_at(&iter,
+ &keylist_single(&whiteout),
+ NULL, &ei->journal_seq,
+ insert_flags);
}
- bch_keylist_enqueue(&keys);
-
- ret = bch_btree_insert_at(&iter, &keys, NULL,
- &ei->journal_seq,
- insert_flags);
- bch_keylist_free(&keys);
-
if (ret != -EINTR && ret != -EAGAIN)
break;
}