[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20080416185924.GP16584@beardog.cca.cpqcorp.net>
Date: Wed, 16 Apr 2008 13:59:24 -0500
From: scameron@...rdog.cca.cpqcorp.net
To: Jens Axboe <jens.axboe@...cle.com>
Cc: linux-kernel@...r.kernel.org, mike.miller@...com,
mikem@...rdog.cca.cpqcorp.net
Subject: Re: [patch] cciss: Fix race between disk-adding code and interrupt handler
Fix race condition between cciss_init_one(), cciss_update_drive_info(),
and cciss_check_queues().
Signed-off-by: Stephen M. Cameron <scameron@...rdog.cca.cpqcorp.net>
---
linux-2.6.25-rc9/drivers/block/cciss.c | 17 ++++++++++++++++-
drivers/block/cciss.h | 0
2 files changed, 16 insertions(+), 1 deletion(-)
diff -puN linux-2.6.25-rc9/drivers/block/cciss.c~cciss_init_one_race linux-2.6.25-rc9/drivers/block/cciss.c
--- linux-2.6.25-rc9/linux-2.6.25-rc9/drivers/block/cciss.c~cciss_init_one_race 2008-04-14 08:21:03.000000000 -0500
+++ linux-2.6.25-rc9-scameron/linux-2.6.25-rc9/drivers/block/cciss.c 2008-04-16 08:15:38.000000000 -0500
@@ -1349,6 +1349,10 @@ static void cciss_update_drive_info(int
spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
h->drv[drv_index].busy_configuring = 1;
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+
+ /* deregister_disk sets h->drv[drv_index].queue = NULL */
+ /* which keeps the interrupt handler from starting */
+ /* the queue. */
ret = deregister_disk(h->gendisk[drv_index],
&h->drv[drv_index], 0);
h->drv[drv_index].busy_configuring = 0;
@@ -1419,6 +1423,10 @@ geo_inq:
blk_queue_hardsect_size(disk->queue,
hba[ctlr]->drv[drv_index].block_size);
+ /* Make sure all queue data is written out before */
+ /* setting h->drv[drv_index].queue, as setting this */
+ /* allows the interrupt handler to start the queue */
+ wmb();
h->drv[drv_index].queue = disk->queue;
add_disk(disk);
}
@@ -3520,10 +3528,17 @@ static int __devinit cciss_init_one(stru
continue;
blk_queue_hardsect_size(q, drv->block_size);
set_capacity(disk, drv->nr_blocks);
- add_disk(disk);
j++;
} while (j <= hba[i]->highest_lun);
+ /* Make sure all queue data is written out before */
+ /* interrupt handler, triggered by add_disk, */
+ /* is allowed to start them. */
+ wmb();
+
+ for (j = 0; j <= hba[i]->highest_lun; j++)
+ add_disk(hba[i]->gendisk[j]);
+
return 1;
clean4:
diff -puN linux-2.6.25-rc9/drivers/block/cciss.h~cciss_init_one_race linux-2.6.25-rc9/drivers/block/cciss.h
_
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists