From: Badari Pulavarty <pbadari@us.ibm.com>

I found one more accounting inconsistency with dio_pages_in_io.  This is a
day-one bug and I started hitting it on latest -mm due to the recent
changes to dio_pages_in_io calculations to be exact.

If the file is badly fragmented (no contiguous blocks at all), and the user
buffer is not page aligned - we need to create IO for each disk block with
2 pages.  (bio with 2 vecs).

dio_bio_add_page() should not decrement dio_pages_in_io for every add page.
 It should only decrement, it only if its done with that page and moving on
to next page.  (since dio_pages_in_io represent how many actual pages we
are operating on).  

Here is the patch to fix this accounting.  Without this patch, we will hit
BUG() in dio_new_bio() with O_DIRECT on filesystems.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/direct-io.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletion(-)

diff -puN fs/direct-io.c~dio-pages-in-io-accounting-fix fs/direct-io.c
--- 25/fs/direct-io.c~dio-pages-in-io-accounting-fix	2004-08-16 11:51:25.669776408 -0700
+++ 25-akpm/fs/direct-io.c	2004-08-16 11:51:25.673775800 -0700
@@ -561,7 +561,11 @@ static int dio_bio_add_page(struct dio *
 	ret = bio_add_page(dio->bio, dio->cur_page,
 			dio->cur_page_len, dio->cur_page_offset);
 	if (ret == dio->cur_page_len) {
-		dio->pages_in_io--;
+		/*
+		 * Decrement count only, if we are done with this page
+		 */
+		if ((dio->cur_page_len + dio->cur_page_offset) == PAGE_SIZE)
+			dio->pages_in_io--;
 		page_cache_get(dio->cur_page);
 		dio->final_block_in_bio = dio->cur_page_block +
 			(dio->cur_page_len >> dio->blkbits);
_