From: Chuck Lever 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; _