aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBadari Pulavarty <pbadari@us.ibm.com>2006-10-01 02:28:46 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-01 03:39:28 -0400
commit027445c37282bc1ed26add45e573ad2d3e4860a5 (patch)
tree93eab101a938ffebaea64703033c8649df4d73f0
parent9ea0f9499d15c49df23e7aac4332d830c40e12d0 (diff)
[PATCH] Vectorize aio_read/aio_write fileop methods
This patch vectorizes aio_read() and aio_write() methods to prepare for collapsing all aio & vectored operations into one interface - which is aio_read()/aio_write(). Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Michael Holzheu <HOLZHEU@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/filesystems/Locking5
-rw-r--r--Documentation/filesystems/vfs.txt4
-rw-r--r--arch/s390/hypfs/inode.c17
-rw-r--r--drivers/char/raw.c14
-rw-r--r--drivers/usb/gadget/inode.c80
-rw-r--r--fs/aio.c15
-rw-r--r--fs/block_dev.c10
-rw-r--r--fs/cifs/cifsfs.c6
-rw-r--r--fs/ext3/file.c5
-rw-r--r--fs/nfs/direct.c26
-rw-r--r--fs/nfs/file.c34
-rw-r--r--fs/ntfs/file.c8
-rw-r--r--fs/ocfs2/file.c28
-rw-r--r--fs/read_write.c20
-rw-r--r--fs/reiserfs/file.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c46
-rw-r--r--include/linux/aio.h2
-rw-r--r--include/linux/fs.h10
-rw-r--r--include/linux/nfs_fs.h10
-rw-r--r--include/net/sock.h1
-rw-r--r--mm/filemap.c39
-rw-r--r--net/socket.c49
22 files changed, 242 insertions, 191 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 247d7f619aa2..eb1a6cad21e6 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -356,10 +356,9 @@ The last two are called only from check_disk_change().
356prototypes: 356prototypes:
357 loff_t (*llseek) (struct file *, loff_t, int); 357 loff_t (*llseek) (struct file *, loff_t, int);
358 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 358 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
359 ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
360 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 359 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
361 ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, 360 ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
362 loff_t); 361 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
363 int (*readdir) (struct file *, void *, filldir_t); 362 int (*readdir) (struct file *, void *, filldir_t);
364 unsigned int (*poll) (struct file *, struct poll_table_struct *); 363 unsigned int (*poll) (struct file *, struct poll_table_struct *);
365 int (*ioctl) (struct inode *, struct file *, unsigned int, 364 int (*ioctl) (struct inode *, struct file *, unsigned int,
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 1cb7e8be927a..cd07c21b8400 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -699,9 +699,9 @@ This describes how the VFS can manipulate an open file. As of kernel
699struct file_operations { 699struct file_operations {
700 loff_t (*llseek) (struct file *, loff_t, int); 700 loff_t (*llseek) (struct file *, loff_t, int);
701 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 701 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
702 ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
703 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 702 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
704 ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t); 703 ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
704 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
705 int (*readdir) (struct file *, void *, filldir_t); 705 int (*readdir) (struct file *, void *, filldir_t);
706 unsigned int (*poll) (struct file *, struct poll_table_struct *); 706 unsigned int (*poll) (struct file *, struct poll_table_struct *);
707 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); 707 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 813fc21358f9..cd702ae45d6d 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -134,12 +134,20 @@ static int hypfs_open(struct inode *inode, struct file *filp)
134 return 0; 134 return 0;
135} 135}
136 136
137static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf, 137static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
138 size_t count, loff_t offset) 138 unsigned long nr_segs, loff_t offset)
139{ 139{
140 char *data; 140 char *data;
141 size_t len; 141 size_t len;
142 struct file *filp = iocb->ki_filp; 142 struct file *filp = iocb->ki_filp;
143 /* XXX: temporary */
144 char __user *buf = iov[0].iov_base;
145 size_t count = iov[0].iov_len;
146
147 if (nr_segs != 1) {
148 count = -EINVAL;
149 goto out;
150 }
143 151
144 data = filp->private_data; 152 data = filp->private_data;
145 len = strlen(data); 153 len = strlen(data);
@@ -158,12 +166,13 @@ static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
158out: 166out:
159 return count; 167 return count;
160} 168}
161static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf, 169static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
162 size_t count, loff_t pos) 170 unsigned long nr_segs, loff_t offset)
163{ 171{
164 int rc; 172 int rc;
165 struct super_block *sb; 173 struct super_block *sb;
166 struct hypfs_sb_info *fs_info; 174 struct hypfs_sb_info *fs_info;
175 size_t count = iov_length(iov, nr_segs);
167 176
168 sb = iocb->ki_filp->f_dentry->d_inode->i_sb; 177 sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
169 fs_info = sb->s_fs_info; 178 fs_info = sb->s_fs_info;
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index c596a08c07b3..173fb08555d5 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -249,23 +249,11 @@ static ssize_t raw_file_write(struct file *file, const char __user *buf,
249 return generic_file_write_nolock(file, &local_iov, 1, ppos); 249 return generic_file_write_nolock(file, &local_iov, 1, ppos);
250} 250}
251 251
252static ssize_t raw_file_aio_write(struct kiocb *iocb, const char __user *buf,
253 size_t count, loff_t pos)
254{
255 struct iovec local_iov = {
256 .iov_base = (char __user *)buf,
257 .iov_len = count
258 };
259
260 return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
261}
262
263
264static const struct file_operations raw_fops = { 252static const struct file_operations raw_fops = {
265 .read = generic_file_read, 253 .read = generic_file_read,
266 .aio_read = generic_file_aio_read, 254 .aio_read = generic_file_aio_read,
267 .write = raw_file_write, 255 .write = raw_file_write,
268 .aio_write = raw_file_aio_write, 256 .aio_write = generic_file_aio_write_nolock,
269 .open = raw_open, 257 .open = raw_open,
270 .release= raw_release, 258 .release= raw_release,
271 .ioctl = raw_ioctl, 259 .ioctl = raw_ioctl,
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 4a000d846a93..86924f9cdd7e 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -533,7 +533,8 @@ struct kiocb_priv {
533 struct usb_request *req; 533 struct usb_request *req;
534 struct ep_data *epdata; 534 struct ep_data *epdata;
535 void *buf; 535 void *buf;
536 char __user *ubuf; /* NULL for writes */ 536 const struct iovec *iv;
537 unsigned long nr_segs;
537 unsigned actual; 538 unsigned actual;
538}; 539};
539 540
@@ -561,17 +562,32 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
561static ssize_t ep_aio_read_retry(struct kiocb *iocb) 562static ssize_t ep_aio_read_retry(struct kiocb *iocb)
562{ 563{
563 struct kiocb_priv *priv = iocb->private; 564 struct kiocb_priv *priv = iocb->private;
564 ssize_t status = priv->actual; 565 ssize_t len, total;
565 566 int i;
566 /* we "retry" to get the right mm context for this: */ 567
567 status = copy_to_user(priv->ubuf, priv->buf, priv->actual); 568 /* we "retry" to get the right mm context for this: */
568 if (unlikely(0 != status)) 569
569 status = -EFAULT; 570 /* copy stuff into user buffers */
570 else 571 total = priv->actual;
571 status = priv->actual; 572 len = 0;
572 kfree(priv->buf); 573 for (i=0; i < priv->nr_segs; i++) {
573 kfree(priv); 574 ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total);
574 return status; 575
576 if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) {
577 if (len == 0)
578 len = -EFAULT;
579 break;
580 }
581
582 total -= this;
583 len += this;
584 if (total == 0)
585 break;
586 }
587 kfree(priv->buf);
588 kfree(priv);
589 aio_put_req(iocb);
590 return len;
575} 591}
576 592
577static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) 593static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
@@ -584,7 +600,7 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
584 spin_lock(&epdata->dev->lock); 600 spin_lock(&epdata->dev->lock);
585 priv->req = NULL; 601 priv->req = NULL;
586 priv->epdata = NULL; 602 priv->epdata = NULL;
587 if (priv->ubuf == NULL 603 if (priv->iv == NULL
588 || unlikely(req->actual == 0) 604 || unlikely(req->actual == 0)
589 || unlikely(kiocbIsCancelled(iocb))) { 605 || unlikely(kiocbIsCancelled(iocb))) {
590 kfree(req->buf); 606 kfree(req->buf);
@@ -619,7 +635,8 @@ ep_aio_rwtail(
619 char *buf, 635 char *buf,
620 size_t len, 636 size_t len,
621 struct ep_data *epdata, 637 struct ep_data *epdata,
622 char __user *ubuf 638 const struct iovec *iv,
639 unsigned long nr_segs
623) 640)
624{ 641{
625 struct kiocb_priv *priv; 642 struct kiocb_priv *priv;
@@ -634,7 +651,8 @@ fail:
634 return value; 651 return value;
635 } 652 }
636 iocb->private = priv; 653 iocb->private = priv;
637 priv->ubuf = ubuf; 654 priv->iv = iv;
655 priv->nr_segs = nr_segs;
638 656
639 value = get_ready_ep(iocb->ki_filp->f_flags, epdata); 657 value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
640 if (unlikely(value < 0)) { 658 if (unlikely(value < 0)) {
@@ -674,41 +692,53 @@ fail:
674 kfree(priv); 692 kfree(priv);
675 put_ep(epdata); 693 put_ep(epdata);
676 } else 694 } else
677 value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED); 695 value = (iv ? -EIOCBRETRY : -EIOCBQUEUED);
678 return value; 696 return value;
679} 697}
680 698
681static ssize_t 699static ssize_t
682ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o) 700ep_aio_read(struct kiocb *iocb, const struct iovec *iov,
701 unsigned long nr_segs, loff_t o)
683{ 702{
684 struct ep_data *epdata = iocb->ki_filp->private_data; 703 struct ep_data *epdata = iocb->ki_filp->private_data;
685 char *buf; 704 char *buf;
686 705
687 if (unlikely(epdata->desc.bEndpointAddress & USB_DIR_IN)) 706 if (unlikely(epdata->desc.bEndpointAddress & USB_DIR_IN))
688 return -EINVAL; 707 return -EINVAL;
689 buf = kmalloc(len, GFP_KERNEL); 708
709 buf = kmalloc(iocb->ki_left, GFP_KERNEL);
690 if (unlikely(!buf)) 710 if (unlikely(!buf))
691 return -ENOMEM; 711 return -ENOMEM;
712
692 iocb->ki_retry = ep_aio_read_retry; 713 iocb->ki_retry = ep_aio_read_retry;
693 return ep_aio_rwtail(iocb, buf, len, epdata, ubuf); 714 return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs);
694} 715}
695 716
696static ssize_t 717static ssize_t
697ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o) 718ep_aio_write(struct kiocb *iocb, const struct iovec *iov,
719 unsigned long nr_segs, loff_t o)
698{ 720{
699 struct ep_data *epdata = iocb->ki_filp->private_data; 721 struct ep_data *epdata = iocb->ki_filp->private_data;
700 char *buf; 722 char *buf;
723 size_t len = 0;
724 int i = 0;
701 725
702 if (unlikely(!(epdata->desc.bEndpointAddress & USB_DIR_IN))) 726 if (unlikely(!(epdata->desc.bEndpointAddress & USB_DIR_IN)))
703 return -EINVAL; 727 return -EINVAL;
704 buf = kmalloc(len, GFP_KERNEL); 728
729 buf = kmalloc(iocb->ki_left, GFP_KERNEL);
705 if (unlikely(!buf)) 730 if (unlikely(!buf))
706 return -ENOMEM; 731 return -ENOMEM;
707 if (unlikely(copy_from_user(buf, ubuf, len) != 0)) { 732
708 kfree(buf); 733 for (i=0; i < nr_segs; i++) {
709 return -EFAULT; 734 if (unlikely(copy_from_user(&buf[len], iov[i].iov_base,
735 iov[i].iov_len) != 0)) {
736 kfree(buf);
737 return -EFAULT;
738 }
739 len += iov[i].iov_len;
710 } 740 }
711 return ep_aio_rwtail(iocb, buf, len, epdata, NULL); 741 return ep_aio_rwtail(iocb, buf, len, epdata, NULL, 0);
712} 742}
713 743
714/*----------------------------------------------------------------------*/ 744/*----------------------------------------------------------------------*/
diff --git a/fs/aio.c b/fs/aio.c
index 950630187acc..27ff56540c73 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -15,6 +15,7 @@
15#include <linux/aio_abi.h> 15#include <linux/aio_abi.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/syscalls.h> 17#include <linux/syscalls.h>
18#include <linux/uio.h>
18 19
19#define DEBUG 0 20#define DEBUG 0
20 21
@@ -1315,8 +1316,11 @@ static ssize_t aio_pread(struct kiocb *iocb)
1315 ssize_t ret = 0; 1316 ssize_t ret = 0;
1316 1317
1317 do { 1318 do {
1318 ret = file->f_op->aio_read(iocb, iocb->ki_buf, 1319 iocb->ki_inline_vec.iov_base = iocb->ki_buf;
1319 iocb->ki_left, iocb->ki_pos); 1320 iocb->ki_inline_vec.iov_len = iocb->ki_left;
1321
1322 ret = file->f_op->aio_read(iocb, &iocb->ki_inline_vec,
1323 1, iocb->ki_pos);
1320 /* 1324 /*
1321 * Can't just depend on iocb->ki_left to determine 1325 * Can't just depend on iocb->ki_left to determine
1322 * whether we are done. This may have been a short read. 1326 * whether we are done. This may have been a short read.
@@ -1349,8 +1353,11 @@ static ssize_t aio_pwrite(struct kiocb *iocb)
1349 ssize_t ret = 0; 1353 ssize_t ret = 0;
1350 1354
1351 do { 1355 do {
1352 ret = file->f_op->aio_write(iocb, iocb->ki_buf, 1356 iocb->ki_inline_vec.iov_base = iocb->ki_buf;
1353 iocb->ki_left, iocb->ki_pos); 1357 iocb->ki_inline_vec.iov_len = iocb->ki_left;
1358
1359 ret = file->f_op->aio_write(iocb, &iocb->ki_inline_vec,
1360 1, iocb->ki_pos);
1354 if (ret > 0) { 1361 if (ret > 0) {
1355 iocb->ki_buf += ret; 1362 iocb->ki_buf += ret;
1356 iocb->ki_left -= ret; 1363 iocb->ki_left -= ret;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 0c361ea7e5a6..8c819117310b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1162,14 +1162,6 @@ static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
1162 return generic_file_write_nolock(file, &local_iov, 1, ppos); 1162 return generic_file_write_nolock(file, &local_iov, 1, ppos);
1163} 1163}
1164 1164
1165static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
1166 size_t count, loff_t pos)
1167{
1168 struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
1169
1170 return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
1171}
1172
1173static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg) 1165static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
1174{ 1166{
1175 return blkdev_ioctl(file->f_mapping->host, file, cmd, arg); 1167 return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
@@ -1192,7 +1184,7 @@ const struct file_operations def_blk_fops = {
1192 .read = generic_file_read, 1184 .read = generic_file_read,
1193 .write = blkdev_file_write, 1185 .write = blkdev_file_write,
1194 .aio_read = generic_file_aio_read, 1186 .aio_read = generic_file_aio_read,
1195 .aio_write = blkdev_file_aio_write, 1187 .aio_write = generic_file_aio_write_nolock,
1196 .mmap = generic_file_mmap, 1188 .mmap = generic_file_mmap,
1197 .fsync = block_fsync, 1189 .fsync = block_fsync,
1198 .unlocked_ioctl = block_ioctl, 1190 .unlocked_ioctl = block_ioctl,
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 22bcf4d7e7ae..5abb42a7c53e 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -492,13 +492,13 @@ static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
492 return written; 492 return written;
493} 493}
494 494
495static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf, 495static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
496 size_t count, loff_t pos) 496 unsigned long nr_segs, loff_t pos)
497{ 497{
498 struct inode *inode = iocb->ki_filp->f_dentry->d_inode; 498 struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
499 ssize_t written; 499 ssize_t written;
500 500
501 written = generic_file_aio_write(iocb, buf, count, pos); 501 written = generic_file_aio_write(iocb, iov, nr_segs, pos);
502 if (!CIFS_I(inode)->clientCanCacheAll) 502 if (!CIFS_I(inode)->clientCanCacheAll)
503 filemap_fdatawrite(inode->i_mapping); 503 filemap_fdatawrite(inode->i_mapping);
504 return written; 504 return written;
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 74ff20f9d09b..5c762457bc89 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -48,14 +48,15 @@ static int ext3_release_file (struct inode * inode, struct file * filp)
48} 48}
49 49
50static ssize_t 50static ssize_t
51ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) 51ext3_file_write(struct kiocb *iocb, const struct iovec *iov,
52 unsigned long nr_segs, loff_t pos)
52{ 53{
53 struct file *file = iocb->ki_filp; 54 struct file *file = iocb->ki_filp;
54 struct inode *inode = file->f_dentry->d_inode; 55 struct inode *inode = file->f_dentry->d_inode;
55 ssize_t ret; 56 ssize_t ret;
56 int err; 57 int err;
57 58
58 ret = generic_file_aio_write(iocb, buf, count, pos); 59 ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
59 60
60 /* 61 /*
61 * Skip flushing if there was an error, or if nothing was written. 62 * Skip flushing if there was an error, or if nothing was written.
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 377839bed172..9f7f8b9ea1e2 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -707,8 +707,8 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
707/** 707/**
708 * nfs_file_direct_read - file direct read operation for NFS files 708 * nfs_file_direct_read - file direct read operation for NFS files
709 * @iocb: target I/O control block 709 * @iocb: target I/O control block
710 * @buf: user's buffer into which to read data 710 * @iov: vector of user buffers into which to read data
711 * @count: number of bytes to read 711 * @nr_segs: size of iov vector
712 * @pos: byte offset in file where reading starts 712 * @pos: byte offset in file where reading starts
713 * 713 *
714 * We use this function for direct reads instead of calling 714 * We use this function for direct reads instead of calling
@@ -725,17 +725,24 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
725 * client must read the updated atime from the server back into its 725 * client must read the updated atime from the server back into its
726 * cache. 726 * cache.
727 */ 727 */
728ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) 728ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
729 unsigned long nr_segs, loff_t pos)
729{ 730{
730 ssize_t retval = -EINVAL; 731 ssize_t retval = -EINVAL;
731 struct file *file = iocb->ki_filp; 732 struct file *file = iocb->ki_filp;
732 struct address_space *mapping = file->f_mapping; 733 struct address_space *mapping = file->f_mapping;
734 /* XXX: temporary */
735 const char __user *buf = iov[0].iov_base;
736 size_t count = iov[0].iov_len;
733 737
734 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", 738 dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
735 file->f_dentry->d_parent->d_name.name, 739 file->f_dentry->d_parent->d_name.name,
736 file->f_dentry->d_name.name, 740 file->f_dentry->d_name.name,
737 (unsigned long) count, (long long) pos); 741 (unsigned long) count, (long long) pos);
738 742
743 if (nr_segs != 1)
744 return -EINVAL;
745
739 if (count < 0) 746 if (count < 0)
740 goto out; 747 goto out;
741 retval = -EFAULT; 748 retval = -EFAULT;
@@ -760,8 +767,8 @@ out:
760/** 767/**
761 * nfs_file_direct_write - file direct write operation for NFS files 768 * nfs_file_direct_write - file direct write operation for NFS files
762 * @iocb: target I/O control block 769 * @iocb: target I/O control block
763 * @buf: user's buffer from which to write data 770 * @iov: vector of user buffers from which to write data
764 * @count: number of bytes to write 771 * @nr_segs: size of iov vector
765 * @pos: byte offset in file where writing starts 772 * @pos: byte offset in file where writing starts
766 * 773 *
767 * We use this function for direct writes instead of calling 774 * We use this function for direct writes instead of calling
@@ -782,17 +789,24 @@ out:
782 * Note that O_APPEND is not supported for NFS direct writes, as there 789 * Note that O_APPEND is not supported for NFS direct writes, as there
783 * is no atomic O_APPEND write facility in the NFS protocol. 790 * is no atomic O_APPEND write facility in the NFS protocol.
784 */ 791 */
785ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) 792ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
793 unsigned long nr_segs, loff_t pos)
786{ 794{
787 ssize_t retval; 795 ssize_t retval;
788 struct file *file = iocb->ki_filp; 796 struct file *file = iocb->ki_filp;
789 struct address_space *mapping = file->f_mapping; 797 struct address_space *mapping = file->f_mapping;
798 /* XXX: temporary */
799 const char __user *buf = iov[0].iov_base;
800 size_t count = iov[0].iov_len;
790 801
791 dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n", 802 dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
792 file->f_dentry->d_parent->d_name.name, 803 file->f_dentry->d_parent->d_name.name,
793 file->f_dentry->d_name.name, 804 file->f_dentry->d_name.name,
794 (unsigned long) count, (long long) pos); 805 (unsigned long) count, (long long) pos);
795 806
807 if (nr_segs != 1)
808 return -EINVAL;
809
796 retval = generic_write_checks(file, &pos, &count, 0); 810 retval = generic_write_checks(file, &pos, &count, 0);
797 if (retval) 811 if (retval)
798 goto out; 812 goto out;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index be997d649127..cc93865cea93 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -41,8 +41,10 @@ static int nfs_file_release(struct inode *, struct file *);
41static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin); 41static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
42static int nfs_file_mmap(struct file *, struct vm_area_struct *); 42static int nfs_file_mmap(struct file *, struct vm_area_struct *);
43static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); 43static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
44static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); 44static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
45static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t); 45 unsigned long nr_segs, loff_t pos);
46static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
47 unsigned long nr_segs, loff_t pos);
46static int nfs_file_flush(struct file *, fl_owner_t id); 48static int nfs_file_flush(struct file *, fl_owner_t id);
47static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); 49static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
48static int nfs_check_flags(int flags); 50static int nfs_check_flags(int flags);
@@ -53,8 +55,8 @@ const struct file_operations nfs_file_operations = {
53 .llseek = nfs_file_llseek, 55 .llseek = nfs_file_llseek,
54 .read = do_sync_read, 56 .read = do_sync_read,
55 .write = do_sync_write, 57 .write = do_sync_write,
56 .aio_read = nfs_file_read, 58 .aio_read = nfs_file_read,
57 .aio_write = nfs_file_write, 59 .aio_write = nfs_file_write,
58 .mmap = nfs_file_mmap, 60 .mmap = nfs_file_mmap,
59 .open = nfs_file_open, 61 .open = nfs_file_open,
60 .flush = nfs_file_flush, 62 .flush = nfs_file_flush,
@@ -196,15 +198,17 @@ nfs_file_flush(struct file *file, fl_owner_t id)
196} 198}
197 199
198static ssize_t 200static ssize_t
199nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos) 201nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
202 unsigned long nr_segs, loff_t pos)
200{ 203{
201 struct dentry * dentry = iocb->ki_filp->f_dentry; 204 struct dentry * dentry = iocb->ki_filp->f_dentry;
202 struct inode * inode = dentry->d_inode; 205 struct inode * inode = dentry->d_inode;
203 ssize_t result; 206 ssize_t result;
207 size_t count = iov_length(iov, nr_segs);
204 208
205#ifdef CONFIG_NFS_DIRECTIO 209#ifdef CONFIG_NFS_DIRECTIO
206 if (iocb->ki_filp->f_flags & O_DIRECT) 210 if (iocb->ki_filp->f_flags & O_DIRECT)
207 return nfs_file_direct_read(iocb, buf, count, pos); 211 return nfs_file_direct_read(iocb, iov, nr_segs, pos);
208#endif 212#endif
209 213
210 dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n", 214 dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
@@ -214,7 +218,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
214 result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); 218 result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
215 nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count); 219 nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
216 if (!result) 220 if (!result)
217 result = generic_file_aio_read(iocb, buf, count, pos); 221 result = generic_file_aio_read(iocb, iov, nr_segs, pos);
218 return result; 222 return result;
219} 223}
220 224
@@ -336,24 +340,22 @@ const struct address_space_operations nfs_file_aops = {
336#endif 340#endif
337}; 341};
338 342
339/* 343static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
340 * Write to a file (through the page cache). 344 unsigned long nr_segs, loff_t pos)
341 */
342static ssize_t
343nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
344{ 345{
345 struct dentry * dentry = iocb->ki_filp->f_dentry; 346 struct dentry * dentry = iocb->ki_filp->f_dentry;
346 struct inode * inode = dentry->d_inode; 347 struct inode * inode = dentry->d_inode;
347 ssize_t result; 348 ssize_t result;
349 size_t count = iov_length(iov, nr_segs);
348 350
349#ifdef CONFIG_NFS_DIRECTIO 351#ifdef CONFIG_NFS_DIRECTIO
350 if (iocb->ki_filp->f_flags & O_DIRECT) 352 if (iocb->ki_filp->f_flags & O_DIRECT)
351 return nfs_file_direct_write(iocb, buf, count, pos); 353 return nfs_file_direct_write(iocb, iov, nr_segs, pos);
352#endif 354#endif
353 355
354 dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n", 356 dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n",
355 dentry->d_parent->d_name.name, dentry->d_name.name, 357 dentry->d_parent->d_name.name, dentry->d_name.name,
356 inode->i_ino, (unsigned long) count, (unsigned long) pos); 358 inode->i_ino, (unsigned long) count, (long long) pos);
357 359
358 result = -EBUSY; 360 result = -EBUSY;
359 if (IS_SWAPFILE(inode)) 361 if (IS_SWAPFILE(inode))
@@ -372,7 +374,7 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
372 goto out; 374 goto out;
373 375
374 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); 376 nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
375 result = generic_file_aio_write(iocb, buf, count, pos); 377 result = generic_file_aio_write(iocb, iov, nr_segs, pos);
376out: 378out:
377 return result; 379 return result;
378 380
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 585a79d39c9d..0c46f5c86b71 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2176,20 +2176,18 @@ out:
2176/** 2176/**
2177 * ntfs_file_aio_write - 2177 * ntfs_file_aio_write -
2178 */ 2178 */
2179static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const char __user *buf, 2179static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
2180 size_t count, loff_t pos) 2180 unsigned long nr_segs, loff_t pos)
2181{ 2181{
2182 struct file *file = iocb->ki_filp; 2182 struct file *file = iocb->ki_filp;
2183 struct address_space *mapping = file->f_mapping; 2183 struct address_space *mapping = file->f_mapping;
2184 struct inode *inode = mapping->host; 2184 struct inode *inode = mapping->host;
2185 ssize_t ret; 2185 ssize_t ret;
2186 struct iovec local_iov = { .iov_base = (void __user *)buf,
2187 .iov_len = count };
2188 2186
2189 BUG_ON(iocb->ki_pos != pos); 2187 BUG_ON(iocb->ki_pos != pos);
2190 2188
2191 mutex_lock(&inode->i_mutex); 2189 mutex_lock(&inode->i_mutex);
2192 ret = ntfs_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); 2190 ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
2193 mutex_unlock(&inode->i_mutex); 2191 mutex_unlock(&inode->i_mutex);
2194 if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { 2192 if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
2195 int err = sync_page_range(inode, mapping, pos, ret); 2193 int err = sync_page_range(inode, mapping, pos, ret);
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 2bbfa17090cf..d9ba0a931a03 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -961,25 +961,23 @@ static inline int ocfs2_write_should_remove_suid(struct inode *inode)
961} 961}
962 962
963static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, 963static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
964 const char __user *buf, 964 const struct iovec *iov,
965 size_t count, 965 unsigned long nr_segs,
966 loff_t pos) 966 loff_t pos)
967{ 967{
968 struct iovec local_iov = { .iov_base = (void __user *)buf,
969 .iov_len = count };
970 int ret, rw_level = -1, meta_level = -1, have_alloc_sem = 0; 968 int ret, rw_level = -1, meta_level = -1, have_alloc_sem = 0;
971 u32 clusters; 969 u32 clusters;
972 struct file *filp = iocb->ki_filp; 970 struct file *filp = iocb->ki_filp;
973 struct inode *inode = filp->f_dentry->d_inode; 971 struct inode *inode = filp->f_dentry->d_inode;
974 loff_t newsize, saved_pos; 972 loff_t newsize, saved_pos;
975 973
976 mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf, 974 mlog_entry("(0x%p, %u, '%.*s')\n", filp,
977 (unsigned int)count, 975 (unsigned int)nr_segs,
978 filp->f_dentry->d_name.len, 976 filp->f_dentry->d_name.len,
979 filp->f_dentry->d_name.name); 977 filp->f_dentry->d_name.name);
980 978
981 /* happy write of zero bytes */ 979 /* happy write of zero bytes */
982 if (count == 0) 980 if (iocb->ki_left == 0)
983 return 0; 981 return 0;
984 982
985 if (!inode) { 983 if (!inode) {
@@ -1048,7 +1046,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
1048 } else { 1046 } else {
1049 saved_pos = iocb->ki_pos; 1047 saved_pos = iocb->ki_pos;
1050 } 1048 }
1051 newsize = count + saved_pos; 1049 newsize = iocb->ki_left + saved_pos;
1052 1050
1053 mlog(0, "pos=%lld newsize=%lld cursize=%lld\n", 1051 mlog(0, "pos=%lld newsize=%lld cursize=%lld\n",
1054 (long long) saved_pos, (long long) newsize, 1052 (long long) saved_pos, (long long) newsize,
@@ -1081,7 +1079,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
1081 if (!clusters) 1079 if (!clusters)
1082 break; 1080 break;
1083 1081
1084 ret = ocfs2_extend_file(inode, NULL, newsize, count); 1082 ret = ocfs2_extend_file(inode, NULL, newsize, iocb->ki_left);
1085 if (ret < 0) { 1083 if (ret < 0) {
1086 if (ret != -ENOSPC) 1084 if (ret != -ENOSPC)
1087 mlog_errno(ret); 1085 mlog_errno(ret);
@@ -1098,7 +1096,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
1098 /* communicate with ocfs2_dio_end_io */ 1096 /* communicate with ocfs2_dio_end_io */
1099 ocfs2_iocb_set_rw_locked(iocb); 1097 ocfs2_iocb_set_rw_locked(iocb);
1100 1098
1101 ret = generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); 1099 ret = generic_file_aio_write_nolock(iocb, iov, nr_segs, iocb->ki_pos);
1102 1100
1103 /* buffered aio wouldn't have proper lock coverage today */ 1101 /* buffered aio wouldn't have proper lock coverage today */
1104 BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT)); 1102 BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
@@ -1132,16 +1130,16 @@ out:
1132} 1130}
1133 1131
1134static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, 1132static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
1135 char __user *buf, 1133 const struct iovec *iov,
1136 size_t count, 1134 unsigned long nr_segs,
1137 loff_t pos) 1135 loff_t pos)
1138{ 1136{
1139 int ret = 0, rw_level = -1, have_alloc_sem = 0; 1137 int ret = 0, rw_level = -1, have_alloc_sem = 0;
1140 struct file *filp = iocb->ki_filp; 1138 struct file *filp = iocb->ki_filp;
1141 struct inode *inode = filp->f_dentry->d_inode; 1139 struct inode *inode = filp->f_dentry->d_inode;
1142 1140
1143 mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf, 1141 mlog_entry("(0x%p, %u, '%.*s')\n", filp,
1144 (unsigned int)count, 1142 (unsigned int)nr_segs,
1145 filp->f_dentry->d_name.len, 1143 filp->f_dentry->d_name.len,
1146 filp->f_dentry->d_name.name); 1144 filp->f_dentry->d_name.name);
1147 1145
@@ -1185,7 +1183,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
1185 } 1183 }
1186 ocfs2_meta_unlock(inode, 0); 1184 ocfs2_meta_unlock(inode, 0);
1187 1185
1188 ret = generic_file_aio_read(iocb, buf, count, iocb->ki_pos); 1186 ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos);
1189 if (ret == -EINVAL) 1187 if (ret == -EINVAL)
1190 mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n"); 1188 mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n");
1191 1189
diff --git a/fs/read_write.c b/fs/read_write.c
index d4cb3183c99c..679dd535380f 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -227,14 +227,20 @@ static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
227 227
228ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) 228ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
229{ 229{
230 struct iovec iov = { .iov_base = buf, .iov_len = len };
230 struct kiocb kiocb; 231 struct kiocb kiocb;
231 ssize_t ret; 232 ssize_t ret;
232 233
233 init_sync_kiocb(&kiocb, filp); 234 init_sync_kiocb(&kiocb, filp);
234 kiocb.ki_pos = *ppos; 235 kiocb.ki_pos = *ppos;
235 while (-EIOCBRETRY == 236 kiocb.ki_left = len;
236 (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos))) 237
238 for (;;) {
239 ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
240 if (ret != -EIOCBRETRY)
241 break;
237 wait_on_retry_sync_kiocb(&kiocb); 242 wait_on_retry_sync_kiocb(&kiocb);
243 }
238 244
239 if (-EIOCBQUEUED == ret) 245 if (-EIOCBQUEUED == ret)
240 ret = wait_on_sync_kiocb(&kiocb); 246 ret = wait_on_sync_kiocb(&kiocb);
@@ -279,14 +285,20 @@ EXPORT_SYMBOL(vfs_read);
279 285
280ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) 286ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
281{ 287{
288 struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
282 struct kiocb kiocb; 289 struct kiocb kiocb;
283 ssize_t ret; 290 ssize_t ret;
284 291
285 init_sync_kiocb(&kiocb, filp); 292 init_sync_kiocb(&kiocb, filp);
286 kiocb.ki_pos = *ppos; 293 kiocb.ki_pos = *ppos;
287 while (-EIOCBRETRY == 294 kiocb.ki_left = len;
288 (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos))) 295
296 for (;;) {
297 ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
298 if (ret != -EIOCBRETRY)
299 break;
289 wait_on_retry_sync_kiocb(&kiocb); 300 wait_on_retry_sync_kiocb(&kiocb);
301 }
290 302
291 if (-EIOCBQUEUED == ret) 303 if (-EIOCBQUEUED == ret)
292 ret = wait_on_sync_kiocb(&kiocb); 304 ret = wait_on_sync_kiocb(&kiocb);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index c11f6118c9ca..41f24369e47a 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1334,7 +1334,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
1334 if (err) 1334 if (err)
1335 return err; 1335 return err;
1336 } 1336 }
1337 result = generic_file_write(file, buf, count, ppos); 1337 result = do_sync_write(file, buf, count, ppos);
1338 1338
1339 if (after_file_end) { /* Now update i_size and remove the savelink */ 1339 if (after_file_end) { /* Now update i_size and remove the savelink */
1340 struct reiserfs_transaction_handle th; 1340 struct reiserfs_transaction_handle th;
@@ -1566,7 +1566,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
1566} 1566}
1567 1567
1568const struct file_operations reiserfs_file_operations = { 1568const struct file_operations reiserfs_file_operations = {
1569 .read = generic_file_read, 1569 .read = do_sync_read,
1570 .write = reiserfs_file_write, 1570 .write = reiserfs_file_write,
1571 .ioctl = reiserfs_ioctl, 1571 .ioctl = reiserfs_ioctl,
1572#ifdef CONFIG_COMPAT 1572#ifdef CONFIG_COMPAT
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 41cfcba7ce49..4737971c6a39 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -49,50 +49,49 @@ static struct vm_operations_struct xfs_dmapi_file_vm_ops;
49STATIC inline ssize_t 49STATIC inline ssize_t
50__xfs_file_read( 50__xfs_file_read(
51 struct kiocb *iocb, 51 struct kiocb *iocb,
52 char __user *buf, 52 const struct iovec *iov,
53 unsigned long nr_segs,
53 int ioflags, 54 int ioflags,
54 size_t count,
55 loff_t pos) 55 loff_t pos)
56{ 56{
57 struct iovec iov = {buf, count};
58 struct file *file = iocb->ki_filp; 57 struct file *file = iocb->ki_filp;
59 bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode); 58 bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode);
60 59
61 BUG_ON(iocb->ki_pos != pos); 60 BUG_ON(iocb->ki_pos != pos);
62 if (unlikely(file->f_flags & O_DIRECT)) 61 if (unlikely(file->f_flags & O_DIRECT))
63 ioflags |= IO_ISDIRECT; 62 ioflags |= IO_ISDIRECT;
64 return bhv_vop_read(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL); 63 return bhv_vop_read(vp, iocb, iov, nr_segs, &iocb->ki_pos,
64 ioflags, NULL);
65} 65}
66 66
67STATIC ssize_t 67STATIC ssize_t
68xfs_file_aio_read( 68xfs_file_aio_read(
69 struct kiocb *iocb, 69 struct kiocb *iocb,
70 char __user *buf, 70 const struct iovec *iov,
71 size_t count, 71 unsigned long nr_segs,
72 loff_t pos) 72 loff_t pos)
73{ 73{
74 return __xfs_file_read(iocb, buf, IO_ISAIO, count, pos); 74 return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO, pos);
75} 75}
76 76
77STATIC ssize_t 77STATIC ssize_t
78xfs_file_aio_read_invis( 78xfs_file_aio_read_invis(
79 struct kiocb *iocb, 79 struct kiocb *iocb,
80 char __user *buf, 80 const struct iovec *iov,
81 size_t count, 81 unsigned long nr_segs,
82 loff_t pos) 82 loff_t pos)
83{ 83{
84 return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); 84 return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
85} 85}
86 86
87STATIC inline ssize_t 87STATIC inline ssize_t
88__xfs_file_write( 88__xfs_file_write(
89 struct kiocb *iocb, 89 struct kiocb *iocb,
90 const char __user *buf, 90 const struct iovec *iov,
91 int ioflags, 91 unsigned long nr_segs,
92 size_t count, 92 int ioflags,
93 loff_t pos) 93 loff_t pos)
94{ 94{
95 struct iovec iov = {(void __user *)buf, count};
96 struct file *file = iocb->ki_filp; 95 struct file *file = iocb->ki_filp;
97 struct inode *inode = file->f_mapping->host; 96 struct inode *inode = file->f_mapping->host;
98 bhv_vnode_t *vp = vn_from_inode(inode); 97 bhv_vnode_t *vp = vn_from_inode(inode);
@@ -100,27 +99,28 @@ __xfs_file_write(
100 BUG_ON(iocb->ki_pos != pos); 99 BUG_ON(iocb->ki_pos != pos);
101 if (unlikely(file->f_flags & O_DIRECT)) 100 if (unlikely(file->f_flags & O_DIRECT))
102 ioflags |= IO_ISDIRECT; 101 ioflags |= IO_ISDIRECT;
103 return bhv_vop_write(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL); 102 return bhv_vop_write(vp, iocb, iov, nr_segs, &iocb->ki_pos,
103 ioflags, NULL);
104} 104}
105 105
106STATIC ssize_t 106STATIC ssize_t
107xfs_file_aio_write( 107xfs_file_aio_write(
108 struct kiocb *iocb, 108 struct kiocb *iocb,
109 const char __user *buf, 109 const struct iovec *iov,
110 size_t count, 110 unsigned long nr_segs,
111 loff_t pos) 111 loff_t pos)
112{ 112{
113 return __xfs_file_write(iocb, buf, IO_ISAIO, count, pos); 113 return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO, pos);
114} 114}
115 115
116STATIC ssize_t 116STATIC ssize_t
117xfs_file_aio_write_invis( 117xfs_file_aio_write_invis(
118 struct kiocb *iocb, 118 struct kiocb *iocb,
119 const char __user *buf, 119 const struct iovec *iov,
120 size_t count, 120 unsigned long nr_segs,
121 loff_t pos) 121 loff_t pos)
122{ 122{
123 return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); 123 return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
124} 124}
125 125
126STATIC inline ssize_t 126STATIC inline ssize_t
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 8a0193385a9b..58349e58b749 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -4,6 +4,7 @@
4#include <linux/list.h> 4#include <linux/list.h>
5#include <linux/workqueue.h> 5#include <linux/workqueue.h>
6#include <linux/aio_abi.h> 6#include <linux/aio_abi.h>
7#include <linux/uio.h>
7 8
8#include <asm/atomic.h> 9#include <asm/atomic.h>
9 10
@@ -112,6 +113,7 @@ struct kiocb {
112 long ki_retried; /* just for testing */ 113 long ki_retried; /* just for testing */
113 long ki_kicked; /* just for testing */ 114 long ki_kicked; /* just for testing */
114 long ki_queued; /* just for testing */ 115 long ki_queued; /* just for testing */
116 struct iovec ki_inline_vec; /* inline vector */
115 117
116 struct list_head ki_list; /* the aio core uses this 118 struct list_head ki_list; /* the aio core uses this
117 * for cancellation */ 119 * for cancellation */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5baf3a153403..257bae16f545 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1097,9 +1097,9 @@ struct file_operations {
1097 struct module *owner; 1097 struct module *owner;
1098 loff_t (*llseek) (struct file *, loff_t, int); 1098 loff_t (*llseek) (struct file *, loff_t, int);
1099 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 1099 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
1100 ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
1101 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 1100 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
1102 ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t); 1101 ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1102 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1103 int (*readdir) (struct file *, void *, filldir_t); 1103 int (*readdir) (struct file *, void *, filldir_t);
1104 unsigned int (*poll) (struct file *, struct poll_table_struct *); 1104 unsigned int (*poll) (struct file *, struct poll_table_struct *);
1105 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); 1105 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
@@ -1704,11 +1704,11 @@ extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned
1704extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *); 1704extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *);
1705int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); 1705int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
1706extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *); 1706extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *);
1707extern ssize_t generic_file_aio_read(struct kiocb *, char __user *, size_t, loff_t); 1707extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
1708extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *); 1708extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *);
1709extern ssize_t generic_file_aio_write(struct kiocb *, const char __user *, size_t, loff_t); 1709extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
1710extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *, 1710extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
1711 unsigned long, loff_t *); 1711 unsigned long, loff_t);
1712extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *, 1712extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
1713 unsigned long *, loff_t, loff_t *, size_t, size_t); 1713 unsigned long *, loff_t, loff_t *, size_t, size_t);
1714extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *, 1714extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 98c9b9f667a5..76ff54846ada 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -367,10 +367,12 @@ extern int nfs3_removexattr (struct dentry *, const char *name);
367 */ 367 */
368extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t, 368extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
369 unsigned long); 369 unsigned long);
370extern ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, 370extern ssize_t nfs_file_direct_read(struct kiocb *iocb,
371 size_t count, loff_t pos); 371 const struct iovec *iov, unsigned long nr_segs,
372extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, 372 loff_t pos);
373 size_t count, loff_t pos); 373extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
374 const struct iovec *iov, unsigned long nr_segs,
375 loff_t pos);
374 376
375/* 377/*
376 * linux/fs/nfs/dir.c 378 * linux/fs/nfs/dir.c
diff --git a/include/net/sock.h b/include/net/sock.h
index edd4d73ce7f5..40bb90ebb2d1 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -665,7 +665,6 @@ struct sock_iocb {
665 struct sock *sk; 665 struct sock *sk;
666 struct scm_cookie *scm; 666 struct scm_cookie *scm;
667 struct msghdr *msg, async_msg; 667 struct msghdr *msg, async_msg;
668 struct iovec async_iov;
669 struct kiocb *kiocb; 668 struct kiocb *kiocb;
670}; 669};
671 670
diff --git a/mm/filemap.c b/mm/filemap.c
index c4fe97f5ace0..f6c1d22b504f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1226,12 +1226,11 @@ out:
1226EXPORT_SYMBOL(__generic_file_aio_read); 1226EXPORT_SYMBOL(__generic_file_aio_read);
1227 1227
1228ssize_t 1228ssize_t
1229generic_file_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) 1229generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
1230 unsigned long nr_segs, loff_t pos)
1230{ 1231{
1231 struct iovec local_iov = { .iov_base = buf, .iov_len = count };
1232
1233 BUG_ON(iocb->ki_pos != pos); 1232 BUG_ON(iocb->ki_pos != pos);
1234 return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos); 1233 return __generic_file_aio_read(iocb, iov, nr_segs, &iocb->ki_pos);
1235} 1234}
1236EXPORT_SYMBOL(generic_file_aio_read); 1235EXPORT_SYMBOL(generic_file_aio_read);
1237 1236
@@ -2315,22 +2314,22 @@ out:
2315 current->backing_dev_info = NULL; 2314 current->backing_dev_info = NULL;
2316 return written ? written : err; 2315 return written ? written : err;
2317} 2316}
2318EXPORT_SYMBOL(generic_file_aio_write_nolock);
2319 2317
2320ssize_t 2318ssize_t generic_file_aio_write_nolock(struct kiocb *iocb,
2321generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, 2319 const struct iovec *iov, unsigned long nr_segs, loff_t pos)
2322 unsigned long nr_segs, loff_t *ppos)
2323{ 2320{
2324 struct file *file = iocb->ki_filp; 2321 struct file *file = iocb->ki_filp;
2325 struct address_space *mapping = file->f_mapping; 2322 struct address_space *mapping = file->f_mapping;
2326 struct inode *inode = mapping->host; 2323 struct inode *inode = mapping->host;
2327 ssize_t ret; 2324 ssize_t ret;
2328 loff_t pos = *ppos;
2329 2325
2330 ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, ppos); 2326 BUG_ON(iocb->ki_pos != pos);
2327
2328 ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs,
2329 &iocb->ki_pos);
2331 2330
2332 if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { 2331 if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
2333 int err; 2332 ssize_t err;
2334 2333
2335 err = sync_page_range_nolock(inode, mapping, pos, ret); 2334 err = sync_page_range_nolock(inode, mapping, pos, ret);
2336 if (err < 0) 2335 if (err < 0)
@@ -2338,6 +2337,7 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
2338 } 2337 }
2339 return ret; 2338 return ret;
2340} 2339}
2340EXPORT_SYMBOL(generic_file_aio_write_nolock);
2341 2341
2342static ssize_t 2342static ssize_t
2343__generic_file_write_nolock(struct file *file, const struct iovec *iov, 2343__generic_file_write_nolock(struct file *file, const struct iovec *iov,
@@ -2347,8 +2347,9 @@ __generic_file_write_nolock(struct file *file, const struct iovec *iov,
2347 ssize_t ret; 2347 ssize_t ret;
2348 2348
2349 init_sync_kiocb(&kiocb, file); 2349 init_sync_kiocb(&kiocb, file);
2350 kiocb.ki_pos = *ppos;
2350 ret = __generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos); 2351 ret = __generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
2351 if (ret == -EIOCBQUEUED) 2352 if (-EIOCBQUEUED == ret)
2352 ret = wait_on_sync_kiocb(&kiocb); 2353 ret = wait_on_sync_kiocb(&kiocb);
2353 return ret; 2354 return ret;
2354} 2355}
@@ -2361,28 +2362,28 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
2361 ssize_t ret; 2362 ssize_t ret;
2362 2363
2363 init_sync_kiocb(&kiocb, file); 2364 init_sync_kiocb(&kiocb, file);
2364 ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos); 2365 kiocb.ki_pos = *ppos;
2366 ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, *ppos);
2365 if (-EIOCBQUEUED == ret) 2367 if (-EIOCBQUEUED == ret)
2366 ret = wait_on_sync_kiocb(&kiocb); 2368 ret = wait_on_sync_kiocb(&kiocb);
2369 *ppos = kiocb.ki_pos;
2367 return ret; 2370 return ret;
2368} 2371}
2369EXPORT_SYMBOL(generic_file_write_nolock); 2372EXPORT_SYMBOL(generic_file_write_nolock);
2370 2373
2371ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf, 2374ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
2372 size_t count, loff_t pos) 2375 unsigned long nr_segs, loff_t pos)
2373{ 2376{
2374 struct file *file = iocb->ki_filp; 2377 struct file *file = iocb->ki_filp;
2375 struct address_space *mapping = file->f_mapping; 2378 struct address_space *mapping = file->f_mapping;
2376 struct inode *inode = mapping->host; 2379 struct inode *inode = mapping->host;
2377 ssize_t ret; 2380 ssize_t ret;
2378 struct iovec local_iov = { .iov_base = (void __user *)buf,
2379 .iov_len = count };
2380 2381
2381 BUG_ON(iocb->ki_pos != pos); 2382 BUG_ON(iocb->ki_pos != pos);
2382 2383
2383 mutex_lock(&inode->i_mutex); 2384 mutex_lock(&inode->i_mutex);
2384 ret = __generic_file_aio_write_nolock(iocb, &local_iov, 1, 2385 ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs,
2385 &iocb->ki_pos); 2386 &iocb->ki_pos);
2386 mutex_unlock(&inode->i_mutex); 2387 mutex_unlock(&inode->i_mutex);
2387 2388
2388 if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { 2389 if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
diff --git a/net/socket.c b/net/socket.c
index 1bc4167e0da8..df92e4252749 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -95,10 +95,10 @@
95#include <linux/netfilter.h> 95#include <linux/netfilter.h>
96 96
97static int sock_no_open(struct inode *irrelevant, struct file *dontcare); 97static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
98static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf, 98static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
99 size_t size, loff_t pos); 99 unsigned long nr_segs, loff_t pos);
100static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *buf, 100static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
101 size_t size, loff_t pos); 101 unsigned long nr_segs, loff_t pos);
102static int sock_mmap(struct file *file, struct vm_area_struct *vma); 102static int sock_mmap(struct file *file, struct vm_area_struct *vma);
103 103
104static int sock_close(struct inode *inode, struct file *file); 104static int sock_close(struct inode *inode, struct file *file);
@@ -664,7 +664,6 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
664} 664}
665 665
666static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, 666static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
667 char __user *ubuf, size_t size,
668 struct sock_iocb *siocb) 667 struct sock_iocb *siocb)
669{ 668{
670 if (!is_sync_kiocb(iocb)) { 669 if (!is_sync_kiocb(iocb)) {
@@ -675,16 +674,13 @@ static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
675 } 674 }
676 675
677 siocb->kiocb = iocb; 676 siocb->kiocb = iocb;
678 siocb->async_iov.iov_base = ubuf;
679 siocb->async_iov.iov_len = size;
680
681 iocb->private = siocb; 677 iocb->private = siocb;
682 return siocb; 678 return siocb;
683} 679}
684 680
685static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, 681static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
686 struct file *file, struct iovec *iov, 682 struct file *file, const struct iovec *iov,
687 unsigned long nr_segs) 683 unsigned long nr_segs)
688{ 684{
689 struct socket *sock = file->private_data; 685 struct socket *sock = file->private_data;
690 size_t size = 0; 686 size_t size = 0;
@@ -715,32 +711,33 @@ static ssize_t sock_readv(struct file *file, const struct iovec *iov,
715 init_sync_kiocb(&iocb, NULL); 711 init_sync_kiocb(&iocb, NULL);
716 iocb.private = &siocb; 712 iocb.private = &siocb;
717 713
718 ret = do_sock_read(&msg, &iocb, file, (struct iovec *)iov, nr_segs); 714 ret = do_sock_read(&msg, &iocb, file, iov, nr_segs);
719 if (-EIOCBQUEUED == ret) 715 if (-EIOCBQUEUED == ret)
720 ret = wait_on_sync_kiocb(&iocb); 716 ret = wait_on_sync_kiocb(&iocb);
721 return ret; 717 return ret;
722} 718}
723 719
724static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, 720static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
725 size_t count, loff_t pos) 721 unsigned long nr_segs, loff_t pos)
726{ 722{
727 struct sock_iocb siocb, *x; 723 struct sock_iocb siocb, *x;
728 724
729 if (pos != 0) 725 if (pos != 0)
730 return -ESPIPE; 726 return -ESPIPE;
731 if (count == 0) /* Match SYS5 behaviour */ 727
728 if (iocb->ki_left == 0) /* Match SYS5 behaviour */
732 return 0; 729 return 0;
733 730
734 x = alloc_sock_iocb(iocb, ubuf, count, &siocb); 731
732 x = alloc_sock_iocb(iocb, &siocb);
735 if (!x) 733 if (!x)
736 return -ENOMEM; 734 return -ENOMEM;
737 return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, 735 return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
738 &x->async_iov, 1);
739} 736}
740 737
741static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, 738static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
742 struct file *file, struct iovec *iov, 739 struct file *file, const struct iovec *iov,
743 unsigned long nr_segs) 740 unsigned long nr_segs)
744{ 741{
745 struct socket *sock = file->private_data; 742 struct socket *sock = file->private_data;
746 size_t size = 0; 743 size_t size = 0;
@@ -773,28 +770,28 @@ static ssize_t sock_writev(struct file *file, const struct iovec *iov,
773 init_sync_kiocb(&iocb, NULL); 770 init_sync_kiocb(&iocb, NULL);
774 iocb.private = &siocb; 771 iocb.private = &siocb;
775 772
776 ret = do_sock_write(&msg, &iocb, file, (struct iovec *)iov, nr_segs); 773 ret = do_sock_write(&msg, &iocb, file, iov, nr_segs);
777 if (-EIOCBQUEUED == ret) 774 if (-EIOCBQUEUED == ret)
778 ret = wait_on_sync_kiocb(&iocb); 775 ret = wait_on_sync_kiocb(&iocb);
779 return ret; 776 return ret;
780} 777}
781 778
782static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, 779static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
783 size_t count, loff_t pos) 780 unsigned long nr_segs, loff_t pos)
784{ 781{
785 struct sock_iocb siocb, *x; 782 struct sock_iocb siocb, *x;
786 783
787 if (pos != 0) 784 if (pos != 0)
788 return -ESPIPE; 785 return -ESPIPE;
789 if (count == 0) /* Match SYS5 behaviour */ 786
787 if (iocb->ki_left == 0) /* Match SYS5 behaviour */
790 return 0; 788 return 0;
791 789
792 x = alloc_sock_iocb(iocb, (void __user *)ubuf, count, &siocb); 790 x = alloc_sock_iocb(iocb, &siocb);
793 if (!x) 791 if (!x)
794 return -ENOMEM; 792 return -ENOMEM;
795 793
796 return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, 794 return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
797 &x->async_iov, 1);
798} 795}
799 796
800/* 797/*