public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Benjamin LaHaise <bcrl@redhat.com>
To: Janet Morgan <janetmor@us.ibm.com>
Cc: William Lee Irwin III <wli@holomorphy.com>,
	akpm@digeo.com, suparna@in.ibm.com, linux-aio@kvack.org,
	linux-kernel@vger.kernel.org
Subject: Re: [Patch 2/2] Retry based aio read - filesystem read changes
Date: Tue, 1 Apr 2003 15:24:24 -0500	[thread overview]
Message-ID: <20030401152424.A26513@redhat.com> (raw)
In-Reply-To: <3E88920A.BB8987D3@us.ibm.com>; from janetmor@us.ibm.com on Mon, Mar 31, 2003 at 11:07:55AM -0800

On Mon, Mar 31, 2003 at 11:07:55AM -0800, Janet Morgan wrote:
> Can you post the patch you're referring to?

Something like this...  It also converts the async rw ops into vectored  
form.

		-ben


 drivers/char/raw.c       |   23 ------
 fs/adfs/file.c           |    4 -
 fs/affs/file.c           |   19 -----
 fs/afs/file.c            |    2 
 fs/aio.c                 |  127 ++++++++++++++++++++++++-----------
 fs/befs/linuxvfs.c       |    4 -
 fs/bfs/file.c            |    4 -
 fs/block_dev.c           |   18 +----
 fs/cifs/cifsfs.c         |    4 -
 fs/direct-io.c           |   10 +-
 fs/ext2/file.c           |    4 -
 fs/ext2/inode.c          |    4 -
 fs/ext3/file.c           |   14 +--
 fs/ext3/inode.c          |    4 -
 fs/fat/file.c            |   15 +---
 fs/freevxfs/vxfs_inode.c |    2 
 fs/hpfs/file.c           |   14 ---
 fs/hpfs/inode.c          |    2 
 fs/jffs/inode-v23.c      |    4 -
 fs/jffs2/file.c          |    4 -
 fs/jfs/file.c            |    4 -
 fs/minix/file.c          |    4 -
 fs/nfs/file.c            |   31 +++-----
 fs/nfs/write.c           |    4 -
 fs/ntfs/aops.c           |    2 
 fs/ntfs/file.c           |    4 -
 fs/qnx4/file.c           |    4 -
 fs/ramfs/inode.c         |    4 -
 fs/read_write.c          |  166 +++++++++++++++++++++++------------------------
 fs/reiserfs/file.c       |    4 -
 fs/smbfs/file.c          |   20 ++---
 fs/sysv/file.c           |    4 -
 fs/udf/file.c            |   18 ++---
 fs/ufs/file.c            |    4 -
 include/linux/aio.h      |   67 ++++++++++++++++--
 include/linux/fs.h       |   32 +++------
 include/net/sock.h       |   14 ++-
 kernel/ksyms.c           |    5 -
 mm/filemap.c             |  145 ++++++++---------------------------------
 net/socket.c             |   67 ++++++++----------
 40 files changed, 400 insertions(+), 485 deletions(-)
diff -purN linux-2.5/drivers/char/raw.c aio-2.5/drivers/char/raw.c
--- linux-2.5/drivers/char/raw.c	Tue Apr  1 15:17:26 2003
+++ aio-2.5/drivers/char/raw.c	Mon Mar 24 15:39:48 2003
@@ -220,33 +220,12 @@ out:
 	return err;
 }
 
-static ssize_t raw_file_write(struct file *file, const char *buf,
-				   size_t count, loff_t *ppos)
-{
-	struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
-
-	return generic_file_write_nolock(file, &local_iov, 1, ppos);
-}
-
-static ssize_t raw_file_aio_write(struct kiocb *iocb, const char *buf,
-					size_t count, loff_t pos)
-{
-	struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
-
-	return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
-}
-
-
 static struct file_operations raw_fops = {
-	.read	=	generic_file_read,
 	.aio_read = 	generic_file_aio_read,
-	.write	=	raw_file_write,
-	.aio_write = 	raw_file_aio_write,
+	.aio_write = 	generic_file_aio_write_nolock,
 	.open	=	raw_open,
 	.release=	raw_release,
 	.ioctl	=	raw_ioctl,
-	.readv	= 	generic_file_readv,
-	.writev	= 	generic_file_writev,
 	.owner	=	THIS_MODULE,
 };
 
diff -purN linux-2.5/fs/adfs/file.c aio-2.5/fs/adfs/file.c
--- linux-2.5/fs/adfs/file.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/adfs/file.c	Mon Mar 24 11:25:00 2003
@@ -31,11 +31,11 @@
 #include "adfs.h"
 
 struct file_operations adfs_file_operations = {
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
 	.mmap		= generic_file_mmap,
 	.fsync		= file_fsync,
-	.write		= generic_file_write,
 	.sendfile	= generic_file_sendfile,
 };
 
diff -purN linux-2.5/fs/affs/file.c aio-2.5/fs/affs/file.c
--- linux-2.5/fs/affs/file.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/affs/file.c	Mon Mar 24 11:25:00 2003
@@ -39,14 +39,13 @@ static int affs_grow_extcache(struct ino
 static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext);
 static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext);
 static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
