aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-wbt.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2018-12-04 12:59:03 -0500
committerJens Axboe <axboe@kernel.dk>2018-12-08 00:26:38 -0500
commitb6c7b58f5fcc2386bddf9852011c42c1d2b83979 (patch)
tree15d379a0c0a184d4d3d0f5c57478072f6dc34d62 /block/blk-wbt.c
parent84f603246db9703aca05aad58b94a54dfbf44327 (diff)
block: convert wbt_wait() to use rq_qos_wait()
Now that we have rq_qos_wait() in place, convert wbt_wait() over to using it with it's specific callbacks. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-wbt.c')
-rw-r--r--block/blk-wbt.c65
1 files changed, 11 insertions, 54 deletions
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
index d051ebfb4852..40207edd1d89 100644
--- a/block/blk-wbt.c
+++ b/block/blk-wbt.c
@@ -489,31 +489,21 @@ static inline unsigned int get_limit(struct rq_wb *rwb, unsigned long rw)
489} 489}
490 490
491struct wbt_wait_data { 491struct wbt_wait_data {
492 struct wait_queue_entry wq;
493 struct task_struct *task;
494 struct rq_wb *rwb; 492 struct rq_wb *rwb;
495 struct rq_wait *rqw; 493 enum wbt_flags wb_acct;
496 unsigned long rw; 494 unsigned long rw;
497 bool got_token;
498}; 495};
499 496
500static int wbt_wake_function(struct wait_queue_entry *curr, unsigned int mode, 497static bool wbt_inflight_cb(struct rq_wait *rqw, void *private_data)
501 int wake_flags, void *key)
502{ 498{
503 struct wbt_wait_data *data = container_of(curr, struct wbt_wait_data, 499 struct wbt_wait_data *data = private_data;
504 wq); 500 return rq_wait_inc_below(rqw, get_limit(data->rwb, data->rw));
505 501}
506 /*
507 * If we fail to get a budget, return -1 to interrupt the wake up
508 * loop in __wake_up_common.
509 */
510 if (!rq_wait_inc_below(data->rqw, get_limit(data->rwb, data->rw)))
511 return -1;
512 502
513 data->got_token = true; 503static void wbt_cleanup_cb(struct rq_wait *rqw, void *private_data)
514 list_del_init(&curr->entry); 504{
515 wake_up_process(data->task); 505 struct wbt_wait_data *data = private_data;
516 return 1; 506 wbt_rqw_done(data->rwb, rqw, data->wb_acct);
517} 507}
518 508
519/* 509/*
@@ -525,45 +515,12 @@ static void __wbt_wait(struct rq_wb *rwb, enum wbt_flags wb_acct,
525{ 515{
526 struct rq_wait *rqw = get_rq_wait(rwb, wb_acct); 516 struct rq_wait *rqw = get_rq_wait(rwb, wb_acct);
527 struct wbt_wait_data data = { 517 struct wbt_wait_data data = {
528 .wq = {
529 .func = wbt_wake_function,
530 .entry = LIST_HEAD_INIT(data.wq.entry),
531 },
532 .task = current,
533 .rwb = rwb, 518 .rwb = rwb,
534 .rqw = rqw, 519 .wb_acct = wb_acct,
535 .rw = rw, 520 .rw = rw,
536 }; 521 };
537 bool has_sleeper;
538
539 has_sleeper = wq_has_sleeper(&rqw->wait);
540 if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw)))
541 return;
542
543 prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE);
544 do {
545 if (data.got_token)
546 break;
547
548 if (!has_sleeper &&
549 rq_wait_inc_below(rqw, get_limit(rwb, rw))) {
550 finish_wait(&rqw->wait, &data.wq);
551
552 /*
553 * We raced with wbt_wake_function() getting a token,
554 * which means we now have two. Put our local token
555 * and wake anyone else potentially waiting for one.
556 */
557 if (data.got_token)
558 wbt_rqw_done(rwb, rqw, wb_acct);
559 break;
560 }
561
562 io_schedule();
563 has_sleeper = false;
564 } while (1);
565 522
566 finish_wait(&rqw->wait, &data.wq); 523 rq_qos_wait(rqw, &data, wbt_inflight_cb, wbt_cleanup_cb);
567} 524}
568 525
569static inline bool wbt_should_throttle(struct rq_wb *rwb, struct bio *bio) 526static inline bool wbt_should_throttle(struct rq_wb *rwb, struct bio *bio)