diff -urNp x-ref/drivers/char/raw.c x/drivers/char/raw.c
--- x-ref/drivers/char/raw.c	2003-01-31 01:47:18.000000000 +0100
+++ x/drivers/char/raw.c	2003-01-31 01:48:58.000000000 +0100
@@ -94,12 +94,6 @@ int raw_open(struct inode *inode, struct
 		filp->f_op = &raw_ctl_fops;
 		return 0;
 	}
-	
-	if (!filp->f_iobuf) {
-		err = alloc_kiovec(1, &filp->f_iobuf);
-		if (err)
-			return err;
-	}
 
 	down(&raw_devices[minor].mutex);
 	/*
@@ -145,7 +139,6 @@ int raw_open(struct inode *inode, struct
 
 	set_blocksize(rdev, sector_size);
 	raw_devices[minor].sector_size = sector_size;
-	filp->f_iobuf->varyio = raw_devices[minor].varyio;
 
 	for (sector_bits = 0; !(sector_size & 1); )
 		sector_size>>=1, sector_bits++;
@@ -303,7 +296,6 @@ ssize_t	rw_raw_dev(int rw, struct file *
 		   size_t size, loff_t *offp)
 {
 	struct kiobuf * iobuf;
-	int		new_iobuf;
 	int		err = 0;
 	unsigned long	blocknr, blocks;
 	size_t		transferred;
@@ -322,19 +314,10 @@ ssize_t	rw_raw_dev(int rw, struct file *
 
 	minor = MINOR(filp->f_dentry->d_inode->i_rdev);
 
-	new_iobuf = 0;
-	iobuf = filp->f_iobuf;
-	if (test_and_set_bit(0, &filp->f_iobuf_lock)) {
-		/*
-		 * A parallel read/write is using the preallocated iobuf
-		 * so just run slow and allocate a new one.
-		 */
-		err = alloc_kiovec(1, &iobuf);
-		if (err)
-			goto out;
-		new_iobuf = 1;
-		iobuf->varyio = raw_devices[minor].varyio;
-	}
+	err = alloc_kiovec(1, &iobuf);
+	if (err)
+		return err;
+	iobuf->varyio = raw_devices[minor].varyio;
 
 	dev = to_kdev_t(raw_devices[minor].binding->bd_dev);
 	sector_size = raw_devices[minor].sector_size;
@@ -407,11 +390,7 @@ ssize_t	rw_raw_dev(int rw, struct file *
 	}
 
  out_free:
-	if (!new_iobuf)
-		clear_bit(0, &filp->f_iobuf_lock);
-	else
-		free_kiovec(1, &iobuf);
- out:	
+	free_kiovec(1, &iobuf);
 	return err;
 }
 
diff -urNp x-ref/fs/fcntl.c x/fs/fcntl.c
--- x-ref/fs/fcntl.c	2003-01-31 01:47:11.000000000 +0100
+++ x/fs/fcntl.c	2003-01-31 01:47:21.000000000 +0100
@@ -214,9 +214,9 @@ static int setfl(int fd, struct file * f
 		return -EPERM;
 
 	/*
-	 * alloc_kiovec() and ->fasync can sleep, so abuse the i_sem
+	 * ->fasync can sleep, so abuse the i_sem
 	 * to serialize against parallel setfl on the same filp,
-	 * to avoid races with ->f_flags and ->f_iobuf.
+	 * to avoid races with ->f_flags.
 	 */
 	down(&inode->i_sem);
 	/* Did FASYNC state change? */
@@ -230,19 +230,6 @@ static int setfl(int fd, struct file * f
 		}
 	}
 
-	if (arg & O_DIRECT) {
-		error = -EINVAL;
-		if (!inode->i_mapping || !inode->i_mapping->a_ops ||
-		    !inode->i_mapping->a_ops->direct_IO)
-			goto out;
-
-		if (!filp->f_iobuf) {
-			error = alloc_kiovec(1, &filp->f_iobuf);
-			if (error < 0)
-				goto out;
-		}
-	}
-
 	/* required for strict SunOS emulation */
 	if (O_NONBLOCK != O_NDELAY)
 	       if (arg & O_NDELAY)
