
From: Neil Brown <neilb@cse.unsw.edu.au>

- Document blk_sync_queue and complete it's functionality.

- blk_sync_queue needs to call kblock_flush as the unplug function is not
  actually called by the timer, but rather by a work_queue that the timer
  triggers.

- Use blk_sync_queue to abstract identical functionality from
  blk_cleanup_queue.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/block/ll_rw_blk.c |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

diff -puN drivers/block/ll_rw_blk.c~blk_sync_queue-updates drivers/block/ll_rw_blk.c
--- 25/drivers/block/ll_rw_blk.c~blk_sync_queue-updates	Mon Nov  8 14:08:02 2004
+++ 25-akpm/drivers/block/ll_rw_blk.c	Mon Nov  8 14:08:02 2004
@@ -1361,12 +1361,21 @@ void blk_stop_queue(request_queue_t *q)
 EXPORT_SYMBOL(blk_stop_queue);
 
 /**
- * blk_sync_queue - prepare to destroy a queue
+ * blk_sync_queue - cancel any pending callbacks 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.
+ *
  */
 void blk_sync_queue(struct request_queue *q)
 {
 	del_timer_sync(&q->unplug_timer);
+	kblockd_flush();
 }
 EXPORT_SYMBOL(blk_sync_queue);
 
@@ -1410,8 +1419,7 @@ void blk_cleanup_queue(request_queue_t *
 	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);
_
