Commit bce6133b authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

cfq-iosched: fix oom cfq_queue ref leak in cfq_set_request()

If the cfq_queue cached in cfq_io_cq is the oom one, cfq_set_request()
replaces it by invoking cfq_get_queue() again without putting the oom
queue leaking the reference it was holding.  While oom queues are not
released through reference counting, they're still reference counted
and this can theoretically lead to the reference count overflowing and
incorrectly invoke the usual release path on it.

Fix it by making cfq_set_request() put the ref it was holding.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarJeff Moyer <jmoyer@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Arianna Avanzini <avanzini.arianna@gmail.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 95e5d6f6
...@@ -4299,6 +4299,8 @@ cfq_set_request(struct request_queue *q, struct request *rq, struct bio *bio, ...@@ -4299,6 +4299,8 @@ cfq_set_request(struct request_queue *q, struct request *rq, struct bio *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) {
if (cfqq)
cfq_put_queue(cfqq);
cfqq = cfq_get_queue(cfqd, is_sync, cic, bio, gfp_mask); cfqq = cfq_get_queue(cfqd, is_sync, cic, bio, gfp_mask);
cic_set_cfqq(cic, cfqq, is_sync); cic_set_cfqq(cic, cfqq, is_sync);
} else { } else {
......
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