* [PATCH 0/3] VFS changes to collapse all the vectored and AIO support
@ 2006-02-02 16:12 Badari Pulavarty
2006-02-02 16:14 ` [PATCH 1/3] Vectorize aio_read/aio_write methods Badari Pulavarty
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Badari Pulavarty @ 2006-02-02 16:12 UTC (permalink / raw)
To: christoph, Benjamin LaHaise, Zach Brown; +Cc: lkml, linux-fsdevel, pbadari
Hi,
This work was originally suggested & started by Christoph Hellwig,
when Zack Brown tried to add vectored support for AIO. These series
of changes collapses all the vectored IO support into single
file-operation method using aio_read/aio_write.
Christoph & Zack, comments/suggestions ? If you are happy with the
work, can you add your Sign-off or Ack ?
Here is the summary:
[PATCH 1/3] Vectorize aio_read/aio_write methods
[PATCH 2/3] Remove readv/writev methods and use aio_read/aio_write
instead.
[PATCH 3/3] Zack's core aio changes to support vectored AIO.
To Do/Issues:
1) Since aio_read/aio_write are vectorized now, need to modify
nfs AIO+DIO and usb/gadget to handle vectors. Is it needed ?
For now, it handles only single vector. Christoph, should I
loop over all the vectors ?
2) AIO changes need careful review & could be cleaned up further.
Zack, can you take a look at those ?
3) Ben's suggestion of kernel iovec to hold precomputed information
(like total iolen) instead of computing every time.
Thanks,
Badari
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] Vectorize aio_read/aio_write methods
2006-02-02 16:12 [PATCH 0/3] VFS changes to collapse all the vectored and AIO support Badari Pulavarty
@ 2006-02-02 16:14 ` Badari Pulavarty
2006-02-04 13:28 ` Christoph Hellwig
2006-02-02 16:15 ` [PATCH 2/3] Remove readv/writev methods and use aio_read/aio_write instead Badari Pulavarty
2006-02-02 16:16 ` [PATCH 3/3] Zack's core aio changes to support vectored AIO Badari Pulavarty
2 siblings, 1 reply; 8+ messages in thread
From: Badari Pulavarty @ 2006-02-02 16:14 UTC (permalink / raw)
To: christoph; +Cc: Benjamin LaHaise, Zach Brown, lkml, linux-fsdevel
[-- Attachment #1: Type: text/plain, Size: 181 bytes --]
This patch vectorizes aio_read() and aio_write() methods to prepare
for colapsing all the vectored operations into one interface -
which is aio_read()/aio_write().
Thanks,
Badari
[-- Attachment #2: aiovector.patch --]
[-- Type: text/x-patch, Size: 31621 bytes --]
This patch vectorizes aio_read() and aio_write() methods to prepare
for colapsing all the vectored operations into one interface -
which is aio_read()/aio_write().
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Index: linux-2.6.16-rc1.quilt/Documentation/filesystems/Locking
===================================================================
--- linux-2.6.16-rc1.quilt.orig/Documentation/filesystems/Locking 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/Documentation/filesystems/Locking 2006-02-01 16:38:14.000000000 -0800
@@ -355,10 +355,9 @@
prototypes:
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t,
- loff_t);
+ ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int,
Index: linux-2.6.16-rc1.quilt/Documentation/filesystems/vfs.txt
===================================================================
--- linux-2.6.16-rc1.quilt.orig/Documentation/filesystems/vfs.txt 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/Documentation/filesystems/vfs.txt 2006-02-01 16:38:14.000000000 -0800
@@ -526,9 +526,9 @@
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
+ ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
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);
Index: linux-2.6.16-rc1.quilt/drivers/char/raw.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/drivers/char/raw.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/drivers/char/raw.c 2006-02-01 16:38:14.000000000 -0800
@@ -249,23 +249,11 @@
return generic_file_write_nolock(file, &local_iov, 1, ppos);
}
-static ssize_t raw_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
-{
- struct iovec local_iov = {
- .iov_base = (char __user *)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,
Index: linux-2.6.16-rc1.quilt/fs/aio.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/aio.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/aio.c 2006-02-01 16:38:14.000000000 -0800
@@ -15,6 +15,7 @@
#include <linux/aio_abi.h>
#include <linux/module.h>
#include <linux/syscalls.h>
+#include <linux/uio.h>
#define DEBUG 0
@@ -1316,8 +1317,12 @@
ssize_t ret = 0;
do {
- ret = file->f_op->aio_read(iocb, iocb->ki_buf,
- iocb->ki_left, iocb->ki_pos);
+ struct iovec iov = {
+ .iov_base = iocb->ki_buf,
+ .iov_len = iocb->ki_left
+ };
+
+ ret = file->f_op->aio_read(iocb, &iov, 1, iocb->ki_pos);
/*
* Can't just depend on iocb->ki_left to determine
* whether we are done. This may have been a short read.
@@ -1350,8 +1355,12 @@
ssize_t ret = 0;
do {
- ret = file->f_op->aio_write(iocb, iocb->ki_buf,
- iocb->ki_left, iocb->ki_pos);
+ struct iovec iov = {
+ .iov_base = iocb->ki_buf,
+ .iov_len = iocb->ki_left
+ };
+
+ ret = file->f_op->aio_write(iocb, &iov, 1, iocb->ki_pos);
if (ret > 0) {
iocb->ki_buf += ret;
iocb->ki_left -= ret;
Index: linux-2.6.16-rc1.quilt/fs/block_dev.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/block_dev.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/block_dev.c 2006-02-01 16:38:14.000000000 -0800
@@ -769,14 +769,6 @@
return generic_file_write_nolock(file, &local_iov, 1, ppos);
}
-static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
-{
- struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
-
- return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
-}
-
static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
@@ -799,7 +791,7 @@
.read = generic_file_read,
.write = blkdev_file_write,
.aio_read = generic_file_aio_read,
- .aio_write = blkdev_file_aio_write,
+ .aio_write = generic_file_aio_write_nolock,
.mmap = generic_file_mmap,
.fsync = block_fsync,
.unlocked_ioctl = block_ioctl,
Index: linux-2.6.16-rc1.quilt/fs/cifs/cifsfs.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/cifs/cifsfs.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/cifs/cifsfs.c 2006-02-01 16:38:14.000000000 -0800
@@ -501,13 +501,13 @@
return written;
}
-static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
+static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
ssize_t written;
- written = generic_file_aio_write(iocb, buf, count, pos);
+ written = generic_file_aio_write(iocb, iov, nr_segs, pos);
if (!CIFS_I(inode)->clientCanCacheAll)
filemap_fdatawrite(inode->i_mapping);
return written;
Index: linux-2.6.16-rc1.quilt/fs/ext3/file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/ext3/file.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/ext3/file.c 2006-02-01 16:38:14.000000000 -0800
@@ -48,14 +48,15 @@
}
static ssize_t
-ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+ext3_file_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_dentry->d_inode;
ssize_t ret;
int err;
- ret = generic_file_aio_write(iocb, buf, count, pos);
+ ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
/*
* Skip flushing if there was an error, or if nothing was written.
Index: linux-2.6.16-rc1.quilt/fs/nfs/file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/nfs/file.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/nfs/file.c 2006-02-01 16:38:14.000000000 -0800
@@ -40,8 +40,10 @@
static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
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 __user *, size_t, loff_t);
-static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
+static ssize_t nfs_file_read(struct kiocb *, const struct iovec *,
+ unsigned long, loff_t);
+static ssize_t nfs_file_write(struct kiocb *, const struct iovec *,
+ unsigned long, loff_t);
static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
static int nfs_check_flags(int flags);
@@ -52,8 +54,8 @@
.llseek = nfs_file_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_file_open,
.flush = nfs_file_flush,
@@ -213,7 +215,8 @@
}
static ssize_t
-nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
+nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct dentry * dentry = iocb->ki_filp->f_dentry;
struct inode * inode = dentry->d_inode;
@@ -221,16 +224,15 @@
#ifdef CONFIG_NFS_DIRECTIO
if (iocb->ki_filp->f_flags & O_DIRECT)
- return nfs_file_direct_read(iocb, buf, count, pos);
+ return nfs_file_direct_read(iocb, iov, nr_segs, pos);
#endif
- 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);
+ dfprintk(VFS, "nfs: read(%s/%s)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
result = nfs_revalidate_file(inode, iocb->ki_filp);
if (!result)
- result = generic_file_aio_read(iocb, buf, count, pos);
+ result = generic_file_aio_read(iocb, iov, nr_segs, pos);
return result;
}
@@ -333,7 +335,8 @@
* Write to a file (through the page cache).
*/
static ssize_t
-nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct dentry * dentry = iocb->ki_filp->f_dentry;
struct inode * inode = dentry->d_inode;
@@ -341,12 +344,12 @@
#ifdef CONFIG_NFS_DIRECTIO
if (iocb->ki_filp->f_flags & O_DIRECT)
- return nfs_file_direct_write(iocb, buf, count, pos);
+ return nfs_file_direct_write(iocb, iov, nr_segs, pos);
#endif
- dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n",
+ dfprintk(VFS, "nfs: write(%s/%s(%ld))\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
- inode->i_ino, (unsigned long) count, (unsigned long) pos);
+ inode->i_ino);
result = -EBUSY;
if (IS_SWAPFILE(inode))
@@ -361,11 +364,7 @@
}
nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
- result = count;
- if (!count)
- goto out;
-
- result = generic_file_aio_write(iocb, buf, count, pos);
+ result = generic_file_aio_write(iocb, iov, nr_segs, pos);
out:
return result;
Index: linux-2.6.16-rc1.quilt/fs/read_write.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/read_write.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/read_write.c 2006-02-01 16:38:14.000000000 -0800
@@ -227,16 +227,21 @@
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
+ struct iovec iov = { .iov_base = buf, .iov_len = len };
struct kiocb kiocb;
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
- while (-EIOCBRETRY ==
- (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos)))
+
+ for (;;) {
+ ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
+ if (ret != -EIOCBRETRY)
+ break;
wait_on_retry_sync_kiocb(&kiocb);
+ }
- if (-EIOCBQUEUED == ret)
+ if (ret == -EIOCBQUEUED)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
return ret;
@@ -279,14 +284,19 @@
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
+ struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
struct kiocb kiocb;
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
- while (-EIOCBRETRY ==
- (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos)))
+
+ for (;;) {
+ ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
+ if (ret != -EIOCBRETRY)
+ break;
wait_on_retry_sync_kiocb(&kiocb);
+ }
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
Index: linux-2.6.16-rc1.quilt/fs/reiserfs/file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/reiserfs/file.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/reiserfs/file.c 2006-02-01 16:38:14.000000000 -0800
@@ -1541,12 +1541,6 @@
return res;
}
-static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf,
- size_t count, loff_t pos)
-{
- return generic_file_aio_write(iocb, buf, count, pos);
-}
-
struct file_operations reiserfs_file_operations = {
.read = generic_file_read,
.write = reiserfs_file_write,
@@ -1556,7 +1550,7 @@
.fsync = reiserfs_sync_file,
.sendfile = generic_file_sendfile,
.aio_read = generic_file_aio_read,
- .aio_write = reiserfs_aio_write,
+ .aio_write = generic_file_aio_write,
};
struct inode_operations reiserfs_file_inode_operations = {
Index: linux-2.6.16-rc1.quilt/fs/xfs/linux-2.6/xfs_file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/xfs/linux-2.6/xfs_file.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/xfs/linux-2.6/xfs_file.c 2006-02-01 16:38:14.000000000 -0800
@@ -51,12 +51,11 @@
STATIC inline ssize_t
__linvfs_read(
struct kiocb *iocb,
- char __user *buf,
+ const struct iovec *iov,
+ unsigned long nr_segs,
int ioflags,
- size_t count,
loff_t pos)
{
- struct iovec iov = {buf, count};
struct file *file = iocb->ki_filp;
vnode_t *vp = LINVFS_GET_VP(file->f_dentry->d_inode);
ssize_t rval;
@@ -65,7 +64,7 @@
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
- VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
+ VOP_READ(vp, iocb, iov, nr_segs, &iocb->ki_pos, ioflags, NULL, rval);
return rval;
}
@@ -73,33 +72,32 @@
STATIC ssize_t
linvfs_aio_read(
struct kiocb *iocb,
- char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __linvfs_read(iocb, buf, IO_ISAIO, count, pos);
+ return __linvfs_read(iocb, iov, nr_segs, IO_ISAIO, pos);
}
STATIC ssize_t
linvfs_aio_read_invis(
struct kiocb *iocb,
- char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __linvfs_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
+ return __linvfs_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
}
STATIC inline ssize_t
__linvfs_write(
- struct kiocb *iocb,
- const char __user *buf,
- int ioflags,
- size_t count,
- loff_t pos)
+ struct kiocb *iocb,
+ const struct iovec *iov,
+ unsigned long nr_segs,
+ int ioflags,
+ loff_t pos)
{
- struct iovec iov = {(void __user *)buf, count};
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
vnode_t *vp = LINVFS_GET_VP(inode);
@@ -109,7 +107,7 @@
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
- VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
+ VOP_WRITE(vp, iocb, iov, nr_segs, &iocb->ki_pos, ioflags, NULL, rval);
return rval;
}
@@ -117,21 +115,21 @@
STATIC ssize_t
linvfs_aio_write(
struct kiocb *iocb,
- const char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __linvfs_write(iocb, buf, IO_ISAIO, count, pos);
+ return __linvfs_write(iocb, iov, nr_segs, IO_ISAIO, pos);
}
STATIC ssize_t
linvfs_aio_write_invis(
struct kiocb *iocb,
- const char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __linvfs_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
+ return __linvfs_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
}
Index: linux-2.6.16-rc1.quilt/include/linux/fs.h
===================================================================
--- linux-2.6.16-rc1.quilt.orig/include/linux/fs.h 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/include/linux/fs.h 2006-02-01 16:38:14.000000000 -0800
@@ -997,9 +997,9 @@
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
+ ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
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);
@@ -1558,11 +1558,11 @@
extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *);
int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *);
-extern ssize_t generic_file_aio_read(struct kiocb *, char __user *, size_t, loff_t);
+extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *);
-extern ssize_t generic_file_aio_write(struct kiocb *, const char __user *, size_t, loff_t);
+extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
- unsigned long, loff_t *);
+ unsigned long, loff_t);
extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
unsigned long *, loff_t, loff_t *, size_t, size_t);
extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
Index: linux-2.6.16-rc1.quilt/include/net/sock.h
===================================================================
--- linux-2.6.16-rc1.quilt.orig/include/net/sock.h 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/include/net/sock.h 2006-02-01 16:38:14.000000000 -0800
@@ -650,7 +650,6 @@
struct sock *sk;
struct scm_cookie *scm;
struct msghdr *msg, async_msg;
- struct iovec async_iov;
struct kiocb *kiocb;
};
Index: linux-2.6.16-rc1.quilt/mm/filemap.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/mm/filemap.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/mm/filemap.c 2006-02-01 16:38:14.000000000 -0800
@@ -1064,14 +1064,12 @@
EXPORT_SYMBOL(__generic_file_aio_read);
ssize_t
-generic_file_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, 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);
+ return __generic_file_aio_read(iocb, iov, nr_segs, &iocb->ki_pos);
}
-
EXPORT_SYMBOL(generic_file_aio_read);
ssize_t
@@ -2131,22 +2129,21 @@
current->backing_dev_info = NULL;
return written ? written : err;
}
-EXPORT_SYMBOL(generic_file_aio_write_nolock);
-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 kiocb *iocb,
+ const struct iovec *iov, unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t ret;
- loff_t pos = *ppos;
- ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, ppos);
+ BUG_ON(iocb->ki_pos != pos);
+
+ ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
- int err;
+ ssize_t err;
err = sync_page_range_nolock(inode, mapping, pos, ret);
if (err < 0)
@@ -2154,6 +2151,7 @@
}
return ret;
}
+EXPORT_SYMBOL(generic_file_aio_write_nolock);
static ssize_t
__generic_file_write_nolock(struct file *file, const struct iovec *iov,
@@ -2163,9 +2161,11 @@
ssize_t ret;
init_sync_kiocb(&kiocb, file);
+ kiocb.ki_pos = *ppos;
ret = __generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
- if (ret == -EIOCBQUEUED)
+ if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
+ *ppos = kiocb.ki_pos;
return ret;
}
@@ -2177,28 +2177,27 @@
ssize_t ret;
init_sync_kiocb(&kiocb, file);
- ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
+ kiocb.ki_pos = *ppos;
+ ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, *ppos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
+ *ppos = kiocb.ki_pos;
return ret;
}
EXPORT_SYMBOL(generic_file_write_nolock);
-ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
+ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t ret;
- struct iovec local_iov = { .iov_base = (void __user *)buf,
- .iov_len = count };
BUG_ON(iocb->ki_pos != pos);
mutex_lock(&inode->i_mutex);
- ret = __generic_file_aio_write_nolock(iocb, &local_iov, 1,
- &iocb->ki_pos);
+ ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
Index: linux-2.6.16-rc1.quilt/net/socket.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/net/socket.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/net/socket.c 2006-02-01 16:38:14.000000000 -0800
@@ -98,10 +98,10 @@
#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 __user *buf,
- size_t size, loff_t pos);
-static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t size, loff_t pos);
+static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
+static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
static int sock_mmap(struct file *file, struct vm_area_struct * vma);
static int sock_close(struct inode *inode, struct file *file);
@@ -635,11 +635,6 @@
return result;
}
-static void sock_aio_dtor(struct kiocb *iocb)
-{
- kfree(iocb->private);
-}
-
static ssize_t sock_sendpage(struct file *file, struct page *page,
int offset, size_t size, loff_t *ppos, int more)
{
@@ -655,8 +650,13 @@
return sock->ops->sendpage(sock, page, offset, size, flags);
}
+static void sock_aio_dtor(struct kiocb *iocb)
+{
+ kfree(iocb->private);
+}
+
static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
- char __user *ubuf, size_t size, struct sock_iocb *siocb)
+ struct sock_iocb *siocb)
{
if (!is_sync_kiocb(iocb)) {
siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
@@ -666,15 +666,13 @@
}
siocb->kiocb = iocb;
- siocb->async_iov.iov_base = ubuf;
- siocb->async_iov.iov_len = size;
-
iocb->private = siocb;
return siocb;
}
static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
- struct file *file, struct iovec *iov, unsigned long nr_segs)
+ struct file *file, const struct iovec *iov,
+ unsigned long nr_segs)
{
struct socket *sock = file->private_data;
size_t size = 0;
@@ -705,31 +703,33 @@
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
- ret = do_sock_read(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
+ ret = do_sock_read(&msg, &iocb, file, iov, nr_segs);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
}
-static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
- size_t count, loff_t pos)
+static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct sock_iocb siocb, *x;
if (pos != 0)
return -ESPIPE;
+#if 0
if (count == 0) /* Match SYS5 behaviour */
return 0;
+#endif
- x = alloc_sock_iocb(iocb, ubuf, count, &siocb);
+ x = alloc_sock_iocb(iocb, &siocb);
if (!x)
return -ENOMEM;
- return do_sock_read(&x->async_msg, iocb, iocb->ki_filp,
- &x->async_iov, 1);
+ return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
}
static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
- struct file *file, struct iovec *iov, unsigned long nr_segs)
+ struct file *file, const struct iovec *iov,
+ unsigned long nr_segs)
{
struct socket *sock = file->private_data;
size_t size = 0;
@@ -762,28 +762,29 @@
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
- ret = do_sock_write(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
+ ret = do_sock_write(&msg, &iocb, file, iov, nr_segs);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
}
-static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
- size_t count, loff_t pos)
+static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct sock_iocb siocb, *x;
if (pos != 0)
return -ESPIPE;
+#if 0
if (count == 0) /* Match SYS5 behaviour */
return 0;
+#endif
- x = alloc_sock_iocb(iocb, (void __user *)ubuf, count, &siocb);
+ x = alloc_sock_iocb(iocb, &siocb);
if (!x)
return -ENOMEM;
- return do_sock_write(&x->async_msg, iocb, iocb->ki_filp,
- &x->async_iov, 1);
+ return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
}
Index: linux-2.6.16-rc1.quilt/fs/nfs/direct.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/nfs/direct.c 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/nfs/direct.c 2006-02-01 16:38:14.000000000 -0800
@@ -648,7 +648,8 @@
* cache.
*/
ssize_t
-nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
ssize_t retval = -EINVAL;
loff_t *ppos = &iocb->ki_pos;
@@ -657,10 +658,11 @@
(struct nfs_open_context *) file->private_data;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = count,
- };
+ ssize_t count;
+
+ /* FIXME: Can we have multiple vectors here ? */
+ BUG_ON(nr_segs != 1);
+ count = iov->iov_len;
dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
@@ -672,7 +674,7 @@
if (count < 0)
goto out;
retval = -EFAULT;
- if (!access_ok(VERIFY_WRITE, iov.iov_base, iov.iov_len))
+ if (!access_ok(VERIFY_WRITE, iov->iov_base, iov->iov_len))
goto out;
retval = 0;
if (!count)
@@ -682,7 +684,7 @@
if (retval)
goto out;
- retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
+ retval = nfs_direct_read(inode, ctx, iov, pos, 1);
if (retval > 0)
*ppos = pos + retval;
@@ -716,7 +718,8 @@
* is no atomic O_APPEND write facility in the NFS protocol.
*/
ssize_t
-nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
ssize_t retval;
struct file *file = iocb->ki_filp;
@@ -724,9 +727,11 @@
(struct nfs_open_context *) file->private_data;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
- struct iovec iov = {
- .iov_base = (char __user *)buf,
- };
+ ssize_t count;
+
+ /* FIXME: Can we have multiple vectors here ? */
+ BUG_ON(nr_segs != 1);
+ count = iov->iov_len;
dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
@@ -747,17 +752,16 @@
retval = 0;
if (!count)
goto out;
- iov.iov_len = count,
retval = -EFAULT;
- if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
+ if (!access_ok(VERIFY_READ, iov->iov_base, iov->iov_len))
goto out;
retval = nfs_sync_mapping(mapping);
if (retval)
goto out;
- retval = nfs_direct_write(inode, ctx, &iov, pos, 1);
+ retval = nfs_direct_write(inode, ctx, iov, pos, 1);
if (mapping->nrpages)
invalidate_inode_pages2(mapping);
if (retval > 0)
Index: linux-2.6.16-rc1.quilt/include/linux/nfs_fs.h
===================================================================
--- linux-2.6.16-rc1.quilt.orig/include/linux/nfs_fs.h 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/include/linux/nfs_fs.h 2006-02-01 16:38:14.000000000 -0800
@@ -369,10 +369,10 @@
*/
extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
unsigned long);
-extern ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf,
- size_t count, loff_t pos);
-extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos);
+extern ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *,
+ unsigned long nr_segs, loff_t pos);
+extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *,
+ unsigned long nr_segs, loff_t pos);
/*
* linux/fs/nfs/dir.c
Index: linux-2.6.16-rc1.quilt/drivers/usb/gadget/inode.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/drivers/usb/gadget/inode.c 2006-02-01 16:16:50.000000000 -0800
+++ linux-2.6.16-rc1.quilt/drivers/usb/gadget/inode.c 2006-02-01 16:39:06.000000000 -0800
@@ -675,32 +675,46 @@
}
static ssize_t
-ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
+ep_aio_read(struct kiocb *iocb, const struct iovec *iv,
+ unsigned long count, loff_t o)
{
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
+ size_t len;
if (unlikely(epdata->desc.bEndpointAddress & USB_DIR_IN))
return -EINVAL;
+
+ /* FIXME: Can we really get a vector here ? If so, handle it */
+ BUG_ON(count != 1);
+ len = iv->iov_len;
+
buf = kmalloc(len, GFP_KERNEL);
if (unlikely(!buf))
return -ENOMEM;
iocb->ki_retry = ep_aio_read_retry;
- return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
+ return ep_aio_rwtail(iocb, buf, len, epdata, iv->iov_base);
}
static ssize_t
-ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
+ep_aio_write(struct kiocb *iocb, const struct iovec *iv,
+ unsigned long count, loff_t o)
{
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
+ size_t len;
if (unlikely(!(epdata->desc.bEndpointAddress & USB_DIR_IN)))
return -EINVAL;
+
+ /* FIXME: Can we really get a vector here ? If so, handle it */
+ BUG_ON(count != 1);
+ len = iv->iov_len;
+
buf = kmalloc(len, GFP_KERNEL);
if (unlikely(!buf))
return -ENOMEM;
- if (unlikely(copy_from_user(buf, ubuf, len) != 0)) {
+ if (unlikely(copy_from_user(buf, iv->iov_base, len) != 0)) {
kfree(buf);
return -EFAULT;
}
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/3] Remove readv/writev methods and use aio_read/aio_write instead.
2006-02-02 16:12 [PATCH 0/3] VFS changes to collapse all the vectored and AIO support Badari Pulavarty
2006-02-02 16:14 ` [PATCH 1/3] Vectorize aio_read/aio_write methods Badari Pulavarty
@ 2006-02-02 16:15 ` Badari Pulavarty
2006-02-02 16:16 ` [PATCH 3/3] Zack's core aio changes to support vectored AIO Badari Pulavarty
2 siblings, 0 replies; 8+ messages in thread
From: Badari Pulavarty @ 2006-02-02 16:15 UTC (permalink / raw)
To: christoph; +Cc: Benjamin LaHaise, Zach Brown, lkml, linux-fsdevel
[-- Attachment #1: Type: text/plain, Size: 121 bytes --]
This patch removes readv() and writev() methods and replaces
them with aio_read()/aio_write() methods.
Thanks,
Badari
[-- Attachment #2: remove-readv-writev.patch --]
[-- Type: text/x-patch, Size: 32909 bytes --]
This patch removes readv() and writev() methods and replaces
them with aio_read()/aio_write() methods.
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Index: linux-2.6.16-rc1.quilt/drivers/char/raw.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/drivers/char/raw.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/drivers/char/raw.c 2006-02-01 16:05:29.000000000 -0800
@@ -257,8 +257,6 @@
.open = raw_open,
.release= raw_release,
.ioctl = raw_ioctl,
- .readv = generic_file_readv,
- .writev = generic_file_writev,
.owner = THIS_MODULE,
};
Index: linux-2.6.16-rc1.quilt/drivers/net/tun.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/drivers/net/tun.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/drivers/net/tun.c 2006-02-01 16:05:29.000000000 -0800
@@ -286,11 +286,10 @@
return len;
}
-/* Writev */
-static ssize_t tun_chr_writev(struct file * file, const struct iovec *iv,
- unsigned long count, loff_t *pos)
+static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
+ unsigned long count, loff_t pos)
{
- struct tun_struct *tun = file->private_data;
+ struct tun_struct *tun = iocb->ki_filp->private_data;
if (!tun)
return -EBADFD;
@@ -300,14 +299,6 @@
return tun_get_user(tun, (struct iovec *) iv, iov_total(iv, count));
}
-/* Write */
-static ssize_t tun_chr_write(struct file * file, const char __user * buf,
- size_t count, loff_t *pos)
-{
- struct iovec iv = { (void __user *) buf, count };
- return tun_chr_writev(file, &iv, 1, pos);
-}
-
/* Put packet to the user space buffer */
static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
struct sk_buff *skb,
@@ -341,10 +332,10 @@
return total;
}
-/* Readv */
-static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
- unsigned long count, loff_t *pos)
+static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
+ unsigned long count, loff_t pos)
{
+ struct file *file = iocb->ki_filp;
struct tun_struct *tun = file->private_data;
DECLARE_WAITQUEUE(wait, current);
struct sk_buff *skb;
@@ -424,14 +415,6 @@
return ret;
}
-/* Read */
-static ssize_t tun_chr_read(struct file * file, char __user * buf,
- size_t count, loff_t *pos)
-{
- struct iovec iv = { buf, count };
- return tun_chr_readv(file, &iv, 1, pos);
-}
-
static void tun_setup(struct net_device *dev)
{
struct tun_struct *tun = netdev_priv(dev);
@@ -759,10 +742,8 @@
static struct file_operations tun_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
- .read = tun_chr_read,
- .readv = tun_chr_readv,
- .write = tun_chr_write,
- .writev = tun_chr_writev,
+ .aio_read = tun_chr_aio_read,
+ .aio_write = tun_chr_aio_write,
.poll = tun_chr_poll,
.ioctl = tun_chr_ioctl,
.open = tun_chr_open,
Index: linux-2.6.16-rc1.quilt/fs/bad_inode.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/bad_inode.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/bad_inode.c 2006-02-01 16:05:29.000000000 -0800
@@ -40,8 +40,6 @@
.aio_fsync = EIO_ERROR,
.fasync = EIO_ERROR,
.lock = EIO_ERROR,
- .readv = EIO_ERROR,
- .writev = EIO_ERROR,
.sendfile = EIO_ERROR,
.sendpage = EIO_ERROR,
.get_unmapped_area = EIO_ERROR,
Index: linux-2.6.16-rc1.quilt/fs/block_dev.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/block_dev.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/block_dev.c 2006-02-01 16:05:29.000000000 -0800
@@ -798,8 +798,6 @@
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_blkdev_ioctl,
#endif
- .readv = generic_file_readv,
- .writev = generic_file_write_nolock,
.sendfile = generic_file_sendfile,
};
Index: linux-2.6.16-rc1.quilt/fs/cifs/cifsfs.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/cifs/cifsfs.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/cifs/cifsfs.c 2006-02-01 16:05:29.000000000 -0800
@@ -489,18 +489,6 @@
return sb;
}
-static ssize_t cifs_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 written;
-
- written = generic_file_writev(file, iov, nr_segs, ppos);
- if (!CIFS_I(inode)->clientCanCacheAll)
- filemap_fdatawrite(inode->i_mapping);
- return written;
-}
-
static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
@@ -575,8 +563,6 @@
struct file_operations cifs_file_ops = {
.read = do_sync_read,
.write = do_sync_write,
- .readv = generic_file_readv,
- .writev = cifs_file_writev,
.aio_read = generic_file_aio_read,
.aio_write = cifs_file_aio_write,
.open = cifs_open,
@@ -617,8 +603,6 @@
struct file_operations cifs_file_nobrl_ops = {
.read = do_sync_read,
.write = do_sync_write,
- .readv = generic_file_readv,
- .writev = cifs_file_writev,
.aio_read = generic_file_aio_read,
.aio_write = cifs_file_aio_write,
.open = cifs_open,
Index: linux-2.6.16-rc1.quilt/fs/compat.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/compat.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/compat.c 2006-02-01 16:05:29.000000000 -0800
@@ -53,6 +53,8 @@
#include <asm/mmu_context.h>
#include <asm/ioctls.h>
+#include "read_write.h"
+
/*
* Not all architectures have sys_utime, so implement this in terms
* of sys_utimes.
@@ -1109,9 +1111,6 @@
const struct compat_iovec __user *uvector,
unsigned long nr_segs, loff_t *pos)
{
- typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
- typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
-
compat_ssize_t tot_len;
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov=iovstack, *vector;
@@ -1190,39 +1189,17 @@
fnv = NULL;
if (type == READ) {
fn = file->f_op->read;
- fnv = file->f_op->readv;
+ fnv = file->f_op->aio_read;
} else {
fn = (io_fn_t)file->f_op->write;
- fnv = file->f_op->writev;
- }
- if (fnv) {
- ret = fnv(file, iov, nr_segs, pos);
- goto out;
+ fnv = file->f_op->aio_write;
}
- /* Do it by hand, with file-ops */
- ret = 0;
- vector = iov;
- while (nr_segs > 0) {
- void __user * base;
- size_t len;
- ssize_t nr;
+ if (fnv)
+ ret = do_sync_readv_writev(file, iov, nr_segs, pos, fnv);
+ else
+ ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
- 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;
- }
out:
if (iov != iovstack)
kfree(iov);
@@ -1250,7 +1227,7 @@
goto out;
ret = -EINVAL;
- if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
+ if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
goto out;
ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos);
@@ -1273,7 +1250,7 @@
goto out;
ret = -EINVAL;
- if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
+ if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
goto out;
ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos);
Index: linux-2.6.16-rc1.quilt/fs/ext2/file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/ext2/file.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/ext2/file.c 2006-02-01 16:05:29.000000000 -0800
@@ -50,8 +50,6 @@
.open = generic_file_open,
.release = ext2_release_file,
.fsync = ext2_sync_file,
- .readv = generic_file_readv,
- .writev = generic_file_writev,
.sendfile = generic_file_sendfile,
};
Index: linux-2.6.16-rc1.quilt/fs/ext3/file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/ext3/file.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/ext3/file.c 2006-02-01 16:05:29.000000000 -0800
@@ -112,8 +112,6 @@
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = ext3_file_write,
- .readv = generic_file_readv,
- .writev = generic_file_writev,
.ioctl = ext3_ioctl,
.mmap = generic_file_mmap,
.open = generic_file_open,
Index: linux-2.6.16-rc1.quilt/fs/fat/file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/fat/file.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/fat/file.c 2006-02-01 16:05:29.000000000 -0800
@@ -116,8 +116,6 @@
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .readv = generic_file_readv,
- .writev = generic_file_writev,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
Index: linux-2.6.16-rc1.quilt/fs/fuse/dev.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/fuse/dev.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/fuse/dev.c 2006-02-01 16:05:29.000000000 -0800
@@ -578,8 +578,8 @@
* request_end(). Otherwise add it to the processing list, and set
* the 'sent' flag.
*/
-static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *off)
+static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
int err;
struct fuse_conn *fc;
@@ -590,7 +590,7 @@
restart:
spin_lock(&fuse_lock);
- fc = file->private_data;
+ fc = iocb->ki_filp->private_data;
err = -EPERM;
if (!fc)
goto err_unlock;
@@ -648,15 +648,6 @@
return err;
}
-static ssize_t fuse_dev_read(struct file *file, char __user *buf,
- size_t nbytes, loff_t *off)
-{
- struct iovec iov;
- iov.iov_len = nbytes;
- iov.iov_base = buf;
- return fuse_dev_readv(file, &iov, 1, off);
-}
-
/* Look up request on processing list by unique ID */
static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
{
@@ -701,15 +692,15 @@
* it from the list and copy the rest of the buffer to the request.
* The request is finished by calling request_end()
*/
-static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *off)
+static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
int err;
unsigned nbytes = iov_length(iov, nr_segs);
struct fuse_req *req;
struct fuse_out_header oh;
struct fuse_copy_state cs;
- struct fuse_conn *fc = fuse_get_conn(file);
+ struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp);
if (!fc)
return -ENODEV;
@@ -769,15 +760,6 @@
return err;
}
-static ssize_t fuse_dev_write(struct file *file, const char __user *buf,
- size_t nbytes, loff_t *off)
-{
- struct iovec iov;
- iov.iov_len = nbytes;
- iov.iov_base = (char __user *) buf;
- return fuse_dev_writev(file, &iov, 1, off);
-}
-
static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
{
struct fuse_conn *fc = fuse_get_conn(file);
@@ -901,10 +883,8 @@
struct file_operations fuse_dev_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
- .read = fuse_dev_read,
- .readv = fuse_dev_readv,
- .write = fuse_dev_write,
- .writev = fuse_dev_writev,
+ .aio_read = fuse_dev_read,
+ .aio_write = fuse_dev_write,
.poll = fuse_dev_poll,
.release = fuse_dev_release,
};
Index: linux-2.6.16-rc1.quilt/fs/hostfs/hostfs_kern.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/hostfs/hostfs_kern.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/hostfs/hostfs_kern.c 2006-02-01 16:05:29.000000000 -0800
@@ -390,8 +390,6 @@
.sendfile = generic_file_sendfile,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
- .readv = generic_file_readv,
- .writev = generic_file_writev,
.write = generic_file_write,
.mmap = generic_file_mmap,
.open = hostfs_file_open,
Index: linux-2.6.16-rc1.quilt/fs/jfs/file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/jfs/file.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/jfs/file.c 2006-02-01 16:05:29.000000000 -0800
@@ -108,8 +108,6 @@
.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,
Index: linux-2.6.16-rc1.quilt/fs/ntfs/file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/ntfs/file.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/ntfs/file.c 2006-02-01 16:05:29.000000000 -0800
@@ -2308,11 +2308,9 @@
.llseek = generic_file_llseek, /* Seek inside file. */
.read = generic_file_read, /* Read from file. */
.aio_read = generic_file_aio_read, /* Async read from file. */
- .readv = generic_file_readv, /* Read from file. */
#ifdef NTFS_RW
.write = ntfs_file_write, /* Write to file. */
.aio_write = ntfs_file_aio_write, /* Async write to file. */
- .writev = ntfs_file_writev, /* Write to file. */
/*.release = ,*/ /* Last file is closed. See
fs/ext2/file.c::
ext2_release_file() for
Index: linux-2.6.16-rc1.quilt/fs/pipe.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/pipe.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/pipe.c 2006-02-01 16:05:29.000000000 -0800
@@ -119,9 +119,10 @@
};
static ssize_t
-pipe_readv(struct file *filp, const struct iovec *_iov,
- unsigned long nr_segs, loff_t *ppos)
+pipe_read(struct kiocb *iocb, const struct iovec *_iov,
+ unsigned long nr_segs, loff_t pos)
{
+ struct file *filp = iocb->ki_filp;
struct inode *inode = filp->f_dentry->d_inode;
struct pipe_inode_info *info;
int do_wakeup;
@@ -212,16 +213,10 @@
}
static ssize_t
-pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
- struct iovec iov = { .iov_base = buf, .iov_len = count };
- return pipe_readv(filp, &iov, 1, ppos);
-}
-
-static ssize_t
-pipe_writev(struct file *filp, const struct iovec *_iov,
- unsigned long nr_segs, loff_t *ppos)
+pipe_write(struct kiocb *iocb, const struct iovec *_iov,
+ unsigned long nr_segs, loff_t pos)
{
+ struct file *filp = iocb->ki_filp;
struct inode *inode = filp->f_dentry->d_inode;
struct pipe_inode_info *info;
ssize_t ret;
@@ -352,14 +347,6 @@
}
static ssize_t
-pipe_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
- return pipe_writev(filp, &iov, 1, ppos);
-}
-
-static ssize_t
bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
return -EBADF;
@@ -570,8 +557,7 @@
*/
struct file_operations read_fifo_fops = {
.llseek = no_llseek,
- .read = pipe_read,
- .readv = pipe_readv,
+ .aio_read = pipe_read,
.write = bad_pipe_w,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
@@ -583,8 +569,7 @@
struct file_operations write_fifo_fops = {
.llseek = no_llseek,
.read = bad_pipe_r,
- .write = pipe_write,
- .writev = pipe_writev,
+ .aio_write = pipe_write,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_write_open,
@@ -594,10 +579,8 @@
struct file_operations rdwr_fifo_fops = {
.llseek = no_llseek,
- .read = pipe_read,
- .readv = pipe_readv,
- .write = pipe_write,
- .writev = pipe_writev,
+ .aio_read = pipe_read,
+ .aio_write = pipe_write,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_rdwr_open,
@@ -607,8 +590,7 @@
struct file_operations read_pipe_fops = {
.llseek = no_llseek,
- .read = pipe_read,
- .readv = pipe_readv,
+ .aio_read = pipe_read,
.write = bad_pipe_w,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
@@ -620,8 +602,7 @@
struct file_operations write_pipe_fops = {
.llseek = no_llseek,
.read = bad_pipe_r,
- .write = pipe_write,
- .writev = pipe_writev,
+ .aio_write = pipe_write,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_write_open,
@@ -631,10 +612,8 @@
struct file_operations rdwr_pipe_fops = {
.llseek = no_llseek,
- .read = pipe_read,
- .readv = pipe_readv,
- .write = pipe_write,
- .writev = pipe_writev,
+ .aio_read = pipe_read,
+ .aio_write = pipe_write,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_rdwr_open,
Index: linux-2.6.16-rc1.quilt/fs/read_write.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/read_write.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/read_write.c 2006-02-01 16:05:29.000000000 -0800
@@ -448,6 +448,66 @@
EXPORT_SYMBOL(iov_shorten);
+typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
+typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
+ unsigned long, loff_t);
+
+
+ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos, iov_fn_t fn)
+{
+ struct kiocb kiocb;
+ ssize_t ret;
+
+ init_sync_kiocb(&kiocb, filp);
+ kiocb.ki_pos = *ppos;
+
+ for (;;) {
+ ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
+ if (ret != -EIOCBRETRY)
+ break;
+ wait_on_retry_sync_kiocb(&kiocb);
+ }
+
+ if (ret == -EIOCBQUEUED)
+ ret = wait_on_sync_kiocb(&kiocb);
+ *ppos = kiocb.ki_pos;
+ return ret;
+}
+
+/* Do it by hand, with file-ops */
+ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
+{
+ struct iovec *vector = iov;
+ ssize_t ret = 0;
+
+
+ while (nr_segs > 0) {
+ void __user * base;
+ size_t len;
+ ssize_t nr;
+
+ base = vector->iov_base;
+ len = vector->iov_len;
+ vector++;
+ nr_segs--;
+
+ nr = fn(filp, base, len, ppos);
+
+ if (nr < 0) {
+ if (!ret)
+ ret = nr;
+ break;
+ }
+ ret += nr;
+ if (nr != len)
+ break;
+ }
+
+ return ret;
+}
+
/* A write operation does a read from user space and vice versa */
#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
@@ -455,12 +515,9 @@
const struct iovec __user * uvector,
unsigned long nr_segs, loff_t *pos)
{
- typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
- typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
-
size_t tot_len;
struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov=iovstack, *vector;
+ struct iovec *iov = iovstack;
ssize_t ret;
int seg;
io_fn_t fn;
@@ -530,39 +587,17 @@
fnv = NULL;
if (type == READ) {
fn = file->f_op->read;
- fnv = file->f_op->readv;
+ fnv = file->f_op->aio_read;
} else {
fn = (io_fn_t)file->f_op->write;
- fnv = file->f_op->writev;
- }
- if (fnv) {
- ret = fnv(file, iov, nr_segs, pos);
- goto out;
+ fnv = file->f_op->aio_write;
}
- /* Do it by hand, with file-ops */
- ret = 0;
- vector = iov;
- while (nr_segs > 0) {
- void __user * 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 (fnv)
+ ret = do_sync_readv_writev(file, iov, nr_segs, pos, fnv);
+ else
+ ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
- if (nr < 0) {
- if (!ret) ret = nr;
- break;
- }
- ret += nr;
- if (nr != len)
- break;
- }
out:
if (iov != iovstack)
kfree(iov);
@@ -583,7 +618,7 @@
{
if (!(file->f_mode & FMODE_READ))
return -EBADF;
- if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
+ if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
return -EINVAL;
return do_readv_writev(READ, file, vec, vlen, pos);
@@ -596,7 +631,7 @@
{
if (!(file->f_mode & FMODE_WRITE))
return -EBADF;
- if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
+ if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
return -EINVAL;
return do_readv_writev(WRITE, file, vec, vlen, pos);
Index: linux-2.6.16-rc1.quilt/fs/read_write.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16-rc1.quilt/fs/read_write.h 2006-02-01 16:05:29.000000000 -0800
@@ -0,0 +1,14 @@
+/*
+ * This file is only for sharing some helpers from read_write.c with compat.c.
+ * Don't use anywhere else.
+ */
+
+
+typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
+typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
+ unsigned long, loff_t);
+
+ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos, iov_fn_t fn);
+ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos, io_fn_t fn);
Index: linux-2.6.16-rc1.quilt/fs/xfs/linux-2.6/xfs_file.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/xfs/linux-2.6/xfs_file.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/xfs/linux-2.6/xfs_file.c 2006-02-01 16:05:29.000000000 -0800
@@ -133,96 +133,6 @@
}
-STATIC inline ssize_t
-__linvfs_readv(
- struct file *file,
- const struct iovec *iov,
- int ioflags,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- struct inode *inode = file->f_mapping->host;
- vnode_t *vp = LINVFS_GET_VP(inode);
- struct kiocb kiocb;
- ssize_t rval;
-
- init_sync_kiocb(&kiocb, file);
- kiocb.ki_pos = *ppos;
-
- if (unlikely(file->f_flags & O_DIRECT))
- ioflags |= IO_ISDIRECT;
- VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
-
- *ppos = kiocb.ki_pos;
- return rval;
-}
-
-STATIC ssize_t
-linvfs_readv(
- struct file *file,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- return __linvfs_readv(file, iov, 0, nr_segs, ppos);
-}
-
-STATIC ssize_t
-linvfs_readv_invis(
- struct file *file,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- return __linvfs_readv(file, iov, IO_INVIS, nr_segs, ppos);
-}
-
-
-STATIC inline ssize_t
-__linvfs_writev(
- struct file *file,
- const struct iovec *iov,
- int ioflags,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- struct inode *inode = file->f_mapping->host;
- vnode_t *vp = LINVFS_GET_VP(inode);
- struct kiocb kiocb;
- ssize_t rval;
-
- init_sync_kiocb(&kiocb, file);
- kiocb.ki_pos = *ppos;
- if (unlikely(file->f_flags & O_DIRECT))
- ioflags |= IO_ISDIRECT;
-
- VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
-
- *ppos = kiocb.ki_pos;
- return rval;
-}
-
-
-STATIC ssize_t
-linvfs_writev(
- struct file *file,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- return __linvfs_writev(file, iov, 0, nr_segs, ppos);
-}
-
-STATIC ssize_t
-linvfs_writev_invis(
- struct file *file,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- return __linvfs_writev(file, iov, IO_INVIS, nr_segs, ppos);
-}
-
STATIC ssize_t
linvfs_sendfile(
struct file *filp,
@@ -529,8 +439,6 @@
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .readv = linvfs_readv,
- .writev = linvfs_writev,
.aio_read = linvfs_aio_read,
.aio_write = linvfs_aio_write,
.sendfile = linvfs_sendfile,
@@ -551,8 +459,6 @@
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .readv = linvfs_readv_invis,
- .writev = linvfs_writev_invis,
.aio_read = linvfs_aio_read_invis,
.aio_write = linvfs_aio_write_invis,
.sendfile = linvfs_sendfile,
Index: linux-2.6.16-rc1.quilt/include/linux/fs.h
===================================================================
--- linux-2.6.16-rc1.quilt.orig/include/linux/fs.h 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/include/linux/fs.h 2006-02-01 16:05:29.000000000 -0800
@@ -1013,8 +1013,6 @@
int (*aio_fsync) (struct kiocb *, int datasync);
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 *);
- ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
@@ -1577,10 +1575,6 @@
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_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);
Index: linux-2.6.16-rc1.quilt/mm/filemap.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/mm/filemap.c 2006-02-01 16:02:49.000000000 -0800
+++ linux-2.6.16-rc1.quilt/mm/filemap.c 2006-02-01 16:05:29.000000000 -0800
@@ -2235,42 +2235,6 @@
}
EXPORT_SYMBOL(generic_file_write);
-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;
-}
-EXPORT_SYMBOL(generic_file_readv);
-
-ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
-{
- struct address_space *mapping = file->f_mapping;
- struct inode *inode = mapping->host;
- ssize_t ret;
-
- mutex_lock(&inode->i_mutex);
- ret = __generic_file_write_nolock(file, iov, nr_segs, ppos);
- mutex_unlock(&inode->i_mutex);
-
- if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
- int err;
-
- err = sync_page_range(inode, mapping, *ppos - ret, ret);
- if (err < 0)
- ret = err;
- }
- return ret;
-}
-EXPORT_SYMBOL(generic_file_writev);
-
/*
* Called under i_mutex for writes to S_ISREG files. Returns -EIO if something
* went wrong during pagecache shootdown.
Index: linux-2.6.16-rc1.quilt/net/socket.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/net/socket.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/net/socket.c 2006-02-01 16:05:29.000000000 -0800
@@ -110,10 +110,6 @@
static long sock_ioctl(struct file *file,
unsigned int cmd, unsigned long arg);
static int sock_fasync(int fd, struct file *filp, int on);
-static ssize_t sock_readv(struct file *file, const struct iovec *vector,
- unsigned long count, loff_t *ppos);
-static ssize_t sock_writev(struct file *file, const struct iovec *vector,
- unsigned long count, loff_t *ppos);
static ssize_t sock_sendpage(struct file *file, struct page *page,
int offset, size_t size, loff_t *ppos, int more);
@@ -134,8 +130,6 @@
.open = sock_no_open, /* special open code to disallow open via /proc */
.release = sock_close,
.fasync = sock_fasync,
- .readv = sock_readv,
- .writev = sock_writev,
.sendpage = sock_sendpage
};
@@ -692,23 +686,6 @@
return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
}
-static ssize_t sock_readv(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
-{
- struct kiocb iocb;
- struct sock_iocb siocb;
- struct msghdr msg;
- int ret;
-
- init_sync_kiocb(&iocb, NULL);
- iocb.private = &siocb;
-
- ret = do_sock_read(&msg, &iocb, file, iov, nr_segs);
- if (-EIOCBQUEUED == ret)
- ret = wait_on_sync_kiocb(&iocb);
- return ret;
-}
-
static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
@@ -751,23 +728,6 @@
return __sock_sendmsg(iocb, sock, msg, size);
}
-static ssize_t sock_writev(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
-{
- struct msghdr msg;
- struct kiocb iocb;
- struct sock_iocb siocb;
- int ret;
-
- init_sync_kiocb(&iocb, NULL);
- iocb.private = &siocb;
-
- ret = do_sock_write(&msg, &iocb, file, iov, nr_segs);
- if (-EIOCBQUEUED == ret)
- ret = wait_on_sync_kiocb(&iocb);
- return ret;
-}
-
static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
Index: linux-2.6.16-rc1.quilt/sound/core/pcm_native.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/sound/core/pcm_native.c 2006-02-01 16:00:37.000000000 -0800
+++ linux-2.6.16-rc1.quilt/sound/core/pcm_native.c 2006-02-01 16:05:29.000000000 -0800
@@ -2824,8 +2824,8 @@
return result;
}
-static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
- unsigned long count, loff_t * offset)
+static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct snd_pcm_file *pcm_file;
@@ -2836,22 +2836,22 @@
void __user **bufs;
snd_pcm_uframes_t frames;
- pcm_file = file->private_data;
+ pcm_file = iocb->ki_filp->private_data;
substream = pcm_file->substream;
snd_assert(substream != NULL, return -ENXIO);
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- if (count > 1024 || count != runtime->channels)
+ if (nr_segs > 1024 || nr_segs != runtime->channels)
return -EINVAL;
- if (!frame_aligned(runtime, _vector->iov_len))
+ if (!frame_aligned(runtime, iov->iov_len))
return -EINVAL;
- frames = bytes_to_samples(runtime, _vector->iov_len);
- bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL);
+ frames = bytes_to_samples(runtime, iov->iov_len);
+ bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
- for (i = 0; i < count; ++i)
- bufs[i] = _vector[i].iov_base;
+ for (i = 0; i < nr_segs; ++i)
+ bufs[i] = iov[i].iov_base;
result = snd_pcm_lib_readv(substream, bufs, frames);
if (result > 0)
result = frames_to_bytes(runtime, result);
@@ -2859,8 +2859,8 @@
return result;
}
-static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
- unsigned long count, loff_t * offset)
+static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
@@ -2870,7 +2870,7 @@
void __user **bufs;
snd_pcm_uframes_t frames;
- pcm_file = file->private_data;
+ pcm_file = iocb->ki_filp->private_data;
substream = pcm_file->substream;
snd_assert(substream != NULL, result = -ENXIO; goto end);
runtime = substream->runtime;
@@ -2878,17 +2878,17 @@
result = -EBADFD;
goto end;
}
- if (count > 128 || count != runtime->channels ||
- !frame_aligned(runtime, _vector->iov_len)) {
+ if (nr_segs > 128 || nr_segs != runtime->channels ||
+ !frame_aligned(runtime, iov->iov_len)) {
result = -EINVAL;
goto end;
}
- frames = bytes_to_samples(runtime, _vector->iov_len);
- bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL);
+ frames = bytes_to_samples(runtime, iov->iov_len);
+ bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
- for (i = 0; i < count; ++i)
- bufs[i] = _vector[i].iov_base;
+ for (i = 0; i < nr_segs; ++i)
+ bufs[i] = iov[i].iov_base;
result = snd_pcm_lib_writev(substream, bufs, frames);
if (result > 0)
result = frames_to_bytes(runtime, result);
@@ -3394,7 +3394,7 @@
{
.owner = THIS_MODULE,
.write = snd_pcm_write,
- .writev = snd_pcm_writev,
+ .aio_write = snd_pcm_aio_write,
.open = snd_pcm_playback_open,
.release = snd_pcm_release,
.poll = snd_pcm_playback_poll,
@@ -3406,7 +3406,7 @@
{
.owner = THIS_MODULE,
.read = snd_pcm_read,
- .readv = snd_pcm_readv,
+ .aio_read = snd_pcm_aio_read,
.open = snd_pcm_capture_open,
.release = snd_pcm_release,
.poll = snd_pcm_capture_poll,
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/3] Zack's core aio changes to support vectored AIO.
2006-02-02 16:12 [PATCH 0/3] VFS changes to collapse all the vectored and AIO support Badari Pulavarty
2006-02-02 16:14 ` [PATCH 1/3] Vectorize aio_read/aio_write methods Badari Pulavarty
2006-02-02 16:15 ` [PATCH 2/3] Remove readv/writev methods and use aio_read/aio_write instead Badari Pulavarty
@ 2006-02-02 16:16 ` Badari Pulavarty
2 siblings, 0 replies; 8+ messages in thread
From: Badari Pulavarty @ 2006-02-02 16:16 UTC (permalink / raw)
To: christoph; +Cc: Benjamin LaHaise, Zach Brown, lkml, linux-fsdevel
[-- Attachment #1: Type: text/plain, Size: 475 bytes --]
This work is initailly done by Zack Brown to add support for
vectored aio. These are the core changes for AIO to support
IOCB_CMD_PREADV/IOCB_CMD_PWRITEV.
Zack, can you please review the changes as I took most of the
core changes and incorporated into my set. And also could we
further colapse aio_pread/aio_write also into aio_rw_vect_retry() ?
BTW, I haven't done any testing on vectored AIO since I don't have
user-level library changes :(
Please do.
Thanks,
Badari
[-- Attachment #2: zack-aiocore-changes.patch --]
[-- Type: text/x-patch, Size: 10434 bytes --]
This work is initailly done by Zack Brown to add support for
vectored aio. These are the core changes for AIO to support
IOCB_CMD_PREADV/IOCB_CMD_PWRITEV.
Zack, can you please review the changes as I took most of the
core changes and incorporated into my set. And also could we
further colapse aio_pread/aio_write also into aio_rw_vect_retry() ?
BTW, I haven't done any testing on vectored AIO :( Please do.
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Index: linux-2.6.16-rc1.quilt/fs/aio.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/aio.c 2006-02-01 11:04:28.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/aio.c 2006-02-01 14:25:32.000000000 -0800
@@ -416,6 +416,7 @@
req->ki_retry = NULL;
req->ki_dtor = NULL;
req->private = NULL;
+ req->ki_iovec = NULL;
INIT_LIST_HEAD(&req->ki_run_list);
/* Check if the completion queue has enough free space to
@@ -461,6 +462,7 @@
if (req->ki_dtor)
req->ki_dtor(req);
+ kfree(req->ki_iovec);
kmem_cache_free(kiocb_cachep, req);
ctx->reqs_active--;
@@ -1302,6 +1304,64 @@
return -EINVAL;
}
+static void aio_advance_iovec(struct kiocb *iocb, ssize_t ret)
+{
+ struct iovec *iov = &iocb->ki_iovec[iocb->ki_cur_seg];
+
+ BUG_ON(ret <= 0);
+
+ while (iocb->ki_cur_seg < iocb->ki_nr_segs && ret > 0) {
+ ssize_t this = min(iov->iov_len, (size_t)ret);
+ iov->iov_base += this;
+ iov->iov_len -= this;
+ iocb->ki_left -= this;
+ ret -= this;
+ if (iov->iov_len == 0) {
+ iocb->ki_cur_seg++;
+ iov++;
+ }
+ }
+
+ /* the caller should not have done more io than what fit in
+ * the remaining iovecs */
+ BUG_ON(ret > 0 && iocb->ki_left == 0);
+}
+
+static ssize_t aio_rw_vect_retry(struct kiocb *iocb)
+{
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ ssize_t (*rw_op)(struct kiocb *, const struct iovec *,
+ unsigned long, loff_t);
+ ssize_t ret = 0;
+
+ if (iocb->ki_opcode == IOCB_CMD_PREADV)
+ rw_op = file->f_op->aio_read;
+ else
+ rw_op = file->f_op->aio_write;
+
+ do {
+ ret = rw_op(iocb, &iocb->ki_iovec[iocb->ki_cur_seg],
+ iocb->ki_nr_segs - iocb->ki_cur_seg,
+ iocb->ki_pos);
+ if (ret > 0)
+ aio_advance_iovec(iocb, ret);
+
+ /* retry all partial writes. retry partial reads as long as its a
+ * regular file. */
+ } while (ret > 0 && iocb->ki_left > 0 &&
+ (iocb->ki_opcode == IOCB_CMD_PWRITEV ||
+ (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))));
+
+ /* This means we must have transferred all that we could */
+ /* No need to retry anymore */
+ if ((ret == 0) || (iocb->ki_left == 0))
+ ret = iocb->ki_nbytes - iocb->ki_left;
+
+ return ret;
+}
+
/*
* aio_p{read,write} are the default ki_retry methods for
* IO_CMD_P{READ,WRITE}. They maintains kiocb retry state around potentially
@@ -1393,6 +1453,27 @@
return ret;
}
+static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb)
+{
+ ssize_t ret;
+
+ ret = rw_copy_check_uvector((struct iovec __user *)kiocb->ki_buf,
+ kiocb->ki_nbytes, 0, NULL,
+ &kiocb->ki_iovec);
+ if (ret < 0)
+ goto out;
+
+ kiocb->ki_nr_segs = kiocb->ki_nbytes;
+ kiocb->ki_cur_seg = 0;
+ /* ki_nbytes/left now reflect bytes instead of segs */
+ kiocb->ki_nbytes = ret;
+ kiocb->ki_left = ret;
+
+ ret = 0;
+out:
+ return ret;
+}
+
/*
* aio_setup_iocb:
* Performs the initial checks and aio retry method
@@ -1434,6 +1515,28 @@
if (file->f_op->aio_write)
kiocb->ki_retry = aio_pwrite;
break;
+ case IOCB_CMD_PREADV:
+ ret = -EBADF;
+ if (unlikely(!(file->f_mode & FMODE_READ)))
+ break;
+ ret = aio_setup_vectored_rw(kiocb);
+ if (ret)
+ break;
+ ret = EINVAL;
+ if (file->f_op->aio_read)
+ kiocb->ki_retry = aio_rw_vect_retry;
+ break;
+ case IOCB_CMD_PWRITEV:
+ ret = -EBADF;
+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
+ break;
+ ret = aio_setup_vectored_rw(kiocb);
+ if (ret)
+ break;
+ ret = EINVAL;
+ if (file->f_op->aio_write)
+ kiocb->ki_retry = aio_rw_vect_retry;
+ break;
case IOCB_CMD_FDSYNC:
ret = -EINVAL;
if (file->f_op->aio_fsync)
Index: linux-2.6.16-rc1.quilt/include/linux/aio.h
===================================================================
--- linux-2.6.16-rc1.quilt.orig/include/linux/aio.h 2006-01-16 23:44:47.000000000 -0800
+++ linux-2.6.16-rc1.quilt/include/linux/aio.h 2006-02-01 14:58:08.000000000 -0800
@@ -112,6 +112,9 @@
long ki_retried; /* just for testing */
long ki_kicked; /* just for testing */
long ki_queued; /* just for testing */
+ struct iovec *ki_iovec;
+ unsigned long ki_nr_segs;
+ unsigned long ki_cur_seg;
struct list_head ki_list; /* the aio core uses this
* for cancellation */
Index: linux-2.6.16-rc1.quilt/include/linux/aio_abi.h
===================================================================
--- linux-2.6.16-rc1.quilt.orig/include/linux/aio_abi.h 2006-01-16 23:44:47.000000000 -0800
+++ linux-2.6.16-rc1.quilt/include/linux/aio_abi.h 2006-02-01 14:58:42.000000000 -0800
@@ -41,6 +41,8 @@
* IOCB_CMD_POLL = 5,
*/
IOCB_CMD_NOOP = 6,
+ IOCB_CMD_PREADV = 7,
+ IOCB_CMD_PWRITEV = 8,
};
/* read() from /dev/aio returns these structures. */
Index: linux-2.6.16-rc1.quilt/fs/read_write.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/fs/read_write.c 2006-02-01 11:04:33.000000000 -0800
+++ linux-2.6.16-rc1.quilt/fs/read_write.c 2006-02-01 15:10:42.000000000 -0800
@@ -511,72 +511,103 @@
/* A write operation does a read from user space and vice versa */
#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
+ssize_t rw_copy_check_uvector(const struct iovec __user * uvector,
+ unsigned long nr_segs, unsigned long fast_segs,
+ struct iovec *fast_pointer,
+ struct iovec **ret_pointer)
+ {
+ unsigned long seg;
+ ssize_t ret;
+ struct iovec *iov = fast_pointer;
+
+ /*
+ * 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...
+ */
+ if (nr_segs == 0) {
+ ret = 0;
+ goto out;
+ }
+
+ /*
+ * First get the "struct iovec" from user memory and
+ * verify all the pointers
+ */
+ if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (nr_segs > fast_segs) {
+ iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
+ if (iov == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+ if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ /*
+ * According to the Single Unix Specification we should return EINVAL
+ * if an element length is < 0 when cast to ssize_t or if the
+ * total length would overflow the ssize_t return value of the
+ * system call.
+ */
+ ret = 0;
+ for (seg = 0; seg < nr_segs; seg++) {
+ void __user *buf = iov[seg].iov_base;
+ ssize_t len = (ssize_t)iov[seg].iov_len;
+
+ /* see if we we're about to use an invalid len or if
+ * it's about to overflow ssize_t */
+ if (len < 0 || (ret + len < ret)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ if (unlikely(!access_ok(vrfy_dir(type), buf, len))) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret += len;
+ }
+out:
+ *ret_pointer = iov;
+ return ret;
+}
+
+/* A write operation does a read from user space and vice versa */
+#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
+
static ssize_t do_readv_writev(int type, struct file *file,
const struct iovec __user * uvector,
unsigned long nr_segs, loff_t *pos)
{
- size_t tot_len;
+ ssize_t tot_len;
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack;
ssize_t ret;
- int seg;
io_fn_t fn;
iov_fn_t fnv;
- /*
- * 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)
- goto out;
-
- /*
- * First get the "struct iovec" from user memory and
- * verify all the pointers
- */
- ret = -EINVAL;
- if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0))
- goto out;
- if (!file->f_op)
+ if (!file->f_op) {
+ ret = -EINVAL;
goto out;
- if (nr_segs > UIO_FASTIOV) {
- ret = -ENOMEM;
- iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
- if (!iov)
- goto out;
}
- ret = -EFAULT;
- if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector)))
+
+ ret = rw_copy_check_uvector(uvector, nr_segs, ARRAY_SIZE(iovstack),
+ iovstack, &iov);
+
+ if (ret < 0)
goto out;
- /*
- * Single unix specification:
- * We should -EINVAL if an element length is not >= 0 and fitting an
- * ssize_t. The total length is fitting an ssize_t
- *
- * 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++) {
- void __user *buf = iov[seg].iov_base;
- ssize_t len = (ssize_t)iov[seg].iov_len;
-
- if (len < 0) /* size_t not fitting an ssize_t .. */
- goto out;
- if (unlikely(!access_ok(vrfy_dir(type), buf, len)))
- goto Efault;
- tot_len += len;
- if ((ssize_t)tot_len < 0) /* maths overflow on the ssize_t */
- goto out;
- }
- if (tot_len == 0) {
- ret = 0;
+ if (ret == 0)
goto out;
- }
+ tot_len = ret;
ret = rw_verify_area(type, file, pos, tot_len);
if (ret < 0)
goto out;
@@ -608,9 +639,6 @@
fsnotify_modify(file->f_dentry);
}
return ret;
-Efault:
- ret = -EFAULT;
- goto out;
}
ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
Index: linux-2.6.16-rc1.quilt/include/linux/fs.h
===================================================================
--- linux-2.6.16-rc1.quilt.orig/include/linux/fs.h 2006-02-01 11:04:33.000000000 -0800
+++ linux-2.6.16-rc1.quilt/include/linux/fs.h 2006-02-01 15:12:51.000000000 -0800
@@ -1048,6 +1048,11 @@
struct seq_file;
+ssize_t rw_copy_check_uvector(const struct iovec __user * uvector,
+ unsigned long nr_segs, unsigned long fast_segs,
+ struct iovec *fast_pointer,
+ struct iovec **ret_pointer);
+
extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] Vectorize aio_read/aio_write methods
2006-02-02 16:14 ` [PATCH 1/3] Vectorize aio_read/aio_write methods Badari Pulavarty
@ 2006-02-04 13:28 ` Christoph Hellwig
2006-02-04 22:10 ` Badari Pulavarty
0 siblings, 1 reply; 8+ messages in thread
From: Christoph Hellwig @ 2006-02-04 13:28 UTC (permalink / raw)
To: Badari Pulavarty; +Cc: Benjamin LaHaise, Zach Brown, lkml, linux-fsdevel
do {
- ret = file->f_op->aio_read(iocb, iocb->ki_buf,
- iocb->ki_left, iocb->ki_pos);
+ struct iovec iov = {
+ .iov_base = iocb->ki_buf,
+ .iov_len = iocb->ki_left
+ };
+
+ ret = file->f_op->aio_read(iocb, &iov, 1, iocb->ki_pos);
this still has the lifetime problems Ben pointed out. aio might still
be outstanding when this thread returned to userspace, so we need to
dynamically allocated the iovec and free it later. (or make it part
of the iocb?)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] Vectorize aio_read/aio_write methods
2006-02-04 13:28 ` Christoph Hellwig
@ 2006-02-04 22:10 ` Badari Pulavarty
0 siblings, 0 replies; 8+ messages in thread
From: Badari Pulavarty @ 2006-02-04 22:10 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Benjamin LaHaise, Zach Brown, lkml, linux-fsdevel
Christoph Hellwig wrote:
> do {
> - ret = file->f_op->aio_read(iocb, iocb->ki_buf,
> - iocb->ki_left, iocb->ki_pos);
> + struct iovec iov = {
> + .iov_base = iocb->ki_buf,
> + .iov_len = iocb->ki_left
> + };
> +
> + ret = file->f_op->aio_read(iocb, &iov, 1, iocb->ki_pos);
>
> this still has the lifetime problems Ben pointed out. aio might still
> be outstanding when this thread returned to userspace, so we need to
> dynamically allocated the iovec and free it later. (or make it part
> of the iocb?)
I left that intentionally alone. I was planning to make it a
special case of Zach's vector IO handling code.
Thanks,
Badari
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] Vectorize aio_read/aio_write methods
2006-03-08 0:19 [RFC PATCH 0/3] VFS changes to collapse all the vectored and AIO support Badari Pulavarty
@ 2006-03-08 0:22 ` Badari Pulavarty
2006-03-08 12:44 ` christoph
0 siblings, 1 reply; 8+ messages in thread
From: Badari Pulavarty @ 2006-03-08 0:22 UTC (permalink / raw)
To: Zach Brown; +Cc: christoph, lkml, linux-fsdevel
[-- Attachment #1: Type: text/plain, Size: 166 bytes --]
This patch vectorizes aio_read() and aio_write() methods to prepare
for colapsing all the vectored operations into one interface -
which is aio_read()/aio_write().
[-- Attachment #2: aiovector.patch --]
[-- Type: text/x-patch, Size: 36291 bytes --]
This patch vectorizes aio_read() and aio_write() methods to prepare
for colapsing all the vectored operations into one interface -
which is aio_read()/aio_write().
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Index: linux-2.6.16-rc5/Documentation/filesystems/Locking
===================================================================
--- linux-2.6.16-rc5.orig/Documentation/filesystems/Locking 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/Documentation/filesystems/Locking 2006-02-27 08:33:22.000000000 -0800
@@ -355,10 +355,9 @@ The last two are called only from check_
prototypes:
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t,
- loff_t);
+ ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int,
Index: linux-2.6.16-rc5/Documentation/filesystems/vfs.txt
===================================================================
--- linux-2.6.16-rc5.orig/Documentation/filesystems/vfs.txt 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/Documentation/filesystems/vfs.txt 2006-02-27 08:33:22.000000000 -0800
@@ -526,9 +526,9 @@ This describes how the VFS can manipulat
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
+ ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
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);
Index: linux-2.6.16-rc5/drivers/char/raw.c
===================================================================
--- linux-2.6.16-rc5.orig/drivers/char/raw.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/drivers/char/raw.c 2006-03-07 13:52:28.000000000 -0800
@@ -249,23 +249,11 @@ static ssize_t raw_file_write(struct fil
return generic_file_write_nolock(file, &local_iov, 1, ppos);
}
-static ssize_t raw_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
-{
- struct iovec local_iov = {
- .iov_base = (char __user *)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,
Index: linux-2.6.16-rc5/fs/aio.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/aio.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/aio.c 2006-03-07 13:44:09.000000000 -0800
@@ -15,6 +15,7 @@
#include <linux/aio_abi.h>
#include <linux/module.h>
#include <linux/syscalls.h>
+#include <linux/uio.h>
#define DEBUG 0
@@ -1316,8 +1317,11 @@ static ssize_t aio_pread(struct kiocb *i
ssize_t ret = 0;
do {
- ret = file->f_op->aio_read(iocb, iocb->ki_buf,
- iocb->ki_left, iocb->ki_pos);
+ iocb->ki_inline_vec.iov_base = iocb->ki_buf;
+ iocb->ki_inline_vec.iov_len = iocb->ki_left;
+
+ ret = file->f_op->aio_read(iocb, &iocb->ki_inline_vec,
+ 1, iocb->ki_pos);
/*
* Can't just depend on iocb->ki_left to determine
* whether we are done. This may have been a short read.
@@ -1350,8 +1354,11 @@ static ssize_t aio_pwrite(struct kiocb *
ssize_t ret = 0;
do {
- ret = file->f_op->aio_write(iocb, iocb->ki_buf,
- iocb->ki_left, iocb->ki_pos);
+ iocb->ki_inline_vec.iov_base = iocb->ki_buf;
+ iocb->ki_inline_vec.iov_len = iocb->ki_left;
+
+ ret = file->f_op->aio_write(iocb, &iocb->ki_inline_vec,
+ 1, iocb->ki_pos);
if (ret > 0) {
iocb->ki_buf += ret;
iocb->ki_left -= ret;
Index: linux-2.6.16-rc5/fs/block_dev.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/block_dev.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/block_dev.c 2006-03-07 13:52:28.000000000 -0800
@@ -769,14 +769,6 @@ static ssize_t blkdev_file_write(struct
return generic_file_write_nolock(file, &local_iov, 1, ppos);
}
-static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
-{
- struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
-
- return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
-}
-
static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
@@ -799,7 +791,7 @@ struct file_operations def_blk_fops = {
.read = generic_file_read,
.write = blkdev_file_write,
.aio_read = generic_file_aio_read,
- .aio_write = blkdev_file_aio_write,
+ .aio_write = generic_file_aio_write_nolock,
.mmap = generic_file_mmap,
.fsync = block_fsync,
.unlocked_ioctl = block_ioctl,
Index: linux-2.6.16-rc5/fs/cifs/cifsfs.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/cifs/cifsfs.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/cifs/cifsfs.c 2006-03-07 13:52:28.000000000 -0800
@@ -501,13 +501,13 @@ static ssize_t cifs_file_writev(struct f
return written;
}
-static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
+static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
ssize_t written;
- written = generic_file_aio_write(iocb, buf, count, pos);
+ written = generic_file_aio_write(iocb, iov, nr_segs, pos);
if (!CIFS_I(inode)->clientCanCacheAll)
filemap_fdatawrite(inode->i_mapping);
return written;
Index: linux-2.6.16-rc5/fs/ext3/file.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/ext3/file.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/ext3/file.c 2006-03-07 13:52:28.000000000 -0800
@@ -48,14 +48,15 @@ static int ext3_release_file (struct ino
}
static ssize_t
-ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+ext3_file_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_dentry->d_inode;
ssize_t ret;
int err;
- ret = generic_file_aio_write(iocb, buf, count, pos);
+ ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
/*
* Skip flushing if there was an error, or if nothing was written.
Index: linux-2.6.16-rc5/fs/nfs/file.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/nfs/file.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/nfs/file.c 2006-02-27 08:33:22.000000000 -0800
@@ -40,8 +40,10 @@ static int nfs_file_release(struct inode
static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
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 __user *, size_t, loff_t);
-static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
+static ssize_t nfs_file_read(struct kiocb *, const struct iovec *,
+ unsigned long, loff_t);
+static ssize_t nfs_file_write(struct kiocb *, const struct iovec *,
+ unsigned long, loff_t);
static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
static int nfs_check_flags(int flags);
@@ -52,8 +54,8 @@ struct file_operations nfs_file_operatio
.llseek = nfs_file_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_file_open,
.flush = nfs_file_flush,
@@ -213,7 +215,8 @@ nfs_file_flush(struct file *file)
}
static ssize_t
-nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
+nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct dentry * dentry = iocb->ki_filp->f_dentry;
struct inode * inode = dentry->d_inode;
@@ -221,16 +224,15 @@ nfs_file_read(struct kiocb *iocb, char _
#ifdef CONFIG_NFS_DIRECTIO
if (iocb->ki_filp->f_flags & O_DIRECT)
- return nfs_file_direct_read(iocb, buf, count, pos);
+ return nfs_file_direct_read(iocb, iov, nr_segs, pos);
#endif
- 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);
+ dfprintk(VFS, "nfs: read(%s/%s)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
result = nfs_revalidate_file(inode, iocb->ki_filp);
if (!result)
- result = generic_file_aio_read(iocb, buf, count, pos);
+ result = generic_file_aio_read(iocb, iov, nr_segs, pos);
return result;
}
@@ -333,7 +335,8 @@ 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 __user *buf, size_t count, loff_t pos)
+nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct dentry * dentry = iocb->ki_filp->f_dentry;
struct inode * inode = dentry->d_inode;
@@ -341,12 +344,12 @@ nfs_file_write(struct kiocb *iocb, const
#ifdef CONFIG_NFS_DIRECTIO
if (iocb->ki_filp->f_flags & O_DIRECT)
- return nfs_file_direct_write(iocb, buf, count, pos);
+ return nfs_file_direct_write(iocb, iov, nr_segs, pos);
#endif
- dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n",
+ dfprintk(VFS, "nfs: write(%s/%s(%ld))\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
- inode->i_ino, (unsigned long) count, (unsigned long) pos);
+ inode->i_ino);
result = -EBUSY;
if (IS_SWAPFILE(inode))
@@ -361,11 +364,7 @@ nfs_file_write(struct kiocb *iocb, const
}
nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
- result = count;
- if (!count)
- goto out;
-
- result = generic_file_aio_write(iocb, buf, count, pos);
+ result = generic_file_aio_write(iocb, iov, nr_segs, pos);
out:
return result;
Index: linux-2.6.16-rc5/fs/read_write.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/read_write.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/read_write.c 2006-03-07 13:52:28.000000000 -0800
@@ -227,14 +227,19 @@ static void wait_on_retry_sync_kiocb(str
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
+ struct iovec iov = { .iov_base = buf, .iov_len = len };
struct kiocb kiocb;
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
- while (-EIOCBRETRY ==
- (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos)))
+
+ for (;;) {
+ ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
+ if (ret != -EIOCBRETRY)
+ break;
wait_on_retry_sync_kiocb(&kiocb);
+ }
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
@@ -279,14 +284,19 @@ EXPORT_SYMBOL(vfs_read);
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
+ struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
struct kiocb kiocb;
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
- while (-EIOCBRETRY ==
- (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos)))
+
+ for (;;) {
+ ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
+ if (ret != -EIOCBRETRY)
+ break;
wait_on_retry_sync_kiocb(&kiocb);
+ }
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
Index: linux-2.6.16-rc5/fs/reiserfs/file.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/reiserfs/file.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/reiserfs/file.c 2006-02-27 08:33:22.000000000 -0800
@@ -1560,12 +1560,6 @@ static ssize_t reiserfs_file_write(struc
return res;
}
-static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf,
- size_t count, loff_t pos)
-{
- return generic_file_aio_write(iocb, buf, count, pos);
-}
-
struct file_operations reiserfs_file_operations = {
.read = generic_file_read,
.write = reiserfs_file_write,
@@ -1575,7 +1569,7 @@ struct file_operations reiserfs_file_ope
.fsync = reiserfs_sync_file,
.sendfile = generic_file_sendfile,
.aio_read = generic_file_aio_read,
- .aio_write = reiserfs_aio_write,
+ .aio_write = generic_file_aio_write,
};
struct inode_operations reiserfs_file_inode_operations = {
Index: linux-2.6.16-rc5/fs/xfs/linux-2.6/xfs_file.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/xfs/linux-2.6/xfs_file.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/xfs/linux-2.6/xfs_file.c 2006-03-07 13:52:28.000000000 -0800
@@ -51,12 +51,11 @@ static struct vm_operations_struct linvf
STATIC inline ssize_t
__linvfs_read(
struct kiocb *iocb,
- char __user *buf,
+ const struct iovec *iov,
+ unsigned long nr_segs,
int ioflags,
- size_t count,
loff_t pos)
{
- struct iovec iov = {buf, count};
struct file *file = iocb->ki_filp;
vnode_t *vp = LINVFS_GET_VP(file->f_dentry->d_inode);
ssize_t rval;
@@ -65,7 +64,7 @@ __linvfs_read(
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
- VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
+ VOP_READ(vp, iocb, iov, nr_segs, &iocb->ki_pos, ioflags, NULL, rval);
return rval;
}
@@ -73,33 +72,32 @@ __linvfs_read(
STATIC ssize_t
linvfs_aio_read(
struct kiocb *iocb,
- char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __linvfs_read(iocb, buf, IO_ISAIO, count, pos);
+ return __linvfs_read(iocb, iov, nr_segs, IO_ISAIO, pos);
}
STATIC ssize_t
linvfs_aio_read_invis(
struct kiocb *iocb,
- char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __linvfs_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
+ return __linvfs_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
}
STATIC inline ssize_t
__linvfs_write(
- struct kiocb *iocb,
- const char __user *buf,
- int ioflags,
- size_t count,
- loff_t pos)
+ struct kiocb *iocb,
+ const struct iovec *iov,
+ unsigned long nr_segs,
+ int ioflags,
+ loff_t pos)
{
- struct iovec iov = {(void __user *)buf, count};
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
vnode_t *vp = LINVFS_GET_VP(inode);
@@ -109,7 +107,7 @@ __linvfs_write(
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
- VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
+ VOP_WRITE(vp, iocb, iov, nr_segs, &iocb->ki_pos, ioflags, NULL, rval);
return rval;
}
@@ -117,21 +115,21 @@ __linvfs_write(
STATIC ssize_t
linvfs_aio_write(
struct kiocb *iocb,
- const char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __linvfs_write(iocb, buf, IO_ISAIO, count, pos);
+ return __linvfs_write(iocb, iov, nr_segs, IO_ISAIO, pos);
}
STATIC ssize_t
linvfs_aio_write_invis(
struct kiocb *iocb,
- const char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __linvfs_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
+ return __linvfs_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
}
Index: linux-2.6.16-rc5/include/linux/fs.h
===================================================================
--- linux-2.6.16-rc5.orig/include/linux/fs.h 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/include/linux/fs.h 2006-03-07 13:52:28.000000000 -0800
@@ -999,9 +999,9 @@ struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
+ ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
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);
@@ -1561,11 +1561,11 @@ extern int file_send_actor(read_descript
extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *);
int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *);
-extern ssize_t generic_file_aio_read(struct kiocb *, char __user *, size_t, loff_t);
+extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *);
-extern ssize_t generic_file_aio_write(struct kiocb *, const char __user *, size_t, loff_t);
+extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
- unsigned long, loff_t *);
+ unsigned long, loff_t);
extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
unsigned long *, loff_t, loff_t *, size_t, size_t);
extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
Index: linux-2.6.16-rc5/include/net/sock.h
===================================================================
--- linux-2.6.16-rc5.orig/include/net/sock.h 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/include/net/sock.h 2006-02-27 08:33:22.000000000 -0800
@@ -650,7 +650,6 @@ struct sock_iocb {
struct sock *sk;
struct scm_cookie *scm;
struct msghdr *msg, async_msg;
- struct iovec async_iov;
struct kiocb *kiocb;
};
Index: linux-2.6.16-rc5/mm/filemap.c
===================================================================
--- linux-2.6.16-rc5.orig/mm/filemap.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/mm/filemap.c 2006-03-07 13:52:28.000000000 -0800
@@ -1065,14 +1065,12 @@ out:
EXPORT_SYMBOL(__generic_file_aio_read);
ssize_t
-generic_file_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, 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);
+ return __generic_file_aio_read(iocb, iov, nr_segs, &iocb->ki_pos);
}
-
EXPORT_SYMBOL(generic_file_aio_read);
ssize_t
@@ -2132,22 +2130,21 @@ out:
current->backing_dev_info = NULL;
return written ? written : err;
}
-EXPORT_SYMBOL(generic_file_aio_write_nolock);
-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 kiocb *iocb,
+ const struct iovec *iov, unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t ret;
- loff_t pos = *ppos;
- ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, ppos);
+ BUG_ON(iocb->ki_pos != pos);
+
+ ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
- int err;
+ ssize_t err;
err = sync_page_range_nolock(inode, mapping, pos, ret);
if (err < 0)
@@ -2155,6 +2152,7 @@ generic_file_aio_write_nolock(struct kio
}
return ret;
}
+EXPORT_SYMBOL(generic_file_aio_write_nolock);
static ssize_t
__generic_file_write_nolock(struct file *file, const struct iovec *iov,
@@ -2164,9 +2162,11 @@ __generic_file_write_nolock(struct file
ssize_t ret;
init_sync_kiocb(&kiocb, file);
+ kiocb.ki_pos = *ppos;
ret = __generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
- if (ret == -EIOCBQUEUED)
+ if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
+ *ppos = kiocb.ki_pos;
return ret;
}
@@ -2178,28 +2178,27 @@ generic_file_write_nolock(struct file *f
ssize_t ret;
init_sync_kiocb(&kiocb, file);
- ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
+ kiocb.ki_pos = *ppos;
+ ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, *ppos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
+ *ppos = kiocb.ki_pos;
return ret;
}
EXPORT_SYMBOL(generic_file_write_nolock);
-ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
+ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t ret;
- struct iovec local_iov = { .iov_base = (void __user *)buf,
- .iov_len = count };
BUG_ON(iocb->ki_pos != pos);
mutex_lock(&inode->i_mutex);
- ret = __generic_file_aio_write_nolock(iocb, &local_iov, 1,
- &iocb->ki_pos);
+ ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
Index: linux-2.6.16-rc5/net/socket.c
===================================================================
--- linux-2.6.16-rc5.orig/net/socket.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/net/socket.c 2006-03-07 13:53:40.000000000 -0800
@@ -98,10 +98,10 @@
#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 __user *buf,
- size_t size, loff_t pos);
-static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t size, loff_t pos);
+static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
+static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
static int sock_mmap(struct file *file, struct vm_area_struct * vma);
static int sock_close(struct inode *inode, struct file *file);
@@ -656,7 +656,7 @@ static ssize_t sock_sendpage(struct file
}
static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
- char __user *ubuf, size_t size, struct sock_iocb *siocb)
+ struct sock_iocb *siocb)
{
if (!is_sync_kiocb(iocb)) {
siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
@@ -666,15 +666,13 @@ static struct sock_iocb *alloc_sock_iocb
}
siocb->kiocb = iocb;
- siocb->async_iov.iov_base = ubuf;
- siocb->async_iov.iov_len = size;
-
iocb->private = siocb;
return siocb;
}
static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
- struct file *file, struct iovec *iov, unsigned long nr_segs)
+ struct file *file, const struct iovec *iov,
+ unsigned long nr_segs)
{
struct socket *sock = file->private_data;
size_t size = 0;
@@ -705,31 +703,33 @@ static ssize_t sock_readv(struct file *f
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
- ret = do_sock_read(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
+ ret = do_sock_read(&msg, &iocb, file, iov, nr_segs);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
}
-static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
- size_t count, loff_t pos)
+static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct sock_iocb siocb, *x;
if (pos != 0)
return -ESPIPE;
- if (count == 0) /* Match SYS5 behaviour */
+
+ if (iocb->ki_left == 0) /* Match SYS5 behaviour */
return 0;
- x = alloc_sock_iocb(iocb, ubuf, count, &siocb);
+
+ x = alloc_sock_iocb(iocb, &siocb);
if (!x)
return -ENOMEM;
- return do_sock_read(&x->async_msg, iocb, iocb->ki_filp,
- &x->async_iov, 1);
+ return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
}
static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
- struct file *file, struct iovec *iov, unsigned long nr_segs)
+ struct file *file, const struct iovec *iov,
+ unsigned long nr_segs)
{
struct socket *sock = file->private_data;
size_t size = 0;
@@ -762,28 +762,28 @@ static ssize_t sock_writev(struct file *
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
- ret = do_sock_write(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
+ ret = do_sock_write(&msg, &iocb, file, iov, nr_segs);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
}
-static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
- size_t count, loff_t pos)
+static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct sock_iocb siocb, *x;
if (pos != 0)
return -ESPIPE;
- if (count == 0) /* Match SYS5 behaviour */
+
+ if (iocb->ki_left == 0) /* Match SYS5 behaviour */
return 0;
- x = alloc_sock_iocb(iocb, (void __user *)ubuf, count, &siocb);
+ x = alloc_sock_iocb(iocb, &siocb);
if (!x)
return -ENOMEM;
- return do_sock_write(&x->async_msg, iocb, iocb->ki_filp,
- &x->async_iov, 1);
+ return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
}
Index: linux-2.6.16-rc5/fs/nfs/direct.c
===================================================================
--- linux-2.6.16-rc5.orig/fs/nfs/direct.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/fs/nfs/direct.c 2006-02-27 08:38:28.000000000 -0800
@@ -626,6 +626,32 @@ nfs_direct_IO(int rw, struct kiocb *iocb
return result;
}
+static ssize_t
+check_access_ok(int type, const struct iovec *iov, unsigned long nr_segs)
+{
+ ssize_t tot_len = 0;
+ ssize_t ret = -EINVAL;
+ int seg;
+
+ for (seg = 0; seg < nr_segs; seg++) {
+ void __user *buf = iov[seg].iov_base;
+ ssize_t len = (ssize_t)iov[seg].iov_len;
+
+ if (len < 0) /* size_t not fitting an ssize_t .. */
+ goto out;
+ if (unlikely(!access_ok(type, buf, len))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ tot_len += len;
+ if ((ssize_t)tot_len < 0) /* maths overflow on the ssize_t */
+ goto out;
+ }
+ ret = tot_len;
+out:
+ return ret;
+}
+
/**
* nfs_file_direct_read - file direct read operation for NFS files
* @iocb: target I/O control block
@@ -648,7 +674,8 @@ nfs_direct_IO(int rw, struct kiocb *iocb
* cache.
*/
ssize_t
-nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
ssize_t retval = -EINVAL;
loff_t *ppos = &iocb->ki_pos;
@@ -657,32 +684,24 @@ nfs_file_direct_read(struct kiocb *iocb,
(struct nfs_open_context *) file->private_data;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = count,
- };
- dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
+ dprintk("nfs: direct read(%s/%s, @%Ld)\n",
file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name,
- (unsigned long) count, (long long) pos);
+ (long long) pos);
if (!is_sync_kiocb(iocb))
goto out;
- if (count < 0)
- goto out;
- retval = -EFAULT;
- if (!access_ok(VERIFY_WRITE, iov.iov_base, iov.iov_len))
- goto out;
- retval = 0;
- if (!count)
+
+ retval = check_access_ok(VERIFY_WRITE, iov, nr_segs);
+ if (retval <= 0)
goto out;
retval = nfs_sync_mapping(mapping);
if (retval)
goto out;
- retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
+ retval = nfs_direct_read(inode, ctx, iov, pos, nr_segs);
if (retval > 0)
*ppos = pos + retval;
@@ -716,7 +735,8 @@ out:
* is no atomic O_APPEND write facility in the NFS protocol.
*/
ssize_t
-nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
ssize_t retval;
struct file *file = iocb->ki_filp;
@@ -724,40 +744,32 @@ nfs_file_direct_write(struct kiocb *iocb
(struct nfs_open_context *) file->private_data;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
- struct iovec iov = {
- .iov_base = (char __user *)buf,
- };
+ ssize_t count;
- dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
+ dfprintk(VFS, "nfs: direct write(%s/%s, @%Ld)\n",
file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name,
- (unsigned long) count, (long long) pos);
+ (long long) pos);
retval = -EINVAL;
if (!is_sync_kiocb(iocb))
goto out;
- retval = generic_write_checks(file, &pos, &count, 0);
- if (retval)
+ retval = check_access_ok(VERIFY_READ, iov, nr_segs);
+ if (retval <= 0)
goto out;
- retval = -EINVAL;
- if ((ssize_t) count < 0)
- goto out;
- retval = 0;
- if (!count)
- goto out;
- iov.iov_len = count,
-
- retval = -EFAULT;
- if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
+ /* FIXME: how to adjust iovec if count gets adjusted ? */
+ count = retval;
+ retval = generic_write_checks(file, &pos, &count, 0);
+ if (retval)
goto out;
retval = nfs_sync_mapping(mapping);
if (retval)
goto out;
- retval = nfs_direct_write(inode, ctx, &iov, pos, 1);
+ retval = nfs_direct_write(inode, ctx, iov, pos, nr_segs);
if (mapping->nrpages)
invalidate_inode_pages2(mapping);
if (retval > 0)
Index: linux-2.6.16-rc5/include/linux/nfs_fs.h
===================================================================
--- linux-2.6.16-rc5.orig/include/linux/nfs_fs.h 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/include/linux/nfs_fs.h 2006-02-27 08:33:22.000000000 -0800
@@ -369,10 +369,10 @@ extern int nfs3_removexattr (struct dent
*/
extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
unsigned long);
-extern ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf,
- size_t count, loff_t pos);
-extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos);
+extern ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *,
+ unsigned long nr_segs, loff_t pos);
+extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *,
+ unsigned long nr_segs, loff_t pos);
/*
* linux/fs/nfs/dir.c
Index: linux-2.6.16-rc5/drivers/usb/gadget/inode.c
===================================================================
--- linux-2.6.16-rc5.orig/drivers/usb/gadget/inode.c 2006-02-26 21:09:35.000000000 -0800
+++ linux-2.6.16-rc5/drivers/usb/gadget/inode.c 2006-03-07 13:26:46.000000000 -0800
@@ -529,7 +529,8 @@ struct kiocb_priv {
struct usb_request *req;
struct ep_data *epdata;
void *buf;
- char __user *ubuf;
+ struct iovec *iv;
+ unsigned long count;
unsigned actual;
};
@@ -557,18 +558,32 @@ static int ep_aio_cancel(struct kiocb *i
static ssize_t ep_aio_read_retry(struct kiocb *iocb)
{
struct kiocb_priv *priv = iocb->private;
- ssize_t status = priv->actual;
+ ssize_t len, total;
/* we "retry" to get the right mm context for this: */
- status = copy_to_user(priv->ubuf, priv->buf, priv->actual);
- if (unlikely(0 != status))
- status = -EFAULT;
- else
- status = priv->actual;
+
+ /* copy stuff into user buffers */
+ total = priv->actual;
+ len = 0;
+ for (i=0; i < priv->count; i++) {
+ ssize_t this = min(priv->iv[i].iov_len, (size_t)total);
+
+ if (copy_to_user(priv->iv[i].iov_buf, priv->buf, this))
+ break;
+
+ total -= this;
+ len += this;
+ if (total <= 0)
+ break;
+ }
+
+ if (unlikely(len != 0))
+ len = -EFAULT;
+
kfree(priv->buf);
kfree(priv);
aio_put_req(iocb);
- return status;
+ return len;
}
static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
@@ -616,7 +631,8 @@ ep_aio_rwtail(
char *buf,
size_t len,
struct ep_data *epdata,
- char __user *ubuf
+ const struct iovec *iv,
+ unsigned long count
)
{
struct kiocb_priv *priv = (void *) &iocb->private;
@@ -631,7 +647,8 @@ fail:
return value;
}
iocb->private = priv;
- priv->ubuf = ubuf;
+ priv->iovec = iv;
+ priv->count = count;
value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
if (unlikely(value < 0)) {
@@ -676,36 +693,52 @@ fail:
}
static ssize_t
-ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
+ep_aio_read(struct kiocb *iocb, const struct iovec *iv,
+ unsigned long count, loff_t o)
{
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
+ size_t len;
+ int i = 0;
+ ssize_t ret;
if (unlikely(epdata->desc.bEndpointAddress & USB_DIR_IN))
return -EINVAL;
- buf = kmalloc(len, GFP_KERNEL);
+
+ buf = kmalloc(iocb->ki_left, GFP_KERNEL);
if (unlikely(!buf))
return -ENOMEM;
+
iocb->ki_retry = ep_aio_read_retry;
- return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
+ return ep_aio_rwtail(iocb, buf, len, epdata, iv, count);
}
static ssize_t
-ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
+ep_aio_write(struct kiocb *iocb, const struct iovec *iv,
+ unsigned long count, loff_t o)
{
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
+ size_t len = 0;
+ int i = 0;
+ ssize_t ret;
if (unlikely(!(epdata->desc.bEndpointAddress & USB_DIR_IN)))
return -EINVAL;
- buf = kmalloc(len, GFP_KERNEL);
+
+ buf = kmalloc(iocb->ki_left, GFP_KERNEL);
if (unlikely(!buf))
return -ENOMEM;
- if (unlikely(copy_from_user(buf, ubuf, len) != 0)) {
- kfree(buf);
- return -EFAULT;
+
+ for (i=0; i < count; i++) {
+ if (unlikely(copy_from_user(&buf[len], iv[i]->iov_base,
+ iv[i]->iov_len) != 0)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+ len += iv[i]->iov_len;
}
- return ep_aio_rwtail(iocb, buf, len, epdata, NULL);
+ return ep_aio_rwtail(iocb, buf, len, epdata, NULL, 0);
}
/*----------------------------------------------------------------------*/
Index: linux-2.6.16-rc5/include/linux/aio.h
===================================================================
--- linux-2.6.16-rc5.orig/include/linux/aio.h 2006-03-07 08:37:05.000000000 -0800
+++ linux-2.6.16-rc5/include/linux/aio.h 2006-03-07 13:44:09.000000000 -0800
@@ -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>
@@ -112,6 +113,7 @@ struct kiocb {
long ki_retried; /* just for testing */
long ki_kicked; /* just for testing */
long ki_queued; /* just for testing */
+ struct iovec ki_inline_vec; /* inline vector */
struct list_head ki_list; /* the aio core uses this
* for cancellation */
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] Vectorize aio_read/aio_write methods
2006-03-08 0:22 ` [PATCH 1/3] Vectorize aio_read/aio_write methods Badari Pulavarty
@ 2006-03-08 12:44 ` christoph
0 siblings, 0 replies; 8+ messages in thread
From: christoph @ 2006-03-08 12:44 UTC (permalink / raw)
To: Badari Pulavarty; +Cc: Zach Brown, christoph, lkml, linux-fsdevel
On Tue, Mar 07, 2006 at 04:22:10PM -0800, Badari Pulavarty wrote:
> This patch vectorizes aio_read() and aio_write() methods to prepare
> for colapsing all the vectored operations into one interface -
> which is aio_read()/aio_write().
ok
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-03-08 12:44 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-02 16:12 [PATCH 0/3] VFS changes to collapse all the vectored and AIO support Badari Pulavarty
2006-02-02 16:14 ` [PATCH 1/3] Vectorize aio_read/aio_write methods Badari Pulavarty
2006-02-04 13:28 ` Christoph Hellwig
2006-02-04 22:10 ` Badari Pulavarty
2006-02-02 16:15 ` [PATCH 2/3] Remove readv/writev methods and use aio_read/aio_write instead Badari Pulavarty
2006-02-02 16:16 ` [PATCH 3/3] Zack's core aio changes to support vectored AIO Badari Pulavarty
-- strict thread matches above, loose matches on Subject: below --
2006-03-08 0:19 [RFC PATCH 0/3] VFS changes to collapse all the vectored and AIO support Badari Pulavarty
2006-03-08 0:22 ` [PATCH 1/3] Vectorize aio_read/aio_write methods Badari Pulavarty
2006-03-08 12:44 ` christoph
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).