aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@fb.com>2014-05-09 15:41:15 -0400
committerJens Axboe <axboe@fb.com>2014-05-09 15:41:15 -0400
commit59d13bf5f57ded658c872fa22276f75ab8f12841 (patch)
treeea3b3bf9395c01a5443c2e01874837a19d6e4c62
parent4bb659b156996f2993dc16fad71fec9ee070153c (diff)
blk-mq: use sparser tag layout for lower queue depth
For best performance, spreading tags over multiple cachelines makes the tagging more efficient on multicore systems. But since we have 8 * sizeof(unsigned long) tags per cacheline, we don't always get a nice spread. Attempt to spread the tags over at least 4 cachelines, using fewer number of bits per unsigned long if we have to. This improves tagging performance in setups with 32-128 tags. For higher depths, the spread is the same as before (BITS_PER_LONG tags per cacheline). Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--block/blk-mq-tag.c45
-rw-r--r--block/blk-mq-tag.h7
2 files changed, 36 insertions, 16 deletions
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index 467f3a20b355..6c78c08865e3 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -44,7 +44,7 @@ static int __bt_get_word(struct blk_mq_bitmap *bm, unsigned int last_tag)
44{ 44{
45 int tag, org_last_tag, end; 45 int tag, org_last_tag, end;
46 46
47 org_last_tag = last_tag = TAG_TO_BIT(last_tag); 47 org_last_tag = last_tag;
48 end = bm->depth; 48 end = bm->depth;
49 do { 49 do {
50restart: 50restart:
@@ -84,12 +84,12 @@ static int __bt_get(struct blk_mq_bitmap_tags *bt, unsigned int *tag_cache)
84 int index, i, tag; 84 int index, i, tag;
85 85
86 last_tag = org_last_tag = *tag_cache; 86 last_tag = org_last_tag = *tag_cache;
87 index = TAG_TO_INDEX(last_tag); 87 index = TAG_TO_INDEX(bt, last_tag);
88 88
89 for (i = 0; i < bt->map_nr; i++) { 89 for (i = 0; i < bt->map_nr; i++) {
90 tag = __bt_get_word(&bt->map[index], last_tag); 90 tag = __bt_get_word(&bt->map[index], TAG_TO_BIT(bt, last_tag));
91 if (tag != -1) { 91 if (tag != -1) {
92 tag += index * BITS_PER_LONG; 92 tag += (index << bt->bits_per_word);
93 goto done; 93 goto done;
94 } 94 }
95 95
@@ -233,10 +233,10 @@ static struct bt_wait_state *bt_wake_ptr(struct blk_mq_bitmap_tags *bt)
233 233
234static void bt_clear_tag(struct blk_mq_bitmap_tags *bt, unsigned int tag) 234static void bt_clear_tag(struct blk_mq_bitmap_tags *bt, unsigned int tag)
235{ 235{
236 const int index = TAG_TO_INDEX(tag); 236 const int index = TAG_TO_INDEX(bt, tag);
237 struct bt_wait_state *bs; 237 struct bt_wait_state *bs;
238 238
239 clear_bit(TAG_TO_BIT(tag), &bt->map[index].word); 239 clear_bit(TAG_TO_BIT(bt, tag), &bt->map[index].word);
240 240
241 bs = bt_wake_ptr(bt); 241 bs = bt_wake_ptr(bt);
242 if (bs && atomic_dec_and_test(&bs->wait_cnt)) { 242 if (bs && atomic_dec_and_test(&bs->wait_cnt)) {
@@ -292,7 +292,7 @@ static void bt_for_each_free(struct blk_mq_bitmap_tags *bt,
292 bit++; 292 bit++;
293 } while (1); 293 } while (1);
294 294
295 off += BITS_PER_LONG; 295 off += (1 << bt->bits_per_word);
296 } 296 }
297} 297}
298 298
@@ -333,14 +333,31 @@ static int bt_alloc(struct blk_mq_bitmap_tags *bt, unsigned int depth,
333{ 333{
334 int i; 334 int i;
335 335
336 bt->bits_per_word = ilog2(BITS_PER_LONG);
337
336 /* 338 /*
337 * Depth can be zero for reserved tags, that's not a failure 339 * Depth can be zero for reserved tags, that's not a failure
338 * condition. 340 * condition.
339 */ 341 */
340 if (depth) { 342 if (depth) {
341 int nr, i, map_depth; 343 unsigned int nr, i, map_depth, tags_per_word;
344
345 tags_per_word = (1 << bt->bits_per_word);
346
347 /*
348 * If the tag space is small, shrink the number of tags
349 * per word so we spread over a few cachelines, at least.
350 * If less than 4 tags, just forget about it, it's not
351 * going to work optimally anyway.
352 */
353 if (depth >= 4) {
354 while (tags_per_word * 4 > depth) {
355 bt->bits_per_word--;
356 tags_per_word = (1 << bt->bits_per_word);
357 }
358 }
342 359
343 nr = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; 360 nr = ALIGN(depth, tags_per_word) / tags_per_word;
344 bt->map = kzalloc_node(nr * sizeof(struct blk_mq_bitmap), 361 bt->map = kzalloc_node(nr * sizeof(struct blk_mq_bitmap),
345 GFP_KERNEL, node); 362 GFP_KERNEL, node);
346 if (!bt->map) 363 if (!bt->map)
@@ -349,8 +366,8 @@ static int bt_alloc(struct blk_mq_bitmap_tags *bt, unsigned int depth,
349 bt->map_nr = nr; 366 bt->map_nr = nr;
350 map_depth = depth; 367 map_depth = depth;
351 for (i = 0; i < nr; i++) { 368 for (i = 0; i < nr; i++) {
352 bt->map[i].depth = min(map_depth, BITS_PER_LONG); 369 bt->map[i].depth = min(map_depth, tags_per_word);
353 map_depth -= BITS_PER_LONG; 370 map_depth -= tags_per_word;
354 } 371 }
355 } 372 }
356 373
@@ -443,8 +460,10 @@ ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page)
443 if (!tags) 460 if (!tags)
444 return 0; 461 return 0;
445 462
446 page += sprintf(page, "nr_tags=%u, reserved_tags=%u\n", 463 page += sprintf(page, "nr_tags=%u, reserved_tags=%u, "
447 tags->nr_tags, tags->nr_reserved_tags); 464 "bits_per_word=%u\n",
465 tags->nr_tags, tags->nr_reserved_tags,
466 tags->bitmap_tags.bits_per_word);
448 467
449 free = bt_unused_tags(&tags->bitmap_tags); 468 free = bt_unused_tags(&tags->bitmap_tags);
450 res = bt_unused_tags(&tags->breserved_tags); 469 res = bt_unused_tags(&tags->breserved_tags);
diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h
index 06d4a2f0f7a0..7aa9f0665489 100644
--- a/block/blk-mq-tag.h
+++ b/block/blk-mq-tag.h
@@ -11,8 +11,8 @@ struct bt_wait_state {
11 wait_queue_head_t wait; 11 wait_queue_head_t wait;
12} ____cacheline_aligned_in_smp; 12} ____cacheline_aligned_in_smp;
13 13
14#define TAG_TO_INDEX(tag) ((tag) / BITS_PER_LONG) 14#define TAG_TO_INDEX(bt, tag) ((tag) >> (bt)->bits_per_word)
15#define TAG_TO_BIT(tag) ((tag) & (BITS_PER_LONG - 1)) 15#define TAG_TO_BIT(bt, tag) ((tag) & ((1 << (bt)->bits_per_word) - 1))
16 16
17struct blk_mq_bitmap { 17struct blk_mq_bitmap {
18 unsigned long word; 18 unsigned long word;
@@ -22,9 +22,10 @@ struct blk_mq_bitmap {
22struct blk_mq_bitmap_tags { 22struct blk_mq_bitmap_tags {
23 unsigned int depth; 23 unsigned int depth;
24 unsigned int wake_cnt; 24 unsigned int wake_cnt;
25 unsigned int bits_per_word;
25 26
26 struct blk_mq_bitmap *map;
27 unsigned int map_nr; 27 unsigned int map_nr;
28 struct blk_mq_bitmap *map;
28 29
29 unsigned int wake_index; 30 unsigned int wake_index;
30 struct bt_wait_state *bs; 31 struct bt_wait_state *bs;