summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2018-12-20 10:50:58 -0500
committerJens Axboe <axboe@kernel.dk>2018-12-20 14:17:21 -0500
commit00203ba40d40d7f33857416adfb18adaf0e40123 (patch)
treee10c6d169b9ca0c8dadccf03aba159c134cefdc2 /block
parent9f6b7ef6c3ebe35be77b0ae3cf12e4d25ae80420 (diff)
kyber: use sbitmap add_wait_queue/list_del wait helpers
sbq_wake_ptr() checks sbq->ws_active to know if it needs to loop the wait indexes or not. This requires the use of the sbitmap waitqueue wrappers, but kyber doesn't use those for its domain token waitqueue handling. Convert kyber to use the helpers. This fixes a hang with waiting for domain tokens. Fixes: 5d2ee7122c73 ("sbitmap: optimize wakeup check") Tested-by: Ming Lei <ming.lei@redhat.com> Reported-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/kyber-iosched.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c
index de78e8aa7b0a..ec6a04e01bc1 100644
--- a/block/kyber-iosched.c
+++ b/block/kyber-iosched.c
@@ -195,7 +195,7 @@ struct kyber_hctx_data {
195 unsigned int batching; 195 unsigned int batching;
196 struct kyber_ctx_queue *kcqs; 196 struct kyber_ctx_queue *kcqs;
197 struct sbitmap kcq_map[KYBER_NUM_DOMAINS]; 197 struct sbitmap kcq_map[KYBER_NUM_DOMAINS];
198 wait_queue_entry_t domain_wait[KYBER_NUM_DOMAINS]; 198 struct sbq_wait domain_wait[KYBER_NUM_DOMAINS];
199 struct sbq_wait_state *domain_ws[KYBER_NUM_DOMAINS]; 199 struct sbq_wait_state *domain_ws[KYBER_NUM_DOMAINS];
200 atomic_t wait_index[KYBER_NUM_DOMAINS]; 200 atomic_t wait_index[KYBER_NUM_DOMAINS];
201}; 201};
@@ -501,10 +501,11 @@ static int kyber_init_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
501 501
502 for (i = 0; i < KYBER_NUM_DOMAINS; i++) { 502 for (i = 0; i < KYBER_NUM_DOMAINS; i++) {
503 INIT_LIST_HEAD(&khd->rqs[i]); 503 INIT_LIST_HEAD(&khd->rqs[i]);
504 init_waitqueue_func_entry(&khd->domain_wait[i], 504 khd->domain_wait[i].sbq = NULL;
505 init_waitqueue_func_entry(&khd->domain_wait[i].wait,
505 kyber_domain_wake); 506 kyber_domain_wake);
506 khd->domain_wait[i].private = hctx; 507 khd->domain_wait[i].wait.private = hctx;
507 INIT_LIST_HEAD(&khd->domain_wait[i].entry); 508 INIT_LIST_HEAD(&khd->domain_wait[i].wait.entry);
508 atomic_set(&khd->wait_index[i], 0); 509 atomic_set(&khd->wait_index[i], 0);
509 } 510 }
510 511
@@ -698,12 +699,13 @@ static void kyber_flush_busy_kcqs(struct kyber_hctx_data *khd,
698 flush_busy_kcq, &data); 699 flush_busy_kcq, &data);
699} 700}
700 701
701static int kyber_domain_wake(wait_queue_entry_t *wait, unsigned mode, int flags, 702static int kyber_domain_wake(wait_queue_entry_t *wqe, unsigned mode, int flags,
702 void *key) 703 void *key)
703{ 704{
704 struct blk_mq_hw_ctx *hctx = READ_ONCE(wait->private); 705 struct blk_mq_hw_ctx *hctx = READ_ONCE(wqe->private);
706 struct sbq_wait *wait = container_of(wqe, struct sbq_wait, wait);
705 707
706 list_del_init(&wait->entry); 708 sbitmap_del_wait_queue(wait);
707 blk_mq_run_hw_queue(hctx, true); 709 blk_mq_run_hw_queue(hctx, true);
708 return 1; 710 return 1;
709} 711}
@@ -714,7 +716,7 @@ static int kyber_get_domain_token(struct kyber_queue_data *kqd,
714{ 716{
715 unsigned int sched_domain = khd->cur_domain; 717 unsigned int sched_domain = khd->cur_domain;
716 struct sbitmap_queue *domain_tokens = &kqd->domain_tokens[sched_domain]; 718 struct sbitmap_queue *domain_tokens = &kqd->domain_tokens[sched_domain];
717 wait_queue_entry_t *wait = &khd->domain_wait[sched_domain]; 719 struct sbq_wait *wait = &khd->domain_wait[sched_domain];
718 struct sbq_wait_state *ws; 720 struct sbq_wait_state *ws;
719 int nr; 721 int nr;
720 722
@@ -725,11 +727,11 @@ static int kyber_get_domain_token(struct kyber_queue_data *kqd,
725 * run when one becomes available. Note that this is serialized on 727 * run when one becomes available. Note that this is serialized on
726 * khd->lock, but we still need to be careful about the waker. 728 * khd->lock, but we still need to be careful about the waker.
727 */ 729 */
728 if (nr < 0 && list_empty_careful(&wait->entry)) { 730 if (nr < 0 && list_empty_careful(&wait->wait.entry)) {
729 ws = sbq_wait_ptr(domain_tokens, 731 ws = sbq_wait_ptr(domain_tokens,
730 &khd->wait_index[sched_domain]); 732 &khd->wait_index[sched_domain]);
731 khd->domain_ws[sched_domain] = ws; 733 khd->domain_ws[sched_domain] = ws;
732 add_wait_queue(&ws->wait, wait); 734 sbitmap_add_wait_queue(domain_tokens, ws, wait);
733 735
734 /* 736 /*
735 * Try again in case a token was freed before we got on the wait 737 * Try again in case a token was freed before we got on the wait
@@ -745,10 +747,10 @@ static int kyber_get_domain_token(struct kyber_queue_data *kqd,
745 * between the !list_empty_careful() check and us grabbing the lock, but 747 * between the !list_empty_careful() check and us grabbing the lock, but
746 * list_del_init() is okay with that. 748 * list_del_init() is okay with that.
747 */ 749 */
748 if (nr >= 0 && !list_empty_careful(&wait->entry)) { 750 if (nr >= 0 && !list_empty_careful(&wait->wait.entry)) {
749 ws = khd->domain_ws[sched_domain]; 751 ws = khd->domain_ws[sched_domain];
750 spin_lock_irq(&ws->wait.lock); 752 spin_lock_irq(&ws->wait.lock);
751 list_del_init(&wait->entry); 753 sbitmap_del_wait_queue(wait);
752 spin_unlock_irq(&ws->wait.lock); 754 spin_unlock_irq(&ws->wait.lock);
753 } 755 }
754 756
@@ -951,7 +953,7 @@ static int kyber_##name##_waiting_show(void *data, struct seq_file *m) \
951{ \ 953{ \
952 struct blk_mq_hw_ctx *hctx = data; \ 954 struct blk_mq_hw_ctx *hctx = data; \
953 struct kyber_hctx_data *khd = hctx->sched_data; \ 955 struct kyber_hctx_data *khd = hctx->sched_data; \
954 wait_queue_entry_t *wait = &khd->domain_wait[domain]; \ 956 wait_queue_entry_t *wait = &khd->domain_wait[domain].wait; \
955 \ 957 \
956 seq_printf(m, "%d\n", !list_empty_careful(&wait->entry)); \ 958 seq_printf(m, "%d\n", !list_empty_careful(&wait->entry)); \
957 return 0; \ 959 return 0; \