patch-2.1.129 linux/fs/nfs/write.c

Next file: linux/fs/open.c
Previous file: linux/fs/nfs/read.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.128/linux/fs/nfs/write.c linux/fs/nfs/write.c
@@ -46,7 +46,6 @@
  * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/malloc.h>
 #include <linux/swap.h>
@@ -332,8 +331,6 @@
 	wreq->wb_bytes  = bytes;
 	wreq->wb_count	= 2;		/* One for the IO, one for us */
 
-	atomic_inc(&page->count);
-
 	append_write_request(&NFS_WRITEBACK(inode), wreq);
 
 	if (nr_write_requests++ > NFS_WRITEBACK_MAX*3/4)
@@ -480,8 +477,7 @@
 
 	/*
 	 * Ok, there's another user of this page with the new request..
-	 * Increment the usage count, and schedule the request (the
-	 * end of the request will drop the usage count..)
+	 * The IO completion will then free the page.
 	 */
 	atomic_inc(&page->count);
 
@@ -546,65 +542,101 @@
 }
 
 /*
- * Try to flush any dirty pages, returning a success marker..
- *
- * Unlike "nfs_flush_dirty_pages()" this does not invalidate
- * the writes if it is interrupted. The caller will instead
- * look at the error code and gracefully fail to do what it
- * wanted to do. 
+ * If we're waiting on somebody else's request
+ * we need to increment the counter during the
+ * wait so that the request doesn't disappear
+ * from under us during the wait..
  */
-int
-nfs_flush_pages(struct inode *inode, pid_t pid, off_t offset, off_t len)
+static int FASTCALL(wait_on_other_req(struct nfs_wreq *));
+static int wait_on_other_req(struct nfs_wreq *req)
 {
 	int retval;
+	req->wb_count++;
+	retval = wait_on_write_request(req);
+	free_write_request(req);
+	return retval;
+}
 
-	do {
-		struct nfs_wreq *req = NFS_WRITEBACK(inode);
-		struct nfs_wreq *head = req;
+/*
+ * This writes back a set of requests according to the condition.
+ *
+ * If this ever gets much more convoluted, use a fn pointer for
+ * the condition..
+ */
+#define NFS_WB(inode, cond) { int retval = 0 ; \
+	do { \
+		struct nfs_wreq *req = NFS_WRITEBACK(inode); \
+		struct nfs_wreq *head = req; \
+		if (!req) break; \
+		for (;;) { \
+			if (!(req->wb_flags & NFS_WRITE_COMPLETE)) \
+				if (cond) break; \
+			req = WB_NEXT(req); \
+			if (req == head) goto out; \
+		} \
+		retval = wait_on_other_req(req); \
+	} while (!retval); \
+out:	return retval; \
+}
 
-		if (!req)
-			return 0;
+int
+nfs_wb_all(struct inode *inode)
+{
+	NFS_WB(inode, 1);
+}
 
-		/*
-		 * Iterate over all outstanding write requests,
-		 * looking for any that are ours..
-		 */
-		for (;;) {
-			if (!(req->wb_flags & NFS_WRITE_COMPLETE)) {
-				if (!pid || req->wb_pid == pid)
-					break;
-			}
-			req = WB_NEXT(req);
-			if (req == head)
-				return 0;
-		}
+/*
+ * Write back all requests on one page - we do this before reading it.
+ */
+int
+nfs_wb_page(struct inode *inode, struct page *page)
+{
+	NFS_WB(inode, req->wb_page == page);
+}
 
-		req->wb_count++;
-		retval = wait_on_write_request(req);
-		free_write_request(req);
-	} while (!retval);
-	return retval;
-}	
+/*
+ * Write back all pending writes for one user.. 
+ */
+int
+nfs_wb_pid(struct inode *inode, pid_t pid)
+{
+	NFS_WB(inode, req->wb_pid == pid);
+}
 
 /*
- * Flush out all dirty pages belonging to a certain user process and
- * maybe wait for the RPC calls to complete.
- *
- * Another purpose of this function is sync()ing a file range before a
- * write lock is released. This is what offset and length are for, even if
- * this isn't used by the nlm module yet.
+ * Write back everything in a specific area for locking purposes..
  */
 int
-nfs_flush_dirty_pages(struct inode *inode, pid_t pid, off_t offset, off_t len)
+nfs_wb_area(struct inode *inode, off_t offset, off_t len)
+{
+	NFS_WB(inode, 1);
+}
+
+/*
+ * Write back and invalidate. Sometimes we can't leave the stuff
+ * hanging if we can't write it out.
+ */
+int
+nfs_wbinval(struct inode *inode)
+{
+	int retval = nfs_wb_all(inode);
+
+	if (retval)
+		nfs_cancel_dirty(inode,0);
+	return retval;
+}
+
+int nfs_wbinval_pid(struct inode *inode, pid_t pid)
 {
-	int retval = nfs_flush_pages(inode, pid, offset, len);
+	int retval = nfs_wb_pid(inode, pid);
+	
 	if (retval)
 		nfs_cancel_dirty(inode,pid);
 	return retval;
 }
 
 void
-nfs_invalidate_pages(struct inode *inode)
+nfs_inval(struct inode *inode)
 {
 	nfs_cancel_dirty(inode,0);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov