diff options
| author | Neil Brown <neilb@cse.unsw.edu.au> | 2004-11-10 21:48:51 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-11-10 21:48:51 -0800 |
| commit | 854d7a6fa60eaa67ef26fb0559b01a2cfb2fbcae (patch) | |
| tree | ad582816cb0ab8f4e41e6f061b0f17b0019c3656 | |
| parent | c07e1a694d656d09179a76e3c74a35d1b6eab047 (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.c | 26 | ||||
| -rw-r--r-- | drivers/md/linear.c | 1 | ||||
| -rw-r--r-- | drivers/md/multipath.c | 1 | ||||
| -rw-r--r-- | drivers/md/raid0.c | 1 | ||||
| -rw-r--r-- | drivers/md/raid1.c | 1 | ||||
| -rw-r--r-- | drivers/md/raid10.c | 1 | ||||
| -rw-r--r-- | drivers/md/raid5.c | 1 | ||||
| -rw-r--r-- | drivers/md/raid6main.c | 1 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 1 |
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 *); |
