Bug#562892: linux-2.6: cfq-related oops
Package: linux-2.6
Version: 2.6.26-21
Severity: important
Tags: patch
Oops happens "while doing preparation for vzt-ss test
(just creating/starting
VEs, with continuous ps axf running in background if it matters): "
http://bugzilla.openvz.org/show_bug.cgi?id=1240
>From 1a6d795abc130bd356b10abbd91ef63ef23f01c4 Mon Sep 17 00:00:00 2001
From: Konstantin Khlebnikov <khlebnikov@openvz.org>
Date: Thu, 24 Dec 2009 20:58:15 +0300
Subject: [PATCH 88/90] cfq: unlink queues at bc destroy
Unlink cfq-queues from cfq-io-contexts at cfq-bc-data destroy and
always revalidate cached cfq-queues from cfq-io-context.
Should fix pdflush oops in cfq_set_request after container stop.
http://bugzilla.openvz.org/show_bug.cgi?id=1240
Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
block/cfq-iosched.c | 20 +++++---------------
kernel/bc/io_prio.c | 11 +++++++++++
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index b25b442..3a9992a 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2014,32 +2014,22 @@ cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
struct cfq_queue *cfqq;
unsigned long flags;
struct ub_iopriv *iopriv;
- struct cfq_bc_data *cfq_bc = NULL;
might_sleep_if(gfp_mask & __GFP_WAIT);
cic = cfq_get_io_context(cfqd, gfp_mask);
iopriv = cfqq_ub_iopriv(cfqd, is_sync);
- if (!is_sync)
- cfq_bc = bc_findcreate_cfq_bc(iopriv, cfqd, gfp_mask);
spin_lock_irqsave(q->queue_lock, flags);
- if (!cic || (!is_sync && cfq_bc == NULL))
+ if (!cic)
goto queue_fail;
cfqq = cic_to_cfqq(cic, is_sync);
- if (!cfqq) {
- cfqq = cfq_get_queue(cfqd, is_sync, cic->ioc, gfp_mask);
-
- if (!cfqq)
- goto queue_fail;
-
- cic_set_cfqq(cic, cfqq, is_sync);
- }
-
- if (!is_sync && cfqq->cfq_bc != cfq_bc) {
- cfq_put_queue(cfqq);
+ if (!cfqq || cfqq->cfq_bc->ub_iopriv != iopriv) {
+ if (cfqq)
+ cfq_put_queue(cfqq);
+ cic_set_cfqq(cic, NULL, is_sync);
cfqq = cfq_get_queue(cfqd, is_sync, cic->ioc, gfp_mask);
cic_set_cfqq(cic, cfqq, is_sync);
if (!cfqq)
diff --git a/kernel/bc/io_prio.c b/kernel/bc/io_prio.c
index 5bb22e5..4a1ee2e 100644
--- a/kernel/bc/io_prio.c
+++ b/kernel/bc/io_prio.c
@@ -88,6 +88,7 @@ static void inline bc_cfq_bc_check_empty(struct cfq_bc_data *cfq_bc)
static void bc_release_cfq_bc(struct cfq_bc_data *cfq_bc)
{
+ struct cfq_io_context *cic;
struct cfq_data *cfqd;
elevator_t *eq;
int i;
@@ -109,6 +110,16 @@ static void bc_release_cfq_bc(struct cfq_bc_data *cfq_bc)
eq->ops->put_queue(cfq_bc->async_idle_cfqq);
cfq_bc->async_idle_cfqq = NULL;
}
+ list_for_each_entry(cic, &cfqd->cic_list, queue_list) {
+ if (cic->cfqq[0] && cic->cfqq[0]->cfq_bc == cfq_bc) {
+ eq->ops->put_queue(cic->cfqq[0]);
+ cic->cfqq[0] = NULL;
+ }
+ if (cic->cfqq[1] && cic->cfqq[1]->cfq_bc == cfq_bc) {
+ eq->ops->put_queue(cic->cfqq[1]);
+ cic->cfqq[1] = NULL;
+ }
+ }
/*
* Note: this cfq_bc is already not in active list,
* but can be still pointed from cfqd as active.
--
1.6.5.7
-- System Information:
Debian Release: squeeze/sid
APT prefers testing
APT policy: (900, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Kernel: Linux 2.6.30-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Reply to: