From: Trond Myklebust <trond.myklebust@fys.uio.no>

  With the following patch I'm able to get good interactive response
even when running a 256-thread iozone session over NFSv3 + X +... (as
opposed to simply crashing due to OOM). It contains the following
elements:

  - Add missing unstable write accounting in sync_inodes_sb()
  - Add missing unstable write accounting in wakeup_bdflush().
  - Decrement nr_unstable only when the COMMIT RPC call is done
    (rather then doing so when we schedule the RPC call). This ensures
    that we do try to wait for completion.
  - It is better to do too many rather than too *few* writes. Don't
    overestimate how many pages we wrote out in nfs_writepages().




 fs/fs-writeback.c   |    3 ++-
 fs/nfs/write.c      |    6 +++---
 mm/page-writeback.c |    2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff -puN fs/fs-writeback.c~nfs-writeback-tweak fs/fs-writeback.c
--- 25/fs/fs-writeback.c~nfs-writeback-tweak	2003-05-04 14:08:36.000000000 -0700
+++ 25-akpm/fs/fs-writeback.c	2003-05-04 14:08:36.000000000 -0700
@@ -367,7 +367,8 @@ void sync_inodes_sb(struct super_block *
 	};
 
 	get_page_state(&ps);
-	wbc.nr_to_write = ps.nr_dirty + ps.nr_dirty / 4;
+	wbc.nr_to_write = ps.nr_dirty + ps.nr_unstable +
+		(ps.nr_dirty + ps.nr_unstable) / 4;
 	spin_lock(&inode_lock);
 	sync_sb_inodes(sb, &wbc);
 	spin_unlock(&inode_lock);
diff -puN fs/nfs/write.c~nfs-writeback-tweak fs/nfs/write.c
--- 25/fs/nfs/write.c~nfs-writeback-tweak	2003-05-04 14:08:36.000000000 -0700
+++ 25-akpm/fs/nfs/write.c	2003-05-04 14:08:36.000000000 -0700
@@ -280,8 +280,6 @@ nfs_writepages(struct address_space *map
 		err = nfs_wb_all(inode);
 	} else
 		nfs_commit_file(inode, NULL, 0, 0, 0);
-	/* Avoid races. Tell upstream we've done all we were told to do */
-	wbc->nr_to_write = 0;
 out:
 	return err;
 }
@@ -490,7 +488,6 @@ nfs_scan_commit(struct inode *inode, str
 	int	res;
 	res = nfs_scan_list(&nfsi->commit, dst, file, idx_start, npages);
 	nfsi->ncommit -= res;
-	sub_page_state(nr_unstable,res);
 	if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
 		printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
 	return res;
@@ -1009,6 +1006,7 @@ nfs_commit_done(struct rpc_task *task)
 {
 	struct nfs_write_data	*data = (struct nfs_write_data *)task->tk_calldata;
 	struct nfs_page		*req;
+	int res = 0;
 
         dprintk("NFS: %4d nfs_commit_done (status %d)\n",
                                 task->tk_pid, task->tk_status);
@@ -1043,7 +1041,9 @@ nfs_commit_done(struct rpc_task *task)
 		nfs_mark_request_dirty(req);
 	next:
 		nfs_unlock_request(req);
+		res++;
 	}
+	sub_page_state(nr_unstable,res);
 }
 #endif
 
diff -puN mm/page-writeback.c~nfs-writeback-tweak mm/page-writeback.c
--- 25/mm/page-writeback.c~nfs-writeback-tweak	2003-05-04 14:08:36.000000000 -0700
+++ 25-akpm/mm/page-writeback.c	2003-05-04 14:08:36.000000000 -0700
@@ -272,7 +272,7 @@ int wakeup_bdflush(long nr_pages)
 		struct page_state ps;
 
 		get_page_state(&ps);
-		nr_pages = ps.nr_dirty;
+		nr_pages = ps.nr_dirty + ps.nr_unstable;
 	}
 	return pdflush_operation(background_writeout, nr_pages);
 }

_