[PATCH] Vectorize aio_read/aio_write fileop methods
This patch vectorizes aio_read() and aio_write() methods to prepare for collapsing all aio & vectored operations into one interface - which is aio_read()/aio_write(). Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Michael Holzheu <HOLZHEU@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
9ea0f9499d
commit
027445c372
|
@ -356,10 +356,9 @@ The last two are called only from check_disk_change().
|
|||
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,
|
||||
|
|
|
@ -699,9 +699,9 @@ This describes how the VFS can manipulate an open file. As of kernel
|
|||
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);
|
||||
|
|
|
@ -134,12 +134,20 @@ static int hypfs_open(struct inode *inode, struct file *filp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
|
||||
size_t count, loff_t offset)
|
||||
static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t offset)
|
||||
{
|
||||
char *data;
|
||||
size_t len;
|
||||
struct file *filp = iocb->ki_filp;
|
||||
/* XXX: temporary */
|
||||
char __user *buf = iov[0].iov_base;
|
||||
size_t count = iov[0].iov_len;
|
||||
|
||||
if (nr_segs != 1) {
|
||||
count = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data = filp->private_data;
|
||||
len = strlen(data);
|
||||
|
@ -158,12 +166,13 @@ static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
|
|||
out:
|
||||
return count;
|
||||
}
|
||||
static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t offset)
|
||||
{
|
||||
int rc;
|
||||
struct super_block *sb;
|
||||
struct hypfs_sb_info *fs_info;
|
||||
size_t count = iov_length(iov, nr_segs);
|
||||
|
||||
sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
|
||||
fs_info = sb->s_fs_info;
|
||||
|
|
|
@ -249,23 +249,11 @@ static ssize_t raw_file_write(struct file *file, const char __user *buf,
|
|||
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 const 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,
|
||||
|
|
|
@ -533,7 +533,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;
|
||||
};
|
||||
|
||||
|
@ -561,17 +562,32 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
|
|||
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)
|
||||
|
@ -584,7 +600,7 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
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);
|
||||
|
@ -619,7 +635,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;
|
||||
|
@ -634,7 +651,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)) {
|
||||
|
@ -674,41 +692,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);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
15
fs/aio.c
15
fs/aio.c
|
@ -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 *iocb)
|
|||
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 *iocb)
|
|||
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;
|
||||
|
|
|
@ -1162,14 +1162,6 @@ static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
|
|||
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);
|
||||
|
@ -1192,7 +1184,7 @@ const struct file_operations def_blk_fops = {
|
|||
.read = generic_file_read,
|
||||
.write = blkdev_file_write,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.aio_write = blkdev_file_aio_write,
|
||||
.aio_write = generic_file_aio_write_nolock,
|
||||
.mmap = generic_file_mmap,
|
||||
.fsync = block_fsync,
|
||||
.unlocked_ioctl = block_ioctl,
|
||||
|
|
|
@ -492,13 +492,13 @@ static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
|
|||
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;
|
||||
|
|
|
@ -48,14 +48,15 @@ static int ext3_release_file (struct inode * inode, struct file * filp)
|
|||
}
|
||||
|
||||
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.
|
||||
|
|
|
@ -707,8 +707,8 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
|
|||
/**
|
||||
* 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
|
||||
|
@ -725,17 +725,24 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
|
|||
* 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;
|
||||
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;
|
||||
|
@ -760,8 +767,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
|
||||
|
@ -782,17 +789,24 @@ 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;
|
||||
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;
|
||||
|
|
|
@ -41,8 +41,10 @@ static int nfs_file_release(struct inode *, struct file *);
|
|||
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_operations = {
|
|||
.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,
|
||||
|
@ -196,15 +198,17 @@ nfs_file_flush(struct file *file, fl_owner_t id)
|
|||
}
|
||||
|
||||
static ssize_t
|
||||
nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
|
||||
nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
struct dentry * dentry = iocb->ki_filp->f_dentry;
|
||||
struct inode * inode = dentry->d_inode;
|
||||
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",
|
||||
|
@ -214,7 +218,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
|
|||
result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -336,24 +340,22 @@ const struct address_space_operations nfs_file_aops = {
|
|||
#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))
|
||||
|
@ -372,7 +374,7 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
|
|||
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;
|
||||
|
||||
|
|
|
@ -2176,20 +2176,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);
|
||||
|
|
|
@ -961,25 +961,23 @@ static inline int ocfs2_write_should_remove_suid(struct inode *inode)
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -1048,7 +1046,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
|||
} 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,
|
||||
|
@ -1081,7 +1079,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
|||
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);
|
||||
|
@ -1098,7 +1096,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
|
|||
/* 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));
|
||||
|
@ -1132,16 +1130,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);
|
||||
|
||||
|
@ -1185,7 +1183,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
|
|||
}
|
||||
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");
|
||||
|
||||
|
|
|
@ -227,14 +227,20 @@ static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
|
|||
|
||||
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);
|
||||
|
|
|
@ -1334,7 +1334,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
|
|||
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;
|
||||
|
@ -1566,7 +1566,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
|
|||
}
|
||||
|
||||
const struct file_operations reiserfs_file_operations = {
|
||||
.read = generic_file_read,
|
||||
.read = do_sync_read,
|
||||
.write = reiserfs_file_write,
|
||||
.ioctl = reiserfs_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
|
|
@ -49,50 +49,49 @@ static struct vm_operations_struct xfs_dmapi_file_vm_ops;
|
|||
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;
|
||||
bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode);
|
||||
|
||||
BUG_ON(iocb->ki_pos != pos);
|
||||
if (unlikely(file->f_flags & O_DIRECT))
|
||||
ioflags |= IO_ISDIRECT;
|
||||
return bhv_vop_read(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
|
||||
return bhv_vop_read(vp, iocb, iov, nr_segs, &iocb->ki_pos,
|
||||
ioflags, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
|
@ -100,27 +99,28 @@ __xfs_file_write(
|
|||
BUG_ON(iocb->ki_pos != pos);
|
||||
if (unlikely(file->f_flags & O_DIRECT))
|
||||
ioflags |= IO_ISDIRECT;
|
||||
return bhv_vop_write(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
|
||||
return bhv_vop_write(vp, iocb, iov, nr_segs, &iocb->ki_pos,
|
||||
ioflags, NULL);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1097,9 +1097,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);
|
||||
|
@ -1704,11 +1704,11 @@ extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned
|
|||
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 *,
|
||||
|
|
|
@ -367,10 +367,12 @@ extern int nfs3_removexattr (struct dentry *, const char *name);
|
|||
*/
|
||||
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
|
||||
|
|
|
@ -665,7 +665,6 @@ struct sock_iocb {
|
|||
struct sock *sk;
|
||||
struct scm_cookie *scm;
|
||||
struct msghdr *msg, async_msg;
|
||||
struct iovec async_iov;
|
||||
struct kiocb *kiocb;
|
||||
};
|
||||
|
||||
|
|
39
mm/filemap.c
39
mm/filemap.c
|
@ -1226,12 +1226,11 @@ 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);
|
||||
|
||||
|
@ -2315,22 +2314,22 @@ 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)
|
||||
|
@ -2338,6 +2337,7 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_aio_write_nolock);
|
||||
|
||||
static ssize_t
|
||||
__generic_file_write_nolock(struct file *file, const struct iovec *iov,
|
||||
|
@ -2347,8 +2347,9 @@ __generic_file_write_nolock(struct file *file, const struct iovec *iov,
|
|||
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;
|
||||
}
|
||||
|
@ -2361,28 +2362,28 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
|
|||
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))) {
|
||||
|
|
49
net/socket.c
49
net/socket.c
|
@ -95,10 +95,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);
|
||||
|
@ -664,7 +664,6 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
|
|||
}
|
||||
|
||||
static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
|
||||
char __user *ubuf, size_t size,
|
||||
struct sock_iocb *siocb)
|
||||
{
|
||||
if (!is_sync_kiocb(iocb)) {
|
||||
|
@ -675,16 +674,13 @@ static struct sock_iocb *alloc_sock_iocb(struct kiocb *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;
|
||||
|
@ -715,32 +711,33 @@ static ssize_t sock_readv(struct file *file, const struct iovec *iov,
|
|||
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;
|
||||
|
@ -773,28 +770,28 @@ static ssize_t sock_writev(struct file *file, const struct iovec *iov,
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue