Commit a85e968e authored by Kent Overstreet's avatar Kent Overstreet

bcache: Add struct btree_keys

Soon, bset.c won't need to depend on struct btree.
Signed-off-by: default avatarKent Overstreet <kmo@daterainc.com>
parent 65d45231
...@@ -679,9 +679,9 @@ struct cache_set { ...@@ -679,9 +679,9 @@ struct cache_set {
unsigned error_decay; unsigned error_decay;
unsigned short journal_delay_ms; unsigned short journal_delay_ms;
bool expensive_debug_checks;
unsigned verify:1; unsigned verify:1;
unsigned key_merging_disabled:1; unsigned key_merging_disabled:1;
unsigned expensive_debug_checks:1;
unsigned gc_always_rewrite:1; unsigned gc_always_rewrite:1;
unsigned shrinker_disabled:1; unsigned shrinker_disabled:1;
unsigned copy_gc_enabled:1; unsigned copy_gc_enabled:1;
......
This diff is collapsed.
...@@ -145,6 +145,9 @@ ...@@ -145,6 +145,9 @@
*/ */
struct btree; struct btree;
struct btree_keys;
struct btree_iter;
struct btree_iter_set;
struct bkey_float; struct bkey_float;
#define MAX_BSETS 4U #define MAX_BSETS 4U
...@@ -181,6 +184,74 @@ struct bset_tree { ...@@ -181,6 +184,74 @@ struct bset_tree {
struct bset *data; struct bset *data;
}; };
struct btree_keys_ops {
bool (*sort_cmp)(struct btree_iter_set,
struct btree_iter_set);
struct bkey *(*sort_fixup)(struct btree_iter *, struct bkey *);
bool (*key_invalid)(struct btree_keys *,
const struct bkey *);
bool (*key_bad)(struct btree_keys *, const struct bkey *);
bool (*key_merge)(struct btree_keys *,
struct bkey *, struct bkey *);
/*
* Only used for deciding whether to use START_KEY(k) or just the key
* itself in a couple places
*/
bool is_extents;
};
struct btree_keys {
const struct btree_keys_ops *ops;
uint8_t page_order;
uint8_t nsets;
unsigned last_set_unwritten:1;
bool *expensive_debug_checks;
/*
* Sets of sorted keys - the real btree node - plus a binary search tree
*
* set[0] is special; set[0]->tree, set[0]->prev and set[0]->data point
* to the memory we have allocated for this btree node. Additionally,
* set[0]->data points to the entire btree node as it exists on disk.
*/
struct bset_tree set[MAX_BSETS];
};
static inline struct bset_tree *bset_tree_last(struct btree_keys *b)
{
return b->set + b->nsets;
}
static inline bool bset_written(struct btree_keys *b, struct bset_tree *t)
{
return t <= b->set + b->nsets - b->last_set_unwritten;
}
static inline bool bkey_written(struct btree_keys *b, struct bkey *k)
{
return !b->last_set_unwritten || k < b->set[b->nsets].data->start;
}
static inline unsigned bset_byte_offset(struct btree_keys *b, struct bset *i)
{
return ((size_t) i) - ((size_t) b->set->data);
}
static inline unsigned bset_sector_offset(struct btree_keys *b, struct bset *i)
{
return bset_byte_offset(b, i) >> 9;
}
static inline bool btree_keys_expensive_checks(struct btree_keys *b)
{
#ifdef CONFIG_BCACHE_DEBUG
return *b->expensive_debug_checks;
#else
return false;
#endif
}
#define __set_bytes(i, k) (sizeof(*(i)) + (k) * sizeof(uint64_t)) #define __set_bytes(i, k) (sizeof(*(i)) + (k) * sizeof(uint64_t))
#define set_bytes(i) __set_bytes(i, i->keys) #define set_bytes(i) __set_bytes(i, i->keys)
...@@ -189,12 +260,34 @@ struct bset_tree { ...@@ -189,12 +260,34 @@ struct bset_tree {
#define set_blocks(i, block_bytes) \ #define set_blocks(i, block_bytes) \
__set_blocks(i, (i)->keys, block_bytes) __set_blocks(i, (i)->keys, block_bytes)
void bch_btree_keys_free(struct btree *); static inline struct bset *bset_next_set(struct btree_keys *b,
int bch_btree_keys_alloc(struct btree *, unsigned, gfp_t); unsigned block_bytes)
{
struct bset *i = bset_tree_last(b)->data;
return ((void *) i) + roundup(set_bytes(i), block_bytes);
}
void bch_btree_keys_free(struct btree_keys *);
int bch_btree_keys_alloc(struct btree_keys *, unsigned, gfp_t);
void bch_btree_keys_init(struct btree_keys *, const struct btree_keys_ops *,
bool *);
void bch_bset_fix_invalidated_key(struct btree *, struct bkey *); void bch_bset_init_next(struct btree_keys *, struct bset *, uint64_t);
void bch_bset_init_next(struct btree *, struct bset *, uint64_t); void bch_bset_build_written_tree(struct btree_keys *);
void bch_bset_insert(struct btree *, struct bkey *, struct bkey *); void bch_bset_fix_invalidated_key(struct btree_keys *, struct bkey *);
void bch_bset_insert(struct btree_keys *, struct bkey *, struct bkey *);
/*
* Tries to merge l and r: l should be lower than r
* Returns true if we were able to merge. If we did merge, l will be the merged
* key, r will be untouched.
*/
static inline bool bch_bkey_try_merge(struct btree_keys *b,
struct bkey *l, struct bkey *r)
{
return b->ops->key_merge ? b->ops->key_merge(b, l, r) : false;
}
/* Btree key iteration */ /* Btree key iteration */
...@@ -208,11 +301,11 @@ struct btree_iter { ...@@ -208,11 +301,11 @@ struct btree_iter {
} data[MAX_BSETS]; } data[MAX_BSETS];
}; };
typedef bool (*ptr_filter_fn)(struct btree *, const struct bkey *); typedef bool (*ptr_filter_fn)(struct btree_keys *, const struct bkey *);
struct bkey *bch_btree_iter_next(struct btree_iter *); struct bkey *bch_btree_iter_next(struct btree_iter *);
struct bkey *bch_btree_iter_next_filter(struct btree_iter *, struct bkey *bch_btree_iter_next_filter(struct btree_iter *,
struct btree *, ptr_filter_fn); struct btree_keys *, ptr_filter_fn);
void bch_btree_iter_push(struct btree_iter *, struct bkey *, struct bkey *); void bch_btree_iter_push(struct btree_iter *, struct bkey *, struct bkey *);
struct bkey *bch_btree_iter_init(struct btree *, struct btree_iter *, struct bkey *bch_btree_iter_init(struct btree *, struct btree_iter *,
...@@ -246,7 +339,7 @@ int bch_bset_sort_state_init(struct bset_sort_state *, unsigned); ...@@ -246,7 +339,7 @@ int bch_bset_sort_state_init(struct bset_sort_state *, unsigned);
void bch_btree_sort_lazy(struct btree *, struct bset_sort_state *); void bch_btree_sort_lazy(struct btree *, struct bset_sort_state *);
void bch_btree_sort_into(struct btree *, struct btree *, void bch_btree_sort_into(struct btree *, struct btree *,
struct bset_sort_state *); struct bset_sort_state *);
void bch_btree_sort_and_fix_extents(struct btree *, struct btree_iter *, void bch_btree_sort_and_fix_extents(struct btree_keys *, struct btree_iter *,
struct bset_sort_state *); struct bset_sort_state *);
void bch_btree_sort_partial(struct btree *, unsigned, void bch_btree_sort_partial(struct btree *, unsigned,
struct bset_sort_state *); struct bset_sort_state *);
...@@ -311,6 +404,16 @@ static inline bool bch_cut_back(const struct bkey *where, struct bkey *k) ...@@ -311,6 +404,16 @@ static inline bool bch_cut_back(const struct bkey *where, struct bkey *k)
_ret; \ _ret; \
}) })
static inline bool bch_ptr_invalid(struct btree_keys *b, const struct bkey *k)
{
return b->ops->key_invalid(b, k);
}
static inline bool bch_ptr_bad(struct btree_keys *b, const struct bkey *k)
{
return b->ops->key_bad(b, k);
}
/* Keylists */ /* Keylists */
struct keylist { struct keylist {
......
This diff is collapsed.
...@@ -113,28 +113,7 @@ struct btree_write { ...@@ -113,28 +113,7 @@ struct btree_write {
int prio_blocked; int prio_blocked;
}; };
struct btree_keys_ops {
bool (*sort_cmp)(struct btree_iter_set,
struct btree_iter_set);
struct bkey *(*sort_fixup)(struct btree_iter *,
struct bkey *);
bool (*key_invalid)(struct btree *,
const struct bkey *);
bool (*key_bad)(struct btree *,
const struct bkey *);
bool (*key_merge)(struct btree *,
struct bkey *, struct bkey *);
/*
* Only used for deciding whether to use START_KEY(k) or just the key
* itself in a couple places
*/
bool is_extents;
};
struct btree { struct btree {
const struct btree_keys_ops *ops;
/* Hottest entries first */ /* Hottest entries first */
struct hlist_node hash; struct hlist_node hash;
...@@ -151,17 +130,8 @@ struct btree { ...@@ -151,17 +130,8 @@ struct btree {
unsigned long flags; unsigned long flags;
uint16_t written; /* would be nice to kill */ uint16_t written; /* would be nice to kill */
uint8_t level; uint8_t level;
uint8_t nsets;
uint8_t page_order; struct btree_keys keys;
/*
* Set of sorted keys - the real btree node - plus a binary search tree
*
* sets[0] is special; set[0]->tree, set[0]->prev and set[0]->data point
* to the memory we have allocated for this btree node. Additionally,
* set[0]->data points to the entire btree node as it exists on disk.
*/
struct bset_tree sets[MAX_BSETS];
/* For outstanding btree writes, used as a lock - protects write_idx */ /* For outstanding btree writes, used as a lock - protects write_idx */
struct closure io; struct closure io;
...@@ -201,49 +171,19 @@ static inline struct btree_write *btree_prev_write(struct btree *b) ...@@ -201,49 +171,19 @@ static inline struct btree_write *btree_prev_write(struct btree *b)
return b->writes + (btree_node_write_idx(b) ^ 1); return b->writes + (btree_node_write_idx(b) ^ 1);
} }
static inline struct bset_tree *bset_tree_last(struct btree *b)
{
return b->sets + b->nsets;
}
static inline struct bset *btree_bset_first(struct btree *b) static inline struct bset *btree_bset_first(struct btree *b)
{ {
return b->sets->data; return b->keys.set->data;
} }
static inline struct bset *btree_bset_last(struct btree *b) static inline struct bset *btree_bset_last(struct btree *b)
{ {
return bset_tree_last(b)->data; return bset_tree_last(&b->keys)->data;
}
static inline unsigned bset_byte_offset(struct btree *b, struct bset *i)
{
return ((size_t) i) - ((size_t) b->sets->data);
}
static inline unsigned bset_sector_offset(struct btree *b, struct bset *i)
{
return (((void *) i) - ((void *) btree_bset_first(b))) >> 9;
} }
static inline unsigned bset_block_offset(struct btree *b, struct bset *i) static inline unsigned bset_block_offset(struct btree *b, struct bset *i)
{ {
return bset_sector_offset(b, i) >> b->c->block_bits; return bset_sector_offset(&b->keys, i) >> b->c->block_bits;
}
static inline struct bset *write_block(struct btree *b)
{
return ((void *) b->sets[0].data) + b->written * block_bytes(b->c);
}
static inline bool bset_written(struct btree *b, struct bset_tree *t)
{
return t->data < write_block(b);
}
static inline bool bkey_written(struct btree *b, struct bkey *k)
{
return k < write_block(b)->start;
} }
static inline void set_gc_sectors(struct cache_set *c) static inline void set_gc_sectors(struct cache_set *c)
...@@ -251,27 +191,6 @@ static inline void set_gc_sectors(struct cache_set *c) ...@@ -251,27 +191,6 @@ static inline void set_gc_sectors(struct cache_set *c)
atomic_set(&c->sectors_to_gc, c->sb.bucket_size * c->nbuckets / 16); atomic_set(&c->sectors_to_gc, c->sb.bucket_size * c->nbuckets / 16);
} }
static inline bool bch_ptr_invalid(struct btree *b, const struct bkey *k)
{
return b->ops->key_invalid(b, k);
}
static inline bool bch_ptr_bad(struct btree *b, const struct bkey *k)
{
return b->ops->key_bad(b, k);
}
/*
* Tries to merge l and r: l should be lower than r
* Returns true if we were able to merge. If we did merge, l will be the merged
* key, r will be untouched.
*/
static inline bool bch_bkey_try_merge(struct btree *b,
struct bkey *l, struct bkey *r)
{
return b->ops->key_merge ? b->ops->key_merge(b, l, r) : false;
}
void bkey_put(struct cache_set *c, struct bkey *k); void bkey_put(struct cache_set *c, struct bkey *k);
/* Looping macros */ /* Looping macros */
...@@ -284,7 +203,7 @@ void bkey_put(struct cache_set *c, struct bkey *k); ...@@ -284,7 +203,7 @@ void bkey_put(struct cache_set *c, struct bkey *k);
#define for_each_key_filter(b, k, iter, filter) \ #define for_each_key_filter(b, k, iter, filter) \
for (bch_btree_iter_init((b), (iter), NULL); \ for (bch_btree_iter_init((b), (iter), NULL); \
((k) = bch_btree_iter_next_filter((iter), b, filter));) ((k) = bch_btree_iter_next_filter((iter), &(b)->keys, filter));)
#define for_each_key(b, k, iter) \ #define for_each_key(b, k, iter) \
for (bch_btree_iter_init((b), (iter), NULL); \ for (bch_btree_iter_init((b), (iter), NULL); \
......
...@@ -113,9 +113,9 @@ static void bch_dump_bucket(struct btree *b) ...@@ -113,9 +113,9 @@ static void bch_dump_bucket(struct btree *b)
unsigned i; unsigned i;
console_lock(); console_lock();
for (i = 0; i <= b->nsets; i++) for (i = 0; i <= b->keys.nsets; i++)
dump_bset(b, b->sets[i].data, dump_bset(b, b->keys.set[i].data,
bset_block_offset(b, b->sets[i].data)); bset_block_offset(b, b->keys.set[i].data));
console_unlock(); console_unlock();
} }
...@@ -139,13 +139,13 @@ void bch_btree_verify(struct btree *b) ...@@ -139,13 +139,13 @@ void bch_btree_verify(struct btree *b)
mutex_lock(&b->c->verify_lock); mutex_lock(&b->c->verify_lock);
ondisk = b->c->verify_ondisk; ondisk = b->c->verify_ondisk;
sorted = b->c->verify_data->sets->data; sorted = b->c->verify_data->keys.set->data;
inmemory = b->sets->data; inmemory = b->keys.set->data;
bkey_copy(&v->key, &b->key); bkey_copy(&v->key, &b->key);
v->written = 0; v->written = 0;
v->level = b->level; v->level = b->level;
v->ops = b->ops; v->keys.ops = b->keys.ops;
bio = bch_bbio_alloc(b->c); bio = bch_bbio_alloc(b->c);
bio->bi_bdev = PTR_CACHE(b->c, &b->key, 0)->bdev; bio->bi_bdev = PTR_CACHE(b->c, &b->key, 0)->bdev;
...@@ -159,7 +159,7 @@ void bch_btree_verify(struct btree *b) ...@@ -159,7 +159,7 @@ void bch_btree_verify(struct btree *b)
memcpy(ondisk, sorted, KEY_SIZE(&v->key) << 9); memcpy(ondisk, sorted, KEY_SIZE(&v->key) << 9);
bch_btree_node_read_done(v); bch_btree_node_read_done(v);
sorted = v->sets->data; sorted = v->keys.set->data;
if (inmemory->keys != sorted->keys || if (inmemory->keys != sorted->keys ||
memcmp(inmemory->start, memcmp(inmemory->start,
...@@ -264,14 +264,14 @@ void __bch_check_keys(struct btree *b, const char *fmt, ...) ...@@ -264,14 +264,14 @@ void __bch_check_keys(struct btree *b, const char *fmt, ...)
if (p && bkey_cmp(&START_KEY(p), &START_KEY(k)) > 0) if (p && bkey_cmp(&START_KEY(p), &START_KEY(k)) > 0)
goto bug; goto bug;
if (bch_ptr_invalid(b, k)) if (bch_ptr_invalid(&b->keys, k))
continue; continue;
err = "Overlapping keys"; err = "Overlapping keys";
if (p && bkey_cmp(p, &START_KEY(k)) > 0) if (p && bkey_cmp(p, &START_KEY(k)) > 0)
goto bug; goto bug;
} else { } else {
if (bch_ptr_bad(b, k)) if (bch_ptr_bad(&b->keys, k))
continue; continue;
err = "Duplicate keys"; err = "Duplicate keys";
......
...@@ -81,8 +81,9 @@ bool __bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k) ...@@ -81,8 +81,9 @@ bool __bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k)
return true; return true;
} }
static bool bch_btree_ptr_invalid(struct btree *b, const struct bkey *k) static bool bch_btree_ptr_invalid(struct btree_keys *bk, const struct bkey *k)
{ {
struct btree *b = container_of(bk, struct btree, keys);
return __bch_btree_ptr_invalid(b->c, k); return __bch_btree_ptr_invalid(b->c, k);
} }
...@@ -118,13 +119,14 @@ static bool btree_ptr_bad_expensive(struct btree *b, const struct bkey *k) ...@@ -118,13 +119,14 @@ static bool btree_ptr_bad_expensive(struct btree *b, const struct bkey *k)
return true; return true;
} }
static bool bch_btree_ptr_bad(struct btree *b, const struct bkey *k) static bool bch_btree_ptr_bad(struct btree_keys *bk, const struct bkey *k)
{ {
struct btree *b = container_of(bk, struct btree, keys);
unsigned i; unsigned i;
if (!bkey_cmp(k, &ZERO_KEY) || if (!bkey_cmp(k, &ZERO_KEY) ||
!KEY_PTRS(k) || !KEY_PTRS(k) ||
bch_ptr_invalid(b, k)) bch_ptr_invalid(bk, k))
return true; return true;
for (i = 0; i < KEY_PTRS(k); i++) for (i = 0; i < KEY_PTRS(k); i++)
...@@ -209,8 +211,9 @@ static struct bkey *bch_extent_sort_fixup(struct btree_iter *iter, ...@@ -209,8 +211,9 @@ static struct bkey *bch_extent_sort_fixup(struct btree_iter *iter,
return NULL; return NULL;
} }
static bool bch_extent_invalid(struct btree *b, const struct bkey *k) static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
{ {
struct btree *b = container_of(bk, struct btree, keys);
char buf[80]; char buf[80];
if (!KEY_SIZE(k)) if (!KEY_SIZE(k))
...@@ -259,13 +262,14 @@ static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k, ...@@ -259,13 +262,14 @@ static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
return true; return true;
} }
static bool bch_extent_bad(struct btree *b, const struct bkey *k) static bool bch_extent_bad(struct btree_keys *bk, const struct bkey *k)
{ {
struct btree *b = container_of(bk, struct btree, keys);
struct bucket *g; struct bucket *g;
unsigned i, stale; unsigned i, stale;
if (!KEY_PTRS(k) || if (!KEY_PTRS(k) ||
bch_extent_invalid(b, k)) bch_extent_invalid(bk, k))
return true; return true;
for (i = 0; i < KEY_PTRS(k); i++) for (i = 0; i < KEY_PTRS(k); i++)
...@@ -303,8 +307,9 @@ static uint64_t merge_chksums(struct bkey *l, struct bkey *r) ...@@ -303,8 +307,9 @@ static uint64_t merge_chksums(struct bkey *l, struct bkey *r)
~((uint64_t)1 << 63); ~((uint64_t)1 << 63);
} }
static bool bch_extent_merge(struct btree *b, struct bkey *l, struct bkey *r) static bool bch_extent_merge(struct btree_keys *bk, struct bkey *l, struct bkey *r)
{ {
struct btree *b = container_of(bk, struct btree, keys);
unsigned i; unsigned i;
if (key_merging_disabled(b->c)) if (key_merging_disabled(b->c))
......
...@@ -433,7 +433,7 @@ SHOW(__bch_cache_set) ...@@ -433,7 +433,7 @@ SHOW(__bch_cache_set)
mutex_lock(&c->bucket_lock); mutex_lock(&c->bucket_lock);
list_for_each_entry(b, &c->btree_cache, list) list_for_each_entry(b, &c->btree_cache, list)
ret += 1 << (b->page_order + PAGE_SHIFT); ret += 1 << (b->keys.page_order + PAGE_SHIFT);
mutex_unlock(&c->bucket_lock); mutex_unlock(&c->bucket_lock);
return ret; return ret;
......
...@@ -247,7 +247,7 @@ TRACE_EVENT(bcache_btree_write, ...@@ -247,7 +247,7 @@ TRACE_EVENT(bcache_btree_write,
TP_fast_assign( TP_fast_assign(
__entry->bucket = PTR_BUCKET_NR(b->c, &b->key, 0); __entry->bucket = PTR_BUCKET_NR(b->c, &b->key, 0);
__entry->block = b->written; __entry->block = b->written;
__entry->keys = b->sets[b->nsets].data->keys; __entry->keys = b->keys.set[b->keys.nsets].data->keys;
), ),
TP_printk("bucket %zu", __entry->bucket) TP_printk("bucket %zu", __entry->bucket)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment