Ensure the queue is flushed when destroying the mmc block device

Pierre Ossman drzeus-list at drzeus.unroutablecx
Thu Nov 16 11:15:25 EST 2006


Commit:     9f9151dbc02eb20bc5b1485f62867821f20fa4a2
Parent:     bc0b9a38bcd71cef7cb013b8593d80f2f54c924a
commit 9f9151dbc02eb20bc5b1485f62867821f20fa4a2
Author:     Pierre Ossman <drzeus-list at drzeus.cx>
AuthorDate: Thu Nov 16 11:19:13 2006 -0500
Commit:     Andres Salomon <dilinger at debian.org>
CommitDate: Thu Nov 16 11:19:13 2006 -0500

    Ensure the queue is flushed when destroying the mmc block device
    
    Signed-off-by: Andres Salomon <dilinger at debian.org>
---
 drivers/mmc/mmc_block.c |   15 ++++++---------
 drivers/mmc/mmc_queue.c |   22 ++++++++++++++++++++++
 2 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 0ea0e92..8939b8d 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -83,7 +83,6 @@ static void mmc_blk_put(struct mmc_blk_d
 	md->usage--;
 	if (md->usage == 0) {
 		put_disk(md->disk);
-		mmc_cleanup_queue(&md->queue);
 		kfree(md);
 	}
 	mutex_unlock(&open_lock);
@@ -225,10 +224,10 @@ static int mmc_blk_issue_rq(struct mmc_q
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	struct mmc_blk_request brq;
-	int ret;
+	int ret = 1;
 
 	if (mmc_card_claim_host(card))
-		goto cmd_err;
+		goto flush_queue;
 
 	do {
 		struct mmc_command cmd;
@@ -350,8 +349,6 @@ #endif
 	return 1;
 
  cmd_err:
-	ret = 1;
-
  	/*
  	 * If this is an SD card and we're writing, we can first
  	 * mark the known good sectors as ok.
@@ -385,6 +382,7 @@ #endif
 
 	mmc_card_release_host(card);
 
+flush_queue:
 	spin_lock_irq(&md->lock);
 	while (ret) {
 		ret = end_that_request_chunk(req, 0,
@@ -558,12 +556,11 @@ static void mmc_blk_remove(struct mmc_ca
 	if (md) {
 		int devidx;
 
+		/* Stop new requests from getting into the queue */
 		del_gendisk(md->disk);
 
-		/*
-		 * I think this is needed.
-		 */
-		md->disk->queue = NULL;
+		/* Then flush out any already in there */
+		mmc_cleanup_queue(&md->queue);
 
 		devidx = md->disk->first_minor >> MMC_SHIFT;
 		__clear_bit(devidx, dev_use);
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index 4ccdd82..b6769e2 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -111,6 +111,19 @@ static int mmc_queue_thread(void *d)
 static void mmc_request(request_queue_t *q)
 {
 	struct mmc_queue *mq = q->queuedata;
+	struct request *req;
+	int ret;
+
+	if (!mq) {
+		printk(KERN_ERR "MMC: killing requests for dead queue\n");
+		while ((req = elv_next_request(q)) != NULL) {
+			do {
+				ret = end_that_request_chunk(req, 0,
+					req->current_nr_sectors << 9);
+			} while (ret);
+		}
+		return;
+	}
 
 	if (!mq->req)
 		wake_up(&mq->thread_wq);
@@ -179,6 +192,15 @@ EXPORT_SYMBOL(mmc_init_queue);
 
 void mmc_cleanup_queue(struct mmc_queue *mq)
 {
+	request_queue_t *q = mq->queue;
+	unsigned long flags;
+
+	/* Mark that we should start throwing out stragglers */
+	spin_lock_irqsave(q->queue_lock, flags);
+	q->queuedata = NULL;
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	/* Then terminate our worker thread */
 	mq->flags |= MMC_QUEUE_EXIT;
 	wake_up(&mq->thread_wq);
 	wait_for_completion(&mq->thread_complete);


More information about the Commits-kernel mailing list