summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/md/bcache/bset.c87
-rw-r--r--drivers/md/bcache/btree_cache.c2
2 files changed, 63 insertions, 26 deletions
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 1f39bd373922..9927273d89da 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -414,12 +414,38 @@ EXPORT_SYMBOL(bch_btree_keys_init);
/* Binary tree stuff for auxiliary search trees */
+#ifdef CONFIG_X86_64
+/* we don't need the rex prefixes, or the rep prefix (lzcnt/tzcnt) */
+
+#define __fls(_x) \
+({ \
+ unsigned _r; \
+ asm("bsr %1,%0" : "=r" (_r) : "rm" (_x)); \
+ _r; \
+})
+
+#define __ffs(_x) \
+({ \
+ unsigned _r; \
+ asm("bsf %1,%0" : "=r" (_r) : "rm" (_x)); \
+ _r; \
+})
+
+#define ffz(_x) \
+({ \
+ unsigned _r; \
+ asm("bsf %1,%0" : "=r" (_r) : "rm" (~(_x))); \
+ _r; \
+})
+
+#endif
+
static unsigned inorder_next(unsigned j, unsigned size)
{
if (j * 2 + 1 < size) {
j = j * 2 + 1;
- j <<= fls(size) - fls(j);
+ j <<= __fls(size) - __fls(j);
j >>= j >= size;
} else
j >>= ffz(j) + 1;
@@ -430,17 +456,13 @@ static unsigned inorder_next(unsigned j, unsigned size)
static unsigned inorder_prev(unsigned j, unsigned size)
{
if (j * 2 < size) {
- unsigned shift;
-
- j = j * 2;
+ j = j * 2 + 1;
- shift = fls(size) - fls(j);
- j += 1;
- j <<= shift;
+ j <<= __fls(size) - __fls(j);
j -= 1;
j >>= j >= size;
} else
- j >>= ffs(j);
+ j >>= __ffs(j) + 1;
return j;
}
@@ -460,10 +482,11 @@ static unsigned inorder_prev(unsigned j, unsigned size)
*/
static inline unsigned __to_inorder(unsigned j, unsigned size, unsigned extra)
{
- unsigned b = fls(j);
- unsigned shift = fls(size - 1) - b;
+ unsigned b = __fls(j);
+ unsigned shift = __fls(size - 1) - b;
+ int s;
- j ^= 1U << (b - 1);
+ j ^= 1U << b;
j <<= 1;
j |= 1;
j <<= shift;
@@ -473,7 +496,8 @@ static inline unsigned __to_inorder(unsigned j, unsigned size, unsigned extra)
if (j > extra)
j -= (j - extra) >> 1;
#else
- j -= ((j - extra) >> 1) & (((int) (extra - j)) >> 31);
+ s = extra - j;
+ j += (s >> 1) & (s >> 31);
#endif
return j;
@@ -487,14 +511,15 @@ static inline unsigned to_inorder(unsigned j, struct bset_tree *t)
static unsigned __inorder_to_tree(unsigned j, unsigned size, unsigned extra)
{
unsigned shift;
+ int s;
- if (j > extra)
- j += j - extra;
+ s = extra - j;
+ j -= s & (s >> 31);
- shift = ffs(j);
+ shift = __ffs(j);
- j >>= shift;
- j |= roundup_pow_of_two(size) >> shift;
+ j >>= shift + 1;
+ j |= 1U << (__fls(size - 1) - shift);
return j;
}
@@ -585,11 +610,11 @@ static unsigned bkey_to_cacheline_offset(struct bset_tree *t,
{
size_t m = __bkey_to_cacheline_offset(t, cacheline, k);
- BUG_ON(m > (1U << BKEY_MID_BITS) - 1);
+ EBUG_ON(m > (1U << BKEY_MID_BITS) - 1);
return m;
}
-static struct bkey_packed *tree_to_bkey(struct bset_tree *t, unsigned j)
+static inline struct bkey_packed *tree_to_bkey(struct bset_tree *t, unsigned j)
{
return cacheline_to_bkey(t, to_inorder(j, t), t->tree[j].m);
}
@@ -1189,11 +1214,25 @@ static struct bkey_packed *bset_search_tree(const struct btree_keys *b,
if (likely(n << 4 < t->size)) {
prefetch(&t->tree[n << 4]);
} else if (n << 3 < t->size) {
+ void *p;
+
inorder = to_inorder(n, t);
- prefetch(cacheline_to_bkey(t, inorder, 0));
- prefetch(cacheline_to_bkey(t, inorder + 1, 0));
- prefetch(cacheline_to_bkey(t, inorder + 2, 0));
- prefetch(cacheline_to_bkey(t, inorder + 3, 0));
+ p = cacheline_to_bkey(t, inorder, 0);
+#ifdef CONFIG_X86_64
+ asm(".intel_syntax noprefix;"
+ "prefetcht0 [%0 - 127 + 64 * 0];"
+ "prefetcht0 [%0 - 127 + 64 * 1];"
+ "prefetcht0 [%0 - 127 + 64 * 2];"
+ "prefetcht0 [%0 - 127 + 64 * 3];"
+ ".att_syntax prefix;"
+ :
+ : "r" (p + 127));
+#else
+ prefetch(p + L1_CACHE_BYTES * 0);
+ prefetch(p + L1_CACHE_BYTES * 1);
+ prefetch(p + L1_CACHE_BYTES * 2);
+ prefetch(p + L1_CACHE_BYTES * 3);
+#endif
} else if (n >= t->size)
break;
@@ -1408,8 +1447,6 @@ void bch_btree_node_iter_init(struct btree_node_iter *iter,
btree_node_iter_init_pack_failed(iter, b, search,
strictly_greater, is_extents);
return;
- default:
- BUG();
}
__bch_btree_node_iter_init(iter, is_extents);
diff --git a/drivers/md/bcache/btree_cache.c b/drivers/md/bcache/btree_cache.c
index bc6f6a7de8a2..809d8be63a0e 100644
--- a/drivers/md/bcache/btree_cache.c
+++ b/drivers/md/bcache/btree_cache.c
@@ -128,7 +128,7 @@ int mca_hash_insert(struct cache_set *c, struct btree *b,
return 0;
}
-noinline __flatten
+__flatten
static inline struct btree *mca_find(struct cache_set *c,
const struct bkey_i *k)
{