Skip to content

Commit 47db9b9

Browse files
committed
Merge tag 'for-linus-2019-09-27' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe: "A few fixes/changes to round off this merge window. This contains: - Small series making some functional tweaks to blk-iocost (Tejun) - Elevator switch locking fix (Ming) - Kill redundant call in blk-wbt (Yufen) - Fix flush timeout handling (Yufen)" * tag 'for-linus-2019-09-27' of git://git.kernel.dk/linux-block: block: fix null pointer dereference in blk_mq_rq_timed_out() rq-qos: get rid of redundant wbt_update_limits() iocost: bump up default latency targets for hard disks iocost: improve nr_lagging handling iocost: better trace vrate changes block: don't release queue's sysfs lock during switching elevator blk-mq: move lockdep_assert_held() into elevator_exit
2 parents d0e00bc + 8d69966 commit 47db9b9

File tree

7 files changed

+47
-54
lines changed

7 files changed

+47
-54
lines changed

block/blk-flush.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,16 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
214214

215215
/* release the tag's ownership to the req cloned from */
216216
spin_lock_irqsave(&fq->mq_flush_lock, flags);
217+
218+
if (!refcount_dec_and_test(&flush_rq->ref)) {
219+
fq->rq_status = error;
220+
spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
221+
return;
222+
}
223+
224+
if (fq->rq_status != BLK_STS_OK)
225+
error = fq->rq_status;
226+
217227
hctx = flush_rq->mq_hctx;
218228
if (!q->elevator) {
219229
blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq);

