--- ext2.c	1999/07/29 16:25:31	1.49
+++ ext2.c	1999/07/29 18:12:25
@@ -89,6 +89,11 @@
 	return fs->devhandle->ops->read(fs->devhandle->cookie, ptr, block, num);
 }
 
+int ext2_read_blocks_iov(struct ext2_fs *fs, void **ptr, blk_t block, blk_t num)
+{
+	return fs->devhandle->ops->readv(fs->devhandle->cookie, ptr, block, num);
+}
+
 void ext2_set_block_state(struct ext2_fs *fs, blk_t block, int state, int updatemetadata)
 {
 	struct ext2_buffer_head *bh;
@@ -122,6 +127,11 @@
 int ext2_write_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num)
 {
 	return fs->devhandle->ops->write(fs->devhandle->cookie, ptr, block, num);
+}
+
+int ext2_write_blocks_iov(struct ext2_fs *fs, void **ptr, blk_t block, blk_t num)
+{
+	return fs->devhandle->ops->writev(fs->devhandle->cookie, ptr, block, num);
 }
 
 void ext2_zero_blocks(struct ext2_fs *fs, blk_t block, blk_t num)
--- ext2.h	1999/07/29 16:25:52	1.47
+++ ext2.h	1999/07/29 18:12:01
@@ -219,9 +219,11 @@
 	void			(*close)(void *cookie);
 	blk_t			(*get_size)(void *cookie);
 	int			(*read)(void *cookie, void *ptr, blk_t block, blk_t num);
+	int			(*readv)(void *cookie, void **ptr, blk_t block, blk_t num);
 	void			(*set_blocksize)(void *cookie, int logsize);
 	void			(*sync)(void *cookie);
 	int			(*write)(void *cookie, void *ptr, blk_t block, blk_t num);
+	int			(*writev)(void *cookie, void **ptr, blk_t block, blk_t num);
 };
 
 struct ext2_dev_handle
@@ -272,10 +274,12 @@
 void		ext2_move_blocks		(struct ext2_fs *fs, blk_t src, blk_t num, blk_t dest);
 struct ext2_fs *ext2_open			(struct ext2_dev_handle *handle);
 int		ext2_read_blocks		(struct ext2_fs *fs, void *ptr, blk_t block, blk_t numblocks);
+int		ext2_read_blocks_iov		(struct ext2_fs *fs, void **ptr, blk_t block, blk_t num);
 void		ext2_read_inode			(struct ext2_fs *fs, ino_t inode, struct ext2_inode *inodep);
 void		ext2_set_inode_state		(struct ext2_fs *fs, ino_t inode, int state, int updatemetadata);
 void		ext2_sync			(struct ext2_fs *fs);
 int		ext2_write_blocks		(struct ext2_fs *fs, void *ptr, blk_t block, blk_t numblocks);
+int		ext2_write_blocks_iov		(struct ext2_fs *fs, void **ptr, blk_t block, blk_t numblocks);
 void		ext2_write_inode		(struct ext2_fs *fs, ino_t inode, const struct ext2_inode *inodep);
 void		ext2_zero_blocks		(struct ext2_fs *fs, blk_t block, blk_t num);
 void		ext2_zero_inode			(struct ext2_fs *fs, ino_t inode);
--- ext2_block_relocator.c	1999/07/29 16:26:01	1.45
+++ ext2_block_relocator.c	1999/07/29 16:50:05
@@ -287,10 +287,38 @@
 
 
 
