<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">

Patch from Trond Myklebust &lt;trond.myklebust@fys.uio.no&gt;




 nfs/pagelist.c |   31 ++++++++++++++-----------------
 nfs/write.c    |   26 +++++++++++++-------------
 2 files changed, 27 insertions(+), 30 deletions(-)

diff -puN fs/nfs/pagelist.c~nfs-oom-fix fs/nfs/pagelist.c
--- 25/fs/nfs/pagelist.c~nfs-oom-fix	2003-02-10 03:07:55.000000000 -0800
+++ 25-akpm/fs/nfs/pagelist.c	2003-02-10 03:07:55.000000000 -0800
@@ -11,6 +11,7 @@
 
 #include &lt;linux/config.h&gt;
 #include &lt;linux/slab.h&gt;
+#include &lt;linux/mempool.h&gt;
 #include &lt;linux/file.h&gt;
 #include &lt;linux/sunrpc/clnt.h&gt;
 #include &lt;linux/nfs3.h&gt;
@@ -26,13 +27,15 @@
  */
 spinlock_t nfs_wreq_lock = SPIN_LOCK_UNLOCKED;
 
+#define MIN_POOL_NFSPAGES	(128)
 static kmem_cache_t *nfs_page_cachep;
+static mempool_t *nfs_page_mempool;
 
 static inline struct nfs_page *
 nfs_page_alloc(void)
 {
 	struct nfs_page	*p;
-	p = kmem_cache_alloc(nfs_page_cachep, SLAB_NOFS);
+	p = mempool_alloc(nfs_page_mempool, SLAB_NOFS);
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&amp;p-&gt;wb_list);
@@ -44,7 +47,7 @@ nfs_page_alloc(void)
 static inline void
 nfs_page_free(struct nfs_page *p)
 {
-	kmem_cache_free(nfs_page_cachep, p);
+	mempool_free(p, nfs_page_mempool);
 }
 
 /**
@@ -66,23 +69,12 @@ nfs_create_request(struct rpc_cred *cred
 		   struct page *page,
 		   unsigned int offset, unsigned int count)
 {
-	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs_page		*req;
 
-	/* Deal with hard limits.  */
-	for (;;) {
-		/* try to allocate the request struct */
-		req = nfs_page_alloc();
-		if (req != NULL)
-			break;
-
-		/* Try to free up at least one request in order to stay
-		 * below the hard limit
-		 */
-		if (signalled() &amp;&amp; (server-&gt;flags &amp; NFS_MOUNT_INTR))
-			return ERR_PTR(-ERESTARTSYS);
-		yield();
-	}
+	/* try to allocate the request struct */
+	req = nfs_page_alloc();
+	if (req == NULL)
+		return ERR_PTR(-ENOMEM);
 
 	/* Initialize the request struct. Initially, we assume a
 	 * long write-back delay. This will be adjusted in
@@ -352,12 +344,17 @@ int nfs_init_nfspagecache(void)
 					    NULL, NULL);
 	if (nfs_page_cachep == NULL)
 		return -ENOMEM;
+	nfs_page_mempool = mempool_create(MIN_POOL_NFSPAGES,
+			mempool_alloc_slab,
+			mempool_free_slab,
+			nfs_page_cachep);
 
 	return 0;
 }
 
 void nfs_destroy_nfspagecache(void)
 {
+	mempool_destroy(nfs_page_mempool);
 	if (kmem_cache_destroy(nfs_page_cachep))
 		printk(KERN_INFO "nfs_page: not all structures were freed\n");
 }
diff -puN fs/nfs/write.c~nfs-oom-fix fs/nfs/write.c
--- 25/fs/nfs/write.c~nfs-oom-fix	2003-02-10 03:07:55.000000000 -0800
+++ 25-akpm/fs/nfs/write.c	2003-02-10 03:07:55.000000000 -0800
@@ -227,30 +227,30 @@ nfs_writepage(struct page *page, struct 
 	struct inode *inode = page-&gt;mapping-&gt;host;
 	unsigned long end_index;
 	unsigned offset = PAGE_CACHE_SIZE;
-	int err;
+	int err = -EIO;
 
 	end_index = inode-&gt;i_size &gt;&gt; PAGE_CACHE_SHIFT;
 
 	/* Ensure we've flushed out any previous writes */
 	nfs_wb_page(inode,page);
 
-	/* easy case */
-	if (page-&gt;index &lt; end_index)
-		goto do_it;
-	/* things got complicated... */
-	offset = inode-&gt;i_size &amp; (PAGE_CACHE_SIZE-1);
-
-	/* OK, are we completely out? */
-	err = -EIO;
-	if (page-&gt;index &gt;= end_index+1 || !offset)
-		goto out;
-do_it:
+	/* easy case ? */
+	if (page-&gt;index &gt;= end_index) {
+		/* things got complicated... */
+		offset = inode-&gt;i_size &amp; (PAGE_CACHE_SIZE-1);
+
+		/* OK, are we completely out? */
+		if (page-&gt;index &gt;= end_index+1 || !offset)
+			goto out;
+	}
+
 	lock_kernel();
 	if (NFS_SERVER(inode)-&gt;wsize &gt;= PAGE_CACHE_SIZE &amp;&amp; !IS_SYNC(inode)) {
 		err = nfs_writepage_async(NULL, inode, page, 0, offset);
 		if (err &gt;= 0)
 			err = 0;
-	} else {
+	}
+	if (err &lt; 0) {
 		err = nfs_writepage_sync(NULL, inode, page, 0, offset); 
 		if (err == offset)
 			err = 0;

_
</pre></body></html>