Skip to content

Commit b8dcdab

Browse files
committed
Merge tag 'for-linus-20180825' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe: "A few small fixes for this merge window: - Locking imbalance fix for bcache (Shan Hai) - A few small fixes for wbt. One is a cleanup/prep, one is a fix for an existing issue, and the last two are fixes for changes that went into this merge window (me)" * tag 'for-linus-20180825' of git://git.kernel.dk/linux-block: blk-wbt: don't maintain inflight counts if disabled blk-wbt: fix has-sleeper queueing check blk-wbt: use wq_has_sleeper() for wq active check blk-wbt: move disable check into get_limit() bcache: release dc->writeback_lock properly in bch_writeback_thread()
2 parents db84abf + c125311 commit b8dcdab

File tree

3 files changed

+38
-22
lines changed

3 files changed

+38
-22
lines changed

block/blk-sysfs.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,26 @@ static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
453453
else if (val >= 0)
454454
val *= 1000ULL;
455455

456-
wbt_set_min_lat(q, val);
456+
/*
457+
* Ensure that the queue is idled, in case the latency update
458+
* ends up either enabling or disabling wbt completely. We can't
459+
* have IO inflight if that happens.
460+
*/
461+
if (q->mq_ops) {
462+
blk_mq_freeze_queue(q);
463+
blk_mq_quiesce_queue(q);
464+
} else
465+
blk_queue_bypass_start(q);
457466

467+
wbt_set_min_lat(q, val);
458468
wbt_update_limits(q);
469+
470+
if (q->mq_ops) {
471+
blk_mq_unquiesce_queue(q);
472+
blk_mq_unfreeze_queue(q);
473+
} else
474+
blk_queue_bypass_end(q);
475+
459476
return count;
460477
}
461478

block/blk-wbt.c

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ static void rwb_wake_all(struct rq_wb *rwb)
118118
for (i = 0; i < WBT_NUM_RWQ; i++) {
119119
struct rq_wait *rqw = &rwb->rq_wait[i];
120120

121-
if (waitqueue_active(&rqw->wait))
121+
if (wq_has_sleeper(&rqw->wait))
122122
wake_up_all(&rqw->wait);
123123
}
124124
}
@@ -162,7 +162,7 @@ static void __wbt_done(struct rq_qos *rqos, enum wbt_flags wb_acct)
162162
if (inflight && inflight >= limit)
163163
return;
164164

165-
if (waitqueue_active(&rqw->wait)) {
165+
if (wq_has_sleeper(&rqw->wait)) {
166166
int diff = limit - inflight;
167167

168168
if (!inflight || diff >= rwb->wb_background / 2)
@@ -449,6 +449,13 @@ static inline unsigned int get_limit(struct rq_wb *rwb, unsigned long rw)
449449
{
450450
unsigned int limit;
451451

452+
/*
453+
* If we got disabled, just return UINT_MAX. This ensures that
454+
* we'll properly inc a new IO, and dec+wakeup at the end.
455+
*/
456+
if (!rwb_enabled(rwb))
457+
return UINT_MAX;
458+
452459
if ((rw & REQ_OP_MASK) == REQ_OP_DISCARD)
453460
return rwb->wb_background;
454461

@@ -485,31 +492,17 @@ static void __wbt_wait(struct rq_wb *rwb, enum wbt_flags wb_acct,
485492
{
486493
struct rq_wait *rqw = get_rq_wait(rwb, wb_acct);
487494
DECLARE_WAITQUEUE(wait, current);
495+
bool has_sleeper;
488496

489-
/*
490-
* inc it here even if disabled, since we'll dec it at completion.
491-
* this only happens if the task was sleeping in __wbt_wait(),
492-
* and someone turned it off at the same time.
493-
*/
494-
if (!rwb_enabled(rwb)) {
495-
atomic_inc(&rqw->inflight);
496-
return;
497-
}
498-
499-
if (!waitqueue_active(&rqw->wait)
500-
&& rq_wait_inc_below(rqw, get_limit(rwb, rw)))
497+
has_sleeper = wq_has_sleeper(&rqw->wait);
498+
if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw)))
501499
return;
502500

503501
add_wait_queue_exclusive(&rqw->wait, &wait);
504502
do {
505503
set_current_state(TASK_UNINTERRUPTIBLE);
506504

507-
if (!rwb_enabled(rwb)) {
508-
atomic_inc(&rqw->inflight);
509-
break;
510-
}
511-
512-
if (rq_wait_inc_below(rqw, get_limit(rwb, rw)))
505+
if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw)))
513506
break;
514507

515508
if (lock) {
@@ -518,6 +511,7 @@ static void __wbt_wait(struct rq_wb *rwb, enum wbt_flags wb_acct,
518511
spin_lock_irq(lock);
519512
} else
520513
io_schedule();
514+
has_sleeper = false;
521515
} while (1);
522516

523517
__set_current_state(TASK_RUNNING);
@@ -546,6 +540,9 @@ static enum wbt_flags bio_to_wbt_flags(struct rq_wb *rwb, struct bio *bio)
546540
{
547541
enum wbt_flags flags = 0;
548542

543+
if (!rwb_enabled(rwb))
544+
return 0;
545+
549546
if (bio_op(bio) == REQ_OP_READ) {
550547
flags = WBT_READ;
551548
} else if (wbt_should_throttle(rwb, bio)) {

drivers/md/bcache/writeback.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,10 @@ static int bch_writeback_thread(void *arg)
685685
* data on cache. BCACHE_DEV_DETACHING flag is set in
686686
* bch_cached_dev_detach().
687687
*/
688-
if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
688+
if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) {
689+
up_write(&dc->writeback_lock);
689690
break;
691+
}
690692
}
691693

692694
up_write(&dc->writeback_lock);

0 commit comments

Comments
 (0)