For an appending write, ext3_commit_write() will call the expensive
ext3_mark_inode_dirty() twice.  Once in generic_commit_write()'s extension of
i_size and once in ext3_commit_write() itself where i_disksize is updated.

But by updating i_disksize _before_ calling generic_commit_write() these can
be piggybacked.

The patch takes the overhead of a write() from 1.96 microseconds down to
1.63.



 fs/ext3/inode.c |   24 +++++++++++++++++-------
 1 files changed, 17 insertions(+), 7 deletions(-)

diff -puN fs/ext3/inode.c~ext3_mark_inode_dirty-less-calls fs/ext3/inode.c
--- 25/fs/ext3/inode.c~ext3_mark_inode_dirty-less-calls	2003-03-22 03:14:33.000000000 -0800
+++ 25-akpm/fs/ext3/inode.c	2003-03-22 03:14:33.000000000 -0800
@@ -1160,6 +1160,12 @@ static int ext3_commit_write(struct file
 		if (pos > inode->i_size)
 			inode->i_size = pos;
 		EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
+		if (inode->i_size > EXT3_I(inode)->i_disksize) {
+			EXT3_I(inode)->i_disksize = inode->i_size;
+			ret2 = ext3_mark_inode_dirty(handle, inode);
+			if (!ret) 
+				ret = ret2;
+		}
 	} else {
 		if (ext3_should_order_data(inode)) {
 			ret = walk_page_buffers(handle, page_buffers(page),
@@ -1167,14 +1173,18 @@ static int ext3_commit_write(struct file
 		}
 		/* Be careful here if generic_commit_write becomes a
 		 * required invocation after block_prepare_write. */
-		if (ret == 0)
+		if (ret == 0) {
+			/*
+			 * generic_commit_write() will run mark_inode_dirty()
+			 * if i_size changes.  So let's piggyback the
+			 * i_disksize mark_inode_dirty into that.
+			 */
+			loff_t new_i_size =
+				((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+			if (new_i_size > EXT3_I(inode)->i_disksize)
+				EXT3_I(inode)->i_disksize = new_i_size;
 			ret = generic_commit_write(file, page, from, to);
-	}
-	if (inode->i_size > EXT3_I(inode)->i_disksize) {
-		EXT3_I(inode)->i_disksize = inode->i_size;
-		ret2 = ext3_mark_inode_dirty(handle, inode);
-		if (!ret) 
-			ret = ret2;
+		}
 	}
 	ret2 = ext3_journal_stop(handle);
 	unlock_kernel();

_