Comments
Patch
From 8ccee6132f376d78bb6e355016ecc06c9ca47b9f Mon Sep 17 00:00:00 2001
From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Tue, 3 Nov 2009 09:48:00 +0200
Subject: [PATCH] block: Move elevator exit from blk_cleanup_queue() to blk_release_queue()
If block_cleanup_queue() should not remove elevator if it is still
in use. Better call the elevator exit in blk_release_queue() when
all the reference to queue are gone. Since drivers could use queue
locks which are freed after returning from blk_cleanup_queue(),
switch the queue lock to internal one.
Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
block/blk-core.c | 8 ++++++--
block/blk-sysfs.c | 3 +++
2 files changed, 9 insertions(+), 2 deletions(-)
@@ -449,6 +449,8 @@ void blk_put_queue(struct request_queue *q)
void blk_cleanup_queue(struct request_queue *q)
{
+ spinlock_t *oldlock;
+
/*
* We know we have process context here, so we can be a little
* cautious and ensure that pending block actions on this device
@@ -461,8 +463,10 @@ void blk_cleanup_queue(struct request_queue *q)
queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q);
mutex_unlock(&q->sysfs_lock);
- if (q->elevator)
- elevator_exit(q->elevator);
+ oldlock = q->queue_lock;
+ spin_lock_irq(oldlock);
+ q->queue_lock = &q->__queue_lock;
+ spin_unlock_irq(oldlock);
blk_put_queue(q);
}
@@ -304,6 +304,9 @@ static void blk_release_queue(struct kobject *kobj)
container_of(kobj, struct request_queue, kobj);
struct request_list *rl = &q->rq;
+ if (q->elevator)
+ elevator_exit(q->elevator);
+
blk_sync_queue(q);
if (rl->rq_pool)
--
1.6.5