diff options
author | Jens Axboe <axboe@kernel.dk> | 2018-11-30 15:18:06 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-11-30 16:47:45 -0500 |
commit | ea86ea2cdced20057da4d2c32965c1219c238197 (patch) | |
tree | 08926009b00df1229668f131d41d2b467a78cc87 /include/linux/sbitmap.h | |
parent | 531724abc3bfb556c1dd68086cf9cb51f76464e3 (diff) |
sbitmap: ammortize cost of clearing bits
sbitmap maintains a set of words that we use to set and clear bits, with
each bit representing a tag for blk-mq. Even though we spread the bits
out and maintain a hint cache, one particular bit allocated will end up
being cleared in the exact same spot.
This introduces batched clearing of bits. Instead of clearing a given
bit, the same bit is set in a cleared/free mask instead. If we fail
allocating a bit from a given word, then we check the free mask, and
batch move those cleared bits at that time. This trades 64 atomic bitops
for 2 cmpxchg().
In a threaded poll test case, half the overhead of getting and clearing
tags is removed with this change. On another poll test case with a
single thread, performance is unchanged.
Reviewed-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'include/linux/sbitmap.h')
-rw-r--r-- | include/linux/sbitmap.h | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h index 804a50983ec5..81359d45751e 100644 --- a/include/linux/sbitmap.h +++ b/include/linux/sbitmap.h | |||
@@ -30,14 +30,24 @@ struct seq_file; | |||
30 | */ | 30 | */ |
31 | struct sbitmap_word { | 31 | struct sbitmap_word { |
32 | /** | 32 | /** |
33 | * @word: The bitmap word itself. | 33 | * @depth: Number of bits being used in @word/@cleared |
34 | */ | 34 | */ |
35 | unsigned long word; | 35 | unsigned long depth; |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * @depth: Number of bits being used in @word. | 38 | * @word: word holding free bits |
39 | */ | 39 | */ |
40 | unsigned long depth; | 40 | unsigned long word ____cacheline_aligned_in_smp; |
41 | |||
42 | /** | ||
43 | * @cleared: word holding cleared bits | ||
44 | */ | ||
45 | unsigned long cleared ____cacheline_aligned_in_smp; | ||
46 | |||
47 | /** | ||
48 | * @swap_lock: Held while swapping word <-> cleared | ||
49 | */ | ||
50 | spinlock_t swap_lock; | ||
41 | } ____cacheline_aligned_in_smp; | 51 | } ____cacheline_aligned_in_smp; |
42 | 52 | ||
43 | /** | 53 | /** |
@@ -310,6 +320,19 @@ static inline void sbitmap_clear_bit(struct sbitmap *sb, unsigned int bitnr) | |||
310 | clear_bit(SB_NR_TO_BIT(sb, bitnr), __sbitmap_word(sb, bitnr)); | 320 | clear_bit(SB_NR_TO_BIT(sb, bitnr), __sbitmap_word(sb, bitnr)); |
311 | } | 321 | } |
312 | 322 | ||
323 | /* | ||
324 | * This one is special, since it doesn't actually clear the bit, rather it | ||
325 | * sets the corresponding bit in the ->cleared mask instead. Paired with | ||
326 | * the caller doing sbitmap_batch_clear() if a given index is full, which | ||
327 | * will clear the previously freed entries in the corresponding ->word. | ||
328 | */ | ||
329 | static inline void sbitmap_deferred_clear_bit(struct sbitmap *sb, unsigned int bitnr) | ||
330 | { | ||
331 | unsigned long *addr = &sb->map[SB_NR_TO_INDEX(sb, bitnr)].cleared; | ||
332 | |||
333 | set_bit(SB_NR_TO_BIT(sb, bitnr), addr); | ||
334 | } | ||
335 | |||
313 | static inline void sbitmap_clear_bit_unlock(struct sbitmap *sb, | 336 | static inline void sbitmap_clear_bit_unlock(struct sbitmap *sb, |
314 | unsigned int bitnr) | 337 | unsigned int bitnr) |
315 | { | 338 | { |
@@ -321,8 +344,6 @@ static inline int sbitmap_test_bit(struct sbitmap *sb, unsigned int bitnr) | |||
321 | return test_bit(SB_NR_TO_BIT(sb, bitnr), __sbitmap_word(sb, bitnr)); | 344 | return test_bit(SB_NR_TO_BIT(sb, bitnr), __sbitmap_word(sb, bitnr)); |
322 | } | 345 | } |
323 | 346 | ||
324 | unsigned int sbitmap_weight(const struct sbitmap *sb); | ||
325 | |||
326 | /** | 347 | /** |
327 | * sbitmap_show() - Dump &struct sbitmap information to a &struct seq_file. | 348 | * sbitmap_show() - Dump &struct sbitmap information to a &struct seq_file. |
328 | * @sb: Bitmap to show. | 349 | * @sb: Bitmap to show. |