Async block read


 fs/buffer.c                 |   27 ++++++++++++++++++++++++---
 include/linux/buffer_head.h |   13 ++++++++++---
 2 files changed, 34 insertions(+), 6 deletions(-)

diff -puN fs/buffer.c~aio-06-bread_wq fs/buffer.c
--- 25/fs/buffer.c~aio-06-bread_wq	2003-08-30 15:42:26.000000000 -0700
+++ 25-akpm/fs/buffer.c	2003-08-30 15:42:26.000000000 -0700
@@ -1319,9 +1319,12 @@ void __bforget(struct buffer_head *bh)
 	__brelse(bh);
 }
 
-static struct buffer_head *__bread_slow(struct buffer_head *bh)
+static struct buffer_head *__bread_slow_wq(struct buffer_head *bh,
+		wait_queue_t *wait)
 {
-	lock_buffer(bh);
+	if (-EIOCBRETRY == lock_buffer_wq(bh, wait))
+		return ERR_PTR(-EIOCBRETRY);
+
 	if (buffer_uptodate(bh)) {
 		unlock_buffer(bh);
 		return bh;
@@ -1331,7 +1334,8 @@ static struct buffer_head *__bread_slow(
 		get_bh(bh);
 		bh->b_end_io = end_buffer_read_sync;
 		submit_bh(READ, bh);
-		wait_on_buffer(bh);
+		if (-EIOCBRETRY == wait_on_buffer_wq(bh, wait))
+			return ERR_PTR(-EIOCBRETRY);
 		if (buffer_uptodate(bh))
 			return bh;
 	}
@@ -1339,6 +1343,11 @@ static struct buffer_head *__bread_slow(
 	return NULL;
 }
 
+static inline struct buffer_head *__bread_slow(struct buffer_head *bh)
+{
+	return __bread_slow_wq(bh, NULL);
+}
+
 /*
  * Per-cpu buffer LRU implementation.  To reduce the cost of __find_get_block().
  * The bhs[] array is sorted - newest buffer is at bhs[0].  Buffers have their
@@ -1524,6 +1533,18 @@ __bread(struct block_device *bdev, secto
 		bh = __bread_slow(bh);
 	return bh;
 }
+
+
+struct buffer_head *
+__bread_wq(struct block_device *bdev, sector_t block, int size,
+	wait_queue_t *wait)
+{
+	struct buffer_head *bh = __getblk(bdev, block, size);
+
+	if (!buffer_uptodate(bh))
+		bh = __bread_slow_wq(bh, wait);
+	return bh;
+}
 EXPORT_SYMBOL(__bread);
 
 /*
diff -puN include/linux/buffer_head.h~aio-06-bread_wq include/linux/buffer_head.h
--- 25/include/linux/buffer_head.h~aio-06-bread_wq	2003-08-30 15:42:26.000000000 -0700
+++ 25-akpm/include/linux/buffer_head.h	2003-08-30 15:42:26.000000000 -0700
@@ -174,6 +174,8 @@ void __brelse(struct buffer_head *);
 void __bforget(struct buffer_head *);
 void __breadahead(struct block_device *, sector_t block, int size);
 struct buffer_head *__bread(struct block_device *, sector_t block, int size);
+struct buffer_head *__bread_wq(struct block_device *, sector_t block,
+	int size, wait_queue_t *wait);
 struct buffer_head *alloc_buffer_head(int gfp_flags);
 void free_buffer_head(struct buffer_head * bh);
 void FASTCALL(unlock_buffer(struct buffer_head *bh));
@@ -231,13 +233,13 @@ static inline void put_bh(struct buffer_
 
 static inline void brelse(struct buffer_head *bh)
 {
-	if (bh)
+	if (bh && !IS_ERR(bh))
 		__brelse(bh);
 }
 
 static inline void bforget(struct buffer_head *bh)
 {
-	if (bh)
+	if (bh && !IS_ERR(bh))
 		__bforget(bh);
 }
 
@@ -254,7 +256,12 @@ sb_breadahead(struct super_block *sb, se
 }
 
 static inline struct buffer_head *
-sb_getblk(struct super_block *sb, sector_t block)
+sb_bread_wq(struct super_block *sb, sector_t block, wait_queue_t *wait)
+{
+	return __bread_wq(sb->s_bdev, block, sb->s_blocksize, wait);
+}
+
+static inline struct buffer_head *sb_getblk(struct super_block *sb, sector_t block)
 {
 	return __getblk(sb->s_bdev, block, sb->s_blocksize);
 }

_