diff options
author | Jens Axboe <axboe@kernel.dk> | 2018-12-20 10:49:00 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-12-20 14:17:05 -0500 |
commit | 9f6b7ef6c3ebe35be77b0ae3cf12e4d25ae80420 (patch) | |
tree | dd94ebc8b17053087b9a459beebdd4ed18ad326d | |
parent | 3a762de55b4ede47a5369f57d0f92979738be638 (diff) |
sbitmap: add helpers for add/del wait queue handling
After commit 5d2ee7122c73, users of sbitmap that need wait queue
handling must use the provided helpers. But we only added
prepare_to_wait()/finish_wait() style helpers, add the equivalent
add_wait_queue/list_del wrappers as we..
This is needed to ensure kyber plays by the sbitmap waitqueue
rules.
Tested-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | include/linux/sbitmap.h | 16 | ||||
-rw-r--r-- | lib/sbitmap.c | 30 |
2 files changed, 40 insertions, 6 deletions
diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h index 03f50fcedc79..14d558146aea 100644 --- a/include/linux/sbitmap.h +++ b/include/linux/sbitmap.h | |||
@@ -560,13 +560,13 @@ void sbitmap_queue_wake_up(struct sbitmap_queue *sbq); | |||
560 | void sbitmap_queue_show(struct sbitmap_queue *sbq, struct seq_file *m); | 560 | void sbitmap_queue_show(struct sbitmap_queue *sbq, struct seq_file *m); |
561 | 561 | ||
562 | struct sbq_wait { | 562 | struct sbq_wait { |
563 | int accounted; | 563 | struct sbitmap_queue *sbq; /* if set, sbq_wait is accounted */ |
564 | struct wait_queue_entry wait; | 564 | struct wait_queue_entry wait; |
565 | }; | 565 | }; |
566 | 566 | ||
567 | #define DEFINE_SBQ_WAIT(name) \ | 567 | #define DEFINE_SBQ_WAIT(name) \ |
568 | struct sbq_wait name = { \ | 568 | struct sbq_wait name = { \ |
569 | .accounted = 0, \ | 569 | .sbq = NULL, \ |
570 | .wait = { \ | 570 | .wait = { \ |
571 | .private = current, \ | 571 | .private = current, \ |
572 | .func = autoremove_wake_function, \ | 572 | .func = autoremove_wake_function, \ |
@@ -588,4 +588,16 @@ void sbitmap_prepare_to_wait(struct sbitmap_queue *sbq, | |||
588 | void sbitmap_finish_wait(struct sbitmap_queue *sbq, struct sbq_wait_state *ws, | 588 | void sbitmap_finish_wait(struct sbitmap_queue *sbq, struct sbq_wait_state *ws, |
589 | struct sbq_wait *sbq_wait); | 589 | struct sbq_wait *sbq_wait); |
590 | 590 | ||
591 | /* | ||
592 | * Wrapper around add_wait_queue(), which maintains some extra internal state | ||
593 | */ | ||
594 | void sbitmap_add_wait_queue(struct sbitmap_queue *sbq, | ||
595 | struct sbq_wait_state *ws, | ||
596 | struct sbq_wait *sbq_wait); | ||
597 | |||
598 | /* | ||
599 | * Must be paired with sbitmap_add_wait_queue() | ||
600 | */ | ||
601 | void sbitmap_del_wait_queue(struct sbq_wait *sbq_wait); | ||
602 | |||
591 | #endif /* __LINUX_SCALE_BITMAP_H */ | 603 | #endif /* __LINUX_SCALE_BITMAP_H */ |
diff --git a/lib/sbitmap.c b/lib/sbitmap.c index 5b3e56d68dab..65c2d06250a6 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c | |||
@@ -671,13 +671,35 @@ void sbitmap_queue_show(struct sbitmap_queue *sbq, struct seq_file *m) | |||
671 | } | 671 | } |
672 | EXPORT_SYMBOL_GPL(sbitmap_queue_show); | 672 | EXPORT_SYMBOL_GPL(sbitmap_queue_show); |
673 | 673 | ||
674 | void sbitmap_add_wait_queue(struct sbitmap_queue *sbq, | ||
675 | struct sbq_wait_state *ws, | ||
676 | struct sbq_wait *sbq_wait) | ||
677 | { | ||
678 | if (!sbq_wait->sbq) { | ||
679 | sbq_wait->sbq = sbq; | ||
680 | atomic_inc(&sbq->ws_active); | ||
681 | } | ||
682 | add_wait_queue(&ws->wait, &sbq_wait->wait); | ||
683 | } | ||
684 | EXPORT_SYMBOL_GPL(sbitmap_add_wait_queue); | ||
685 | |||
686 | void sbitmap_del_wait_queue(struct sbq_wait *sbq_wait) | ||
687 | { | ||
688 | list_del_init(&sbq_wait->wait.entry); | ||
689 | if (sbq_wait->sbq) { | ||
690 | atomic_dec(&sbq_wait->sbq->ws_active); | ||
691 | sbq_wait->sbq = NULL; | ||
692 | } | ||
693 | } | ||
694 | EXPORT_SYMBOL_GPL(sbitmap_del_wait_queue); | ||
695 | |||
674 | void sbitmap_prepare_to_wait(struct sbitmap_queue *sbq, | 696 | void sbitmap_prepare_to_wait(struct sbitmap_queue *sbq, |
675 | struct sbq_wait_state *ws, | 697 | struct sbq_wait_state *ws, |
676 | struct sbq_wait *sbq_wait, int state) | 698 | struct sbq_wait *sbq_wait, int state) |
677 | { | 699 | { |
678 | if (!sbq_wait->accounted) { | 700 | if (!sbq_wait->sbq) { |
679 | atomic_inc(&sbq->ws_active); | 701 | atomic_inc(&sbq->ws_active); |
680 | sbq_wait->accounted = 1; | 702 | sbq_wait->sbq = sbq; |
681 | } | 703 | } |
682 | prepare_to_wait_exclusive(&ws->wait, &sbq_wait->wait, state); | 704 | prepare_to_wait_exclusive(&ws->wait, &sbq_wait->wait, state); |
683 | } | 705 | } |
@@ -687,9 +709,9 @@ void sbitmap_finish_wait(struct sbitmap_queue *sbq, struct sbq_wait_state *ws, | |||
687 | struct sbq_wait *sbq_wait) | 709 | struct sbq_wait *sbq_wait) |
688 | { | 710 | { |
689 | finish_wait(&ws->wait, &sbq_wait->wait); | 711 | finish_wait(&ws->wait, &sbq_wait->wait); |
690 | if (sbq_wait->accounted) { | 712 | if (sbq_wait->sbq) { |
691 | atomic_dec(&sbq->ws_active); | 713 | atomic_dec(&sbq->ws_active); |
692 | sbq_wait->accounted = 0; | 714 | sbq_wait->sbq = NULL; |
693 | } | 715 | } |
694 | } | 716 | } |
695 | EXPORT_SYMBOL_GPL(sbitmap_finish_wait); | 717 | EXPORT_SYMBOL_GPL(sbitmap_finish_wait); |