block/blk-iocost.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,8 @@ struct iocg_wake_ctx {
529529
static const struct ioc_params autop[] = {
530530
[AUTOP_HDD] = {
531531
.qos = {
532-
[QOS_RLAT] = 50000, /* 50ms */
533-
[QOS_WLAT] = 50000,
532+
[QOS_RLAT] = 250000, /* 250ms */
533+
[QOS_WLAT] = 250000,
534534
[QOS_MIN] = VRATE_MIN_PPM,
535535
[QOS_MAX] = VRATE_MAX_PPM,
536536
},
@@ -1343,7 +1343,7 @@ static void ioc_timer_fn(struct timer_list *timer)
13431343
u32 ppm_wthr = MILLION - ioc->params.qos[QOS_WPPM];
13441344
u32 missed_ppm[2], rq_wait_pct;
13451345
u64 period_vtime;
1346-
int i;
1346+
int prev_busy_level, i;
13471347

13481348
/* how were the latencies during the period? */
13491349
ioc_lat_stat(ioc, missed_ppm, &rq_wait_pct);
@@ -1407,7 +1407,8 @@ static void ioc_timer_fn(struct timer_list *timer)
14071407
* comparing vdone against period start. If lagging behind
14081408
* IOs from past periods, don't increase vrate.
14091409
*/
1410-
if (!atomic_read(&iocg_to_blkg(iocg)->use_delay) &&
1410+
if ((ppm_rthr != MILLION || ppm_wthr != MILLION) &&
1411+
!atomic_read(&iocg_to_blkg(iocg)->use_delay) &&
14111412
time_after64(vtime, vdone) &&
14121413
time_after64(vtime, now.vnow -
14131414
MAX_LAGGING_PERIODS * period_vtime) &&
@@ -1531,26 +1532,29 @@ static void ioc_timer_fn(struct timer_list *timer)
15311532
* and experiencing shortages but not surpluses, we're too stingy
15321533
* and should increase vtime rate.
15331534
*/
1535+
prev_busy_level = ioc->busy_level;
15341536
if (rq_wait_pct > RQ_WAIT_BUSY_PCT ||
15351537
missed_ppm[READ] > ppm_rthr ||
15361538
missed_ppm[WRITE] > ppm_wthr) {
15371539
ioc->busy_level = max(ioc->busy_level, 0);
15381540
ioc->busy_level++;
1539-
} else if (nr_lagging) {
1540-
ioc->busy_level = max(ioc->busy_level, 0);
1541-
} else if (nr_shortages && !nr_surpluses &&
1542-
rq_wait_pct <= RQ_WAIT_BUSY_PCT * UNBUSY_THR_PCT / 100 &&
1541+
} else if (rq_wait_pct <= RQ_WAIT_BUSY_PCT * UNBUSY_THR_PCT / 100 &&
15431542
missed_ppm[READ] <= ppm_rthr * UNBUSY_THR_PCT / 100 &&
15441543
missed_ppm[WRITE] <= ppm_wthr * UNBUSY_THR_PCT / 100) {
1545-
ioc->busy_level = min(ioc->busy_level, 0);
1546-
ioc->busy_level--;
1544+
/* take action iff there is contention */
1545+
if (nr_shortages && !nr_lagging) {
1546+
ioc->busy_level = min(ioc->busy_level, 0);
1547+
/* redistribute surpluses first */
1548+
if (!nr_surpluses)
1549+
ioc->busy_level--;
1550+
}
15471551
} else {
15481552
ioc->busy_level = 0;
15491553
}
15501554

15511555
ioc->busy_level = clamp(ioc->busy_level, -1000, 1000);
15521556

1553-
if (ioc->busy_level) {
1557+
if (ioc->busy_level > 0 || (ioc->busy_level < 0 && !nr_lagging)) {
15541558
u64 vrate = atomic64_read(&ioc->vtime_rate);
15551559
u64 vrate_min = ioc->vrate_min, vrate_max = ioc->vrate_max;
15561560

@@ -1592,6 +1596,10 @@ static void ioc_timer_fn(struct timer_list *timer)
15921596
atomic64_set(&ioc->vtime_rate, vrate);
15931597
ioc->inuse_margin_vtime = DIV64_U64_ROUND_UP(
15941598
ioc->period_us * vrate * INUSE_MARGIN_PCT, 100);
1599+
} else if (ioc->busy_level != prev_busy_level || nr_lagging) {
1600+
trace_iocost_ioc_vrate_adj(ioc, atomic64_read(&ioc->vtime_rate),
1601+
&missed_ppm, rq_wait_pct, nr_lagging,
1602+
nr_shortages, nr_surpluses);
15951603
}
15961604

15971605
ioc_refresh_params(ioc, false);

block/blk-mq-sched.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,6 @@ void blk_mq_sched_free_requests(struct request_queue *q)
555555
struct blk_mq_hw_ctx *hctx;
556556
int i;
557557

558-
lockdep_assert_held(&q->sysfs_lock);
559-
560558
queue_for_each_hw_ctx(q, hctx, i) {
561559
if (hctx->sched_tags)
562560
blk_mq_free_rqs(q->tag_set, hctx->sched_tags, i);

block/blk-mq.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,10 @@ static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
918918
*/
919919
if (blk_mq_req_expired(rq, next))
920920
blk_mq_rq_timed_out(rq, reserved);
921-
if (refcount_dec_and_test(&rq->ref))
921+
922+
if (is_flush_rq(rq, hctx))
923+
rq->end_io(rq, 0);
924+
else if (refcount_dec_and_test(&rq->ref))
922925
__blk_mq_free_request(rq);
923926

924927
return true;

block/blk-sysfs.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,6 @@ static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
482482
blk_mq_quiesce_queue(q);
483483

484484
wbt_set_min_lat(q, val);
485-
wbt_update_limits(q);
486485

487486
blk_mq_unquiesce_queue(q);
488487
blk_mq_unfreeze_queue(q);
@@ -989,13 +988,11 @@ int blk_register_queue(struct gendisk *disk)
989988
blk_mq_debugfs_register(q);
990989
}
991990

992-
/*
993-
* The flag of QUEUE_FLAG_REGISTERED isn't set yet, so elevator
994-
* switch won't happen at all.
995-
*/
991+
mutex_lock(&q->sysfs_lock);
996992
if (q->elevator) {
997993
ret = elv_register_queue(q, false);
998994
if (ret) {
995+
mutex_unlock(&q->sysfs_lock);
999996
mutex_unlock(&q->sysfs_dir_lock);
1000997
kobject_del(&q->kobj);
1001998
blk_trace_remove_sysfs(dev);
@@ -1005,7 +1002,6 @@ int blk_register_queue(struct gendisk *disk)
10051002
has_elevator = true;
10061003
}
10071004

1008-
mutex_lock(&q->sysfs_lock);
10091005
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);
10101006
wbt_enable_default(q);
10111007
blk_throtl_register_queue(q);
@@ -1062,12 +1058,10 @@ void blk_unregister_queue(struct gendisk *disk)
10621058
kobject_del(&q->kobj);
10631059
blk_trace_remove_sysfs(disk_to_dev(disk));
10641060

1065-
/*
1066-
* q->kobj has been removed, so it is safe to check if elevator
1067-
* exists without holding q->sysfs_lock.
1068-
*/
1061+
mutex_lock(&q->sysfs_lock);
10691062
if (q->elevator)
10701063
elv_unregister_queue(q);
1064+
mutex_unlock(&q->sysfs_lock);
10711065
mutex_unlock(&q->sysfs_dir_lock);
10721066

10731067
kobject_put(&disk_to_dev(disk)->kobj);

block/blk.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct blk_flush_queue {
1919
unsigned int flush_queue_delayed:1;
2020
unsigned int flush_pending_idx:1;
2121
unsigned int flush_running_idx:1;
22+
blk_status_t rq_status;
2223
unsigned long flush_pending_since;
2324
struct list_head flush_queue[2];
2425
struct list_head flush_data_in_flight;
@@ -47,6 +48,12 @@ static inline void __blk_get_queue(struct request_queue *q)
4748
kobject_get(&q->kobj);
4849
}
4950

51+
static inline bool
52+
is_flush_rq(struct request *req, struct blk_mq_hw_ctx *hctx)
53+
{
54+
return hctx->fq->flush_rq == req;
55+
}
56+
5057
struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q,
5158
int node, int cmd_size, gfp_t flags);
5259
void blk_free_flush_queue(struct blk_flush_queue *q);
@@ -194,6 +201,8 @@ void elv_unregister_queue(struct request_queue *q);
194201
static inline void elevator_exit(struct request_queue *q,
195202
struct elevator_queue *e)
196203
{
204+
lockdep_assert_held(&q->sysfs_lock);
205+
197206
blk_mq_sched_free_requests(q);
198207
__elevator_exit(q, e);
199208
}

block/elevator.c

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -503,9 +503,7 @@ int elv_register_queue(struct request_queue *q, bool uevent)
503503
if (uevent)
504504
kobject_uevent(&e->kobj, KOBJ_ADD);
505505

506-
mutex_lock(&q->sysfs_lock);
507506
e->registered = 1;
508-
mutex_unlock(&q->sysfs_lock);
509507
}
510508
return error;
511509
}
@@ -523,11 +521,9 @@ void elv_unregister_queue(struct request_queue *q)
523521
kobject_uevent(&e->kobj, KOBJ_REMOVE);
524522
kobject_del(&e->kobj);
525523

526-
mutex_lock(&q->sysfs_lock);
527524
e->registered = 0;
528525
/* Re-enable throttling in case elevator disabled it */
529526
wbt_enable_default(q);
530-
mutex_unlock(&q->sysfs_lock);
531527
}
532528
}
533529

@@ -590,44 +586,19 @@ int elevator_switch_mq(struct request_queue *q,
590586
lockdep_assert_held(&q->sysfs_lock);
591587

592588
if (q->elevator) {
593-
if (q->elevator->registered) {
594-
mutex_unlock(&q->sysfs_lock);
595-
596-
/*
597-
* Concurrent elevator switch can't happen becasue
598-
* sysfs write is always exclusively on same file.
599-
*
600-
* Also the elevator queue won't be freed after
601-
* sysfs_lock is released becasue kobject_del() in
602-
* blk_unregister_queue() waits for completion of
603-
* .store & .show on its attributes.
604-
*/
589+
if (q->elevator->registered)
605590
elv_unregister_queue(q);
606591

607-
mutex_lock(&q->sysfs_lock);
608-
}
609592
ioc_clear_queue(q);
610593
elevator_exit(q, q->elevator);
611-
612-
/*
613-
* sysfs_lock may be dropped, so re-check if queue is
614-
* unregistered. If yes, don't switch to new elevator
615-
* any more
616-
*/
617-
if (!blk_queue_registered(q))
618-
return 0;
619594
}
620595

621596
ret = blk_mq_init_sched(q, new_e);
622597
if (ret)
623598
goto out;
624599

625600
if (new_e) {
626-
mutex_unlock(&q->sysfs_lock);
627-
628601
ret = elv_register_queue(q, true);
629-
630-
mutex_lock(&q->sysfs_lock);
631602
if (ret) {
632603
elevator_exit(q, q->elevator);
633604
goto out;

0 commit comments

Comments
 (0)