From: Chuck Lever <cel@citi.umich.edu>

hi trond, andrew-

as you know, the original idea for NFS O_DIRECT in the 2.5 kernel involved
issuing RPCs asynchronously to provide better request execution
concurrency on large reads and writes.  the NFS client in 2.5 relies on
page locking to handle I/O completion waits, which has a bevy of problems
with respect to direct I/O.  as the priority for the 2.5 NFS client is
completing the NFSv4 implementation, it appears unlikely that we will have
a reasonable I/O completion architecture until the next kernel development
cycle.

so i've backed away from support for issuing RPCs asynchronously in NFS
O_DIRECT for 2.5.  here is a synchronous implementation that works pretty
much like the 2.4 version.  this version also works over NFSv4, and uses
no request alignment restrictions.

the patches i'm sending today are for your review.  these compile with no
warnings, with and without NFSv4 support.  the changes to the read and
write procs have been tested with connectathon for NFSv2 and NFSv3 using
small rsize and wsize (with NFSv4, at least the basic tests pass).  i've 
done minimal testing of this O_DIRECT implementation, enough to be fairly 
confident that there are no architectural problems with it.

these are against 2.5.71, but probably go smoothly on 2.5.72 as well.

the first patch removes a couple of routines from pagelist.c that were 
added to support issuing RPCs asynchronously in the direct I/O code.  they 
are no longer needed for the synchronous direct I/O implementation.




 fs/nfs/direct.c          |    2 -
 fs/nfs/pagelist.c        |   51 -----------------------------------------------
 include/linux/nfs_page.h |    2 -
 3 files changed, 55 deletions(-)

diff -puN fs/nfs/direct.c~nfs-O_DIRECT-remove-async-cruft fs/nfs/direct.c
--- 25/fs/nfs/direct.c~nfs-O_DIRECT-remove-async-cruft	2003-06-17 16:00:18.000000000 -0700
+++ 25-akpm/fs/nfs/direct.c	2003-06-17 16:00:18.000000000 -0700
@@ -123,7 +123,6 @@ nfs_iov2pagelist(int rw, const struct in
 
 		page_count = nfs_get_user_pages(user_addr, bytes, &pages, rw);
 		if (page_count < 0) {
-			nfs_release_list(requests);
 			return page_count;
 		}
 
@@ -201,7 +200,6 @@ do_nfs_direct_IO(int rw, const struct in
 			break;
 		}
 		result = nfs_pagein_list(&requests, NFS_SERVER(inode)->rpages);
-		nfs_wait_for_reads(&requests);
 		break;
 	case WRITE:
 		if (IS_SYNC(inode) || (NFS_SERVER(inode)->wsize < PAGE_SIZE))
diff -puN fs/nfs/pagelist.c~nfs-O_DIRECT-remove-async-cruft fs/nfs/pagelist.c
--- 25/fs/nfs/pagelist.c~nfs-O_DIRECT-remove-async-cruft	2003-06-17 16:00:18.000000000 -0700
+++ 25-akpm/fs/nfs/pagelist.c	2003-06-17 16:00:18.000000000 -0700
@@ -154,26 +154,6 @@ nfs_release_request(struct nfs_page *req
 }
 
 /**
- * nfs_release_list - cleanly dispose of an unattached list of page requests
- * @list: list of doomed page requests
- */
-void
-nfs_release_list(struct list_head *list)
-{
-	while (!list_empty(list)) {
-		struct nfs_page *req = nfs_list_entry(list);
-
-		nfs_list_remove_request(req);
-
-		page_cache_release(req->wb_page);
-
-		/* Release struct file or cached credential */
-		nfs_clear_request(req);
-		nfs_page_free(req);
-	}
-}
-
-/**
  * nfs_list_add_request - Insert a request into a sorted list
  * @req: request
  * @head: head of list into which to insert the request.
@@ -222,37 +202,6 @@ nfs_wait_on_request(struct nfs_page *req
 }
 
 /**
- * nfs_wait_for_reads - wait for outstanding requests to complete
- * @head: list of page requests to wait for
- */
-int
-nfs_wait_for_reads(struct list_head *head)
-{
-	struct list_head *p = head->next;
-	unsigned int res = 0;
-
-	while (p != head) {
-		struct nfs_page *req = nfs_list_entry(p);
-		int error;
-
-		if (!NFS_WBACK_BUSY(req))
-			continue;
-
-		req->wb_count++;
-		error = nfs_wait_on_request(req);
-		if (error < 0)
-			return error;
-		nfs_list_remove_request(req);
-		nfs_clear_request(req);
-		nfs_page_free(req);
-
-		p = head->next;
-		res++;
-	}
-	return res;
-}
-
-/**
  * nfs_coalesce_requests - Split coalesced requests out from a list.
  * @head: source list
  * @dst: destination list
diff -puN include/linux/nfs_page.h~nfs-O_DIRECT-remove-async-cruft include/linux/nfs_page.h
--- 25/include/linux/nfs_page.h~nfs-O_DIRECT-remove-async-cruft	2003-06-17 16:00:18.000000000 -0700
+++ 25-akpm/include/linux/nfs_page.h	2003-06-17 16:00:18.000000000 -0700
@@ -46,7 +46,6 @@ extern	struct nfs_page *nfs_create_reque
 					    unsigned int, unsigned int);
 extern	void nfs_clear_request(struct nfs_page *req);
 extern	void nfs_release_request(struct nfs_page *req);
-extern	void nfs_release_list(struct list_head *list);
 
 
 extern	void nfs_list_add_request(struct nfs_page *, struct list_head *);
@@ -56,7 +55,6 @@ extern	int nfs_scan_list(struct list_hea
 extern	int nfs_coalesce_requests(struct list_head *, struct list_head *,
 				  unsigned int);
 extern  int nfs_wait_on_request(struct nfs_page *);
-extern	int nfs_wait_for_reads(struct list_head *);
 
 extern	spinlock_t nfs_wreq_lock;
 

_