summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2004-11-10 21:48:51 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-11-10 21:48:51 -0800
commit854d7a6fa60eaa67ef26fb0559b01a2cfb2fbcae (patch)
treead582816cb0ab8f4e41e6f061b0f17b0019c3656
parentc07e1a694d656d09179a76e3c74a35d1b6eab047 (diff)
[PATCH] md: delete unplug timer before shutting down md array
As the unplug timer can potentially fire at any time, and and it access data that is released by the md ->stop function, we need to del_timer_sync before releasing that data. (After much discussion, we created blk_sync_queue() for this) Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au> Contributions from Jens Axboe <axboe@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/block/ll_rw_blk.c26
-rw-r--r--drivers/md/linear.c1
-rw-r--r--drivers/md/multipath.c1
-rw-r--r--drivers/md/raid0.c1
-rw-r--r--drivers/md/raid1.c1
-rw-r--r--drivers/md/raid10.c1
-rw-r--r--drivers/md/raid5.c1
-rw-r--r--drivers/md/raid6main.c1
-rw-r--r--include/linux/blkdev.h1
9 files changed, 30 insertions, 4 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 12958fa9ea82..7aac17054084 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1357,10 +1357,30 @@ void blk_stop_queue(request_queue_t *q)
blk_remove_plug(q);
set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
}
-
EXPORT_SYMBOL(blk_stop_queue);
/**
+ * blk_sync_queue - cancel any pending callbacks on a queue
+ * @q: the queue
+ *
+ * Description:
+ * The block layer may perform asynchronous callback activity
+ * on a queue, such as calling the unplug function after a timeout.
+ * A block device may call blk_sync_queue to ensure that any
+ * such activity is cancelled, thus allowing it to release resources
+ * the the callbacks might use. The caller must already have made sure
+ * that its ->make_request_fn will not re-add plugging prior to calling
+ * this function.
+ *
+ */
+void blk_sync_queue(struct request_queue *q)
+{
+ del_timer_sync(&q->unplug_timer);
+ kblockd_flush();
+}
+EXPORT_SYMBOL(blk_sync_queue);
+
+/**
* blk_run_queue - run a single device queue
* @q: The queue to run
*/
@@ -1373,7 +1393,6 @@ void blk_run_queue(struct request_queue *q)
q->request_fn(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
-
EXPORT_SYMBOL(blk_run_queue);
/**
@@ -1401,8 +1420,7 @@ void blk_cleanup_queue(request_queue_t * q)
if (q->elevator)
elevator_exit(q->elevator);
- del_timer_sync(&q->unplug_timer);
- kblockd_flush();
+ blk_sync_queue(q);
if (rl->rq_pool)
mempool_destroy(rl->rq_pool);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 6fb445a5c4f4..09e32023083c 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -231,6 +231,7 @@ static int linear_stop (mddev_t *mddev)
{
linear_conf_t *conf = mddev_to_conf(mddev);
+ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf->hash_table);
kfree(conf);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index cbce9d22093e..309398219556 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -547,6 +547,7 @@ static int multipath_stop (mddev_t *mddev)
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
+ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
mempool_destroy(conf->pool);
kfree(conf->multipaths);
kfree(conf);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 76c59f160447..e7d934eca06f 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -385,6 +385,7 @@ static int raid0_stop (mddev_t *mddev)
{
raid0_conf_t *conf = mddev_to_conf(mddev);
+ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree (conf->hash_table);
conf->hash_table = NULL;
kfree (conf->strip_zone);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 6fc90e363644..4e25ebd53385 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1293,6 +1293,7 @@ static int stop(mddev_t *mddev)
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
+ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
if (conf->r1bio_pool)
mempool_destroy(conf->r1bio_pool);
if (conf->mirrors)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 9596358572e3..271566095306 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1744,6 +1744,7 @@ static int stop(mddev_t *mddev)
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
+ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool);
if (conf->mirrors)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 90dd9f8a596a..1dceb098a7fb 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1707,6 +1707,7 @@ static int stop (mddev_t *mddev)
mddev->thread = NULL;
shrink_stripes(conf);
free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
+ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf);
mddev->private = NULL;
return 0;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index ac588c53c3cb..9a27f8f88a91 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1878,6 +1878,7 @@ static int stop (mddev_t *mddev)
mddev->thread = NULL;
shrink_stripes(conf);
free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
+ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf);
mddev->private = NULL;
return 0;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index f04b0e223d82..1b7dc44bf3c1 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -522,6 +522,7 @@ extern int blk_hw_contig_segment(request_queue_t *q, struct bio *, struct bio *)
extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
extern void blk_start_queue(request_queue_t *q);
extern void blk_stop_queue(request_queue_t *q);
+extern void blk_sync_queue(struct request_queue *q);
extern void __blk_stop_queue(request_queue_t *q);
extern void blk_run_queue(request_queue_t *);
extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *);