Skip to content

Commit

Permalink
mmc: Flush block queue when removing card
Browse files Browse the repository at this point in the history
After mmc_block's remove function has exited, we must not
touch the card structure in any way. This means we not only
must remove the gendisk, we must also flush out any
remaning requests already queued up.

We previously removed the disk, but didn't flush it,
causing oops:es when removing a card in the middle of a
transfer.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
  • Loading branch information
Pierre Ossman committed Dec 1, 2006
1 parent 077df88 commit 89b4e13
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 5 deletions.
8 changes: 3 additions & 5 deletions drivers/mmc/mmc_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ static void mmc_blk_put(struct mmc_blk_data *md)
md->usage--;
if (md->usage == 0) {
put_disk(md->disk);
mmc_cleanup_queue(&md->queue);
kfree(md);
}
mutex_unlock(&open_lock);
Expand Down Expand Up @@ -553,12 +552,11 @@ static void mmc_blk_remove(struct mmc_card *card)
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);
Expand Down
22 changes: 22 additions & 0 deletions drivers/mmc/mmc_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,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_process(mq->thread);
Expand Down Expand Up @@ -168,6 +181,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 */
kthread_stop(mq->thread);

kfree(mq->sg);
Expand Down

0 comments on commit 89b4e13

Please sign in to comment.