diff options
-rw-r--r-- | block/blk-mq-tag.c | 59 | ||||
-rw-r--r-- | block/blk-mq-tag.h | 7 |
2 files changed, 41 insertions, 25 deletions
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index 467f3a20b355..8d526a3e02f6 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 { |
50 | restart: | 50 | restart: |
@@ -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,14 +233,17 @@ static struct bt_wait_state *bt_wake_ptr(struct blk_mq_bitmap_tags *bt) | |||
233 | 233 | ||
234 | static void bt_clear_tag(struct blk_mq_bitmap_tags *bt, unsigned int tag) | 234 | static 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 | /* |
240 | * The unlock memory barrier need to order access to req in free | ||
241 | * path and clearing tag bit | ||
242 | */ | ||
243 | clear_bit_unlock(TAG_TO_BIT(bt, tag), &bt->map[index].word); | ||
240 | 244 | ||
241 | bs = bt_wake_ptr(bt); | 245 | bs = bt_wake_ptr(bt); |
242 | if (bs && atomic_dec_and_test(&bs->wait_cnt)) { | 246 | if (bs && atomic_dec_and_test(&bs->wait_cnt)) { |
243 | smp_mb__after_clear_bit(); | ||
244 | atomic_set(&bs->wait_cnt, bt->wake_cnt); | 247 | atomic_set(&bs->wait_cnt, bt->wake_cnt); |
245 | bt_index_inc(&bt->wake_index); | 248 | bt_index_inc(&bt->wake_index); |
246 | wake_up(&bs->wait); | 249 | wake_up(&bs->wait); |
@@ -292,7 +295,7 @@ static void bt_for_each_free(struct blk_mq_bitmap_tags *bt, | |||
292 | bit++; | 295 | bit++; |
293 | } while (1); | 296 | } while (1); |
294 | 297 | ||
295 | off += BITS_PER_LONG; | 298 | off += (1 << bt->bits_per_word); |
296 | } | 299 | } |
297 | } | 300 | } |
298 | 301 | ||
@@ -333,14 +336,31 @@ static int bt_alloc(struct blk_mq_bitmap_tags *bt, unsigned int depth, | |||
333 | { | 336 | { |
334 | int i; | 337 | int i; |
335 | 338 | ||
339 | bt->bits_per_word = ilog2(BITS_PER_LONG); | ||
340 | |||
336 | /* | 341 | /* |
337 | * Depth can be zero for reserved tags, that's not a failure | 342 | * Depth can be zero for reserved tags, that's not a failure |
338 | * condition. | 343 | * condition. |
339 | */ | 344 | */ |
340 | if (depth) { | 345 | if (depth) { |
341 | int nr, i, map_depth; | 346 | unsigned int nr, i, map_depth, tags_per_word; |
347 | |||
348 | tags_per_word = (1 << bt->bits_per_word); | ||
349 | |||
350 | /* | ||
351 | * If the tag space is small, shrink the number of tags | ||
352 | * per word so we spread over a few cachelines, at least. | ||
353 | * If less than 4 tags, just forget about it, it's not | ||
354 | * going to work optimally anyway. | ||
355 | */ | ||
356 | if (depth >= 4) { | ||
357 | while (tags_per_word * 4 > depth) { | ||
358 | bt->bits_per_word--; | ||
359 | tags_per_word = (1 << bt->bits_per_word); | ||
360 | } | ||
361 | } | ||
342 | 362 | ||
343 | nr = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; | 363 | nr = ALIGN(depth, tags_per_word) / tags_per_word; |
344 | bt->map = kzalloc_node(nr * sizeof(struct blk_mq_bitmap), | 364 | bt->map = kzalloc_node(nr * sizeof(struct blk_mq_bitmap), |
345 | GFP_KERNEL, node); | 365 | GFP_KERNEL, node); |
346 | if (!bt->map) | 366 | if (!bt->map) |
@@ -349,8 +369,8 @@ static int bt_alloc(struct blk_mq_bitmap_tags *bt, unsigned int depth, | |||
349 | bt->map_nr = nr; | 369 | bt->map_nr = nr; |
350 | map_depth = depth; | 370 | map_depth = depth; |
351 | for (i = 0; i < nr; i++) { | 371 | for (i = 0; i < nr; i++) { |
352 | bt->map[i].depth = min(map_depth, BITS_PER_LONG); | 372 | bt->map[i].depth = min(map_depth, tags_per_word); |
353 | map_depth -= BITS_PER_LONG; | 373 | map_depth -= tags_per_word; |
354 | } | 374 | } |
355 | } | 375 | } |
356 | 376 | ||
@@ -397,7 +417,6 @@ enomem: | |||
397 | struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, | 417 | struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, |
398 | unsigned int reserved_tags, int node) | 418 | unsigned int reserved_tags, int node) |
399 | { | 419 | { |
400 | unsigned int nr_tags, nr_cache; | ||
401 | struct blk_mq_tags *tags; | 420 | struct blk_mq_tags *tags; |
402 | 421 | ||
403 | if (total_tags > BLK_MQ_TAG_MAX) { | 422 | if (total_tags > BLK_MQ_TAG_MAX) { |
@@ -409,9 +428,6 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, | |||
409 | if (!tags) | 428 | if (!tags) |
410 | return NULL; | 429 | return NULL; |
411 | 430 | ||
412 | nr_tags = total_tags - reserved_tags; | ||
413 | nr_cache = nr_tags / num_online_cpus(); | ||
414 | |||
415 | tags->nr_tags = total_tags; | 431 | tags->nr_tags = total_tags; |
416 | tags->nr_reserved_tags = reserved_tags; | 432 | tags->nr_reserved_tags = reserved_tags; |
417 | 433 | ||
@@ -429,10 +445,7 @@ void blk_mq_tag_init_last_tag(struct blk_mq_tags *tags, unsigned int *tag) | |||
429 | { | 445 | { |
430 | unsigned int depth = tags->nr_tags - tags->nr_reserved_tags; | 446 | unsigned int depth = tags->nr_tags - tags->nr_reserved_tags; |
431 | 447 | ||
432 | if (depth > 1) | 448 | *tag = prandom_u32() % depth; |
433 | *tag = prandom_u32() % (depth - 1); | ||
434 | else | ||
435 | *tag = 0; | ||
436 | } | 449 | } |
437 | 450 | ||
438 | ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page) | 451 | ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page) |
@@ -443,8 +456,10 @@ ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page) | |||
443 | if (!tags) | 456 | if (!tags) |
444 | return 0; | 457 | return 0; |
445 | 458 | ||
446 | page += sprintf(page, "nr_tags=%u, reserved_tags=%u\n", | 459 | page += sprintf(page, "nr_tags=%u, reserved_tags=%u, " |
447 | tags->nr_tags, tags->nr_reserved_tags); | 460 | "bits_per_word=%u\n", |
461 | tags->nr_tags, tags->nr_reserved_tags, | ||
462 | tags->bitmap_tags.bits_per_word); | ||
448 | 463 | ||
449 | free = bt_unused_tags(&tags->bitmap_tags); | 464 | free = bt_unused_tags(&tags->bitmap_tags); |
450 | res = bt_unused_tags(&tags->breserved_tags); | 465 | 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 | ||
17 | struct blk_mq_bitmap { | 17 | struct blk_mq_bitmap { |
18 | unsigned long word; | 18 | unsigned long word; |
@@ -22,9 +22,10 @@ struct blk_mq_bitmap { | |||
22 | struct blk_mq_bitmap_tags { | 22 | struct 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; |