Commit 5d7f5ce1 authored by Jens Axboe's avatar Jens Axboe

cfq-iosched: don't call wbt_disable_default() with IRQs disabled

wbt_disable_default() calls del_timer_sync() to wait for the wbt
timer to finish before disabling throttling. We can't do this with
IRQs disable. This fixes a lockdep splat on boot, if non-root
cgroups are used.
Reported-by: default avatarGabriel C <nix.or.die@gmail.com>
Fixes: 87760e5e ("block: hook up writeback throttling")
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent eeeefd41
...@@ -3758,7 +3758,7 @@ static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq, ...@@ -3758,7 +3758,7 @@ static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
} }
#ifdef CONFIG_CFQ_GROUP_IOSCHED #ifdef CONFIG_CFQ_GROUP_IOSCHED
static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio) static bool check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
{ {
struct cfq_data *cfqd = cic_to_cfqd(cic); struct cfq_data *cfqd = cic_to_cfqd(cic);
struct cfq_queue *cfqq; struct cfq_queue *cfqq;
...@@ -3775,15 +3775,7 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio) ...@@ -3775,15 +3775,7 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
* spuriously on a newly created cic but there's no harm. * spuriously on a newly created cic but there's no harm.
*/ */
if (unlikely(!cfqd) || likely(cic->blkcg_serial_nr == serial_nr)) if (unlikely(!cfqd) || likely(cic->blkcg_serial_nr == serial_nr))
return; return nonroot_cg;
/*
* If we have a non-root cgroup, we can depend on that to
* do proper throttling of writes. Turn off wbt for that
* case, if it was enabled by default.
*/
if (nonroot_cg)
wbt_disable_default(cfqd->queue);
/* /*
* Drop reference to queues. New queues will be assigned in new * Drop reference to queues. New queues will be assigned in new
...@@ -3804,9 +3796,13 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio) ...@@ -3804,9 +3796,13 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
} }
cic->blkcg_serial_nr = serial_nr; cic->blkcg_serial_nr = serial_nr;
return nonroot_cg;
} }
#else #else
static inline void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio) { } static inline bool check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
{
return false;
}
#endif /* CONFIG_CFQ_GROUP_IOSCHED */ #endif /* CONFIG_CFQ_GROUP_IOSCHED */
static struct cfq_queue ** static struct cfq_queue **
...@@ -4448,11 +4444,12 @@ cfq_set_request(struct request_queue *q, struct request *rq, struct bio *bio, ...@@ -4448,11 +4444,12 @@ cfq_set_request(struct request_queue *q, struct request *rq, struct bio *bio,
const int rw = rq_data_dir(rq); const int rw = rq_data_dir(rq);
const bool is_sync = rq_is_sync(rq); const bool is_sync = rq_is_sync(rq);
struct cfq_queue *cfqq; struct cfq_queue *cfqq;
bool disable_wbt;
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
check_ioprio_changed(cic, bio); check_ioprio_changed(cic, bio);
check_blkcg_changed(cic, bio); disable_wbt = check_blkcg_changed(cic, bio);
new_queue: new_queue:
cfqq = cic_to_cfqq(cic, is_sync); cfqq = cic_to_cfqq(cic, is_sync);
if (!cfqq || cfqq == &cfqd->oom_cfqq) { if (!cfqq || cfqq == &cfqd->oom_cfqq) {
...@@ -4488,6 +4485,10 @@ cfq_set_request(struct request_queue *q, struct request *rq, struct bio *bio, ...@@ -4488,6 +4485,10 @@ cfq_set_request(struct request_queue *q, struct request *rq, struct bio *bio,
rq->elv.priv[0] = cfqq; rq->elv.priv[0] = cfqq;
rq->elv.priv[1] = cfqq->cfqg; rq->elv.priv[1] = cfqq->cfqg;
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
if (disable_wbt)
wbt_disable_default(q);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment