* [PATCH 1/4] Vectorize aio_read/aio_write methods
2006-06-02 19:06 [PATCH 0/4] VFS fileop cleanups by collapsing AIO and vector IO (2.6.17-rc5-mm2) Badari Pulavarty
@ 2006-06-02 19:07 ` Badari Pulavarty
2006-06-02 19:08 ` [PATCH 2/4] Remove readv/writev methods and use aio_read/aio_write instead Badari Pulavarty
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Badari Pulavarty @ 2006-06-02 19:07 UTC (permalink / raw)
To: lkml; +Cc: akpm, christoph, Zach Brown, cel
This patch vectorizes aio_read() and aio_write() methods to prepare
for collapsing all aio & vectored operations into one interface -
which is aio_read()/aio_write().
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Documentation/filesystems/Locking | 5 --
Documentation/filesystems/vfs.txt | 4 -
drivers/char/raw.c | 14 ------
drivers/usb/gadget/inode.c | 78 ++++++++++++++++++++++++++------------
fs/aio.c | 15 +++++--
fs/block_dev.c | 10 ----
fs/cifs/cifsfs.c | 6 +-
fs/ext3/file.c | 5 +-
fs/gfs2/ops_file.c | 30 +++++---------
fs/nfs/direct.c | 26 +++++++++---
fs/nfs/file.c | 39 +++++++++----------
fs/ntfs/file.c | 8 +--
fs/ocfs2/file.c | 28 ++++++-------
fs/read_write.c | 20 +++++++--
fs/reiserfs/file.c | 12 +----
fs/xfs/linux-2.6/xfs_file.c | 44 ++++++++++-----------
include/linux/aio.h | 2
include/linux/fs.h | 10 ++--
include/linux/nfs_fs.h | 8 +--
include/net/sock.h | 1
mm/filemap.c | 38 ++++++++----------
net/socket.c | 48 +++++++++++------------
22 files changed, 238 insertions(+), 213 deletions(-)
Index: linux-2.6.17-rc5-mm2/Documentation/filesystems/Locking
===================================================================
--- linux-2.6.17-rc5-mm2.orig/Documentation/filesystems/Locking 2006-06-02 11:51:38.419846040 -0700
+++ linux-2.6.17-rc5-mm2/Documentation/filesystems/Locking 2006-06-02 11:52:26.123593968 -0700
@@ -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.17-rc5-mm2/Documentation/filesystems/vfs.txt
===================================================================
--- linux-2.6.17-rc5-mm2.orig/Documentation/filesystems/vfs.txt 2006-06-02 11:51:38.419846040 -0700
+++ linux-2.6.17-rc5-mm2/Documentation/filesystems/vfs.txt 2006-06-02 11:52:26.124593816 -0700
@@ -699,9 +699,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.17-rc5-mm2/drivers/char/raw.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/drivers/char/raw.c 2006-06-02 11:51:38.419846040 -0700
+++ linux-2.6.17-rc5-mm2/drivers/char/raw.c 2006-06-02 11:57:43.271380176 -0700
@@ -250,23 +250,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.17-rc5-mm2/fs/aio.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/aio.c 2006-06-02 11:51:38.416846496 -0700
+++ linux-2.6.17-rc5-mm2/fs/aio.c 2006-06-02 11:52:26.126593512 -0700
@@ -15,6 +15,7 @@
#include <linux/aio_abi.h>
#include <linux/module.h>
#include <linux/syscalls.h>
+#include <linux/uio.h>
#define DEBUG 0
@@ -1315,8 +1316,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.
@@ -1349,8 +1353,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.17-rc5-mm2/fs/block_dev.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/block_dev.c 2006-06-02 11:51:38.416846496 -0700
+++ linux-2.6.17-rc5-mm2/fs/block_dev.c 2006-06-02 11:57:43.266380936 -0700
@@ -1166,14 +1166,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);
@@ -1196,7 +1188,7 @@ const struct file_operations def_blk_fop
.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.17-rc5-mm2/fs/cifs/cifsfs.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/cifs/cifsfs.c 2006-06-02 11:51:38.413846952 -0700
+++ linux-2.6.17-rc5-mm2/fs/cifs/cifsfs.c 2006-06-02 11:57:43.264381240 -0700
@@ -498,13 +498,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.17-rc5-mm2/fs/ext3/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ext3/file.c 2006-06-02 11:51:38.414846800 -0700
+++ linux-2.6.17-rc5-mm2/fs/ext3/file.c 2006-06-02 11:57:43.264381240 -0700
@@ -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.17-rc5-mm2/fs/read_write.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/read_write.c 2006-06-02 11:51:38.417846344 -0700
+++ linux-2.6.17-rc5-mm2/fs/read_write.c 2006-06-02 11:57:43.268380632 -0700
@@ -227,14 +227,20 @@ 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)))
+ kiocb.ki_left = len;
+
+ 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 +285,20 @@ 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)))
+ kiocb.ki_left = len;
+
+ 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.17-rc5-mm2/fs/reiserfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/reiserfs/file.c 2006-06-02 11:51:38.415846648 -0700
+++ linux-2.6.17-rc5-mm2/fs/reiserfs/file.c 2006-06-02 11:52:26.130592904 -0700
@@ -1329,7 +1329,7 @@ static ssize_t reiserfs_file_write(struc
if (err)
return err;
}
- result = generic_file_write(file, buf, count, ppos);
+ result = do_sync_write(file, buf, count, ppos);
if (after_file_end) { /* Now update i_size and remove the savelink */
struct reiserfs_transaction_handle th;
@@ -1560,14 +1560,8 @@ 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);
-}
-
const struct file_operations reiserfs_file_operations = {
- .read = generic_file_read,
+ .read = do_sync_read,
.write = reiserfs_file_write,
.ioctl = reiserfs_ioctl,
.mmap = generic_file_mmap,
@@ -1575,7 +1569,7 @@ const struct file_operations reiserfs_fi
.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,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
Index: linux-2.6.17-rc5-mm2/fs/xfs/linux-2.6/xfs_file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/xfs/linux-2.6/xfs_file.c 2006-06-02 11:51:38.413846952 -0700
+++ linux-2.6.17-rc5-mm2/fs/xfs/linux-2.6/xfs_file.c 2006-06-02 11:57:43.263381392 -0700
@@ -51,12 +51,11 @@ static struct vm_operations_struct xfs_d
STATIC inline ssize_t
__xfs_file_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 = vn_from_inode(file->f_dentry->d_inode);
ssize_t rval;
@@ -65,39 +64,38 @@ __xfs_file_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;
}
STATIC ssize_t
xfs_file_aio_read(
struct kiocb *iocb,
- char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __xfs_file_read(iocb, buf, IO_ISAIO, count, pos);
+ return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO, pos);
}
STATIC ssize_t
xfs_file_aio_read_invis(
struct kiocb *iocb,
- char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
+ return __xfs_file_read(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
}
STATIC inline ssize_t
__xfs_file_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 = vn_from_inode(inode);
@@ -107,28 +105,28 @@ __xfs_file_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;
}
STATIC ssize_t
xfs_file_aio_write(
struct kiocb *iocb,
- const char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- return __xfs_file_write(iocb, buf, IO_ISAIO, count, pos);
+ return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO, pos);
}
STATIC ssize_t
xfs_file_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 __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
+ return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
}
STATIC inline ssize_t
Index: linux-2.6.17-rc5-mm2/include/linux/fs.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/linux/fs.h 2006-06-02 11:51:38.420845888 -0700
+++ linux-2.6.17-rc5-mm2/include/linux/fs.h 2006-06-02 11:57:43.271380176 -0700
@@ -1098,9 +1098,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);
@@ -1687,11 +1687,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.17-rc5-mm2/include/net/sock.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/net/sock.h 2006-06-02 11:51:38.420845888 -0700
+++ linux-2.6.17-rc5-mm2/include/net/sock.h 2006-06-02 11:52:26.134592296 -0700
@@ -654,7 +654,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.17-rc5-mm2/mm/filemap.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/mm/filemap.c 2006-06-02 11:51:38.417846344 -0700
+++ linux-2.6.17-rc5-mm2/mm/filemap.c 2006-06-02 11:57:43.269380480 -0700
@@ -1199,14 +1199,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
@@ -2288,22 +2286,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)
@@ -2311,6 +2308,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,
@@ -2320,8 +2318,9 @@ __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);
return ret;
}
@@ -2334,28 +2333,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.17-rc5-mm2/net/socket.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/net/socket.c 2006-06-02 11:51:38.417846344 -0700
+++ linux-2.6.17-rc5-mm2/net/socket.c 2006-06-02 11:57:43.269380480 -0700
@@ -96,10 +96,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);
@@ -702,7 +702,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);
@@ -712,15 +712,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;
@@ -751,31 +749,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;
@@ -808,28 +808,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.17-rc5-mm2/drivers/usb/gadget/inode.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/drivers/usb/gadget/inode.c 2006-06-02 11:51:38.418846192 -0700
+++ linux-2.6.17-rc5-mm2/drivers/usb/gadget/inode.c 2006-06-02 11:52:26.139591536 -0700
@@ -528,7 +528,8 @@ struct kiocb_priv {
struct usb_request *req;
struct ep_data *epdata;
void *buf;
- char __user *ubuf; /* NULL for writes */
+ const struct iovec *iv;
+ unsigned long nr_segs;
unsigned actual;
};
@@ -556,17 +557,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;
+ int i;
- /* 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;
- kfree(priv->buf);
- kfree(priv);
- return status;
+ /* we "retry" to get the right mm context for this: */
+
+ /* copy stuff into user buffers */
+ total = priv->actual;
+ len = 0;
+ for (i=0; i < priv->nr_segs; i++) {
+ ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total);
+
+ if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) {
+ if (len == 0)
+ len = -EFAULT;
+ break;
+ }
+
+ total -= this;
+ len += this;
+ if (total == 0)
+ break;
+ }
+ kfree(priv->buf);
+ kfree(priv);
+ aio_put_req(iocb);
+ return len;
}
static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
@@ -579,7 +595,7 @@ static void ep_aio_complete(struct usb_e
spin_lock(&epdata->dev->lock);
priv->req = NULL;
priv->epdata = NULL;
- if (priv->ubuf == NULL
+ if (priv->iv == NULL
|| unlikely(req->actual == 0)
|| unlikely(kiocbIsCancelled(iocb))) {
kfree(req->buf);
@@ -614,7 +630,8 @@ ep_aio_rwtail(
char *buf,
size_t len,
struct ep_data *epdata,
- char __user *ubuf
+ const struct iovec *iv,
+ unsigned long nr_segs
)
{
struct kiocb_priv *priv;
@@ -629,7 +646,8 @@ fail:
return value;
}
iocb->private = priv;
- priv->ubuf = ubuf;
+ priv->iv = iv;
+ priv->nr_segs = nr_segs;
value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
if (unlikely(value < 0)) {
@@ -669,41 +687,53 @@ fail:
kfree(priv);
put_ep(epdata);
} else
- value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED);
+ value = (iv ? -EIOCBRETRY : -EIOCBQUEUED);
return value;
}
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 *iov,
+ unsigned long nr_segs, loff_t o)
{
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
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, iocb->ki_left, epdata, iov, nr_segs);
}
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 *iov,
+ unsigned long nr_segs, loff_t o)
{
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
+ size_t len = 0;
+ int i = 0;
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 < nr_segs; i++) {
+ if (unlikely(copy_from_user(&buf[len], iov[i].iov_base,
+ iov[i].iov_len) != 0)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+ len += iov[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.17-rc5-mm2/include/linux/aio.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/linux/aio.h 2006-06-02 11:51:38.421845736 -0700
+++ linux-2.6.17-rc5-mm2/include/linux/aio.h 2006-06-02 11:52:26.139591536 -0700
@@ -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 */
Index: linux-2.6.17-rc5-mm2/fs/nfs/direct.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/nfs/direct.c 2006-06-02 11:51:38.412847104 -0700
+++ linux-2.6.17-rc5-mm2/fs/nfs/direct.c 2006-06-02 11:52:26.140591384 -0700
@@ -745,8 +745,8 @@ static ssize_t nfs_direct_write(struct k
/**
* nfs_file_direct_read - file direct read operation for NFS files
* @iocb: target I/O control block
- * @buf: user's buffer into which to read data
- * @count: number of bytes to read
+ * @iov: vector of user buffers into which to read data
+ * @nr_segs: size of iov vector
* @pos: byte offset in file where reading starts
*
* We use this function for direct reads instead of calling
@@ -763,19 +763,26 @@ static ssize_t nfs_direct_write(struct k
* client must read the updated atime from the server back into its
* cache.
*/
-ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
ssize_t retval = -EINVAL;
int page_count;
struct page **pages;
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
+ /* XXX: temporary */
+ const char __user *buf = iov[0].iov_base;
+ size_t count = iov[0].iov_len;
dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name,
(unsigned long) count, (long long) pos);
+ if (nr_segs != 1)
+ return -EINVAL;
+
if (count < 0)
goto out;
retval = -EFAULT;
@@ -807,8 +814,8 @@ out:
/**
* nfs_file_direct_write - file direct write operation for NFS files
* @iocb: target I/O control block
- * @buf: user's buffer from which to write data
- * @count: number of bytes to write
+ * @iov: vector of user buffers from which to write data
+ * @nr_segs: size of iov vector
* @pos: byte offset in file where writing starts
*
* We use this function for direct writes instead of calling
@@ -829,19 +836,26 @@ out:
* Note that O_APPEND is not supported for NFS direct writes, as there
* 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)
+ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
ssize_t retval;
int page_count;
struct page **pages;
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
+ /* XXX: temporary */
+ const char __user *buf = iov[0].iov_base;
+ size_t count = iov[0].iov_len;
dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name,
(unsigned long) count, (long long) pos);
+ if (nr_segs != 1)
+ return -EINVAL;
+
retval = generic_write_checks(file, &pos, &count, 0);
if (retval)
goto out;
Index: linux-2.6.17-rc5-mm2/fs/nfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/nfs/file.c 2006-06-02 11:51:38.412847104 -0700
+++ linux-2.6.17-rc5-mm2/fs/nfs/file.c 2006-06-02 11:52:26.141591232 -0700
@@ -41,8 +41,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 *iov,
+ unsigned long nr_segs, loff_t pos);
+static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
static int nfs_file_flush(struct file *, fl_owner_t id);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
static int nfs_check_flags(int flags);
@@ -53,8 +55,8 @@ const struct file_operations nfs_file_op
.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,
@@ -212,26 +214,27 @@ nfs_file_flush(struct file *file, fl_own
return status;
}
-static ssize_t
-nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
+static ssize_t 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;
ssize_t result;
+ size_t count = iov_length(iov, nr_segs);
#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",
+ dfprintk(VFS, "nfs: read(%s/%s, %lu@%Ld)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
- (unsigned long) count, (unsigned long) pos);
+ (unsigned long) count, (long long) pos);
result = nfs_revalidate_file(inode, iocb->ki_filp);
nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
if (!result)
- result = generic_file_aio_read(iocb, buf, count, pos);
+ result = generic_file_aio_read(iocb, iov, nr_segs, pos);
return result;
}
@@ -343,24 +346,22 @@ const struct address_space_operations nf
#endif
};
-/*
- * 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)
+static ssize_t 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;
ssize_t result;
+ size_t count = iov_length(iov, nr_segs);
#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), %lu@%Ld)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
- inode->i_ino, (unsigned long) count, (unsigned long) pos);
+ inode->i_ino, (unsigned long) count, (long long) pos);
result = -EBUSY;
if (IS_SWAPFILE(inode))
@@ -380,7 +381,7 @@ nfs_file_write(struct kiocb *iocb, const
goto out;
nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
- 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.17-rc5-mm2/include/linux/nfs_fs.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/linux/nfs_fs.h 2006-06-02 11:51:38.421845736 -0700
+++ linux-2.6.17-rc5-mm2/include/linux/nfs_fs.h 2006-06-02 11:52:26.142591080 -0700
@@ -365,10 +365,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 *iov,
+ unsigned long nr_segs, loff_t pos);
+extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
/*
* linux/fs/nfs/dir.c
Index: linux-2.6.17-rc5-mm2/fs/ocfs2/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ocfs2/file.c 2006-06-02 11:51:38.416846496 -0700
+++ linux-2.6.17-rc5-mm2/fs/ocfs2/file.c 2006-06-02 11:52:26.143590928 -0700
@@ -960,25 +960,23 @@ static inline int ocfs2_write_should_rem
}
static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
- const char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
- struct iovec local_iov = { .iov_base = (void __user *)buf,
- .iov_len = count };
int ret, rw_level = -1, meta_level = -1, have_alloc_sem = 0;
u32 clusters;
struct file *filp = iocb->ki_filp;
struct inode *inode = filp->f_dentry->d_inode;
loff_t newsize, saved_pos;
- mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf,
- (unsigned int)count,
+ mlog_entry("(0x%p, %u, '%.*s')\n", filp,
+ (unsigned int)nr_segs,
filp->f_dentry->d_name.len,
filp->f_dentry->d_name.name);
/* happy write of zero bytes */
- if (count == 0)
+ if (iocb->ki_left == 0)
return 0;
if (!inode) {
@@ -1047,7 +1045,7 @@ static ssize_t ocfs2_file_aio_write(stru
} else {
saved_pos = iocb->ki_pos;
}
- newsize = count + saved_pos;
+ newsize = iocb->ki_left + saved_pos;
mlog(0, "pos=%lld newsize=%lld cursize=%lld\n",
(long long) saved_pos, (long long) newsize,
@@ -1080,7 +1078,7 @@ static ssize_t ocfs2_file_aio_write(stru
if (!clusters)
break;
- ret = ocfs2_extend_file(inode, NULL, newsize, count);
+ ret = ocfs2_extend_file(inode, NULL, newsize, iocb->ki_left);
if (ret < 0) {
if (ret != -ENOSPC)
mlog_errno(ret);
@@ -1097,7 +1095,7 @@ static ssize_t ocfs2_file_aio_write(stru
/* communicate with ocfs2_dio_end_io */
ocfs2_iocb_set_rw_locked(iocb);
- 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);
/* buffered aio wouldn't have proper lock coverage today */
BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
@@ -1131,16 +1129,16 @@ out:
}
static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
- char __user *buf,
- size_t count,
+ const struct iovec *iov,
+ unsigned long nr_segs,
loff_t pos)
{
int ret = 0, rw_level = -1, have_alloc_sem = 0;
struct file *filp = iocb->ki_filp;
struct inode *inode = filp->f_dentry->d_inode;
- mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf,
- (unsigned int)count,
+ mlog_entry("(0x%p, %u, '%.*s')\n", filp,
+ (unsigned int)nr_segs,
filp->f_dentry->d_name.len,
filp->f_dentry->d_name.name);
@@ -1184,7 +1182,7 @@ static ssize_t ocfs2_file_aio_read(struc
}
ocfs2_meta_unlock(inode, 0);
- ret = generic_file_aio_read(iocb, buf, count, iocb->ki_pos);
+ ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos);
if (ret == -EINVAL)
mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n");
Index: linux-2.6.17-rc5-mm2/fs/ntfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ntfs/file.c 2006-06-02 11:51:38.415846648 -0700
+++ linux-2.6.17-rc5-mm2/fs/ntfs/file.c 2006-06-02 11:57:43.266380936 -0700
@@ -2175,20 +2175,18 @@ out:
/**
* ntfs_file_aio_write -
*/
-static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
+static ssize_t ntfs_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 = ntfs_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
+ ret = ntfs_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))) {
int err = sync_page_range(inode, mapping, pos, ret);
Index: linux-2.6.17-rc5-mm2/fs/gfs2/ops_file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/gfs2/ops_file.c 2006-06-02 11:51:38.414846800 -0700
+++ linux-2.6.17-rc5-mm2/fs/gfs2/ops_file.c 2006-06-02 11:57:55.801475312 -0700
@@ -165,7 +165,7 @@ static ssize_t gfs2_direct_IO_read(struc
}
/**
- * __gfs2_file_aio_read - The main GFS2 read function
+ * gfs2_file_aio_read - The main GFS2 read function
*
* N.B. This is almost, but not quite the same as __generic_file_aio_read()
* the important subtle different being that inode->i_size isn't valid
@@ -173,9 +173,9 @@ static ssize_t gfs2_direct_IO_read(struc
* path since otherwise locking is done entirely at the page cache
* layer.
*/
-static ssize_t __gfs2_file_aio_read(struct kiocb *iocb,
+static ssize_t gfs2_file_aio_read(struct kiocb *iocb,
const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
+ unsigned long nr_segs, loff_t pos)
{
struct file *filp = iocb->ki_filp;
struct gfs2_inode *ip = filp->f_mapping->host->u.generic_ip;
@@ -184,6 +184,7 @@ static ssize_t __gfs2_file_aio_read(stru
unsigned long seg;
size_t count;
+ BUG_ON(iocb->ki_pos != pos);
count = 0;
for (seg = 0; seg < nr_segs; seg++) {
const struct iovec *iv = &iov[seg];
@@ -206,7 +207,7 @@ static ssize_t __gfs2_file_aio_read(stru
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (filp->f_flags & O_DIRECT) {
- loff_t pos = *ppos, size;
+ loff_t size;
struct address_space *mapping;
struct inode *inode;
@@ -231,7 +232,7 @@ static ssize_t __gfs2_file_aio_read(stru
if (retval > 0 && !is_sync_kiocb(iocb))
retval = -EIOCBQUEUED;
if (retval > 0)
- *ppos = pos + retval;
+ iocb->ki_pos = pos + retval;
}
file_accessed(filp);
gfs2_glock_dq_m(1, &gh);
@@ -251,7 +252,8 @@ fallback_to_normal:
if (desc.count == 0)
continue;
desc.error = 0;
- do_generic_file_read(filp,ppos,&desc,file_read_actor);
+ do_generic_file_read(filp, &iocb->ki_pos, &desc,
+ file_read_actor);
retval += desc.written;
if (desc.error) {
retval = retval ?: desc.error;
@@ -283,7 +285,8 @@ static ssize_t gfs2_read(struct file *fi
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
- ret = __gfs2_file_aio_read(&kiocb, &local_iov, 1, offset);
+ kiocb.ki_pos = *offset;
+ ret = gfs2_file_aio_read(&kiocb, &local_iov, 1, *offset);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
return ret;
@@ -296,22 +299,13 @@ static ssize_t gfs2_file_readv(struct fi
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
- ret = __gfs2_file_aio_read(&kiocb, iov, nr_segs, ppos);
+ kiocb.ki_pos = *ppos;
+ ret = gfs2_file_aio_read(&kiocb, iov, nr_segs, *ppos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
return ret;
}
-static ssize_t gfs2_file_aio_read(struct kiocb *iocb, char __user *buf,
- size_t count, loff_t pos)
-{
- struct iovec local_iov = { .iov_base = buf, .iov_len = count };
-
- BUG_ON(iocb->ki_pos != pos);
- return __gfs2_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
-}
-
-
/**
* filldir_reg_func - Report a directory entry to the caller of gfs2_dir_read()
* @opaque: opaque data used by the function
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/4] Remove readv/writev methods and use aio_read/aio_write instead
2006-06-02 19:06 [PATCH 0/4] VFS fileop cleanups by collapsing AIO and vector IO (2.6.17-rc5-mm2) Badari Pulavarty
2006-06-02 19:07 ` [PATCH 1/4] Vectorize aio_read/aio_write methods Badari Pulavarty
@ 2006-06-02 19:08 ` Badari Pulavarty
2006-06-02 19:10 ` [PATCH 3/4] Core aio changes to support vectored AIO Badari Pulavarty
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Badari Pulavarty @ 2006-06-02 19:08 UTC (permalink / raw)
To: lkml; +Cc: akpm, christoph, Zach Brown, cel
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>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/char/raw.c | 2
drivers/net/tun.c | 37 ++++------------
fs/bad_inode.c | 2
fs/block_dev.c | 2
fs/cifs/cifsfs.c | 16 ------
fs/compat.c | 44 ++++---------------
fs/ext2/file.c | 2
fs/ext3/file.c | 2
fs/fat/file.c | 2
fs/fuse/dev.c | 37 ++++------------
fs/gfs2/ops_file.c | 47 --------------------
fs/hostfs/hostfs_kern.c | 2
fs/jfs/file.c | 2
fs/ntfs/file.c | 2
fs/pipe.c | 59 +++++++++----------------
fs/read_write.c | 101 +++++++++++++++++++++++++++++---------------
fs/read_write.h | 14 ++++++
fs/xfs/linux-2.6/xfs_file.c | 92 ----------------------------------------
include/linux/fs.h | 6 --
mm/filemap.c | 36 ---------------
net/socket.c | 40 -----------------
sound/core/pcm_native.c | 40 ++++++++---------
22 files changed, 156 insertions(+), 431 deletions(-)
Index: linux-2.6.17-rc5-mm2/drivers/char/raw.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/drivers/char/raw.c 2006-06-02 11:57:43.271380176 -0700
+++ linux-2.6.17-rc5-mm2/drivers/char/raw.c 2006-06-02 11:58:08.714512232 -0700
@@ -258,8 +258,6 @@ static struct file_operations raw_fops =
.open = raw_open,
.release= raw_release,
.ioctl = raw_ioctl,
- .readv = generic_file_readv,
- .writev = generic_file_writev,
.owner = THIS_MODULE,
};
Index: linux-2.6.17-rc5-mm2/drivers/net/tun.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/drivers/net/tun.c 2006-06-02 11:57:43.270380328 -0700
+++ linux-2.6.17-rc5-mm2/drivers/net/tun.c 2006-06-02 11:58:08.715512080 -0700
@@ -289,11 +289,10 @@ static inline size_t iov_total(const str
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;
@@ -303,14 +302,6 @@ static ssize_t tun_chr_writev(struct fil
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,
@@ -344,10 +335,10 @@ static __inline__ ssize_t tun_put_user(s
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;
@@ -427,14 +418,6 @@ static ssize_t tun_chr_readv(struct file
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);
@@ -762,10 +745,10 @@ static int tun_chr_close(struct inode *i
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,
+ .read = do_sync_read,
+ .aio_read = tun_chr_aio_read,
+ .write = do_sync_write,
+ .aio_write = tun_chr_aio_write,
.poll = tun_chr_poll,
.ioctl = tun_chr_ioctl,
.open = tun_chr_open,
Index: linux-2.6.17-rc5-mm2/fs/bad_inode.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/bad_inode.c 2006-06-02 11:57:43.267380784 -0700
+++ linux-2.6.17-rc5-mm2/fs/bad_inode.c 2006-06-02 11:58:08.715512080 -0700
@@ -40,8 +40,6 @@ static const struct file_operations bad_
.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.17-rc5-mm2/fs/block_dev.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/block_dev.c 2006-06-02 11:57:43.266380936 -0700
+++ linux-2.6.17-rc5-mm2/fs/block_dev.c 2006-06-02 11:58:08.716511928 -0700
@@ -1195,8 +1195,6 @@ const struct file_operations def_blk_fop
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_blkdev_ioctl,
#endif
- .readv = generic_file_readv,
- .writev = generic_file_write_nolock,
.sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
Index: linux-2.6.17-rc5-mm2/fs/cifs/cifsfs.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/cifs/cifsfs.c 2006-06-02 11:57:43.264381240 -0700
+++ linux-2.6.17-rc5-mm2/fs/cifs/cifsfs.c 2006-06-02 11:58:08.717511776 -0700
@@ -486,18 +486,6 @@ cifs_get_sb(struct file_system_type *fs_
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)
{
@@ -583,8 +571,6 @@ struct inode_operations cifs_symlink_ino
const 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,
@@ -626,8 +612,6 @@ const struct file_operations cifs_file_d
const 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.17-rc5-mm2/fs/compat.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/compat.c 2006-06-02 11:57:43.267380784 -0700
+++ linux-2.6.17-rc5-mm2/fs/compat.c 2006-06-02 11:58:08.719511472 -0700
@@ -69,6 +69,8 @@ int compat_printk(const char *fmt, ...)
return ret;
}
+#include "read_write.h"
+
/*
* Not all architectures have sys_utime, so implement this in terms
* of sys_utimes.
@@ -1153,9 +1155,6 @@ static ssize_t compat_do_readv_writev(in
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;
@@ -1238,39 +1237,18 @@ static ssize_t compat_do_readv_writev(in
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, tot_len,
+ 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);
@@ -1298,7 +1276,7 @@ compat_sys_readv(unsigned long fd, const
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);
@@ -1321,7 +1299,7 @@ compat_sys_writev(unsigned long fd, cons
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.17-rc5-mm2/fs/ext2/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ext2/file.c 2006-06-02 11:57:43.264381240 -0700
+++ linux-2.6.17-rc5-mm2/fs/ext2/file.c 2006-06-02 11:58:08.719511472 -0700
@@ -50,8 +50,6 @@ const struct file_operations ext2_file_o
.open = generic_file_open,
.release = ext2_release_file,
.fsync = ext2_sync_file,
- .readv = generic_file_readv,
- .writev = generic_file_writev,
.sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
Index: linux-2.6.17-rc5-mm2/fs/ext3/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ext3/file.c 2006-06-02 11:57:43.264381240 -0700
+++ linux-2.6.17-rc5-mm2/fs/ext3/file.c 2006-06-02 11:58:08.720511320 -0700
@@ -112,8 +112,6 @@ const struct file_operations ext3_file_o
.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.17-rc5-mm2/fs/fat/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/fat/file.c 2006-06-02 11:57:43.262381544 -0700
+++ linux-2.6.17-rc5-mm2/fs/fat/file.c 2006-06-02 11:58:08.721511168 -0700
@@ -116,8 +116,6 @@ const struct file_operations fat_file_op
.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.17-rc5-mm2/fs/fuse/dev.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/fuse/dev.c 2006-06-02 11:57:43.265381088 -0700
+++ linux-2.6.17-rc5-mm2/fs/fuse/dev.c 2006-06-02 11:58:08.721511168 -0700
@@ -585,14 +585,15 @@ static void request_wait(struct fuse_con
* 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_req *req;
struct fuse_in *in;
struct fuse_copy_state cs;
unsigned reqsize;
+ struct file *file = iocb->ki_filp;
struct fuse_conn *fc = fuse_get_conn(file);
if (!fc)
return -EPERM;
@@ -658,15 +659,6 @@ static ssize_t fuse_dev_readv(struct fil
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)
{
@@ -711,15 +703,15 @@ static int copy_out_args(struct fuse_cop
* 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 -EPERM;
@@ -779,15 +771,6 @@ static ssize_t fuse_dev_writev(struct fi
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)
{
unsigned mask = POLLOUT | POLLWRNORM;
@@ -921,10 +904,10 @@ static int fuse_dev_fasync(int fd, struc
const 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,
+ .read = do_sync_read,
+ .aio_read = fuse_dev_read,
+ .write = do_sync_write,
+ .aio_write = fuse_dev_write,
.poll = fuse_dev_poll,
.release = fuse_dev_release,
.fasync = fuse_dev_fasync,
Index: linux-2.6.17-rc5-mm2/fs/hostfs/hostfs_kern.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/hostfs/hostfs_kern.c 2006-06-02 11:57:43.267380784 -0700
+++ linux-2.6.17-rc5-mm2/fs/hostfs/hostfs_kern.c 2006-06-02 11:58:08.722511016 -0700
@@ -390,8 +390,6 @@ static const struct file_operations host
.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.17-rc5-mm2/fs/jfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/jfs/file.c 2006-06-02 11:57:43.263381392 -0700
+++ linux-2.6.17-rc5-mm2/fs/jfs/file.c 2006-06-02 11:58:08.723510864 -0700
@@ -108,8 +108,6 @@ const struct file_operations jfs_file_op
.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.17-rc5-mm2/fs/ntfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ntfs/file.c 2006-06-02 11:57:43.266380936 -0700
+++ linux-2.6.17-rc5-mm2/fs/ntfs/file.c 2006-06-02 11:58:08.724510712 -0700
@@ -2297,11 +2297,9 @@ const struct file_operations ntfs_file_o
.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.17-rc5-mm2/fs/pipe.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/pipe.c 2006-06-02 11:57:43.268380632 -0700
+++ linux-2.6.17-rc5-mm2/fs/pipe.c 2006-06-02 11:58:08.725510560 -0700
@@ -218,9 +218,10 @@ static struct pipe_buf_operations anon_p
};
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 *pipe;
int do_wakeup;
@@ -330,17 +331,10 @@ redo:
}
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 ppos)
{
+ struct file *filp = iocb->ki_filp;
struct inode *inode = filp->f_dentry->d_inode;
struct pipe_inode_info *pipe;
ssize_t ret;
@@ -510,15 +504,6 @@ out:
}
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;
@@ -736,8 +721,8 @@ pipe_rdwr_open(struct inode *inode, stru
*/
const struct file_operations read_fifo_fops = {
.llseek = no_llseek,
- .read = pipe_read,
- .readv = pipe_readv,
+ .read = do_sync_read,
+ .aio_read = pipe_read,
.write = bad_pipe_w,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
@@ -749,8 +734,8 @@ const struct file_operations read_fifo_f
const struct file_operations write_fifo_fops = {
.llseek = no_llseek,
.read = bad_pipe_r,
- .write = pipe_write,
- .writev = pipe_writev,
+ .write = do_sync_write,
+ .aio_write = pipe_write,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_write_open,
@@ -760,10 +745,10 @@ const struct file_operations write_fifo_
const struct file_operations rdwr_fifo_fops = {
.llseek = no_llseek,
- .read = pipe_read,
- .readv = pipe_readv,
- .write = pipe_write,
- .writev = pipe_writev,
+ .read = do_sync_read,
+ .aio_read = pipe_read,
+ .write = do_sync_write,
+ .aio_write = pipe_write,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_rdwr_open,
@@ -773,8 +758,8 @@ const struct file_operations rdwr_fifo_f
static struct file_operations read_pipe_fops = {
.llseek = no_llseek,
- .read = pipe_read,
- .readv = pipe_readv,
+ .read = do_sync_read,
+ .aio_read = pipe_read,
.write = bad_pipe_w,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
@@ -786,8 +771,8 @@ static struct file_operations read_pipe_
static struct file_operations write_pipe_fops = {
.llseek = no_llseek,
.read = bad_pipe_r,
- .write = pipe_write,
- .writev = pipe_writev,
+ .write = do_sync_write,
+ .aio_write = pipe_write,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_write_open,
@@ -797,10 +782,10 @@ static struct file_operations write_pipe
static struct file_operations rdwr_pipe_fops = {
.llseek = no_llseek,
- .read = pipe_read,
- .readv = pipe_readv,
- .write = pipe_write,
- .writev = pipe_writev,
+ .read = do_sync_read,
+ .aio_read = pipe_read,
+ .write = do_sync_write,
+ .aio_write = pipe_write,
.poll = pipe_poll,
.ioctl = pipe_ioctl,
.open = pipe_rdwr_open,
Index: linux-2.6.17-rc5-mm2/fs/read_write.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/read_write.c 2006-06-02 11:57:43.268380632 -0700
+++ linux-2.6.17-rc5-mm2/fs/read_write.c 2006-06-02 11:58:08.726510408 -0700
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/pagemap.h>
+#include "read_write.h"
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -450,6 +451,62 @@ unsigned long iov_shorten(struct iovec *
EXPORT_SYMBOL(iov_shorten);
+ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
+ unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
+{
+ struct kiocb kiocb;
+ ssize_t ret;
+
+ init_sync_kiocb(&kiocb, filp);
+ kiocb.ki_pos = *ppos;
+ kiocb.ki_left = len;
+ kiocb.ki_nbytes = len;
+
+ 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)
@@ -457,12 +514,9 @@ static ssize_t do_readv_writev(int type,
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;
@@ -532,39 +586,18 @@ static ssize_t do_readv_writev(int type,
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, tot_len,
+ 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);
@@ -585,7 +618,7 @@ ssize_t vfs_readv(struct file *file, con
{
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);
@@ -598,7 +631,7 @@ ssize_t vfs_writev(struct file *file, co
{
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.17-rc5-mm2/fs/read_write.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17-rc5-mm2/fs/read_write.h 2006-06-02 11:58:08.727510256 -0700
@@ -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, size_t len, 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.17-rc5-mm2/fs/xfs/linux-2.6/xfs_file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/xfs/linux-2.6/xfs_file.c 2006-06-02 11:57:43.263381392 -0700
+++ linux-2.6.17-rc5-mm2/fs/xfs/linux-2.6/xfs_file.c 2006-06-02 11:58:08.727510256 -0700
@@ -129,94 +129,6 @@ xfs_file_aio_write_invis(
return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos);
}
-STATIC inline ssize_t
-__xfs_file_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 = vn_from_inode(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
-xfs_file_readv(
- struct file *file,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- return __xfs_file_readv(file, iov, 0, nr_segs, ppos);
-}
-
-STATIC ssize_t
-xfs_file_readv_invis(
- struct file *file,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
-}
-
-STATIC inline ssize_t
-__xfs_file_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 = vn_from_inode(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
-xfs_file_writev(
- struct file *file,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- return __xfs_file_writev(file, iov, 0, nr_segs, ppos);
-}
-
-STATIC ssize_t
-xfs_file_writev_invis(
- struct file *file,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t *ppos)
-{
- return __xfs_file_writev(file, iov, IO_INVIS, nr_segs, ppos);
-}
-
STATIC ssize_t
xfs_file_sendfile(
struct file *filp,
@@ -577,8 +489,6 @@ const struct file_operations xfs_file_op
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .readv = xfs_file_readv,
- .writev = xfs_file_writev,
.aio_read = xfs_file_aio_read,
.aio_write = xfs_file_aio_write,
.sendfile = xfs_file_sendfile,
@@ -601,8 +511,6 @@ const struct file_operations xfs_invis_f
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .readv = xfs_file_readv_invis,
- .writev = xfs_file_writev_invis,
.aio_read = xfs_file_aio_read_invis,
.aio_write = xfs_file_aio_write_invis,
.sendfile = xfs_file_sendfile_invis,
Index: linux-2.6.17-rc5-mm2/include/linux/fs.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/linux/fs.h 2006-06-02 11:57:43.271380176 -0700
+++ linux-2.6.17-rc5-mm2/include/linux/fs.h 2006-06-02 11:58:08.729509952 -0700
@@ -1114,8 +1114,6 @@ struct file_operations {
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);
@@ -1717,10 +1715,6 @@ extern long do_splice_direct(struct file
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.17-rc5-mm2/mm/filemap.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/mm/filemap.c 2006-06-02 11:57:43.269380480 -0700
+++ linux-2.6.17-rc5-mm2/mm/filemap.c 2006-06-02 11:58:08.731509648 -0700
@@ -2391,42 +2391,6 @@ ssize_t generic_file_write(struct file *
}
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.17-rc5-mm2/net/socket.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/net/socket.c 2006-06-02 11:57:43.269380480 -0700
+++ linux-2.6.17-rc5-mm2/net/socket.c 2006-06-02 11:58:08.732509496 -0700
@@ -112,10 +112,6 @@ static long compat_sock_ioctl(struct fil
unsigned int cmd, unsigned long arg);
#endif
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);
@@ -138,8 +134,6 @@ static struct file_operations socket_fil
.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,
.splice_write = generic_splice_sendpage,
};
@@ -738,23 +732,6 @@ static ssize_t do_sock_read(struct msghd
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)
{
@@ -797,23 +774,6 @@ static ssize_t do_sock_write(struct msgh
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.17-rc5-mm2/sound/core/pcm_native.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/sound/core/pcm_native.c 2006-06-02 11:57:43.270380328 -0700
+++ linux-2.6.17-rc5-mm2/sound/core/pcm_native.c 2006-06-02 11:58:08.734509192 -0700
@@ -2863,8 +2863,8 @@ static ssize_t snd_pcm_write(struct file
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;
@@ -2875,22 +2875,22 @@ static ssize_t snd_pcm_readv(struct file
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);
@@ -2898,8 +2898,8 @@ static ssize_t snd_pcm_readv(struct file
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;
@@ -2909,7 +2909,7 @@ static ssize_t snd_pcm_writev(struct fil
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;
@@ -2917,17 +2917,17 @@ static ssize_t snd_pcm_writev(struct fil
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);
@@ -3437,7 +3437,7 @@ struct file_operations snd_pcm_f_ops[2]
{
.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,
@@ -3449,7 +3449,7 @@ struct file_operations snd_pcm_f_ops[2]
{
.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,
Index: linux-2.6.17-rc5-mm2/fs/gfs2/ops_file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/gfs2/ops_file.c 2006-06-02 11:57:55.801475312 -0700
+++ linux-2.6.17-rc5-mm2/fs/gfs2/ops_file.c 2006-06-02 12:01:00.500396808 -0700
@@ -266,47 +266,6 @@ out:
}
/**
- * gfs2_read - Read bytes from a file
- * @file: The file to read from
- * @buf: The buffer to copy into
- * @size: The amount of data requested
- * @offset: The current file offset
- *
- * Outputs: Offset - updated according to number of bytes read
- *
- * Returns: The number of bytes read, errno on failure
- */
-
-static ssize_t gfs2_read(struct file *filp, char __user *buf, size_t size,
- loff_t *offset)
-{
- struct iovec local_iov = { .iov_base = buf, .iov_len = size };
- struct kiocb kiocb;
- ssize_t ret;
-
- init_sync_kiocb(&kiocb, filp);
- kiocb.ki_pos = *offset;
- ret = gfs2_file_aio_read(&kiocb, &local_iov, 1, *offset);
- if (-EIOCBQUEUED == ret)
- ret = wait_on_sync_kiocb(&kiocb);
- return ret;
-}
-
-static ssize_t gfs2_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);
- kiocb.ki_pos = *ppos;
- ret = gfs2_file_aio_read(&kiocb, iov, nr_segs, *ppos);
- if (-EIOCBQUEUED == ret)
- ret = wait_on_sync_kiocb(&kiocb);
- return ret;
-}
-
-/**
* filldir_reg_func - Report a directory entry to the caller of gfs2_dir_read()
* @opaque: opaque data used by the function
* @name: the name of the directory entry
@@ -964,11 +923,9 @@ static int gfs2_flock(struct file *file,
struct file_operations gfs2_file_fops = {
.llseek = gfs2_llseek,
- .read = gfs2_read,
- .readv = gfs2_file_readv,
+ .read = do_sync_read,
.aio_read = gfs2_file_aio_read,
- .write = generic_file_write,
- .writev = generic_file_writev,
+ .write = do_sync_write,
.aio_write = generic_file_aio_write,
.unlocked_ioctl = gfs2_ioctl,
.mmap = gfs2_mmap,
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/4] Core aio changes to support vectored AIO
2006-06-02 19:06 [PATCH 0/4] VFS fileop cleanups by collapsing AIO and vector IO (2.6.17-rc5-mm2) Badari Pulavarty
2006-06-02 19:07 ` [PATCH 1/4] Vectorize aio_read/aio_write methods Badari Pulavarty
2006-06-02 19:08 ` [PATCH 2/4] Remove readv/writev methods and use aio_read/aio_write instead Badari Pulavarty
@ 2006-06-02 19:10 ` Badari Pulavarty
2006-06-02 19:10 ` [PATCH 4/4] Streamline generic_file_* interfaces and filemap cleanups Badari Pulavarty
2006-06-02 21:38 ` [PATCH 0/4] VFS fileop cleanups by collapsing AIO and vector IO (2.6.17-rc5-mm2) Badari Pulavarty
4 siblings, 0 replies; 10+ messages in thread
From: Badari Pulavarty @ 2006-06-02 19:10 UTC (permalink / raw)
To: lkml; +Cc: akpm, christoph, Zach Brown, cel
This work is initially done by Zach Brown to add support for
vectored aio. These are the core changes for AIO to support
IOCB_CMD_PREADV/IOCB_CMD_PWRITEV.
I made few extra changes beyond Zach's work. They are
- took out aio_pread/aio_pwrite and made them
a special case into vectored support
- added single inlined vector to save on kmalloc()
for a simple aio_read/aio_write
- kiocb->ki_left always indicates the amount of
IO need to be done. Made sure that this gets
set in sync case also, so that we don't need
to loop over iovecs to figure out IO size all
the time.
Signed-off-by: Zach Brown <zach.brown@oracle.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Acked-by: Benjamin LaHaise <bcrl@kvack.org>
fs/aio.c | 165 +++++++++++++++++++++++++++++++++---------------
fs/read_write.c | 129 +++++++++++++++++++++----------------
include/linux/aio.h | 4 +
include/linux/aio_abi.h | 2
include/linux/fs.h | 5 +
5 files changed, 200 insertions(+), 105 deletions(-)
Index: linux-2.6.17-rc5-mm2/fs/aio.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/aio.c 2006-06-02 11:52:26.126593512 -0700
+++ linux-2.6.17-rc5-mm2/fs/aio.c 2006-06-02 12:01:35.264111920 -0700
@@ -415,6 +415,7 @@ static struct kiocb fastcall *__aio_get_
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
@@ -460,6 +461,8 @@ static inline void really_put_req(struct
if (req->ki_dtor)
req->ki_dtor(req);
+ if (req->ki_iovec != &req->ki_inline_vec)
+ kfree(req->ki_iovec);
kmem_cache_free(kiocb_cachep, req);
ctx->reqs_active--;
@@ -1301,69 +1304,63 @@ asmlinkage long sys_io_destroy(aio_conte
return -EINVAL;
}
-/*
- * aio_p{read,write} are the default ki_retry methods for
- * IO_CMD_P{READ,WRITE}. They maintains kiocb retry state around potentially
- * multiple calls to f_op->aio_read(). They loop around partial progress
- * instead of returning -EIOCBRETRY because they don't have the means to call
- * kick_iocb().
- */
-static ssize_t aio_pread(struct kiocb *iocb)
+static void aio_advance_iovec(struct kiocb *iocb, ssize_t ret)
{
- struct file *file = iocb->ki_filp;
- struct address_space *mapping = file->f_mapping;
- struct inode *inode = mapping->host;
- ssize_t ret = 0;
+ struct iovec *iov = &iocb->ki_iovec[iocb->ki_cur_seg];
- do {
- iocb->ki_inline_vec.iov_base = iocb->ki_buf;
- iocb->ki_inline_vec.iov_len = iocb->ki_left;
+ BUG_ON(ret <= 0);
- 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.
- */
- if (ret > 0) {
- iocb->ki_buf += ret;
- iocb->ki_left -= ret;
+ while (iocb->ki_cur_seg < iocb->ki_nr_segs && ret > 0) {
+ ssize_t this = min((ssize_t)iov->iov_len, 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++;
}
+ }
- /*
- * For pipes and sockets we return once we have some data; for
- * regular files we retry till we complete the entire read or
- * find that we can't read any more data (e.g short reads).
- */
- } while (ret > 0 && iocb->ki_left > 0 &&
- !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;
+ /* the caller should not have done more io than what fit in
+ * the remaining iovecs */
+ BUG_ON(ret > 0 && iocb->ki_left == 0);
}
-/* see aio_pread() */
-static ssize_t aio_pwrite(struct kiocb *iocb)
+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;
+ unsigned short opcode;
+
+ if ((iocb->ki_opcode == IOCB_CMD_PREADV) ||
+ (iocb->ki_opcode == IOCB_CMD_PREAD)) {
+ rw_op = file->f_op->aio_read;
+ opcode = IOCB_CMD_PREADV;
+ } else {
+ rw_op = file->f_op->aio_write;
+ opcode = IOCB_CMD_PWRITEV;
+ }
do {
- iocb->ki_inline_vec.iov_base = iocb->ki_buf;
- iocb->ki_inline_vec.iov_len = iocb->ki_left;
+ 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);
- 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;
- }
- } while (ret > 0 && iocb->ki_left > 0);
+ /* retry all partial writes. retry partial reads as long as its a
+ * regular file. */
+ } while (ret > 0 && iocb->ki_left > 0 &&
+ (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;
@@ -1390,6 +1387,38 @@ static ssize_t aio_fsync(struct kiocb *i
return ret;
}
+static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb)
+{
+ ssize_t ret;
+
+ ret = rw_copy_check_uvector(type, (struct iovec __user *)kiocb->ki_buf,
+ kiocb->ki_nbytes, 1,
+ &kiocb->ki_inline_vec, &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;
+}
+
+static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
+{
+ kiocb->ki_iovec = &kiocb->ki_inline_vec;
+ kiocb->ki_iovec->iov_base = kiocb->ki_buf;
+ kiocb->ki_iovec->iov_len = kiocb->ki_left;
+ kiocb->ki_nr_segs = 1;
+ kiocb->ki_cur_seg = 0;
+ kiocb->ki_nbytes = kiocb->ki_left;
+ return 0;
+}
+
/*
* aio_setup_iocb:
* Performs the initial checks and aio retry method
@@ -1412,9 +1441,12 @@ static ssize_t aio_setup_iocb(struct kio
ret = security_file_permission(file, MAY_READ);
if (unlikely(ret))
break;
+ ret = aio_setup_single_vector(kiocb);
+ if (ret)
+ break;
ret = -EINVAL;
if (file->f_op->aio_read)
- kiocb->ki_retry = aio_pread;
+ kiocb->ki_retry = aio_rw_vect_retry;
break;
case IOCB_CMD_PWRITE:
ret = -EBADF;
@@ -1427,9 +1459,40 @@ static ssize_t aio_setup_iocb(struct kio
ret = security_file_permission(file, MAY_WRITE);
if (unlikely(ret))
break;
+ ret = aio_setup_single_vector(kiocb);
+ if (ret)
+ break;
+ ret = -EINVAL;
+ if (file->f_op->aio_write)
+ kiocb->ki_retry = aio_rw_vect_retry;
+ break;
+ case IOCB_CMD_PREADV:
+ ret = -EBADF;
+ if (unlikely(!(file->f_mode & FMODE_READ)))
+ break;
+ ret = security_file_permission(file, MAY_READ);
+ if (unlikely(ret))
+ break;
+ ret = aio_setup_vectored_rw(READ, 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 = security_file_permission(file, MAY_WRITE);
+ if (unlikely(ret))
+ break;
+ ret = aio_setup_vectored_rw(WRITE, kiocb);
+ if (ret)
+ break;
ret = -EINVAL;
if (file->f_op->aio_write)
- kiocb->ki_retry = aio_pwrite;
+ kiocb->ki_retry = aio_rw_vect_retry;
break;
case IOCB_CMD_FDSYNC:
ret = -EINVAL;
Index: linux-2.6.17-rc5-mm2/include/linux/aio.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/linux/aio.h 2006-06-02 11:52:26.139591536 -0700
+++ linux-2.6.17-rc5-mm2/include/linux/aio.h 2006-06-02 12:01:35.265111768 -0700
@@ -7,6 +7,7 @@
#include <linux/uio.h>
#include <asm/atomic.h>
+#include <linux/uio.h>
#define AIO_MAXSEGS 4
#define AIO_KIOGRP_NR_ATOMIC 8
@@ -114,6 +115,9 @@ struct kiocb {
long ki_kicked; /* just for testing */
long ki_queued; /* just for testing */
struct iovec ki_inline_vec; /* inline vector */
+ 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.17-rc5-mm2/include/linux/aio_abi.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/linux/aio_abi.h 2006-06-02 11:51:36.260174360 -0700
+++ linux-2.6.17-rc5-mm2/include/linux/aio_abi.h 2006-06-02 12:01:35.265111768 -0700
@@ -41,6 +41,8 @@ enum {
* 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.17-rc5-mm2/fs/read_write.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/read_write.c 2006-06-02 11:58:08.726510408 -0700
+++ linux-2.6.17-rc5-mm2/fs/read_write.c 2006-06-02 12:01:35.266111616 -0700
@@ -508,7 +508,75 @@ ssize_t do_loop_readv_writev(struct file
}
/* A write operation does a read from user space and vice versa */
-#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
+#define rw_verify_direction(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
+
+ssize_t rw_copy_check_uvector(int type,
+ 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) {
+ 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(rw_verify_direction(type), buf, len))) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret += len;
+ }
+out:
+ *ret_pointer = iov;
+ return ret;
+}
static ssize_t do_readv_writev(int type, struct file *file,
const struct iovec __user * uvector,
@@ -518,64 +586,20 @@ static ssize_t do_readv_writev(int type,
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)
- 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)))
- 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;
+ ret = rw_copy_check_uvector(type, uvector, nr_segs,
+ ARRAY_SIZE(iovstack), iovstack, &iov);
+ if (ret <= 0)
goto out;
- }
+ tot_len = ret;
ret = rw_verify_area(type, file, pos, tot_len);
if (ret < 0)
goto out;
@@ -608,9 +632,6 @@ out:
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.17-rc5-mm2/include/linux/fs.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/linux/fs.h 2006-06-02 11:58:08.729509952 -0700
+++ linux-2.6.17-rc5-mm2/include/linux/fs.h 2006-06-02 12:01:35.268111312 -0700
@@ -1151,6 +1151,11 @@ struct inode_operations {
struct seq_file;
+ssize_t rw_copy_check_uvector(int type, 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] 10+ messages in thread
* [PATCH 4/4] Streamline generic_file_* interfaces and filemap cleanups
2006-06-02 19:06 [PATCH 0/4] VFS fileop cleanups by collapsing AIO and vector IO (2.6.17-rc5-mm2) Badari Pulavarty
` (2 preceding siblings ...)
2006-06-02 19:10 ` [PATCH 3/4] Core aio changes to support vectored AIO Badari Pulavarty
@ 2006-06-02 19:10 ` Badari Pulavarty
2006-06-02 21:38 ` [PATCH 0/4] VFS fileop cleanups by collapsing AIO and vector IO (2.6.17-rc5-mm2) Badari Pulavarty
4 siblings, 0 replies; 10+ messages in thread
From: Badari Pulavarty @ 2006-06-02 19:10 UTC (permalink / raw)
To: lkml; +Cc: akpm, christoph, Zach Brown, cel
This patch cleans up generic_file_*_read/write() interfaces.
Christoph Hellwig gave me the idea for this clean ups.
In a nutshell, all filesystems should set .aio_read/.aio_write
methods and use do_sync_read/ do_sync_write() as their .read/.write
methods. This allows us to cleanup all variants of generic_file_*
routines.
Final available interfaces:
generic_file_aio_read() - read handler
generic_file_aio_write() - write handler
generic_file_aio_write_nolock() - no lock write handler
__generic_file_aio_write_nolock() - internal worker routine
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/char/raw.c | 15 +------
fs/adfs/file.c | 6 ++-
fs/affs/file.c | 6 ++-
fs/bfs/file.c | 6 ++-
fs/block_dev.c | 12 +-----
fs/ecryptfs/file.c | 20 +++++++---
fs/ext2/file.c | 4 +-
fs/fuse/file.c | 6 ++-
fs/hfs/inode.c | 6 ++-
fs/hfsplus/inode.c | 6 ++-
fs/hostfs/hostfs_kern.c | 4 +-
fs/hpfs/file.c | 6 ++-
fs/jffs/inode-v23.c | 6 ++-
fs/jffs2/file.c | 6 ++-
fs/jfs/file.c | 4 +-
fs/minix/file.c | 6 ++-
fs/ntfs/file.c | 2 -
fs/qnx4/file.c | 6 ++-
fs/ramfs/file-mmu.c | 6 ++-
fs/ramfs/file-nommu.c | 6 ++-
fs/read_write.c | 3 +
fs/smbfs/file.c | 24 +++++++-----
fs/sysv/file.c | 6 ++-
fs/udf/file.c | 16 +++++---
fs/ufs/file.c | 6 ++-
fs/xfs/linux-2.6/xfs_lrw.c | 4 +-
include/linux/fs.h | 5 --
mm/filemap.c | 88 ++-------------------------------------------
28 files changed, 120 insertions(+), 171 deletions(-)
Index: linux-2.6.17-rc5-mm2/drivers/char/raw.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/drivers/char/raw.c 2006-06-02 11:58:08.714512232 -0700
+++ linux-2.6.17-rc5-mm2/drivers/char/raw.c 2006-06-02 12:01:39.695438256 -0700
@@ -239,21 +239,10 @@ out:
return err;
}
-static ssize_t raw_file_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct iovec local_iov = {
- .iov_base = (char __user *)buf,
- .iov_len = count
- };
-
- return generic_file_write_nolock(file, &local_iov, 1, ppos);
-}
-
static struct file_operations raw_fops = {
- .read = generic_file_read,
+ .read = do_sync_read,
.aio_read = generic_file_aio_read,
- .write = raw_file_write,
+ .write = do_sync_write,
.aio_write = generic_file_aio_write_nolock,
.open = raw_open,
.release= raw_release,
Index: linux-2.6.17-rc5-mm2/fs/adfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/adfs/file.c 2006-06-02 11:51:35.242329096 -0700
+++ linux-2.6.17-rc5-mm2/fs/adfs/file.c 2006-06-02 12:01:39.696438104 -0700
@@ -27,10 +27,12 @@
const struct file_operations adfs_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
.mmap = generic_file_mmap,
.fsync = file_fsync,
- .write = generic_file_write,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.sendfile = generic_file_sendfile,
};
Index: linux-2.6.17-rc5-mm2/fs/affs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/affs/file.c 2006-06-02 11:51:35.243328944 -0700
+++ linux-2.6.17-rc5-mm2/fs/affs/file.c 2006-06-02 12:01:39.697437952 -0700
@@ -27,8 +27,10 @@ static int affs_file_release(struct inod
const struct file_operations affs_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.open = affs_file_open,
.release = affs_file_release,
Index: linux-2.6.17-rc5-mm2/fs/bfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/bfs/file.c 2006-06-02 11:51:35.239329552 -0700
+++ linux-2.6.17-rc5-mm2/fs/bfs/file.c 2006-06-02 12:01:39.697437952 -0700
@@ -19,8 +19,10 @@
const struct file_operations bfs_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.sendfile = generic_file_sendfile,
};
Index: linux-2.6.17-rc5-mm2/fs/block_dev.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/block_dev.c 2006-06-02 11:58:08.716511928 -0700
+++ linux-2.6.17-rc5-mm2/fs/block_dev.c 2006-06-02 12:01:39.698437800 -0700
@@ -1158,14 +1158,6 @@ static int blkdev_close(struct inode * i
return blkdev_put(bdev);
}
-static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
-
- return generic_file_write_nolock(file, &local_iov, 1, ppos);
-}
-
static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
@@ -1185,8 +1177,8 @@ const struct file_operations def_blk_fop
.open = blkdev_open,
.release = blkdev_close,
.llseek = block_llseek,
- .read = generic_file_read,
- .write = blkdev_file_write,
+ .read = do_sync_read,
+ .write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write_nolock,
.mmap = generic_file_mmap,
Index: linux-2.6.17-rc5-mm2/fs/ext2/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ext2/file.c 2006-06-02 11:58:08.719511472 -0700
+++ linux-2.6.17-rc5-mm2/fs/ext2/file.c 2006-06-02 12:01:39.699437648 -0700
@@ -41,8 +41,8 @@ static int ext2_release_file (struct ino
*/
const struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.ioctl = ext2_ioctl,
Index: linux-2.6.17-rc5-mm2/fs/fuse/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/fuse/file.c 2006-06-02 11:51:35.243328944 -0700
+++ linux-2.6.17-rc5-mm2/fs/fuse/file.c 2006-06-02 12:01:39.700437496 -0700
@@ -621,8 +621,10 @@ static int fuse_set_page_dirty(struct pa
static const struct file_operations fuse_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = fuse_file_mmap,
.open = fuse_open,
.flush = fuse_flush,
Index: linux-2.6.17-rc5-mm2/fs/hfs/inode.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/hfs/inode.c 2006-06-02 11:51:35.239329552 -0700
+++ linux-2.6.17-rc5-mm2/fs/hfs/inode.c 2006-06-02 12:01:39.700437496 -0700
@@ -603,8 +603,10 @@ int hfs_inode_setattr(struct dentry *den
static const struct file_operations hfs_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.sendfile = generic_file_sendfile,
.fsync = file_fsync,
Index: linux-2.6.17-rc5-mm2/fs/hfsplus/inode.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/hfsplus/inode.c 2006-06-02 11:51:35.248328184 -0700
+++ linux-2.6.17-rc5-mm2/fs/hfsplus/inode.c 2006-06-02 12:01:39.701437344 -0700
@@ -282,8 +282,10 @@ static struct inode_operations hfsplus_f
static const struct file_operations hfsplus_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.sendfile = generic_file_sendfile,
.fsync = file_fsync,
Index: linux-2.6.17-rc5-mm2/fs/hostfs/hostfs_kern.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/hostfs/hostfs_kern.c 2006-06-02 11:58:08.722511016 -0700
+++ linux-2.6.17-rc5-mm2/fs/hostfs/hostfs_kern.c 2006-06-02 12:01:39.702437192 -0700
@@ -386,11 +386,11 @@ int hostfs_fsync(struct file *file, stru
static const struct file_operations hostfs_file_fops = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
+ .read = do_sync_read,
.sendfile = generic_file_sendfile,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
- .write = generic_file_write,
+ .write = do_sync_write,
.mmap = generic_file_mmap,
.open = hostfs_file_open,
.release = NULL,
Index: linux-2.6.17-rc5-mm2/fs/hpfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/hpfs/file.c 2006-06-02 11:51:35.244328792 -0700
+++ linux-2.6.17-rc5-mm2/fs/hpfs/file.c 2006-06-02 12:01:39.703437040 -0700
@@ -113,7 +113,7 @@ static ssize_t hpfs_file_write(struct fi
{
ssize_t retval;
- retval = generic_file_write(file, buf, count, ppos);
+ retval = do_sync_write(file, buf, count, ppos);
if (retval > 0)
hpfs_i(file->f_dentry->d_inode)->i_dirty = 1;
return retval;
@@ -122,8 +122,10 @@ static ssize_t hpfs_file_write(struct fi
const struct file_operations hpfs_file_ops =
{
.llseek = generic_file_llseek,
- .read = generic_file_read,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
.write = hpfs_file_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.release = hpfs_file_release,
.fsync = hpfs_file_fsync,
Index: linux-2.6.17-rc5-mm2/fs/jffs/inode-v23.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/jffs/inode-v23.c 2006-06-02 11:51:35.244328792 -0700
+++ linux-2.6.17-rc5-mm2/fs/jffs/inode-v23.c 2006-06-02 12:01:39.704436888 -0700
@@ -1633,8 +1633,10 @@ static const struct file_operations jffs
{
.open = generic_file_open,
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.ioctl = jffs_ioctl,
.mmap = generic_file_readonly_mmap,
.fsync = jffs_fsync,
Index: linux-2.6.17-rc5-mm2/fs/jffs2/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/jffs2/file.c 2006-06-02 11:51:35.246328488 -0700
+++ linux-2.6.17-rc5-mm2/fs/jffs2/file.c 2006-06-02 12:01:39.705436736 -0700
@@ -42,8 +42,10 @@ const struct file_operations jffs2_file_
{
.llseek = generic_file_llseek,
.open = generic_file_open,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_readonly_mmap,
.fsync = jffs2_fsync,
.sendfile = generic_file_sendfile
Index: linux-2.6.17-rc5-mm2/fs/jfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/jfs/file.c 2006-06-02 11:58:08.723510864 -0700
+++ linux-2.6.17-rc5-mm2/fs/jfs/file.c 2006-06-02 12:01:39.705436736 -0700
@@ -103,8 +103,8 @@ struct inode_operations jfs_file_inode_o
const struct file_operations jfs_file_operations = {
.open = jfs_open,
.llseek = generic_file_llseek,
- .write = generic_file_write,
- .read = generic_file_read,
+ .write = do_sync_write,
+ .read = do_sync_read,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
Index: linux-2.6.17-rc5-mm2/fs/minix/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/minix/file.c 2006-06-02 11:51:35.247328336 -0700
+++ linux-2.6.17-rc5-mm2/fs/minix/file.c 2006-06-02 12:01:39.706436584 -0700
@@ -17,8 +17,10 @@ int minix_sync_file(struct file *, struc
const struct file_operations minix_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = minix_sync_file,
.sendfile = generic_file_sendfile,
Index: linux-2.6.17-rc5-mm2/fs/ntfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ntfs/file.c 2006-06-02 11:58:08.724510712 -0700
+++ linux-2.6.17-rc5-mm2/fs/ntfs/file.c 2006-06-02 12:01:39.707436432 -0700
@@ -2295,7 +2295,7 @@ static int ntfs_file_fsync(struct file *
const struct file_operations ntfs_file_ops = {
.llseek = generic_file_llseek, /* Seek inside file. */
- .read = generic_file_read, /* Read from file. */
+ .read = do_sync_read, /* Read from file. */
.aio_read = generic_file_aio_read, /* Async read from file. */
#ifdef NTFS_RW
.write = ntfs_file_write, /* Write to file. */
Index: linux-2.6.17-rc5-mm2/fs/qnx4/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/qnx4/file.c 2006-06-02 11:51:35.245328640 -0700
+++ linux-2.6.17-rc5-mm2/fs/qnx4/file.c 2006-06-02 12:01:39.708436280 -0700
@@ -22,11 +22,13 @@
const struct file_operations qnx4_file_operations =
{
.llseek = generic_file_llseek,
- .read = generic_file_read,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
.mmap = generic_file_mmap,
.sendfile = generic_file_sendfile,
#ifdef CONFIG_QNX4FS_RW
- .write = generic_file_write,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.fsync = qnx4_sync_file,
#endif
};
Index: linux-2.6.17-rc5-mm2/fs/ramfs/file-mmu.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ramfs/file-mmu.c 2006-06-02 11:51:35.247328336 -0700
+++ linux-2.6.17-rc5-mm2/fs/ramfs/file-mmu.c 2006-06-02 12:01:39.709436128 -0700
@@ -33,8 +33,10 @@ const struct address_space_operations ra
};
const struct file_operations ramfs_file_operations = {
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = simple_sync_file,
.sendfile = generic_file_sendfile,
Index: linux-2.6.17-rc5-mm2/fs/ramfs/file-nommu.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ramfs/file-nommu.c 2006-06-02 11:51:35.247328336 -0700
+++ linux-2.6.17-rc5-mm2/fs/ramfs/file-nommu.c 2006-06-02 12:01:39.709436128 -0700
@@ -36,8 +36,10 @@ const struct address_space_operations ra
const struct file_operations ramfs_file_operations = {
.mmap = ramfs_nommu_mmap,
.get_unmapped_area = ramfs_nommu_get_unmapped_area,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.fsync = simple_sync_file,
.sendfile = generic_file_sendfile,
.llseek = generic_file_llseek,
Index: linux-2.6.17-rc5-mm2/fs/read_write.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/read_write.c 2006-06-02 12:01:35.266111616 -0700
+++ linux-2.6.17-rc5-mm2/fs/read_write.c 2006-06-02 12:01:39.710435976 -0700
@@ -22,7 +22,8 @@
const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
.mmap = generic_file_readonly_mmap,
.sendfile = generic_file_sendfile,
};
Index: linux-2.6.17-rc5-mm2/include/linux/fs.h
===================================================================
--- linux-2.6.17-rc5-mm2.orig/include/linux/fs.h 2006-06-02 12:01:35.268111312 -0700
+++ linux-2.6.17-rc5-mm2/include/linux/fs.h 2006-06-02 12:01:39.711435824 -0700
@@ -1687,11 +1687,8 @@ extern int generic_file_mmap(struct file
extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
-extern ssize_t generic_file_read(struct file *, char __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 *, 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 struct iovec *, unsigned long, loff_t);
extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
unsigned long, loff_t);
@@ -1701,8 +1698,6 @@ extern ssize_t generic_file_buffered_wri
unsigned long, loff_t, loff_t *, size_t, ssize_t);
extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
-ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos);
extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
extern void do_generic_mapping_read(struct address_space *mapping,
struct file_ra_state *, struct file *,
Index: linux-2.6.17-rc5-mm2/mm/filemap.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/mm/filemap.c 2006-06-02 11:58:08.731509648 -0700
+++ linux-2.6.17-rc5-mm2/mm/filemap.c 2006-06-02 12:01:39.713435520 -0700
@@ -1121,13 +1121,14 @@ EXPORT_SYMBOL(file_read_actor);
* that can use the page cache directly.
*/
ssize_t
-__generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
+generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
struct file *filp = iocb->ki_filp;
ssize_t retval;
unsigned long seg;
size_t count;
+ loff_t *ppos = &iocb->ki_pos;
count = 0;
for (seg = 0; seg < nr_segs; seg++) {
@@ -1151,7 +1152,7 @@ __generic_file_aio_read(struct kiocb *io
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (filp->f_flags & O_DIRECT) {
- loff_t pos = *ppos, size;
+ loff_t size;
struct address_space *mapping;
struct inode *inode;
@@ -1196,33 +1197,8 @@ out:
return retval;
}
-EXPORT_SYMBOL(__generic_file_aio_read);
-
-ssize_t
-generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
-{
- BUG_ON(iocb->ki_pos != pos);
- return __generic_file_aio_read(iocb, iov, nr_segs, &iocb->ki_pos);
-}
EXPORT_SYMBOL(generic_file_aio_read);
-ssize_t
-generic_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
-{
- struct iovec local_iov = { .iov_base = buf, .iov_len = count };
- struct kiocb kiocb;
- ssize_t ret;
-
- init_sync_kiocb(&kiocb, filp);
- ret = __generic_file_aio_read(&kiocb, &local_iov, 1, ppos);
- if (-EIOCBQUEUED == ret)
- ret = wait_on_sync_kiocb(&kiocb);
- return ret;
-}
-
-EXPORT_SYMBOL(generic_file_read);
-
int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
{
ssize_t written;
@@ -2310,38 +2286,6 @@ ssize_t generic_file_aio_write_nolock(st
}
EXPORT_SYMBOL(generic_file_aio_write_nolock);
-static ssize_t
-__generic_file_write_nolock(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
-{
- struct kiocb kiocb;
- ssize_t ret;
-
- init_sync_kiocb(&kiocb, file);
- kiocb.ki_pos = *ppos;
- ret = __generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
- if (-EIOCBQUEUED == ret)
- ret = wait_on_sync_kiocb(&kiocb);
- return ret;
-}
-
-ssize_t
-generic_file_write_nolock(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
-{
- struct kiocb kiocb;
- ssize_t ret;
-
- init_sync_kiocb(&kiocb, file);
- 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 struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
@@ -2367,30 +2311,6 @@ ssize_t generic_file_aio_write(struct ki
}
EXPORT_SYMBOL(generic_file_aio_write);
-ssize_t generic_file_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- 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 };
-
- mutex_lock(&inode->i_mutex);
- ret = __generic_file_write_nolock(file, &local_iov, 1, ppos);
- mutex_unlock(&inode->i_mutex);
-
- if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
- ssize_t err;
-
- err = sync_page_range(inode, mapping, *ppos - ret, ret);
- if (err < 0)
- ret = err;
- }
- return ret;
-}
-EXPORT_SYMBOL(generic_file_write);
-
/*
* Called under i_mutex for writes to S_ISREG files. Returns -EIO if something
* went wrong during pagecache shootdown.
Index: linux-2.6.17-rc5-mm2/fs/xfs/linux-2.6/xfs_lrw.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/xfs/linux-2.6/xfs_lrw.c 2006-06-02 11:51:35.241329248 -0700
+++ linux-2.6.17-rc5-mm2/fs/xfs/linux-2.6/xfs_lrw.c 2006-06-02 12:01:39.714435368 -0700
@@ -276,7 +276,9 @@ xfs_read(
xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
(void *)iovp, segs, *offset, ioflags);
- ret = __generic_file_aio_read(iocb, iovp, segs, offset);
+
+ iocb->ki_pos = *offset;
+ ret = generic_file_aio_read(iocb, iovp, segs, *offset);
if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO))
ret = wait_on_sync_kiocb(iocb);
if (ret > 0)
Index: linux-2.6.17-rc5-mm2/fs/smbfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/smbfs/file.c 2006-06-02 11:51:35.248328184 -0700
+++ linux-2.6.17-rc5-mm2/fs/smbfs/file.c 2006-06-02 12:01:39.715435216 -0700
@@ -214,13 +214,15 @@ smb_updatepage(struct file *file, struct
}
static ssize_t
-smb_file_read(struct file * file, char __user * buf, size_t count, loff_t *ppos)
+smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
+ struct file * file = iocb->ki_filp;
struct dentry * dentry = file->f_dentry;
ssize_t status;
VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
- (unsigned long) count, (unsigned long) *ppos);
+ (unsigned long) iocb->ki_left, (unsigned long) pos);
status = smb_revalidate_inode(dentry);
if (status) {
@@ -233,7 +235,7 @@ smb_file_read(struct file * file, char _
(long)dentry->d_inode->i_size,
dentry->d_inode->i_flags, dentry->d_inode->i_atime);
- status = generic_file_read(file, buf, count, ppos);
+ status = generic_file_aio_read(iocb, iov, nr_segs, pos);
out:
return status;
}
@@ -317,14 +319,16 @@ const struct address_space_operations sm
* Write to a file (through the page cache).
*/
static ssize_t
-smb_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
+ struct file * file = iocb->ki_filp;
struct dentry * dentry = file->f_dentry;
ssize_t result;
VERBOSE("file %s/%s, count=%lu@%lu\n",
DENTRY_PATH(dentry),
- (unsigned long) count, (unsigned long) *ppos);
+ (unsigned long) iocb->ki_left, (unsigned long) pos);
result = smb_revalidate_inode(dentry);
if (result) {
@@ -337,8 +341,8 @@ smb_file_write(struct file *file, const
if (result)
goto out;
- if (count > 0) {
- result = generic_file_write(file, buf, count, ppos);
+ if (iocb->ki_left > 0) {
+ result = generic_file_aio_write(iocb, iov, nr_segs, pos);
VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
(long) file->f_pos, (long) dentry->d_inode->i_size,
dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
@@ -402,8 +406,10 @@ smb_file_permission(struct inode *inode,
const struct file_operations smb_file_operations =
{
.llseek = remote_llseek,
- .read = smb_file_read,
- .write = smb_file_write,
+ .read = do_sync_read,
+ .aio_read = smb_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = smb_file_aio_write,
.ioctl = smb_ioctl,
.mmap = smb_file_mmap,
.open = smb_file_open,
Index: linux-2.6.17-rc5-mm2/fs/sysv/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/sysv/file.c 2006-06-02 11:51:35.245328640 -0700
+++ linux-2.6.17-rc5-mm2/fs/sysv/file.c 2006-06-02 12:01:39.716435064 -0700
@@ -21,8 +21,10 @@
*/
const struct file_operations sysv_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = sysv_sync_file,
.sendfile = generic_file_sendfile,
Index: linux-2.6.17-rc5-mm2/fs/udf/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/udf/file.c 2006-06-02 11:51:35.240329400 -0700
+++ linux-2.6.17-rc5-mm2/fs/udf/file.c 2006-06-02 12:01:39.716435064 -0700
@@ -103,19 +103,21 @@ const struct address_space_operations ud
.commit_write = udf_adinicb_commit_write,
};
-static ssize_t udf_file_write(struct file * file, const char __user * buf,
- size_t count, loff_t *ppos)
+static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t ppos)
{
ssize_t retval;
+ struct file *file = iocb->ki_filp;
struct inode *inode = file->f_dentry->d_inode;
int err, pos;
+ size_t count = iocb->ki_left;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
{
if (file->f_flags & O_APPEND)
pos = inode->i_size;
else
- pos = *ppos;
+ pos = ppos;
if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
pos + count))
@@ -136,7 +138,7 @@ static ssize_t udf_file_write(struct fil
}
}
- retval = generic_file_write(file, buf, count, ppos);
+ retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
if (retval > 0)
mark_inode_dirty(inode);
@@ -249,11 +251,13 @@ static int udf_release_file(struct inode
}
const struct file_operations udf_file_operations = {
- .read = generic_file_read,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
.ioctl = udf_ioctl,
.open = generic_file_open,
.mmap = generic_file_mmap,
- .write = udf_file_write,
+ .write = do_sync_write,
+ .aio_write = udf_file_aio_write,
.release = udf_release_file,
.fsync = udf_fsync_file,
.sendfile = generic_file_sendfile,
Index: linux-2.6.17-rc5-mm2/fs/ufs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ufs/file.c 2006-06-02 11:51:35.241329248 -0700
+++ linux-2.6.17-rc5-mm2/fs/ufs/file.c 2006-06-02 12:01:39.717434912 -0700
@@ -33,8 +33,10 @@
const struct file_operations ufs_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = generic_file_aio_read,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.open = generic_file_open,
.sendfile = generic_file_sendfile,
Index: linux-2.6.17-rc5-mm2/fs/ecryptfs/file.c
===================================================================
--- linux-2.6.17-rc5-mm2.orig/fs/ecryptfs/file.c 2006-06-02 11:51:35.242329096 -0700
+++ linux-2.6.17-rc5-mm2/fs/ecryptfs/file.c 2006-06-02 12:01:39.718434760 -0700
@@ -99,14 +99,22 @@ out:
* returns without any errors. This is to be used only for file reads.
* The function to be used for directory reads is ecryptfs_read.
*/
-static ssize_t ecryptfs_read_update_atime(struct file *file, char __user * buf,
- size_t count, loff_t * ppos)
+static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
+ const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
int rc;
struct dentry *lower_dentry;
struct vfsmount *lower_vfsmount;
+ struct file *file = iocb->ki_filp;
- rc = generic_file_read(file, buf, count, ppos);
+ rc = generic_file_aio_read(iocb, iov, nr_segs, pos);
+ /*
+ * Even though this is a async interface, we need to wait
+ * for IO to finish to update atime
+ */
+ if (-EIOCBQUEUED == rc)
+ rc = wait_on_sync_kiocb(iocb);
if (rc >= 0) {
lower_dentry = ecryptfs_dentry_to_lower(file->f_dentry);
lower_vfsmount = ecryptfs_superblock_to_private(
@@ -473,8 +481,10 @@ const struct file_operations ecryptfs_di
const struct file_operations ecryptfs_main_fops = {
.llseek = ecryptfs_llseek,
- .read = ecryptfs_read_update_atime,
- .write = generic_file_write,
+ .read = do_sync_read,
+ .aio_read = ecryptfs_read_update_atime,
+ .write = do_sync_write,
+ .aio_write = generic_file_aio_write,
.readdir = ecryptfs_readdir,
.ioctl = ecryptfs_ioctl,
.mmap = generic_file_mmap,
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/4] VFS fileop cleanups by collapsing AIO and vector IO (2.6.17-rc5-mm2)
2006-06-02 19:06 [PATCH 0/4] VFS fileop cleanups by collapsing AIO and vector IO (2.6.17-rc5-mm2) Badari Pulavarty
` (3 preceding siblings ...)
2006-06-02 19:10 ` [PATCH 4/4] Streamline generic_file_* interfaces and filemap cleanups Badari Pulavarty
@ 2006-06-02 21:38 ` Badari Pulavarty
4 siblings, 0 replies; 10+ messages in thread
From: Badari Pulavarty @ 2006-06-02 21:38 UTC (permalink / raw)
To: Badari Pulavarty; +Cc: lkml, akpm, hch, Zach Brown, cel
Badari Pulavarty wrote:
>Hi Andrew,
>
>Here is the updated set of patches for 2.6.17-rc5-mm2 with
>autofs fixes. Ian and I verified with autofs tests and also
>running on Fedora Core 5.
>
Correction !! I tested these series of patches (heavily) on mainline
2.6.17-rc5 and
then ported to current -mm. -mm2 is not really stable enough for me yet,
running into
few issues. I will continue to test these on -mm also.
Thanks,
Badari
^ permalink raw reply [flat|nested] 10+ messages in thread