-static ssize_t affs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos);
 static int affs_file_open(struct inode *inode, struct file *filp);
 static int affs_file_release(struct inode *inode, struct file *filp);
 
 struct file_operations affs_file_operations = {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= affs_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.open		= affs_file_open,
 	.release	= affs_file_release,
@@ -490,20 +489,6 @@ affs_getemptyblk_ino(struct inode *inode
 	return ERR_PTR(err);
 }
 
-static ssize_t
-affs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-	ssize_t retval;
-
-	retval = generic_file_write (file, buf, count, ppos);
-	if (retval >0) {
-		struct inode *inode = file->f_dentry->d_inode;
-		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-		mark_inode_dirty(inode);
-	}
-	return retval;
-}
-
 static int
 affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
 {
diff -purN linux-2.5/fs/afs/file.c aio-2.5/fs/afs/file.c
--- linux-2.5/fs/afs/file.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/afs/file.c	Mon Mar 24 11:25:00 2003
@@ -35,7 +35,7 @@ struct inode_operations afs_file_inode_o
 };
 
 struct file_operations afs_file_file_operations = {
-	.read		= generic_file_read,
+	.aio_read	= generic_file_aio_read,
 	.write		= afs_file_write,
 	.mmap		= generic_file_readonly_mmap,
 #if 0
diff -purN linux-2.5/fs/aio.c aio-2.5/fs/aio.c
--- linux-2.5/fs/aio.c	Tue Mar 25 16:50:38 2003
+++ aio-2.5/fs/aio.c	Mon Mar 31 14:41:41 2003
@@ -64,7 +64,7 @@ static void aio_kick_handler(void *);
  */
 static int __init aio_setup(void)
 {
-	kiocb_cachep = kmem_cache_create("kiocb", sizeof(struct kiocb),
+	kiocb_cachep = kmem_cache_create("kiocb", sizeof(struct sync_iocb),
 				0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 	if (!kiocb_cachep)
 		panic("unable to create kiocb cache\n");
@@ -148,7 +148,7 @@ static int aio_setup_ring(struct kioctx 
 
 	dprintk("mmap address: 0x%08lx\n", info->mmap_base);
 	info->nr_pages = get_user_pages(current, ctx->mm,
-					info->mmap_base, info->mmap_size, 
+					info->mmap_base, nr_pages, 
 					1, 0, info->ring_pages, NULL);
 	up_write(&ctx->mm->mmap_sem);
 
@@ -790,6 +790,20 @@ static inline void set_timeout(long star
 	add_timer(&to->timer);
 }
 
+static inline void update_ts(struct timespec *ts, long jiffies)
+{
+	struct timespec tmp;
+	jiffies_to_timespec(jiffies, &tmp);
+	ts->tv_sec -= tmp.tv_sec;
+	ts->tv_nsec -= tmp.tv_nsec;
+	if (ts->tv_nsec < 0) {
+		ts->tv_nsec += 1000000000;
+		ts->tv_sec -= 1;
+	}
+	if (ts->tv_sec < 0)
+		ts->tv_sec = ts->tv_nsec = 0;
+}
+
 static inline void clear_timeout(struct timeout *to)
 {
 	del_timer_sync(&to->timer);
@@ -807,6 +821,7 @@ static int read_events(struct kioctx *ct
 	int			i = 0;
 	struct io_event		ent;
 	struct timeout		to;
+	struct timespec		ts;
 
 	/* needed to zero any padding within an entry (there shouldn't be 
 	 * any, but C is fun!
@@ -844,7 +859,6 @@ static int read_events(struct kioctx *ct
 
 	init_timeout(&to);
 	if (timeout) {
-		struct timespec	ts;
 		ret = -EFAULT;
 		if (unlikely(copy_from_user(&ts, timeout, sizeof(ts))))
 			goto out;
@@ -890,8 +904,12 @@ static int read_events(struct kioctx *ct
 		i ++;
 	}
 
-	if (timeout)
+	if (timeout) {
 		clear_timeout(&to);
+		update_ts(&ts, jiffies - start_jiffies);
+		if (copy_to_user(timeout, &ts, sizeof(ts)))
+			ret = -EFAULT;
+	}
 out:
 	return i ? i : ret;
 }
@@ -984,6 +1002,63 @@ asmlinkage long sys_io_destroy(aio_conte
 	return -EINVAL;
 }
 
+static ssize_t rw_issue(struct rw_iocb *rw, struct file *file,
+		        struct iocb *iocb, ssize_t (*op)(struct rw_iocb *))
+{
+	ssize_t ret;
+
+	if (unlikely(NULL == op))
+		return -EINVAL;
+	if (unlikely(!(file->f_mode &
+			(rw->rw == WRITE ? FMODE_WRITE : FMODE_READ))))
+		return -EBADF;
+	if (unlikely(!access_ok((rw->rw == WRITE ? VERIFY_READ : VERIFY_WRITE),
+				rw->rw_local_iov.iov_base,
+				rw->rw_local_iov.iov_len)))
+		return -EFAULT;
+
+	rw->rw_local_iov.iov_base = (char *)(unsigned long)iocb->aio_buf;
+	rw->rw_local_iov.iov_len = iocb->aio_nbytes;
+	rw->rw_nsegs = 1;
+	rw->rw_iov = &rw->rw_local_iov;
+	rw->rw_pos = iocb->aio_offset;
+
+	ret = op(rw);
+	if (-EIOCBQUEUED != ret)
+		aio_complete(&rw->kiocb, ret, 0);
+	return 0;
+}
+
+static ssize_t io_submit_pread(struct kiocb *kiocb, struct file *file,
+			       struct iocb *iocb)
+{
+	struct rw_iocb *rw = kiocb_to_rw_iocb(kiocb);
+	rw->rw = READ;
+	return rw_issue(rw, file, iocb, file->f_op->aio_read);
+}
+
+static ssize_t io_submit_pwrite(struct kiocb *kiocb, struct file *file,
+				struct iocb *iocb)
+{
+	struct rw_iocb *rw = (struct rw_iocb *)kiocb;
+	rw->rw = WRITE;
+	return rw_issue(rw, file, iocb, file->f_op->aio_write);
+}
+static ssize_t io_submit_fsync(struct kiocb *kiocb, struct file *file,
+			       int dsync)
+{
+	struct fsync_iocb *fsync_iocb = kiocb_to_fsync_iocb(kiocb);
+	ssize_t ret = -EINVAL;
+	fsync_iocb->dsync = dsync;
+	if (NULL != file->f_op->aio_fsync) {
+		ret = file->f_op->aio_fsync(fsync_iocb);
+		if (-EIOCBQUEUED != ret)
+			aio_complete(&fsync_iocb->kiocb, ret, 0);
+		ret = 0;
+	}
+	return ret;
+}
+
 static int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
 				  struct iocb *iocb));
 static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
@@ -992,7 +1067,6 @@ static int io_submit_one(struct kioctx *
 	struct kiocb *req;
 	struct file *file;
 	ssize_t ret;
-	char *buf;
 
 	/* enforce forwards compatibility on users */
 	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
@@ -1031,57 +1105,30 @@ static int io_submit_one(struct kioctx *
 
 	req->ki_user_obj = user_iocb;
 	req->ki_user_data = iocb->aio_data;
-	req->ki_pos = iocb->aio_offset;
-
-	buf = (char *)(unsigned long)iocb->aio_buf;
 
 	switch (iocb->aio_lio_opcode) {
 	case IOCB_CMD_PREAD:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_READ)))
-			goto out_put_req;
-		ret = -EFAULT;
-		if (unlikely(!access_ok(VERIFY_WRITE, buf, iocb->aio_nbytes)))
-			goto out_put_req;
-		ret = -EINVAL;
-		if (file->f_op->aio_read)
-			ret = file->f_op->aio_read(req, buf,
-					iocb->aio_nbytes, req->ki_pos);
+		ret = io_submit_pread(req, file, iocb);
 		break;
 	case IOCB_CMD_PWRITE:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_WRITE)))
-			goto out_put_req;
-		ret = -EFAULT;
-		if (unlikely(!access_ok(VERIFY_READ, buf, iocb->aio_nbytes)))
-			goto out_put_req;
-		ret = -EINVAL;
-		if (file->f_op->aio_write)
-			ret = file->f_op->aio_write(req, buf,
-					iocb->aio_nbytes, req->ki_pos);
+		ret = io_submit_pwrite(req, file, iocb);
 		break;
 	case IOCB_CMD_FDSYNC:
-		ret = -EINVAL;
-		if (file->f_op->aio_fsync)
-			ret = file->f_op->aio_fsync(req, 1);
+		ret = io_submit_fsync(req, file, 1);
 		break;
 	case IOCB_CMD_FSYNC:
-		ret = -EINVAL;
-		if (file->f_op->aio_fsync)
-			ret = file->f_op->aio_fsync(req, 0);
+		ret = io_submit_fsync(req, file, 0);
 		break;
 	default:
 		dprintk("EINVAL: io_submit: no operation provided\n");
 		ret = -EINVAL;
 	}
 
-	if (likely(-EIOCBQUEUED == ret))
-		return 0;
-	aio_complete(req, ret, 0);
-	return 0;
-
+	if (-EIOCBQUEUED == ret)
+		ret = 0;
 out_put_req:
-	aio_put_req(req);
+	if (ret)
+		aio_put_req(req);
 	return ret;
 }
 
diff -purN linux-2.5/fs/befs/linuxvfs.c aio-2.5/fs/befs/linuxvfs.c
--- linux-2.5/fs/befs/linuxvfs.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/befs/linuxvfs.c	Mon Mar 24 11:25:00 2003
@@ -73,7 +73,7 @@ struct inode_operations befs_dir_inode_o
 
 struct file_operations befs_file_operations = {
 	.llseek		= default_llseek,
-	.read		= generic_file_read,
+	.aio_read	= generic_file_aio_read,
 	.mmap		= generic_file_readonly_mmap,
 };
 
@@ -89,7 +89,7 @@ static struct inode_operations befs_syml
 };
 
 /* 
- * Called by generic_file_read() to read a page of data
+ * Called by generic_file_aio_read() to read a page of data
  * 
  * In turn, simply calls a generic block read function and
  * passes it the address of befs_get_block, for mapping file
diff -purN linux-2.5/fs/bfs/file.c aio-2.5/fs/bfs/file.c
--- linux-2.5/fs/bfs/file.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/bfs/file.c	Mon Mar 24 11:25:00 2003
@@ -19,8 +19,8 @@
 
 struct file_operations bfs_file_operations = {
 	.llseek 	= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= generic_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.sendfile	= generic_file_sendfile,
 };
diff -purN linux-2.5/fs/block_dev.c aio-2.5/fs/block_dev.c
--- linux-2.5/fs/block_dev.c	Tue Apr  1 15:17:52 2003
+++ aio-2.5/fs/block_dev.c	Mon Mar 24 17:25:12 2003
@@ -118,10 +118,10 @@ blkdev_get_blocks(struct inode *inode, s
 }
 
 static int
-blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+blkdev_direct_IO(int rw, struct rw_iocb *iocb, const struct iovec *iov,
 			loff_t offset, unsigned long nr_segs)
 {
-	struct file *file = iocb->ki_filp;
+	struct file *file = iocb->kiocb.ki_filp;
 	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 
 	return blockdev_direct_IO(rw, iocb, inode, inode->i_bdev, iov, offset,
@@ -694,14 +694,6 @@ int blkdev_close(struct inode * inode, s
 	return blkdev_put(inode->i_bdev, BDEV_FILE);
 }
 
-static ssize_t blkdev_file_write(struct file *file, const char *buf,
-				   size_t count, loff_t *ppos)
-{
-	struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
-
-	return generic_file_write_nolock(file, &local_iov, 1, ppos);
-}
-
 struct address_space_operations def_blk_aops = {
 	.readpage	= blkdev_readpage,
 	.writepage	= blkdev_writepage,
@@ -716,13 +708,11 @@ struct file_operations def_blk_fops = {
 	.open		= blkdev_open,
 	.release	= blkdev_close,
 	.llseek		= block_llseek,
-	.read		= generic_file_read,
-	.write		= blkdev_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write_nolock,
 	.mmap		= generic_file_mmap,
 	.fsync		= block_fsync,
 	.ioctl		= blkdev_ioctl,
-	.readv		= generic_file_readv,
-	.writev		= generic_file_writev,
 	.sendfile	= generic_file_sendfile,
 };
 
diff -purN linux-2.5/fs/cifs/cifsfs.c aio-2.5/fs/cifs/cifsfs.c
--- linux-2.5/fs/cifs/cifsfs.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/cifs/cifsfs.c	Mon Mar 24 11:25:00 2003
@@ -316,8 +316,8 @@ struct inode_operations cifs_symlink_ino
 };
 
 struct file_operations cifs_file_ops = {
-	.read = generic_file_read,
-	.write = generic_file_write, 
+	.aio_read = generic_file_aio_read,
+	.aio_write = generic_file_aio_write, 
 	.open = cifs_open,
 	.release = cifs_close,
 	.lock = cifs_lock,
diff -purN linux-2.5/fs/direct-io.c aio-2.5/fs/direct-io.c
--- linux-2.5/fs/direct-io.c	Tue Apr  1 15:17:52 2003
+++ aio-2.5/fs/direct-io.c	Mon Mar 24 17:26:02 2003
@@ -113,7 +113,7 @@ struct dio {
 	struct task_struct *waiter;	/* waiting task (NULL if none) */
 
 	/* AIO related stuff */
-	struct kiocb *iocb;		/* kiocb */
+	struct rw_iocb *iocb;		/* kiocb */
 	int is_async;			/* is IO async ? */
 	int result;			/* IO result */
 };
