Async buffer wait


 25-akpm/fs/buffer.c                 |   20 ++++++++++++++++----
 25-akpm/include/linux/buffer_head.h |   17 +++++++++++++++++
 2 files changed, 33 insertions(+), 4 deletions(-)

diff -puN fs/buffer.c~aio-04-buffer_wq fs/buffer.c
--- 25/fs/buffer.c~aio-04-buffer_wq	Fri May 16 16:29:34 2003
+++ 25-akpm/fs/buffer.c	Fri May 16 16:29:34 2003
@@ -118,23 +118,35 @@ void unlock_buffer(struct buffer_head *b
  * from becoming locked again - you have to lock it yourself
  * if you want to preserve its state.
  */
-void __wait_on_buffer(struct buffer_head * bh)
+int __wait_on_buffer_wq(struct buffer_head * bh, wait_queue_t *wait)
 {
 	wait_queue_head_t *wqh = bh_waitq_head(bh);
-	DEFINE_WAIT(wait);
+	DEFINE_WAIT(local_wait);
+
+	if (!wait)
+		wait = &local_wait;
 
 	if (atomic_read(&bh->b_count) == 0 &&
 			(!bh->b_page || !PageLocked(bh->b_page)))
 		buffer_error();
 
 	do {
-		prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(wqh, wait, TASK_UNINTERRUPTIBLE);
 		if (buffer_locked(bh)) {
 			blk_run_queues();
+			if (!is_sync_wait(wait)) {
+				return -EIOCBRETRY;
+			}
 			io_schedule();
 		}
 	} while (buffer_locked(bh));
-	finish_wait(wqh, &wait);
+	finish_wait(wqh, wait);
+	return 0;
+}
+
+void __wait_on_buffer(struct buffer_head * bh)
+{
+	__wait_on_buffer_wq(bh, NULL);
 }
 
 static void
diff -puN include/linux/buffer_head.h~aio-04-buffer_wq include/linux/buffer_head.h
--- 25/include/linux/buffer_head.h~aio-04-buffer_wq	Fri May 16 16:29:34 2003
+++ 25-akpm/include/linux/buffer_head.h	Fri May 16 16:29:34 2003
@@ -158,6 +158,7 @@ void mark_buffer_async_write(struct buff
 void invalidate_bdev(struct block_device *, int);
 int sync_blockdev(struct block_device *bdev);
 void __wait_on_buffer(struct buffer_head *);
+int __wait_on_buffer_wq(struct buffer_head *, wait_queue_t *wait);
 wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
 void wake_up_buffer(struct buffer_head *bh);
 int fsync_bdev(struct block_device *);
@@ -272,10 +273,26 @@ static inline void wait_on_buffer(struct
 		__wait_on_buffer(bh);
 }
 
+static inline int wait_on_buffer_wq(struct buffer_head *bh, wait_queue_t *wait)
+{
+	if (buffer_locked(bh))
+		return __wait_on_buffer_wq(bh, wait);
+
+	return 0;
+}
+
 static inline void lock_buffer(struct buffer_head *bh)
 {
 	while (test_set_buffer_locked(bh))
 		__wait_on_buffer(bh);
 }
 
+static inline int lock_buffer_wq(struct buffer_head *bh, wait_queue_t *wait)
+{
+	if (test_set_buffer_locked(bh))
+		return __wait_on_buffer_wq(bh, wait);
+
+	return 0;
+}
+
 #endif /* _LINUX_BUFFER_HEAD_H */

_