NFS: Simplify O_DIRECT page referencing

The O_DIRECT code shouldn't need to hold 2 references to each page. The
reference held by the struct nfs_page should suffice.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: Fred Isaman <iisaman@netapp.com>
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index af02bde..78d1ead 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -268,10 +268,9 @@
 			}
 			bytes += req->wb_bytes;
 			nfs_list_remove_request(req);
-			nfs_direct_readpage_release(req);
 			if (!PageCompound(page))
 				set_page_dirty(page);
-			page_cache_release(page);
+			nfs_direct_readpage_release(req);
 		}
 	} else {
 		while (!list_empty(&hdr->pages)) {
@@ -281,7 +280,6 @@
 				if (!PageCompound(req->wb_page))
 					set_page_dirty(req->wb_page);
 			bytes += req->wb_bytes;
-			page_cache_release(req->wb_page);
 			nfs_list_remove_request(req);
 			nfs_direct_readpage_release(req);
 		}
@@ -375,8 +373,6 @@
 						 pagevec[i],
 						 pgbase, req_len);
 			if (IS_ERR(req)) {
-				nfs_direct_release_pages(pagevec + i,
-							 npages - i);
 				result = PTR_ERR(req);
 				break;
 			}
@@ -385,8 +381,6 @@
 			if (!nfs_pageio_add_request(desc, req)) {
 				result = desc->pg_error;
 				nfs_release_request(req);
-				nfs_direct_release_pages(pagevec + i,
-							 npages - i);
 				break;
 			}
 			pgbase = 0;
@@ -396,6 +390,8 @@
 			pos += req_len;
 			count -= req_len;
 		}
+		/* The nfs_page now hold references to these pages */
+		nfs_direct_release_pages(pagevec, npages);
 	} while (count != 0 && result >= 0);
 
 	kfree(pagevec);
@@ -509,7 +505,6 @@
 	nfs_pageio_complete(&desc);
 
 	while (!list_empty(&failed)) {
-		page_cache_release(req->wb_page);
 		nfs_release_request(req);
 		nfs_unlock_request(req);
 	}
@@ -542,10 +537,8 @@
 		if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) {
 			/* Note the rewrite will go through mds */
 			nfs_mark_request_commit(req, NULL, &cinfo);
-		} else {
-			page_cache_release(req->wb_page);
+		} else
 			nfs_release_request(req);
-		}
 		nfs_unlock_request(req);
 	}
 
@@ -678,8 +671,6 @@
 						 pagevec[i],
 						 pgbase, req_len);
 			if (IS_ERR(req)) {
-				nfs_direct_release_pages(pagevec + i,
-							 npages - i);
 				result = PTR_ERR(req);
 				break;
 			}
@@ -690,8 +681,6 @@
 				result = desc->pg_error;
 				nfs_unlock_request(req);
 				nfs_release_request(req);
-				nfs_direct_release_pages(pagevec + i,
-							 npages - i);
 				break;
 			}
 			pgbase = 0;
@@ -701,6 +690,8 @@
 			pos += req_len;
 			count -= req_len;
 		}
+		/* The nfs_page now hold references to these pages */
+		nfs_direct_release_pages(pagevec, npages);
 	} while (count != 0 && result >= 0);
 
 	kfree(pagevec);
@@ -763,7 +754,6 @@
 			nfs_mark_request_commit(req, hdr->lseg, &cinfo);
 			break;
 		default:
-			page_cache_release(req->wb_page);
 			nfs_release_request(req);
 		}
 		nfs_unlock_request(req);