+#define MAXCONT 256
 static void ext2_block_relocator_copy(struct ext2_fs *fs, struct ext2_block_relocator_state *state)
 {
-	int i;
+	int num;
+	int numleft;
+	struct ext2_block_entry *ptr;
+	unsigned char buf[MAXCONT * fs->blocksize];
 
+	numleft = state->usedentries;
+	ptr = state->block;
+	while (numleft)
+	{
+		for (num=1;num<MAXCONT;num++)
+			if (ptr[0].num + num != ptr[num].num ||
+			    ptr[0].dest + num != ptr[num].dest)
+				break;
+
+#if DEBUG
+		printf("%i contiguous!\n", num);
+#endif
+
+		ext2_bcache_flush_range(fs, ptr[0].num, ptr[0].num + num);
+		ext2_bcache_flush_range(fs, ptr[0].dest, ptr[0].dest + num);
+
+		ext2_read_blocks(fs, buf, ptr[0].num, num);
+		ext2_write_blocks(fs, buf, ptr[0].dest, num);
+
+		ptr += num;
+		numleft -= num;
+	}
+
+#if 0
 	for (i=0;i<state->usedentries;i++)
 	{
 		struct ext2_block_entry *block;
@@ -298,6 +326,7 @@
 		block = &state->block[i];
 		ext2_copy_block(fs, block->num, block->dest);
 	}
+#endif
 
 #if SAFE
 	ext2_sync(fs);
--- ext2_buffer.c	1999/07/29 16:26:15	1.33
+++ ext2_buffer.c	1999/07/29 18:38:30
@@ -38,7 +38,6 @@
 static struct ext2_buffer_head *ext2_bh_alloc   (struct ext2_buffer_cache *, blk_t);
 static void                     ext2_bh_dealloc (struct ext2_buffer_head *);
 static struct ext2_buffer_head *ext2_bh_find    (struct ext2_buffer_cache *, blk_t);
-static void                     ext2_bh_do_read (struct ext2_buffer_head *);
 static void                     ext2_bh_do_write(struct ext2_buffer_head *);
 static void                     ext2_bh_hash    (struct ext2_buffer_head *);
 static void                     ext2_bh_unhash  (struct ext2_buffer_head *);
@@ -157,15 +156,48 @@
 	return NULL;
 }
 
-static void ext2_bh_do_read(struct ext2_buffer_head *bh)
-{
-	ext2_read_blocks(bh->bc->fs, bh->data, bh->block, 1);
-}
-
+#define WAHEAD 4
 static void ext2_bh_do_write(struct ext2_buffer_head *bh)
 {
-	ext2_write_blocks(bh->bc->fs, bh->data, bh->block, 1);
+	struct ext2_buffer_head *bhw[WAHEAD];
+	int			 i;
+	int			 num;
+	void			*ptr[WAHEAD];
+
+	for (num=1;num<WAHEAD;num++)
+		if ((bhw[num] = ext2_bh_find(bh->bc, bh->block + num)) == NULL || !bhw[num]->dirty)
+			break;
+
+	if (num == 1)
+	{
+		ext2_write_blocks(bh->bc->fs, bh->data, bh->block, 1);
+		bh->dirty = 0;
+	}
+
+	ptr[0] = bh->data;
 	bh->dirty = 0;
+	for (i=1;i<num;i++)
+	{
+		ptr[i] = bhw[i]->data;
+		bhw[i]->dirty = 0;
+	}
+
+	ext2_write_blocks_iov(bh->bc->fs, ptr, bh->block, num);
+
+#if 0
+	bh2 = ext2_bh_find(bh->bc, bh->block+1);
+	if (bh2 && bh2->dirty)
+	{
+		void *ptr[2];
+
+		ptr[0] = bh->data;
+		ptr[1] = bh2->data;
+		ext2_write_blocks_iov(bh->bc->fs, ptr, bh->block, 2);
+		bh->dirty = 0;
+		bh2->dirty = 0;
+		return;
+	}
+#endif
 }
 
 static void ext2_bh_hash(struct ext2_buffer_head *bh)
@@ -387,9 +419,12 @@
 	return bh;
 }
 
+#define RAHEAD 4
 struct ext2_buffer_head *ext2_bread(struct ext2_fs *fs, blk_t block)
 {
 	struct ext2_buffer_head *bh;
+	struct ext2_buffer_head *bhr[RAHEAD];
+	int i;
 
 	if ((bh = fs->bc->cache)->block == block)
 	{
@@ -415,9 +450,21 @@
 #endif
 
 	bh = ext2_bh_alloc(fs->bc, block);
-	fs->bc->cache = bh;
 	bh->usecount = 1;
-	ext2_bh_do_read(bh);
+	fs->bc->cache = bh;
+
+	for (i=1;i<RAHEAD;i++)
+		bhr[i] = ext2_bh_alloc(fs->bc, block + i);
+
+	{
+		void *ptr[RAHEAD];
+
+		ptr[0] = bh->data;
+		for (i=1;i<RAHEAD;i++)
+			ptr[i] = bhr[i]->data;
+
+		ext2_read_blocks_iov(bh->bc->fs, ptr, bh->block, RAHEAD);
+	}
 
 	return bh;
 }
--- ext2_unix_io.c	1999/07/26 09:13:57	1.1
+++ ext2_unix_io.c	1999/07/29 18:10:21
@@ -27,6 +27,7 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/uio.h>
 #include <unistd.h>
 #include "ext2.h"
 
@@ -51,20 +52,24 @@
 /* ...then this must be pseudo-code  :-) */
 
 static void  do_close        (void *cookie);
-static void  do_sync         (void *cookie);
 static blk_t do_get_size     (void *cookie);
 static int   do_read         (void *cookie, void *ptr, blk_t block, blk_t numblocks);
+static int   do_readv        (void *cookie, void **ptr, blk_t block, blk_t numblocks);
 static void  do_set_blocksize(void *cookie, int logsize);
+static void  do_sync         (void *cookie);
 static int   do_write        (void *cookie, void *ptr, blk_t block, blk_t numblocks);
+static int   do_writev       (void *cookie, void **ptr, blk_t block, blk_t numblocks);
 
 struct ext2_dev_ops ops =
 {
 	close:		do_close,
 	get_size:	do_get_size,
 	read:		do_read,
+	readv:		do_readv,
 	set_blocksize:	do_set_blocksize,
 	sync:		do_sync,
-	write:		do_write
+	write:		do_write,
+	writev:		do_writev
 };
 
 
@@ -124,15 +129,48 @@
 {
 	struct my_cookie *monster = cookie;
 	loff_t offset;
+	int ret;
 
 	offset = ((loff_t)block) << monster->logsize;
 	if (monster->readoff != offset)
-		llseek(monster->fdread, offset, SEEK_SET);
+		if (llseek(monster->fdread, offset, SEEK_SET) < 0)
+			return 0;
+
+	ret = read(monster->fdread, ptr, numblocks << monster->logsize);
+	monster->readoff = ((loff_t)block+numblocks) << monster->logsize;
+
+	if (ret == numblocks << monster->logsize)
+		return 1;
+
+	return 0;
+}
+
+static int do_readv(void *cookie, void **ptr, blk_t block, blk_t numblocks)
+{
+	int i;
+	struct iovec iov[numblocks];
+	struct my_cookie *monster = cookie;
+	loff_t offset;
+	int ret;
+
+	offset = ((loff_t)block) << monster->logsize;
+	if (monster->readoff != offset)
+		if (llseek(monster->fdread, offset, SEEK_SET) < 0)
+			return 0;
+
+	for (i=0;i<numblocks;i++)
+	{
+		iov[i].iov_base = ptr[i];
+		iov[i].iov_len = 1 << monster->logsize;
+	}
 
-	read(monster->fdread, ptr, numblocks << monster->logsize);
+	ret = readv(monster->fdread, iov, numblocks);
 	monster->readoff = ((loff_t)block+numblocks) << monster->logsize;
 
-	return 1;   /* FIXXXME */
+	if (ret == numblocks << monster->logsize)
+		return 1;
+
+	return 0;
 }
 
 static void do_set_blocksize(void *cookie, int logsize)
@@ -146,15 +184,48 @@
 {
 	struct my_cookie *monster = cookie;
 	loff_t offset;
+	int ret;
 
 	offset = ((loff_t)block) << monster->logsize;
 	if (monster->writeoff != offset)
-		llseek(monster->fdwrite, offset, SEEK_SET);
+		if (llseek(monster->fdwrite, offset, SEEK_SET) < 0)
+			return 0;
 
-	write(monster->fdwrite, ptr, numblocks << monster->logsize);
+	ret = write(monster->fdwrite, ptr, numblocks << monster->logsize);
 	monster->writeoff = ((loff_t)block+numblocks) << monster->logsize;
 
-	return 1; /* FIXXXME */
+	if (ret == numblocks << monster->logsize)
+		return 1;
+
+	return 0;
+}
+
+static int do_writev(void *cookie, void **ptr, blk_t block, blk_t numblocks)
+{
+	int i;
+	struct iovec iov[numblocks];
+	struct my_cookie *monster = cookie;
+	loff_t offset;
+	int ret;
+
+	offset = ((loff_t)block) << monster->logsize;
+	if (monster->writeoff != offset)
+		if (llseek(monster->fdwrite, offset, SEEK_SET) < 0)
+			return 0;
+
+	for (i=0;i<numblocks;i++)
+	{
+		iov[i].iov_base = ptr[i];
+		iov[i].iov_len = 1 << monster->logsize;
+	}
+
+	ret = writev(monster->fdwrite, iov, numblocks);
+	monster->writeoff = ((loff_t)block+numblocks) << monster->logsize;
+
+	if (ret == numblocks << monster->logsize)
+		return 1;
+
+	return 0;
 }
 
 struct ext2_dev_handle *ext2_make_dev_handle_from_file(char *dev)