diff -urNp x-ref/fs/file_table.c x/fs/file_table.c
--- x-ref/fs/file_table.c	2003-01-31 01:47:18.000000000 +0100
+++ x/fs/file_table.c	2003-01-31 01:47:21.000000000 +0100
@@ -105,9 +105,6 @@ inline void __fput(struct file * file)
 
 	locks_remove_flock(file);
 
-	if (file->f_iobuf)
-		free_kiovec(1, &file->f_iobuf);
-
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
 	fops_put(file->f_op);
diff -urNp x-ref/fs/iobuf.c x/fs/iobuf.c
--- x-ref/fs/iobuf.c	2003-01-31 01:47:08.000000000 +0100
+++ x/fs/iobuf.c	2003-01-31 01:47:21.000000000 +0100
@@ -8,7 +8,6 @@
 
 #include <linux/iobuf.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 
 
 static kmem_cache_t *kiobuf_cachep;
@@ -27,6 +26,8 @@ void end_kio_request(struct kiobuf *kiob
 
 static int kiobuf_init(struct kiobuf *iobuf)
 {
+	int retval;
+
 	init_waitqueue_head(&iobuf->wait_queue);
 	iobuf->array_len = 0;
 	iobuf->nr_pages = 0;
@@ -36,7 +37,17 @@ static int kiobuf_init(struct kiobuf *io
 	iobuf->blocks = NULL;
 	atomic_set(&iobuf->io_count, 0);
 	iobuf->end_io = NULL;
-	return expand_kiobuf(iobuf, KIO_STATIC_PAGES);
+	iobuf->initialized = 0;
+	retval = expand_kiobuf(iobuf, KIO_STATIC_PAGES);
+	if (unlikely(retval))
+		return retval;
+	retval = alloc_kiobuf_bhs(iobuf);
+	if (unlikely(retval)) {
+		kfree(iobuf->maplist);
+		return retval;
+	}
+	iobuf->initialized = 1;
+	return 0;
 }
 
 int alloc_kiobuf_bhs(struct kiobuf * kiobuf)
@@ -90,6 +101,23 @@ void free_kiobuf_bhs(struct kiobuf * kio
 	}
 }
 
+void kiobuf_ctor(void * objp, kmem_cache_t * cachep, unsigned long flag)
+{
+	struct kiobuf * iobuf = (struct kiobuf *) objp;
+
+	kiobuf_init(iobuf);
+}
+
+void kiobuf_dtor(void * objp, kmem_cache_t * cachep, unsigned long flag)
+{
+	struct kiobuf * iobuf = (struct kiobuf *) objp;
+
+	if (likely(iobuf->initialized)) {
+		kfree(iobuf->maplist);
+		free_kiobuf_bhs(iobuf);
+	}
+}
+
 int alloc_kiovec(int nr, struct kiobuf **bufp)
 {
 	int i;
@@ -99,9 +127,7 @@ int alloc_kiovec(int nr, struct kiobuf *
 		iobuf = kmem_cache_alloc(kiobuf_cachep, GFP_KERNEL);
 		if (unlikely(!iobuf))
 			goto nomem;
-		if (unlikely(kiobuf_init(iobuf)))
-			goto nomem2;
- 		if (unlikely(alloc_kiobuf_bhs(iobuf)))
+		if (unlikely(!iobuf->initialized))
 			goto nomem2;
 		bufp[i] = iobuf;
 	}
@@ -124,9 +150,8 @@ void free_kiovec(int nr, struct kiobuf *
 		iobuf = bufp[i];
 		if (iobuf->locked)
 			unlock_kiovec(1, &iobuf);
-		kfree(iobuf->maplist);
-		free_kiobuf_bhs(iobuf);
-		kmem_cache_free(kiobuf_cachep, bufp[i]);
+		iobuf->end_io = NULL;
+		kmem_cache_free(kiobuf_cachep, iobuf);	
 	}
 }
 
@@ -181,7 +206,7 @@ repeat:
 void __init iobuf_cache_init(void)
 {
 	kiobuf_cachep = kmem_cache_create("kiobuf", sizeof(struct kiobuf),
-					  0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+					  0, SLAB_HWCACHE_ALIGN, kiobuf_ctor, kiobuf_dtor);
 	if (!kiobuf_cachep)
 		panic("Cannot create kiobuf SLAB cache");
 }
diff -urNp x-ref/fs/open.c x/fs/open.c
--- x-ref/fs/open.c	2003-01-31 01:47:18.000000000 +0100
+++ x/fs/open.c	2003-01-31 01:47:21.000000000 +0100
@@ -683,15 +683,6 @@ struct file *dentry_open(struct dentry *
 	f->f_op = fops_get(inode->i_fop);
 	file_move(f, &inode->i_sb->s_files);
 
-	/* preallocate kiobuf for O_DIRECT */
-	f->f_iobuf = NULL;
-	f->f_iobuf_lock = 0;
-	if (f->f_flags & O_DIRECT) {
-		error = alloc_kiovec(1, &f->f_iobuf);
-		if (error)
-			goto cleanup_all;
-	}
-
 	if (f->f_op && f->f_op->open) {
 		error = f->f_op->open(inode,f);
 		if (error)
@@ -708,8 +699,6 @@ struct file *dentry_open(struct dentry *
 	return f;
 
 cleanup_all:
-	if (f->f_iobuf)
-		free_kiovec(1, &f->f_iobuf);
 	fops_put(f->f_op);
 	if (f->f_mode & FMODE_WRITE)
 		put_write_access(inode);
diff -urNp x-ref/include/linux/fs.h x/include/linux/fs.h
--- x-ref/include/linux/fs.h	2003-01-31 01:47:20.000000000 +0100
+++ x/include/linux/fs.h	2003-01-31 01:47:21.000000000 +0100
@@ -649,10 +649,6 @@ struct file {
 
 	/* needed for tty driver, and maybe others */
 	void			*private_data;
-
-	/* preallocated helper kiobuf to speedup O_DIRECT */
-	struct kiobuf		*f_iobuf;
-	long			f_iobuf_lock;
 };
 extern spinlock_t files_lock;
 #define file_list_lock() spin_lock(&files_lock);
diff -urNp x-ref/include/linux/iobuf.h x/include/linux/iobuf.h
--- x-ref/include/linux/iobuf.h	2003-01-31 01:47:08.000000000 +0100
+++ x/include/linux/iobuf.h	2003-01-31 01:47:21.000000000 +0100
@@ -41,7 +41,8 @@ struct kiobuf 
 	int		length;		/* Number of valid bytes of data */
 
 	unsigned int	locked : 1,	/* If set, pages has been locked */
-			varyio : 1;	/* If set, do variable size IO */
+			varyio : 1,	/* If set, do variable size IO */
+			initialized:1;	/* If set, done initialize */
 
 	struct page **  maplist;
 	struct buffer_head ** bh;
diff -urNp x-ref/mm/filemap.c x/mm/filemap.c
--- x-ref/mm/filemap.c	2003-01-31 01:47:20.000000000 +0100
+++ x/mm/filemap.c	2003-01-31 01:47:21.000000000 +0100
@@ -1553,24 +1553,15 @@ no_cached_page:
 static ssize_t generic_file_direct_IO(int rw, struct file * filp, char * buf, size_t count, loff_t offset)
 {
 	ssize_t retval;
-	int new_iobuf, chunk_size, blocksize_mask, blocksize, blocksize_bits, iosize, progress;
+	int chunk_size, blocksize_mask, blocksize, blocksize_bits, iosize, progress;
 	struct kiobuf * iobuf;
 	struct address_space * mapping = filp->f_dentry->d_inode->i_mapping;
 	struct inode * inode = mapping->host;
 	loff_t	size = i_size_read(inode);
 
-	new_iobuf = 0;
-	iobuf = filp->f_iobuf;
-	if (test_and_set_bit(0, &filp->f_iobuf_lock)) {
-		/*
-		 * A parallel read/write is using the preallocated iobuf
-		 * so just run slow and allocate a new one.
-		 */
-		retval = alloc_kiovec(1, &iobuf);
-		if (retval)
-			goto out;
-		new_iobuf = 1;
-	}
+	retval = alloc_kiovec(1, &iobuf);
+	if (retval)
+		goto out;
 
 	blocksize = 1 << inode->i_blkbits;
 	blocksize_bits = inode->i_blkbits;
@@ -1628,10 +1619,7 @@ static ssize_t generic_file_direct_IO(in
 		retval = progress;
 
  out_free:
-	if (!new_iobuf)
-		clear_bit(0, &filp->f_iobuf_lock);
-	else
-		free_kiovec(1, &iobuf);
+	free_kiovec(1, &iobuf);
  out:	
 	return retval;
 }