summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-01-14 09:14:33 +1100
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-17 14:47:24 -0800
commit7896fe54a75c5bfd8dfed08d98cb7e15896e3749 (patch)
treee692ce100e27855167290a8c0c96d0ebba9fdd4f /drivers
parenta53775f3a5b7cfdca47560285bf87616a808f25b (diff)
md: Ensure no IO request to get md device before it is properly initialised.
commit 0ca69886a8273ac1350143d562280bfcbe4760dc upstream. When an md device is in the process of coming on line it is possible for an IO request (typically a partition table probe) to get through before the array is fully initialised, which can cause unexpected behaviour (e.g. a crash). So explicitly record when the array is ready for IO and don't allow IO through until then. There is no possibility for a similar problem when the array is going off-line as there must only be one 'open' at that time, and it is busy off-lining the array and so cannot send IO requests. So no memory barrier is needed in md_stop() This has been a bug since commit 409c57f3801 in 2.6.30 which introduced md_make_request. Before then, each personality would register its own make_request_fn when it was ready. This is suitable for any stable kernel from 2.6.30.y onwards. Signed-off-by: NeilBrown <neilb@suse.de> Reported-by: "Hawrylewicz Czarnowski, Przemyslaw" <przemyslaw.hawrylewicz.czarnowski@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/md.c8
-rw-r--r--drivers/md/md.h3
2 files changed, 8 insertions, 3 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3b0e10ce9fa5..94bb484973a3 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -221,10 +221,12 @@ static int md_make_request(struct request_queue *q, struct bio *bio)
int rv;
int cpu;
- if (mddev == NULL || mddev->pers == NULL) {
+ if (mddev == NULL || mddev->pers == NULL
+ || !mddev->ready) {
bio_io_error(bio);
return 0;
}
+ smp_rmb(); /* Ensure implications of 'active' are visible */
rcu_read_lock();
if (mddev->suspended || mddev->barrier) {
DEFINE_WAIT(__wait);
@@ -4554,7 +4556,8 @@ int md_run(mddev_t *mddev)
mddev->safemode_timer.data = (unsigned long) mddev;
mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
mddev->in_sync = 1;
-
+ smp_wmb();
+ mddev->ready = 1;
list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0) {
char nm[20];
@@ -4716,6 +4719,7 @@ EXPORT_SYMBOL_GPL(md_stop_writes);
void md_stop(mddev_t *mddev)
{
+ mddev->ready = 0;
mddev->pers->stop(mddev);
if (mddev->pers->sync_request && mddev->to_remove == NULL)
mddev->to_remove = &md_redundancy_group;
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 3931299788dc..563ede31d5fc 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -149,7 +149,8 @@ struct mddev_s
* are happening, so run/
* takeover/stop are not safe
*/
-
+ int ready; /* See when safe to pass
+ * IO requests down */
struct gendisk *gendisk;
struct kobject kobj;