@@ -200,7 +200,7 @@ static void finished_one_bio(struct dio 
 {
 	if (atomic_dec_and_test(&dio->bio_count)) {
 		if(dio->is_async) {
-			aio_complete(dio->iocb, dio->result, 0);
+			aio_complete(&dio->iocb->kiocb, dio->result, 0);
 			kfree(dio);
 		}
 	}
@@ -822,7 +822,7 @@ out:
 }
 
 static int
-direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, 
+direct_io_worker(int rw, struct rw_iocb *iocb, struct inode *inode, 
 	const struct iovec *iov, loff_t offset, unsigned long nr_segs, 
 	unsigned blkbits, get_blocks_t get_blocks)
 {
@@ -836,7 +836,7 @@ direct_io_worker(int rw, struct kiocb *i
 	dio = kmalloc(sizeof(*dio), GFP_KERNEL);
 	if (!dio)
 		return -ENOMEM;
-	dio->is_async = !is_sync_kiocb(iocb);
+	dio->is_async = !is_sync_kiocb(&iocb->kiocb);
 
 	dio->bio = NULL;
 	dio->inode = inode;
@@ -960,7 +960,7 @@ direct_io_worker(int rw, struct kiocb *i
  * This is a library function for use by filesystem drivers.
  */
 int
-blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, 
+blockdev_direct_IO(int rw, struct rw_iocb *iocb, struct inode *inode, 
 	struct block_device *bdev, const struct iovec *iov, loff_t offset, 
 	unsigned long nr_segs, get_blocks_t get_blocks)
 {
diff -purN linux-2.5/fs/ext2/file.c aio-2.5/fs/ext2/file.c
--- linux-2.5/fs/ext2/file.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/ext2/file.c	Mon Mar 24 15:39:52 2003
@@ -41,8 +41,6 @@ static int ext2_release_file (struct ino
  */
 struct file_operations ext2_file_operations = {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= generic_file_write,
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.ioctl		= ext2_ioctl,
@@ -50,8 +48,6 @@ struct file_operations ext2_file_operati
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
 	.fsync		= ext2_sync_file,
-	.readv		= generic_file_readv,
-	.writev		= generic_file_writev,
 	.sendfile	= generic_file_sendfile,
 };
 
diff -purN linux-2.5/fs/ext2/inode.c aio-2.5/fs/ext2/inode.c
--- linux-2.5/fs/ext2/inode.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/ext2/inode.c	Mon Mar 24 17:26:06 2003
@@ -650,10 +650,10 @@ ext2_get_blocks(struct inode *inode, sec
 }
 
 static int
-ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+ext2_direct_IO(int rw, struct rw_iocb *iocb, const struct iovec *iov,
 			loff_t offset, unsigned long nr_segs)
 {
-	struct file *file = iocb->ki_filp;
+	struct file *file = iocb->kiocb.ki_filp;
 	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 
 	return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
diff -purN linux-2.5/fs/ext3/file.c aio-2.5/fs/ext3/file.c
--- linux-2.5/fs/ext3/file.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/ext3/file.c	Mon Mar 24 17:26:09 2003
@@ -56,13 +56,13 @@ static int ext3_open_file (struct inode 
 }
 
 static ssize_t
-ext3_file_write(struct kiocb *iocb, const char *buf, size_t count, loff_t pos)
+ext3_file_write(struct rw_iocb *iocb)
 {
-	struct file *file = iocb->ki_filp;
+	struct file *file = iocb->kiocb.ki_filp;
 	struct inode *inode = file->f_dentry->d_inode;
 	int ret, err;
 
-	ret = generic_file_aio_write(iocb, buf, count, pos);
+	ret = generic_file_aio_write(iocb);
 
 	/*
 	 * Skip flushing if there was an error, or if nothing was written.
@@ -114,12 +114,8 @@ force_commit:
 
 struct file_operations ext3_file_operations = {
 	.llseek		= generic_file_llseek,
-	.read		= do_sync_read,
-	.write		= do_sync_write,
-	.aio_read		= generic_file_aio_read,
-	.aio_write		= ext3_file_write,
-	.readv		= generic_file_readv,
-	.writev		= generic_file_writev,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= ext3_file_write,
 	.ioctl		= ext3_ioctl,
 	.mmap		= generic_file_mmap,
 	.open		= ext3_open_file,
diff -purN linux-2.5/fs/ext3/inode.c aio-2.5/fs/ext3/inode.c
--- linux-2.5/fs/ext3/inode.c	Tue Apr  1 15:17:53 2003
+++ aio-2.5/fs/ext3/inode.c	Mon Mar 24 17:26:13 2003
@@ -1426,11 +1426,11 @@ static int ext3_releasepage(struct page 
  * If the O_DIRECT write is intantiating holes inside i_size and the machine
  * crashes then stale disk data _may_ be exposed inside the file.
  */
-static int ext3_direct_IO(int rw, struct kiocb *iocb,
+static int ext3_direct_IO(int rw, struct rw_iocb *iocb,
 			const struct iovec *iov, loff_t offset,
 			unsigned long nr_segs)
 {
-	struct file *file = iocb->ki_filp;
+	struct file *file = iocb->kiocb.ki_filp;
 	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	handle_t *handle = NULL;
diff -purN linux-2.5/fs/fat/file.c aio-2.5/fs/fat/file.c
--- linux-2.5/fs/fat/file.c	Tue Apr  1 15:17:54 2003
+++ aio-2.5/fs/fat/file.c	Mon Mar 24 17:54:55 2003
@@ -11,13 +11,12 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 
-static ssize_t fat_file_write(struct file *filp, const char *buf, size_t count,
-			      loff_t *ppos);
+static ssize_t fat_file_write(struct rw_iocb *iocb);
 
 struct file_operations fat_file_operations = {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= fat_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= fat_file_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= file_fsync,
 	.sendfile	= generic_file_sendfile,
@@ -65,14 +64,14 @@ int fat_get_block(struct inode *inode, s
 	return 0;
 }
 
-static ssize_t fat_file_write(struct file *filp, const char *buf, size_t count,
-			      loff_t *ppos)
+static ssize_t fat_file_write(struct rw_iocb *iocb)
 {
-	struct inode *inode = filp->f_dentry->d_inode;
+	struct file *filp = iocb->kiocb.ki_filp;
 	int retval;
 
-	retval = generic_file_write(filp, buf, count, ppos);
+	retval = generic_file_aio_write(iocb);
 	if (retval > 0) {
+		struct inode *inode = filp->f_dentry->d_inode;
 		inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
 		mark_inode_dirty(inode);
diff -purN linux-2.5/fs/freevxfs/vxfs_inode.c aio-2.5/fs/freevxfs/vxfs_inode.c
--- linux-2.5/fs/freevxfs/vxfs_inode.c	Tue Apr  1 15:17:55 2003
+++ aio-2.5/fs/freevxfs/vxfs_inode.c	Mon Mar 24 11:25:00 2003
@@ -51,7 +51,7 @@ extern struct inode_operations vxfs_imme
 static struct file_operations vxfs_file_operations = {
 	.open =			generic_file_open,
 	.llseek =		generic_file_llseek,
-	.read =			generic_file_read,
+	.aio_read =		generic_file_aio_read,
 	.mmap =			generic_file_mmap,
 	.sendfile =		generic_file_sendfile,
 };
diff -purN linux-2.5/fs/hpfs/file.c aio-2.5/fs/hpfs/file.c
--- linux-2.5/fs/hpfs/file.c	Tue Apr  1 15:17:55 2003
+++ aio-2.5/fs/hpfs/file.c	Mon Mar 24 11:25:00 2003
@@ -123,17 +123,3 @@ struct address_space_operations hpfs_aop
 	.commit_write = generic_commit_write,
 	.bmap = _hpfs_bmap
 };
-
-ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-	ssize_t retval;
-
-	retval = generic_file_write(file, buf, count, ppos);
-	if (retval > 0) {
-		struct inode *inode = file->f_dentry->d_inode;
-		inode->i_mtime = CURRENT_TIME;
-		hpfs_i(inode)->i_dirty = 1;
-	}
-	return retval;
-}
-
diff -purN linux-2.5/fs/hpfs/inode.c aio-2.5/fs/hpfs/inode.c
--- linux-2.5/fs/hpfs/inode.c	Tue Apr  1 15:17:55 2003
+++ aio-2.5/fs/hpfs/inode.c	Mon Mar 24 11:25:00 2003
@@ -15,7 +15,7 @@
 static struct file_operations hpfs_file_ops =
 {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
+	.aio_read	= generic_file_aio_read,
 	.write		= hpfs_file_write,
 	.mmap		= generic_file_mmap,
 	.open		= hpfs_open,
diff -purN linux-2.5/fs/jffs/inode-v23.c aio-2.5/fs/jffs/inode-v23.c
--- linux-2.5/fs/jffs/inode-v23.c	Tue Apr  1 15:17:55 2003
+++ aio-2.5/fs/jffs/inode-v23.c	Mon Mar 24 11:25:00 2003
@@ -1639,8 +1639,8 @@ static struct file_operations jffs_file_
 {
 	.open		= generic_file_open,
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= generic_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
 	.ioctl		= jffs_ioctl,
 	.mmap		= generic_file_readonly_mmap,
 	.fsync		= jffs_fsync,
diff -purN linux-2.5/fs/jffs2/file.c aio-2.5/fs/jffs2/file.c
--- linux-2.5/fs/jffs2/file.c	Tue Apr  1 15:17:55 2003
+++ aio-2.5/fs/jffs2/file.c	Mon Mar 24 11:46:18 2003
@@ -55,8 +55,8 @@ struct file_operations jffs2_file_operat
 {
 	.llseek =	generic_file_llseek,
 	.open =		generic_file_open,
-	.read =		generic_file_read,
-	.write =	generic_file_write,
+	.aio_read =	generic_file_aio_read,
+	.aio_write =	generic_file_aio_write,
 	.ioctl =	jffs2_ioctl,
 	.mmap =		generic_file_readonly_mmap,
 	.fsync =	jffs2_fsync,
diff -purN linux-2.5/fs/jfs/file.c aio-2.5/fs/jfs/file.c
--- linux-2.5/fs/jfs/file.c	Tue Apr  1 15:17:55 2003
+++ aio-2.5/fs/jfs/file.c	Mon Mar 24 15:40:01 2003
@@ -100,13 +100,9 @@ struct inode_operations jfs_file_inode_o
 struct file_operations jfs_file_operations = {
 	.open		= jfs_open,
 	.llseek		= generic_file_llseek,
-	.write		= generic_file_write,
-	.read		= generic_file_read,
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.readv		= generic_file_readv,
-	.writev		= generic_file_writev,
  	.sendfile	= generic_file_sendfile,
 	.fsync		= jfs_fsync,
 	.release	= jfs_release,
diff -purN linux-2.5/fs/minix/file.c aio-2.5/fs/minix/file.c
--- linux-2.5/fs/minix/file.c	Tue Apr  1 15:17:55 2003
+++ aio-2.5/fs/minix/file.c	Mon Mar 24 11:25:00 2003
@@ -17,8 +17,8 @@ int minix_sync_file(struct file *, struc
 
 struct file_operations minix_file_operations = {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= generic_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= minix_sync_file,
 	.sendfile	= generic_file_sendfile,
diff -purN linux-2.5/fs/nfs/file.c aio-2.5/fs/nfs/file.c
--- linux-2.5/fs/nfs/file.c	Tue Apr  1 15:17:56 2003
+++ aio-2.5/fs/nfs/file.c	Mon Mar 24 17:26:18 2003
@@ -36,17 +36,15 @@
 
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
 static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
-static ssize_t nfs_file_read(struct kiocb *, char *, size_t, loff_t);
-static ssize_t nfs_file_write(struct kiocb *, const char *, size_t, loff_t);
+static ssize_t nfs_file_read(struct rw_iocb *);
+static ssize_t nfs_file_write(struct rw_iocb *);
 static int  nfs_file_flush(struct file *);
 static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
 
 struct file_operations nfs_file_operations = {
 	.llseek		= remote_llseek,
-	.read		= do_sync_read,
-	.write		= do_sync_write,
-	.aio_read		= nfs_file_read,
-	.aio_write		= nfs_file_write,
+	.aio_read	= nfs_file_read,
+	.aio_write	= nfs_file_write,
 	.mmap		= nfs_file_mmap,
 	.open		= nfs_open,
 	.flush		= nfs_file_flush,
@@ -88,19 +86,19 @@ nfs_file_flush(struct file *file)
 }
 
 static ssize_t
-nfs_file_read(struct kiocb *iocb, char * buf, size_t count, loff_t pos)
+nfs_file_read(struct rw_iocb *iocb)
 {
-	struct dentry * dentry = iocb->ki_filp->f_dentry;
+	struct dentry * dentry = iocb->kiocb.ki_filp->f_dentry;
 	struct inode * inode = dentry->d_inode;
 	ssize_t result;
 
 	dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
-		(unsigned long) count, (unsigned long) pos);
+		(unsigned long)iocb->rw_iov->iov_len, (unsigned long)iocb->rw_pos);
 
 	result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	if (!result)
-		result = generic_file_aio_read(iocb, buf, count, pos);
+		result = generic_file_aio_read(iocb);
 	return result;
 }
 
@@ -202,15 +200,16 @@ struct address_space_operations nfs_file
  * Write to a file (through the page cache).
  */
 static ssize_t
-nfs_file_write(struct kiocb *iocb, const char *buf, size_t count, loff_t pos)
+nfs_file_write(struct rw_iocb *iocb)
 {
-	struct dentry * dentry = iocb->ki_filp->f_dentry;
+	struct dentry * dentry = iocb->kiocb.ki_filp->f_dentry;
 	struct inode * inode = dentry->d_inode;
 	ssize_t result;
 
 	dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
-		inode->i_ino, (unsigned long) count, (unsigned long) pos);
+		inode->i_ino, (unsigned long)iocb->rw_iov->iov_len,
+		(unsigned long)iocb->rw_pos);
 
 	result = -EBUSY;
 	if (IS_SWAPFILE(inode))
@@ -219,11 +218,7 @@ nfs_file_write(struct kiocb *iocb, const
 	if (result)
 		goto out;
 
-	result = count;
-	if (!count)
-		goto out;
-
-	result = generic_file_aio_write(iocb, buf, count, pos);
+	result = generic_file_aio_write(iocb);
 out:
 	return result;
 
diff -purN linux-2.5/fs/nfs/write.c aio-2.5/fs/nfs/write.c
--- linux-2.5/fs/nfs/write.c	Tue Apr  1 15:17:56 2003
+++ aio-2.5/fs/nfs/write.c	Mon Mar 24 11:25:01 2003
@@ -28,7 +28,7 @@
  *
  *  -	A write request is in progress.
  *  -	A user process is in generic_file_write/nfs_update_page
- *  -	A user process is in generic_file_read
+ *  -	A user process is in generic_file_aio_read
  *
  * Also note that because of the way pages are invalidated in
  * nfs_revalidate_inode, the following assertions hold:
@@ -645,7 +645,7 @@ nfs_flush_incompatible(struct file *file
 /*
  * Update and possibly write a cached page of an NFS file.
  *
- * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad
+ * XXX: Keep an eye on generic_file_aio_read to make sure it doesn't do bad
  * things with a page scheduled for an RPC call (e.g. invalidate it).
  */
 int
diff -purN linux-2.5/fs/ntfs/aops.c aio-2.5/fs/ntfs/aops.c
--- linux-2.5/fs/ntfs/aops.c	Tue Apr  1 15:17:56 2003
+++ aio-2.5/fs/ntfs/aops.c	Mon Mar 24 11:25:01 2003
@@ -157,7 +157,7 @@ still_busy:
  * unlocking it.
  *
  * We only enforce allocated_size limit because i_size is checked for in
- * generic_file_read().
+ * generic_file_aio_read().
  *
  * Return 0 on success and -errno on error.
  *
diff -purN linux-2.5/fs/ntfs/file.c aio-2.5/fs/ntfs/file.c
--- linux-2.5/fs/ntfs/file.c	Tue Apr  1 15:17:56 2003
+++ aio-2.5/fs/ntfs/file.c	Mon Mar 24 11:46:18 2003
@@ -50,9 +50,9 @@ static int ntfs_file_open(struct inode *
 
 struct file_operations ntfs_file_ops = {
 	.llseek		= generic_file_llseek,	/* Seek inside file. */
-	.read		= generic_file_read,	/* Read from file. */
+	.aio_read	= generic_file_aio_read,/* Read from file. */
 #ifdef NTFS_RW
-	.write		= generic_file_write,	/* Write to a file. */
+	.aio_write	= generic_file_aio_write,/* Write to a file. */
 #endif
 	.mmap		= generic_file_mmap,	/* Mmap file. */
 	.sendfile	= generic_file_sendfile,/* Zero-copy data send with the
diff -purN linux-2.5/fs/qnx4/file.c aio-2.5/fs/qnx4/file.c
--- linux-2.5/fs/qnx4/file.c	Tue Apr  1 15:17:56 2003
+++ aio-2.5/fs/qnx4/file.c	Mon Mar 24 11:25:01 2003
@@ -25,11 +25,11 @@
 struct file_operations qnx4_file_operations =
 {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
+	.aio_read	= generic_file_aio_read,
 	.mmap		= generic_file_mmap,
 	.sendfile	= generic_file_sendfile,
 #ifdef CONFIG_QNX4FS_RW
-	.write		= generic_file_write,
+	.aio_write	= generic_file_aio_write,
 	.fsync		= qnx4_sync_file,
 #endif
 };
diff -purN linux-2.5/fs/ramfs/inode.c aio-2.5/fs/ramfs/inode.c
--- linux-2.5/fs/ramfs/inode.c	Tue Apr  1 15:17:56 2003
+++ aio-2.5/fs/ramfs/inode.c	Mon Mar 24 11:25:01 2003
@@ -141,8 +141,8 @@ static struct address_space_operations r
 };
 
 static struct file_operations ramfs_file_operations = {
-	.read		= generic_file_read,
-	.write		= generic_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= simple_sync_file,
 	.sendfile	= generic_file_sendfile,
diff -purN linux-2.5/fs/read_write.c aio-2.5/fs/read_write.c
--- linux-2.5/fs/read_write.c	Tue Mar 25 16:50:38 2003
+++ aio-2.5/fs/read_write.c	Tue Mar 25 16:17:41 2003
@@ -18,7 +18,7 @@
 
 struct file_operations generic_ro_fops = {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
+	.aio_read	= generic_file_aio_read,
 	.mmap		= generic_file_readonly_mmap,
 	.sendfile	= generic_file_sendfile,
 };
@@ -167,28 +167,44 @@ bad:
 }
 #endif
 
-ssize_t do_sync_read(struct file *filp, char *buf, size_t len, loff_t *ppos)
+static ssize_t do_sync_rwv(struct file *filp, char *buf, size_t tot_len,
+			   struct iovec *iov, unsigned nr_segs, loff_t *ppos,
+			   ssize_t (*op)(struct rw_iocb *), int rw)
 {
-	struct kiocb kiocb;
+	struct sync_iocb sync_iocb;
+	struct rw_iocb *iocb = kiocb_to_rw_iocb(&sync_iocb.kiocb);
 	ssize_t ret;
 
-	init_sync_kiocb(&kiocb, filp);
-	kiocb.ki_pos = *ppos;
-	ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos);
+	init_sync_kiocb(&iocb->kiocb, filp);
+	iocb->rw = rw;
+	iocb->rw_pos = *ppos;
+	iocb->rw_nsegs = nr_segs;
+	iocb->rw_iov = (NULL == iov) ? &iocb->rw_local_iov : iov;
+	iocb->rw_local_iov.iov_base = buf;
+	iocb->rw_local_iov.iov_len = tot_len;
+	
+	ret = op(iocb);
 	if (-EIOCBQUEUED == ret)
-		ret = wait_on_sync_kiocb(&kiocb);
-	*ppos = kiocb.ki_pos;
+		ret = wait_on_sync_kiocb(&iocb->kiocb);
+	*ppos = iocb->rw_pos;
 	return ret;
 }
 
+ssize_t do_sync_rw(struct file *filp, char *buf, size_t count, loff_t *ppos,
+		   ssize_t (*op)(struct rw_iocb *), int rw)
+{
+	return do_sync_rwv(filp, buf, count, NULL, 1, ppos, op, rw);
+}
+
 ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	ssize_t ret;
 
-	if (!(file->f_mode & FMODE_READ))
+	if (unlikely(!(file->f_mode & FMODE_READ)))
 		return -EBADF;
-	if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
+	if (unlikely(!file->f_op ||
+		     (!file->f_op->read && !file->f_op->aio_read)))
 		return -EINVAL;
 
 	ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count);
@@ -198,7 +214,8 @@ ssize_t vfs_read(struct file *file, char
 			if (file->f_op->read)
 				ret = file->f_op->read(file, buf, count, pos);
 			else
-				ret = do_sync_read(file, buf, count, pos);
+				ret = do_sync_rw(file, buf, count, pos,
+						 file->f_op->aio_read, READ);
 			if (ret > 0)
 				dnotify_parent(file->f_dentry, DN_ACCESS);
 		}
@@ -207,28 +224,15 @@ ssize_t vfs_read(struct file *file, char
 	return ret;
 }
 
-ssize_t do_sync_write(struct file *filp, const char *buf, size_t len, loff_t *ppos)
-{
-	struct kiocb kiocb;
-	ssize_t ret;
-
-	init_sync_kiocb(&kiocb, filp);
-	kiocb.ki_pos = *ppos;
-	ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos);
-	if (-EIOCBQUEUED == ret)
-		ret = wait_on_sync_kiocb(&kiocb);
-	*ppos = kiocb.ki_pos;
-	return ret;
-}
-
 ssize_t vfs_write(struct file *file, const char *buf, size_t count, loff_t *pos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	ssize_t ret;
 
-	if (!(file->f_mode & FMODE_WRITE))
+	if (unlikely(!(file->f_mode & FMODE_WRITE)))
 		return -EBADF;
-	if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
+	if (unlikely(!file->f_op ||
+		     (!file->f_op->write && !file->f_op->aio_write)))
 		return -EINVAL;
 
 	ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count);
@@ -238,7 +242,8 @@ ssize_t vfs_write(struct file *file, con
 			if (file->f_op->write)
 				ret = file->f_op->write(file, buf, count, pos);
 			else
-				ret = do_sync_write(file, buf, count, pos);
+				ret = do_sync_rw(file, (char *)buf, count, pos,
+						 file->f_op->aio_write, WRITE);
 			if (ret > 0)
 				dnotify_parent(file->f_dentry, DN_MODIFY);
 		}
@@ -331,29 +336,58 @@ unsigned long iov_shorten(struct iovec *
 	return seg;
 }
 
-static ssize_t do_readv_writev(int type, struct file *file,
+ssize_t compat_rwv(struct file *file, const struct iovec *vector,
+		   unsigned long nr_segs, loff_t *ppos,
+		   ssize_t (*fn)(struct file *, char *, size_t, loff_t *))
+{
+	ssize_t ret = 0;
+
+	if (NULL == fn)
+		return -EINVAL;
+
+	/* Do it by hand, with file-ops */
+	for (; nr_segs > 0; vector++, nr_segs--) {
+		void *base = vector->iov_base;
+		size_t len = vector->iov_len;
+		ssize_t nr = fn(file, base, len, ppos);
+
+		if (nr < 0) {
+			if (!ret)
+				ret = nr;
+			break;
+		}
+		ret += nr;
+		if (nr != len)
+			break;
+	}
+	return ret;
+}
+
+static ssize_t do_readv_writev(int fmode, int type, struct file *file,
 			       const struct iovec * vector,
 			       unsigned long nr_segs, loff_t *pos)
 {
 	typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
 	typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
+	typedef ssize_t (*ioa_fn_t)(struct rw_iocb *);
 
-	size_t tot_len;
+	size_t tot_len = 0;
 	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov=iovstack;
-	ssize_t ret;
+	struct iovec *iov = iovstack;
+	ssize_t ret = 0;
 	int seg;
 	io_fn_t fn;
 	iov_fn_t fnv;
-	struct inode *inode;
+	ioa_fn_t fna;
 
+	if (!(file->f_mode & fmode))
+		return -EBADF;
 	/*
 	 * SuS says "The readv() function *may* fail if the iovcnt argument
 	 * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
 	 * traditionally returned zero for zero segments, so...
 	 */
-	ret = 0;
-	if (nr_segs == 0)
+	if (unlikely(nr_segs == 0))
 		goto out;
 
 	/*
@@ -365,6 +399,7 @@ static ssize_t do_readv_writev(int type,
 		goto out;
 	if (!file->f_op)
 		goto out;
+
 	if (nr_segs > UIO_FASTIOV) {
 		ret = -ENOMEM;
 		iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
@@ -382,7 +417,6 @@ static ssize_t do_readv_writev(int type,
 	 *
 	 * Be careful here because iov_len is a size_t not an ssize_t
 	 */
-	tot_len = 0;
 	ret = -EINVAL;
 	for (seg = 0 ; seg < nr_segs; seg++) {
 		ssize_t tmp = tot_len;
@@ -393,55 +427,32 @@ static ssize_t do_readv_writev(int type,
 		if (tot_len < tmp) /* maths overflow on the ssize_t */
 			goto out;
 	}
-	if (tot_len == 0) {
-		ret = 0;
+	ret = 0;
+	if (tot_len == 0)
 		goto out;
-	}
 
-	inode = file->f_dentry->d_inode;
 	/* VERIFY_WRITE actually means a read, as we write to user space */
 	ret = locks_verify_area((type == READ 
 				 ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
-				inode, file, *pos, tot_len);
+				file->f_dentry->d_inode, file, *pos, tot_len);
 	if (ret)
 		goto out;
 
-	fnv = NULL;
 	if (type == READ) {
 		fn = file->f_op->read;
 		fnv = file->f_op->readv;
+		fna = file->f_op->aio_read;
 	} else {
 		fn = (io_fn_t)file->f_op->write;
 		fnv = file->f_op->writev;
+		fna = file->f_op->aio_write;
 	}
-	if (fnv) {
+	if (fnv)
 		ret = fnv(file, iov, nr_segs, pos);
-		goto out;
-	}
-
-	/* Do it by hand, with file-ops */
-	ret = 0;
-	vector = iov;
-	while (nr_segs > 0) {
-		void * base;
-		size_t len;
-		ssize_t nr;
-
-		base = vector->iov_base;
-		len = vector->iov_len;
-		vector++;
-		nr_segs--;
-
-		nr = fn(file, base, len, pos);
-
-		if (nr < 0) {
-			if (!ret) ret = nr;
-			break;
-		}
-		ret += nr;
-		if (nr != len)
-			break;
-	}
+	else if (fna)
+		ret = do_sync_rwv(file, NULL, tot_len, iov, nr_segs, pos, fna, type);
+	else
+		ret = compat_rwv(file, iov, nr_segs, pos, fn);
 out:
 	if (iov != iovstack)
 		kfree(iov);
@@ -454,23 +465,13 @@ out:
 ssize_t vfs_readv(struct file *file, const struct iovec *vec,
 		  unsigned long vlen, loff_t *pos)
 {
-	if (!(file->f_mode & FMODE_READ))
-		return -EBADF;
-	if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
-		return -EINVAL;
-
-	return do_readv_writev(READ, file, vec, vlen, pos);
+	return do_readv_writev(FMODE_READ, READ, file, vec, vlen, pos);
 }
 
 ssize_t vfs_writev(struct file *file, const struct iovec *vec,
 		   unsigned long vlen, loff_t *pos)
 {
-	if (!(file->f_mode & FMODE_WRITE))
-		return -EBADF;
-	if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
-		return -EINVAL;
-
-	return do_readv_writev(WRITE, file, vec, vlen, pos);
+	return do_readv_writev(FMODE_WRITE, WRITE, file, vec, vlen, pos);
 }
 
 
@@ -622,5 +623,4 @@ asmlinkage ssize_t sys_sendfile64(int ou
 	return do_sendfile(out_fd, in_fd, NULL, count, 0);
 }
 
-EXPORT_SYMBOL(do_sync_read);
-EXPORT_SYMBOL(do_sync_write);
+EXPORT_SYMBOL(do_sync_rw);
diff -purN linux-2.5/fs/reiserfs/file.c aio-2.5/fs/reiserfs/file.c
--- linux-2.5/fs/reiserfs/file.c	Tue Apr  1 15:17:56 2003
+++ aio-2.5/fs/reiserfs/file.c	Mon Mar 24 11:25:01 2003
@@ -141,8 +141,8 @@ out:
 }
 
 struct file_operations reiserfs_file_operations = {
-    .read	= generic_file_read,
-    .write	= generic_file_write,
+    .aio_read	= generic_file_aio_read,
+    .aio_write	= generic_file_aio_write,
     .ioctl	= reiserfs_ioctl,
     .mmap	= generic_file_mmap,
     .release	= reiserfs_file_release,
diff -purN linux-2.5/fs/smbfs/file.c aio-2.5/fs/smbfs/file.c
--- linux-2.5/fs/smbfs/file.c	Tue Apr  1 15:17:56 2003
+++ aio-2.5/fs/smbfs/file.c	Mon Mar 24 11:46:18 2003
@@ -216,13 +216,13 @@ smb_updatepage(struct file *file, struct
 }
 
 static ssize_t
-smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
+smb_file_read(struct kiocb *iocb, char *buf, size_t count, loff_t pos)
 {
-	struct dentry * dentry = file->f_dentry;
+	struct dentry * dentry = iocb->ki_filp->f_dentry;
 	ssize_t	status;
 
 	VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
-		(unsigned long) count, (unsigned long) *ppos);
+		(unsigned long) count, (unsigned long) pos);
 
 	status = smb_revalidate_inode(dentry);
 	if (status) {
@@ -235,7 +235,7 @@ smb_file_read(struct file * file, char *
 		(long)dentry->d_inode->i_size,
 		dentry->d_inode->i_flags, dentry->d_inode->i_atime);
 
-	status = generic_file_read(file, buf, count, ppos);
+	status = generic_file_aio_read(iocb, buf, count, pos);
 out:
 	return status;
 }
@@ -298,14 +298,14 @@ struct address_space_operations smb_file
  * Write to a file (through the page cache).
  */
 static ssize_t
-smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+smb_file_write(struct kiocb *iocb, const char *buf, size_t count, loff_t pos)
 {
-	struct dentry * dentry = file->f_dentry;
+	struct dentry * dentry = iocb->ki_filp->f_dentry;
 	ssize_t	result;
 
 	VERBOSE("file %s/%s, count=%lu@%lu\n",
 		DENTRY_PATH(dentry),
-		(unsigned long) count, (unsigned long) *ppos);
+		(unsigned long) count, (unsigned long) pos);
 
 	result = smb_revalidate_inode(dentry);
 	if (result) {
@@ -319,7 +319,7 @@ smb_file_write(struct file *file, const 
 		goto out;
 
 	if (count > 0) {
-		result = generic_file_write(file, buf, count, ppos);
+		result = generic_file_aio_write(iocb, buf, count, pos);
 		VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
 			(long) file->f_pos, (long) dentry->d_inode->i_size,
 			dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
@@ -384,8 +384,8 @@ smb_file_permission(struct inode *inode,
 struct file_operations smb_file_operations =
 {
 	.llseek		= remote_llseek,
-	.read		= smb_file_read,
-	.write		= smb_file_write,
+	.aio_read	= smb_file_read,
+	.aio_write	= smb_file_write,
 	.ioctl		= smb_ioctl,
 	.mmap		= smb_file_mmap,
 	.open		= smb_file_open,
diff -purN linux-2.5/fs/sysv/file.c aio-2.5/fs/sysv/file.c
--- linux-2.5/fs/sysv/file.c	Tue Apr  1 15:17:57 2003
+++ aio-2.5/fs/sysv/file.c	Mon Mar 24 11:25:05 2003
@@ -21,8 +21,8 @@
  */
 struct file_operations sysv_file_operations = {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= generic_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= sysv_sync_file,
 	.sendfile	= generic_file_sendfile,
diff -purN linux-2.5/fs/udf/file.c aio-2.5/fs/udf/file.c
--- linux-2.5/fs/udf/file.c	Tue Apr  1 15:17:57 2003
+++ aio-2.5/fs/udf/file.c	Mon Mar 24 11:25:05 2003
@@ -109,19 +109,17 @@ struct address_space_operations udf_adin
 	.commit_write		= udf_adinicb_commit_write,
 };
 
-static ssize_t udf_file_write(struct file * file, const char * buf,
-	size_t count, loff_t *ppos)
+static ssize_t udf_file_write(struct kiocb *iocb, const char * buf,
+			      size_t count, loff_t pos)
 {
 	ssize_t retval;
-	struct inode *inode = file->f_dentry->d_inode;
-	int err, pos;
+	struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+	int err;
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
 	{
-		if (file->f_flags & O_APPEND)
+		if (iocb->ki_filp->f_flags & O_APPEND)
 			pos = inode->i_size;
-		else
-			pos = *ppos;
 
 		if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
 			pos + count))
@@ -142,7 +140,7 @@ static ssize_t udf_file_write(struct fil
 		}
 	}
 
-	retval = generic_file_write(file, buf, count, ppos);
+	retval = generic_file_aio_write(iocb, buf, count, pos);
 
 	if (retval > 0)
 		mark_inode_dirty(inode);
@@ -275,11 +273,11 @@ static int udf_open_file(struct inode * 
 }
 
 struct file_operations udf_file_operations = {
-	.read			= generic_file_read,
+	.aio_read		= generic_file_aio_read,
+	.aio_write		= udf_file_write,
 	.ioctl			= udf_ioctl,
 	.open			= udf_open_file,
 	.mmap			= generic_file_mmap,
-	.write			= udf_file_write,
 	.release		= udf_release_file,
 	.fsync			= udf_fsync_file,
 	.sendfile		= generic_file_sendfile,
diff -purN linux-2.5/fs/ufs/file.c aio-2.5/fs/ufs/file.c
--- linux-2.5/fs/ufs/file.c	Tue Apr  1 15:17:57 2003
+++ aio-2.5/fs/ufs/file.c	Mon Mar 24 11:25:05 2003
@@ -43,8 +43,8 @@
  
 struct file_operations ufs_file_operations = {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= generic_file_write,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.open           = generic_file_open,
 	.sendfile	= generic_file_sendfile,
diff -purN linux-2.5/include/linux/aio.h aio-2.5/include/linux/aio.h
--- linux-2.5/include/linux/aio.h	Tue Apr  1 15:18:08 2003
+++ aio-2.5/include/linux/aio.h	Tue Mar 25 15:35:56 2003
@@ -4,6 +4,7 @@
 #include <linux/list.h>
 #include <linux/workqueue.h>
 #include <linux/aio_abi.h>
+#include <linux/uio.h>
 
 #include <asm/atomic.h>
 
@@ -61,22 +62,68 @@ struct kiocb {
 
 	void			*ki_user_obj;	/* pointer to userland's iocb */
 	__u64			ki_user_data;	/* user's data for completion */
-	loff_t			ki_pos;
 
-	char			private[KIOCB_PRIVATE_SIZE];
+	long			private[0];	/* KIOCB_PRIVATE_SIZE alloc'd */
 };
 
-#define is_sync_kiocb(iocb)	((iocb)->ki_key == KIOCB_SYNC_KEY)
+struct rw_iocb {
+	struct kiocb	kiocb;
+	loff_t		rw_pos;
+	unsigned long	rw_nsegs;
+
+	struct iovec	*rw_iov;
+	struct iovec	rw_local_iov;
+
+	unsigned	rw : 2,			/* READ or WRITE */
+			rw_have_i_sem : 1;	/* true if we hold i_sem */
+};
+
+struct fsync_iocb {
+	struct kiocb	kiocb;
+	unsigned	dsync;
+};
+
+struct sync_iocb {
+	union {
+	struct kiocb		kiocb;
+	struct rw_iocb		rw_iocb;
+	struct fsync_iocb	fsync_iocb;
+	};
+	char		private[KIOCB_PRIVATE_SIZE];
+};
+
+typedef union {
+	struct kiocb		kiocb;
+	struct rw_iocb		rw_iocb;
+	struct sync_iocb	sync_iocb;
+} iocb_t;
+
+static inline struct rw_iocb *kiocb_to_rw_iocb(struct kiocb *iocb)
+{
+	return (struct rw_iocb *)iocb;
+}
+
+static inline struct fsync_iocb *kiocb_to_fsync_iocb(struct kiocb *iocb)
+{
+	return (struct fsync_iocb *)iocb;
+}
+
+static inline int is_sync_kiocb(struct kiocb *iocb)
+{
+	return iocb->ki_key == KIOCB_SYNC_KEY;
+}
+
 #define init_sync_kiocb(x, filp)			\
 	do {						\
+		struct kiocb *__iocb = (x);		\
 		struct task_struct *tsk = current;	\
-		(x)->ki_flags = 0;			\
-		(x)->ki_users = 1;			\
-		(x)->ki_key = KIOCB_SYNC_KEY;		\
-		(x)->ki_filp = (filp);			\
-		(x)->ki_ctx = &tsk->active_mm->default_kioctx;	\
-		(x)->ki_cancel = NULL;			\
-		(x)->ki_user_obj = tsk;			\
+		__iocb->ki_flags = 0;			\
+		__iocb->ki_users = 1;			\
+		__iocb->ki_key = KIOCB_SYNC_KEY;	\
+		__iocb->ki_filp = (filp);		\
+		__iocb->ki_ctx = &tsk->active_mm->default_kioctx;\
+		__iocb->ki_cancel = NULL;		\
+		__iocb->ki_user_obj = tsk;		\
 	} while (0)
 
 #define AIO_RING_MAGIC			0xa10a10a1
diff -purN linux-2.5/include/linux/fs.h aio-2.5/include/linux/fs.h
--- linux-2.5/include/linux/fs.h	Tue Mar 25 16:38:50 2003
+++ aio-2.5/include/linux/fs.h	Tue Mar 25 15:29:13 2003
@@ -21,6 +21,8 @@
 #include <linux/kobject.h>
 #include <asm/atomic.h>
 
+struct rw_iocb;
+struct fsync_iocb;
 struct iovec;
 struct nameidata;
 struct pipe_inode_info;
@@ -305,7 +307,7 @@ struct address_space_operations {
 	sector_t (*bmap)(struct address_space *, sector_t);
 	int (*invalidatepage) (struct page *, unsigned long);
 	int (*releasepage) (struct page *, int);
-	int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
+	int (*direct_IO)(int, struct rw_iocb *, const struct iovec *iov,
 			loff_t offset, unsigned long nr_segs);
 };
 
@@ -706,9 +708,9 @@ struct file_operations {
 	struct module *owner;
 	loff_t (*llseek) (struct file *, loff_t, int);
 	ssize_t (*read) (struct file *, char *, size_t, loff_t *);
-	ssize_t (*aio_read) (struct kiocb *, char *, size_t, loff_t);
+	ssize_t (*aio_read) (struct rw_iocb *);
 	ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
-	ssize_t (*aio_write) (struct kiocb *, const char *, size_t, loff_t);
+	ssize_t (*aio_write) (struct rw_iocb *);
 	int (*readdir) (struct file *, void *, filldir_t);
 	unsigned int (*poll) (struct file *, struct poll_table_struct *);
 	int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
@@ -717,7 +719,7 @@ struct file_operations {
 	int (*flush) (struct file *);
 	int (*release) (struct inode *, struct file *);
 	int (*fsync) (struct file *, struct dentry *, int datasync);
-	int (*aio_fsync) (struct kiocb *, int datasync);
+	int (*aio_fsync) (struct fsync_iocb *);
 	int (*fasync) (int, struct file *, int);
 	int (*lock) (struct file *, int, struct file_lock *);
 	ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
@@ -1200,32 +1202,22 @@ extern int generic_file_mmap(struct file
 extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
-extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
 int generic_write_checks(struct inode *inode, struct file *file,
 			loff_t *pos, size_t *count, int isblk);
-extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
-extern ssize_t generic_file_aio_read(struct kiocb *, char *, size_t, loff_t);
-extern ssize_t generic_file_aio_write(struct kiocb *, const char *, size_t, loff_t);
-extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
-				unsigned long, loff_t *);
-extern ssize_t do_sync_read(struct file *filp, char *buf, size_t len, loff_t *ppos);
-extern ssize_t do_sync_write(struct file *filp, const char *buf, size_t len, loff_t *ppos);
-ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
-				unsigned long nr_segs, loff_t *ppos);
+extern ssize_t generic_file_aio_read(struct rw_iocb *);
+extern ssize_t generic_file_aio_write(struct rw_iocb *);
+extern ssize_t generic_file_aio_write_nolock(struct rw_iocb *);
+extern ssize_t FASTCALL(do_sync_rw(struct file *filp, char *buf, size_t len, loff_t *ppos, ssize_t (*op)(struct rw_iocb *), int type));
 extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
 extern void do_generic_mapping_read(struct address_space *, struct file_ra_state *, struct file *,
 				    loff_t *, read_descriptor_t *, read_actor_t);
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
-extern ssize_t generic_file_direct_IO(int rw, struct kiocb *iocb,
+extern ssize_t generic_file_direct_IO(int rw, struct rw_iocb *iocb,
 	const struct iovec *iov, loff_t offset, unsigned long nr_segs);
-extern int blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, 
+extern int blockdev_direct_IO(int rw, struct rw_iocb *iocb, struct inode *inode, 
 	struct block_device *bdev, const struct iovec *iov, loff_t offset, 
 	unsigned long nr_segs, get_blocks_t *get_blocks);
-extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, 
-	unsigned long nr_segs, loff_t *ppos);
-ssize_t generic_file_writev(struct file *filp, const struct iovec *iov, 
-			unsigned long nr_segs, loff_t *ppos);
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t remote_llseek(struct file *file, loff_t offset, int origin);
diff -purN linux-2.5/include/net/sock.h aio-2.5/include/net/sock.h
--- linux-2.5/include/net/sock.h	Tue Apr  1 15:18:12 2003
+++ aio-2.5/include/net/sock.h	Mon Mar 24 17:26:21 2003
@@ -302,6 +302,7 @@ static __inline__ void sock_prot_dec_use
 
 /* sock_iocb: used to kick off async processing of socket ios */
 struct sock_iocb {
+	struct rw_iocb		iocb;
 	struct list_head	list;
 
 	int			flags;
@@ -310,18 +311,23 @@ struct sock_iocb {
 	struct sock		*sk;
 	struct scm_cookie	*scm;
 	struct msghdr		*msg, async_msg;
-	struct iovec		async_iov;
 };
 
 static inline struct sock_iocb *kiocb_to_siocb(struct kiocb *iocb)
 {
-	BUG_ON(sizeof(struct sock_iocb) > KIOCB_PRIVATE_SIZE);
-	return (struct sock_iocb *)iocb->private;
+	BUG_ON(sizeof(struct sock_iocb) > sizeof(iocb_t));
+	return (struct sock_iocb *)iocb;
+}
+
+static inline struct sock_iocb *rw_iocb_to_siocb(struct rw_iocb *iocb)
+{
+	BUG_ON(sizeof(struct sock_iocb) > sizeof(iocb_t));
+	return (struct sock_iocb *)iocb;
 }
 
 static inline struct kiocb *siocb_to_kiocb(struct sock_iocb *si)
 {
-	return container_of((void *)si, struct kiocb, private);
+	return &si->iocb.kiocb;
 }
 
 struct socket_alloc {
diff -purN linux-2.5/kernel/ksyms.c aio-2.5/kernel/ksyms.c
--- linux-2.5/kernel/ksyms.c	Tue Apr  1 15:18:13 2003
+++ aio-2.5/kernel/ksyms.c	Mon Mar 24 12:13:45 2003
@@ -226,12 +226,9 @@ EXPORT_SYMBOL(cont_prepare_write);
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(generic_block_bmap);
-EXPORT_SYMBOL(generic_file_read);
 EXPORT_SYMBOL(generic_file_sendfile);
 EXPORT_SYMBOL(do_generic_mapping_read);
 EXPORT_SYMBOL(file_ra_state_init);
-EXPORT_SYMBOL(generic_file_write);
-EXPORT_SYMBOL(generic_file_write_nolock);
 EXPORT_SYMBOL(generic_file_mmap);
 EXPORT_SYMBOL(generic_file_readonly_mmap);
 EXPORT_SYMBOL(generic_ro_fops);
@@ -356,8 +353,6 @@ EXPORT_SYMBOL(ioctl_by_bdev);
 EXPORT_SYMBOL(read_dev_sector);
 EXPORT_SYMBOL(init_buffer);
 EXPORT_SYMBOL_GPL(generic_file_direct_IO);
-EXPORT_SYMBOL(generic_file_readv);
-EXPORT_SYMBOL(generic_file_writev);
 EXPORT_SYMBOL(iov_shorten);
 EXPORT_SYMBOL_GPL(default_backing_dev_info);
 
diff -purN linux-2.5/mm/filemap.c aio-2.5/mm/filemap.c
--- linux-2.5/mm/filemap.c	Tue Apr  1 15:18:14 2003
+++ aio-2.5/mm/filemap.c	Mon Mar 24 17:24:19 2003
@@ -711,18 +711,16 @@ success:
  * This is the "read()" routine for all filesystems
  * that can use the page cache directly.
  */
-static ssize_t
-__generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
-		unsigned long nr_segs, loff_t *ppos)
+ssize_t generic_file_aio_read(struct rw_iocb *iocb)
 {
-	struct file *filp = iocb->ki_filp;
+	struct file *filp = iocb->kiocb.ki_filp;
 	ssize_t retval;
-	unsigned long seg;
+	unsigned long seg, nr_segs = iocb->rw_nsegs;
 	size_t count;
 
 	count = 0;
 	for (seg = 0; seg < nr_segs; seg++) {
-		const struct iovec *iv = &iov[seg];
+		const struct iovec *iv = &iocb->rw_iov[seg];
 
 		/*
 		 * If any segment has a negative length, or the cumulative
@@ -742,7 +740,7 @@ __generic_file_aio_read(struct kiocb *io
 
 	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
 	if (filp->f_flags & O_DIRECT) {
-		loff_t pos = *ppos, size;
+		loff_t pos = iocb->rw_pos, size;
 		struct address_space *mapping;
 		struct inode *inode;
 
@@ -754,11 +752,11 @@ __generic_file_aio_read(struct kiocb *io
 		size = inode->i_size;
 		if (pos < size) {
 			retval = generic_file_direct_IO(READ, iocb,
-						iov, pos, nr_segs);
-			if (retval >= 0 && !is_sync_kiocb(iocb))
+						iocb->rw_iov, pos, nr_segs);
+			if (retval >= 0 && !is_sync_kiocb(&iocb->kiocb))
 				retval = -EIOCBQUEUED;
 			if (retval > 0)
-				*ppos = pos + retval;
+				iocb->rw_pos = pos + retval;
 		}
 		UPDATE_ATIME(filp->f_dentry->d_inode);
 		goto out;
@@ -770,12 +768,12 @@ __generic_file_aio_read(struct kiocb *io
 			read_descriptor_t desc;
 
 			desc.written = 0;
-			desc.buf = iov[seg].iov_base;
-			desc.count = iov[seg].iov_len;
+			desc.buf = iocb->rw_iov[seg].iov_base;
+			desc.count = iocb->rw_iov[seg].iov_len;
 			if (desc.count == 0)
 				continue;
 			desc.error = 0;
-			do_generic_file_read(filp,ppos,&desc,file_read_actor);
+			do_generic_file_read(filp,&iocb->rw_pos,&desc,file_read_actor);
 			retval += desc.written;
 			if (!retval) {
 				retval = desc.error;
@@ -787,30 +785,8 @@ out:
 	return retval;
 }
 
-ssize_t
-generic_file_aio_read(struct kiocb *iocb, char *buf, size_t count, loff_t pos)
-{
-	struct iovec local_iov = { .iov_base = buf, .iov_len = count };
-
-	BUG_ON(iocb->ki_pos != pos);
-	return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
-}
 EXPORT_SYMBOL(generic_file_aio_read);
 
-ssize_t
-generic_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
-{
-	struct iovec local_iov = { .iov_base = buf, .iov_len = count };
-	struct kiocb kiocb;
-	ssize_t ret;
-
-	init_sync_kiocb(&kiocb, filp);
-	ret = __generic_file_aio_read(&kiocb, &local_iov, 1, ppos);
-	if (-EIOCBQUEUED == ret)
-		ret = wait_on_sync_kiocb(&kiocb);
-	return ret;
-}
-
 int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
 {
 	ssize_t written;
@@ -1572,11 +1548,9 @@ EXPORT_SYMBOL(generic_write_checks);
  * it for writing by marking it dirty.
  *							okir@monad.swb.de
  */
-ssize_t
-generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
-				unsigned long nr_segs, loff_t *ppos)
+ssize_t generic_file_aio_write_nolock(struct rw_iocb *iocb)
 {
-	struct file *file = iocb->ki_filp;
+	struct file *file = iocb->kiocb.ki_filp;
 	struct address_space * mapping = file->f_dentry->d_inode->i_mapping;
 	struct address_space_operations *a_ops = mapping->a_ops;
 	size_t ocount;		/* original count */
@@ -1591,14 +1565,14 @@ generic_file_aio_write_nolock(struct kio
 	ssize_t		err;
 	size_t		bytes;
 	struct pagevec	lru_pvec;
-	const struct iovec *cur_iov = iov; /* current iovec */
+	const struct iovec *cur_iov = iocb->rw_iov; /* current iovec */
 	size_t		iov_base = 0;	   /* offset in the current iovec */
-	unsigned long	seg;
+	unsigned long	seg, nr_segs = iocb->rw_nsegs;
 	char		*buf;
 
 	ocount = 0;
 	for (seg = 0; seg < nr_segs; seg++) {
-		const struct iovec *iv = &iov[seg];
+		const struct iovec *iv = &iocb->rw_iov[seg];
 
 		/*
 		 * If any segment has a negative length, or the cumulative
@@ -1617,7 +1591,7 @@ generic_file_aio_write_nolock(struct kio
 	}
 
 	count = ocount;
-	pos = *ppos;
+	pos = iocb->rw_pos;
 	pagevec_init(&lru_pvec, 0);
 
 	/* We can write back this queue in page reclaim */
@@ -1638,17 +1612,17 @@ generic_file_aio_write_nolock(struct kio
 	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
 	if (unlikely(file->f_flags & O_DIRECT)) {
 		if (count != ocount)
-			nr_segs = iov_shorten((struct iovec *)iov,
+			nr_segs = iov_shorten(iocb->rw_iov,
 						nr_segs, count);
 		written = generic_file_direct_IO(WRITE, iocb,
-					iov, pos, nr_segs);
+					iocb->rw_iov, pos, nr_segs);
 		if (written > 0) {
 			loff_t end = pos + written;
 			if (end > inode->i_size && !isblk) {
 				inode->i_size = end;
 				mark_inode_dirty(inode);
 			}
-			*ppos = end;
+			iocb->rw_pos = end;
 		}
 		/*
 		 * Sync the fs metadata but not the minor inode changes and
@@ -1656,12 +1630,12 @@ generic_file_aio_write_nolock(struct kio
 		 */
 		if (written >= 0 && file->f_flags & O_SYNC)
 			status = generic_osync_inode(inode, OSYNC_METADATA);
-		if (written >= 0 && !is_sync_kiocb(iocb))
+		if (written >= 0 && !is_sync_kiocb(&iocb->kiocb))
 			written = -EIOCBQUEUED;
 		goto out_status;
 	}
 
-	buf = iov->iov_base;
+	buf = iocb->rw_iov->iov_base;
 	do {
 		unsigned long index;
 		unsigned long offset;
@@ -1732,7 +1706,7 @@ generic_file_aio_write_nolock(struct kio
 		balance_dirty_pages_ratelimited(mapping);
 		cond_resched();
 	} while (count);
-	*ppos = pos;
+	iocb->rw_pos = pos;
 
 	if (cached_page)
 		page_cache_release(cached_page);
@@ -1754,84 +1728,23 @@ out:
 	return err;
 }
 
-ssize_t
-generic_file_write_nolock(struct file *file, const struct iovec *iov,
-				unsigned long nr_segs, loff_t *ppos)
-{
-	struct kiocb kiocb;
-	ssize_t ret;
-
-	init_sync_kiocb(&kiocb, file);
-	ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
-	if (-EIOCBQUEUED == ret)
-		ret = wait_on_sync_kiocb(&kiocb);
-	return ret;
-}
-
-ssize_t generic_file_aio_write(struct kiocb *iocb, const char *buf,
-			       size_t count, loff_t pos)
+ssize_t generic_file_aio_write(struct rw_iocb *iocb)
 {
-	struct file *file = iocb->ki_filp;
-	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 	ssize_t err;
-	struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
-
-	BUG_ON(iocb->ki_pos != pos);
-
-	down(&inode->i_sem);
-	err = generic_file_aio_write_nolock(iocb, &local_iov, 1, 
-						&iocb->ki_pos);
-	up(&inode->i_sem);
 
+	down(&iocb->kiocb.ki_filp->f_dentry->d_inode->i_sem);
+	err = generic_file_aio_write_nolock(iocb);
+	up(&iocb->kiocb.ki_filp->f_dentry->d_inode->i_sem);
 	return err;
 }
 EXPORT_SYMBOL(generic_file_aio_write);
 EXPORT_SYMBOL(generic_file_aio_write_nolock);
 
-ssize_t generic_file_write(struct file *file, const char *buf,
-			   size_t count, loff_t *ppos)
-{
-	struct inode	*inode = file->f_dentry->d_inode->i_mapping->host;
-	ssize_t		err;
-	struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
-
-	down(&inode->i_sem);
-	err = generic_file_write_nolock(file, &local_iov, 1, ppos);
-	up(&inode->i_sem);
-
-	return err;
-}
-
-ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
-			unsigned long nr_segs, loff_t *ppos)
-{
-	struct kiocb kiocb;
-	ssize_t ret;
-
-	init_sync_kiocb(&kiocb, filp);
-	ret = __generic_file_aio_read(&kiocb, iov, nr_segs, ppos);
-	if (-EIOCBQUEUED == ret)
-		ret = wait_on_sync_kiocb(&kiocb);
-	return ret;
-}
-
-ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
-			unsigned long nr_segs, loff_t * ppos) 
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	ssize_t ret;
-
-	down(&inode->i_sem);
-	ret = generic_file_write_nolock(file, iov, nr_segs, ppos);
-	up(&inode->i_sem);
-	return ret;
-}
-
 ssize_t
-generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+generic_file_direct_IO(int rw, struct rw_iocb *iocb, const struct iovec *iov,
 	loff_t offset, unsigned long nr_segs)
 {
-	struct file *file = iocb->ki_filp;
+	struct file *file = iocb->kiocb.ki_filp;
 	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
 	ssize_t retval;
 
diff -purN linux-2.5/net/socket.c aio-2.5/net/socket.c
--- linux-2.5/net/socket.c	Tue Apr  1 15:18:19 2003
+++ aio-2.5/net/socket.c	Tue Mar 25 14:29:33 2003
@@ -95,10 +95,8 @@
 #include <linux/netfilter.h>
 
 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
-static ssize_t sock_aio_read(struct kiocb *iocb, char *buf,
-			 size_t size, loff_t pos);
-static ssize_t sock_aio_write(struct kiocb *iocb, const char *buf,
-			  size_t size, loff_t pos);
+static ssize_t sock_aio_read(struct rw_iocb *iocb);
+static ssize_t sock_aio_write(struct rw_iocb *iocb);
 static int sock_mmap(struct file *file, struct vm_area_struct * vma);
 
 static int sock_close(struct inode *inode, struct file *file);
@@ -528,6 +526,7 @@ static inline int __sock_sendmsg(struct 
 	si->scm = NULL;
 	si->msg = msg;
 	si->size = size;
+	si->flags = 0;
 
 	err = security_socket_sendmsg(sock, msg, size);
 	if (err)
@@ -538,13 +537,14 @@ static inline int __sock_sendmsg(struct 
 
 int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size)
 {
-	struct kiocb iocb;
+	struct sync_iocb iocb;
 	int ret;
 
-	init_sync_kiocb(&iocb, NULL);
-	ret = __sock_sendmsg(&iocb, sock, msg, size);
+	init_sync_kiocb(&iocb.kiocb, NULL);
+	
+	ret = __sock_sendmsg(&iocb.kiocb, sock, msg, size);
 	if (-EIOCBQUEUED == ret)
-		ret = wait_on_sync_kiocb(&iocb);
+		ret = wait_on_sync_kiocb(&iocb.kiocb);
 	return ret;
 }
 
@@ -569,13 +569,13 @@ static inline int __sock_recvmsg(struct 
 
 int sock_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags)
 {
-	struct kiocb iocb;
+	struct sync_iocb iocb;
 	int ret;
 
-        init_sync_kiocb(&iocb, NULL);
-	ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
+        init_sync_kiocb(&iocb.kiocb, NULL);
+	ret = __sock_recvmsg(&iocb.kiocb, sock, msg, size, flags);
 	if (-EIOCBQUEUED == ret)
-		ret = wait_on_sync_kiocb(&iocb);
+		ret = wait_on_sync_kiocb(&iocb.kiocb);
 	return ret;
 }
 
@@ -584,31 +584,29 @@ int sock_recvmsg(struct socket *sock, st
  *	area ubuf...ubuf+size-1 is writable before asking the protocol.
  */
 
-static ssize_t sock_aio_read(struct kiocb *iocb, char *ubuf,
-			 size_t size, loff_t pos)
+static ssize_t sock_aio_read(struct rw_iocb *iocb)
 {
-	struct sock_iocb *x = kiocb_to_siocb(iocb);
+	struct sock_iocb *x = rw_iocb_to_siocb(iocb);
 	struct socket *sock;
 	int flags;
 
-	if (pos != 0)
+	if (x->iocb.rw_pos != 0)
 		return -ESPIPE;
-	if (size==0)		/* Match SYS5 behaviour */
+	if (0 == x->iocb.rw_local_iov.iov_len)
 		return 0;
 
-	sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode); 
+	sock = SOCKET_I(x->iocb.kiocb.ki_filp->f_dentry->d_inode); 
 
 	x->async_msg.msg_name = NULL;
 	x->async_msg.msg_namelen = 0;
-	x->async_msg.msg_iov = &x->async_iov;
-	x->async_msg.msg_iovlen = 1;
+	x->async_msg.msg_iov = x->iocb.rw_iov;
+	x->async_msg.msg_iovlen = x->iocb.rw_nsegs;
 	x->async_msg.msg_control = NULL;
 	x->async_msg.msg_controllen = 0;
-	x->async_iov.iov_base = ubuf;
-	x->async_iov.iov_len = size;
-	flags = !(iocb->ki_filp->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
+	flags = !(x->iocb.kiocb.ki_filp->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
 
-	return __sock_recvmsg(iocb, sock, &x->async_msg, size, flags);
+	return __sock_recvmsg(&x->iocb.kiocb, sock, &x->async_msg,
+			      x->iocb.rw_local_iov.iov_len, flags);
 }
 
 
@@ -617,32 +615,29 @@ static ssize_t sock_aio_read(struct kioc
  *	is readable by the user process.
  */
 
-static ssize_t sock_aio_write(struct kiocb *iocb, const char *ubuf,
-			  size_t size, loff_t pos)
+static ssize_t sock_aio_write(struct rw_iocb *iocb)
 {
-	struct sock_iocb *x = kiocb_to_siocb(iocb);
+	struct sock_iocb *x = rw_iocb_to_siocb(iocb);
 	struct socket *sock;
 	
-	if (pos != 0)
+	if (x->iocb.rw_pos != 0)
 		return -ESPIPE;
-	if(size==0)		/* Match SYS5 behaviour */
+	if (0 == x->iocb.rw_local_iov.iov_len)
 		return 0;
 
-	sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode); 
+	sock = SOCKET_I(x->iocb.kiocb.ki_filp->f_dentry->d_inode); 
 
 	x->async_msg.msg_name = NULL;
 	x->async_msg.msg_namelen = 0;
-	x->async_msg.msg_iov = &x->async_iov;
-	x->async_msg.msg_iovlen = 1;
+	x->async_msg.msg_iov = x->iocb.rw_iov;
+	x->async_msg.msg_iovlen = x->iocb.rw_nsegs;
 	x->async_msg.msg_control = NULL;
 	x->async_msg.msg_controllen = 0;
-	x->async_msg.msg_flags = !(iocb->ki_filp->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
+	x->async_msg.msg_flags = !(x->iocb.kiocb.ki_filp->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
 	if (sock->type == SOCK_SEQPACKET)
 		x->async_msg.msg_flags |= MSG_EOR;
-	x->async_iov.iov_base = (void *)ubuf;
-	x->async_iov.iov_len = size;
 	
-	return __sock_sendmsg(iocb, sock, &x->async_msg, size);
+	return __sock_sendmsg(&iocb->kiocb, sock, &x->async_msg, x->iocb.rw_local_iov.iov_len);
 }
 
 ssize_t sock_sendpage(struct file *file, struct page *page,

  reply	other threads:[~2003-04-01 20:13 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-03-05  9:17 [RFC][Patch] Retry based aio read for filesystems Suparna Bhattacharya
2003-03-05  9:26 ` [Patch 1/2] Retry based aio read - core aio changes Suparna Bhattacharya
2003-03-14 13:23   ` Suparna Bhattacharya
2003-03-05  9:30 ` [Patch 2/2] Retry based aio read - filesystem read changes Suparna Bhattacharya
2003-03-05 10:42   ` Andrew Morton
2003-03-05 12:14     ` Suparna Bhattacharya
2003-03-31 18:32       ` Janet Morgan
2003-03-31 19:11         ` William Lee Irwin III
2003-03-31 19:16           ` Benjamin LaHaise
2003-03-31 19:07             ` Janet Morgan
2003-04-01 20:24               ` Benjamin LaHaise [this message]
2003-03-31 19:17             ` William Lee Irwin III
2003-03-31 19:25               ` Benjamin LaHaise
2003-04-07  3:51             ` Suparna Bhattacharya
2003-03-05 23:00 ` [RFC][Patch] Retry based aio read for filesystems Janet Morgan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030401152424.A26513@redhat.com \
    --to=bcrl@redhat.com \
    --cc=akpm@digeo.com \
    --cc=janetmor@us.ibm.com \
    --cc=linux-aio@kvack.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=suparna@in.ibm.com \
    --cc=wli@holomorphy.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox