linux/fs/ext2
Hisashi Hifumi 8ab22b9abb vfs: pagecache usage optimization for pagesize!=blocksize
When we read some part of a file through pagecache, if there is a
pagecache of corresponding index but this page is not uptodate, read IO
is issued and this page will be uptodate.

I think this is good for pagesize == blocksize environment but there is
room for improvement on pagesize != blocksize environment.  Because in
this case a page can have multiple buffers and even if a page is not
uptodate, some buffers can be uptodate.

So I suggest that when all buffers which correspond to a part of a file
that we want to read are uptodate, use this pagecache and copy data from
this pagecache to user buffer even if a page is not uptodate.  This can
reduce read IO and improve system throughput.

I wrote a benchmark program and got result number with this program.

This benchmark do:

  1: mount and open a test file.

  2: create a 512MB file.

  3: close a file and umount.

  4: mount and again open a test file.

  5: pwrite randomly 300000 times on a test file.  offset is aligned
     by IO size(1024bytes).

  6: measure time of preading randomly 100000 times on a test file.

The result was:
	2.6.26
        330 sec

	2.6.26-patched
        226 sec

Arch:i386
Filesystem:ext3
Blocksize:1024 bytes
Memory: 1GB

On ext3/4, a file is written through buffer/block.  So random read/write
mixed workloads or random read after random write workloads are optimized
with this patch under pagesize != blocksize environment.  This test result
showed this.

The benchmark program is as follows:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>

#define LEN 1024
#define LOOP 1024*512 /* 512MB */

main(void)
{
	unsigned long i, offset, filesize;
	int fd;
	char buf[LEN];
	time_t t1, t2;

	if (mount("/dev/sda1", "/root/test1/", "ext3", 0, 0) < 0) {
		perror("cannot mount\n");
		exit(1);
	}
	memset(buf, 0, LEN);
	fd = open("/root/test1/testfile", O_CREAT|O_RDWR|O_TRUNC);
	if (fd < 0) {
		perror("cannot open file\n");
		exit(1);
	}
	for (i = 0; i < LOOP; i++)
		write(fd, buf, LEN);
	close(fd);
	if (umount("/root/test1/") < 0) {
		perror("cannot umount\n");
		exit(1);
	}
	if (mount("/dev/sda1", "/root/test1/", "ext3", 0, 0) < 0) {
		perror("cannot mount\n");
		exit(1);
	}
	fd = open("/root/test1/testfile", O_RDWR);
	if (fd < 0) {
		perror("cannot open file\n");
		exit(1);
	}

	filesize = LEN * LOOP;
	for (i = 0; i < 300000; i++){
		offset = (random() % filesize) & (~(LEN - 1));
		pwrite(fd, buf, LEN, offset);
	}
	printf("start test\n");
	time(&t1);
	for (i = 0; i < 100000; i++){
		offset = (random() % filesize) & (~(LEN - 1));
		pread(fd, buf, LEN, offset);
	}
	time(&t2);
	printf("%ld sec\n", t2-t1);
	close(fd);
	if (umount("/root/test1/") < 0) {
		perror("cannot umount\n");
		exit(1);
	}
}

Signed-off-by: Hisashi Hifumi <hifumi.hisashi@oss.ntt.co.jp>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Jan Kara <jack@ucw.cz>
Cc: <linux-ext4@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-07-28 16:30:21 -07:00
..
acl.c [PATCH] sanitize ->permission() prototype 2008-07-26 20:53:14 -04:00
acl.h [PATCH] sanitize ->permission() prototype 2008-07-26 20:53:14 -04:00
balloc.c ext2: retry block allocation if new blocks are allocated from system zone 2008-04-28 08:58:43 -07:00
dir.c ext2: replace remaining __FUNCTION__ occurrences 2008-04-28 08:58:43 -07:00
ext2.h ext2: remove unused ext2_put_inode prototype 2008-02-08 09:22:33 -08:00
file.c BKL-removal: convert ext2 over to use unlocked_ioctl 2008-02-06 10:41:20 -08:00
fsync.c header cleaning: don't include smp_lock.h when not used 2007-05-08 11:15:07 -07:00
ialloc.c ext2: le*_add_cpu conversion 2008-04-28 08:58:43 -07:00
inode.c vfs: pagecache usage optimization for pagesize!=blocksize 2008-07-28 16:30:21 -07:00
ioctl.c [PATCH] r/o bind mounts: elevate write count for ioctls() 2008-04-19 00:29:24 -04:00
Makefile [PATCH] Make EXT2_DEBUG work again 2006-06-25 10:01:12 -07:00
namei.c iget: stop EXT2 from using iget() and read_inode() 2008-02-07 08:42:27 -08:00
super.c SL*B: drop kmem cache argument from constructor 2008-07-26 12:00:07 -07:00
symlink.c [PATCH] mark struct inode_operations const 1 2007-02-12 09:48:46 -08:00
xattr.c ext2: use ext2_group_first_block_no() 2008-04-28 08:58:43 -07:00
xattr.h Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
xattr_security.c ext2: remove double definitions of xattr macros 2008-07-25 10:53:31 -07:00
xattr_trusted.c ext2: remove double definitions of xattr macros 2008-07-25 10:53:31 -07:00
xattr_user.c ext2: remove double definitions of xattr macros 2008-07-25 10:53:31 -07:00
xip.c ext2: replace remaining __FUNCTION__ occurrences 2008-04-28 08:58:43 -07:00
xip.h xip: support non-struct page backed memory 2008-04-28 08:58:23 -07:00