Commit e828d709 authored by Benjamin LaHaise's avatar Benjamin LaHaise

several updates for testing aio_{read,write}

support for file descriptors with only async ops in vfs_{read,write}
parent d3eee8ac
...@@ -935,6 +935,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb, ...@@ -935,6 +935,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
req->ki_user_obj = user_iocb; req->ki_user_obj = user_iocb;
req->ki_user_data = iocb->aio_data; req->ki_user_data = iocb->aio_data;
req->ki_pos = iocb->aio_offset;
buf = (char *)(unsigned long)iocb->aio_buf; buf = (char *)(unsigned long)iocb->aio_buf;
...@@ -949,7 +950,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb, ...@@ -949,7 +950,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
ret = -EINVAL; ret = -EINVAL;
if (file->f_op->aio_read) if (file->f_op->aio_read)
ret = file->f_op->aio_read(req, buf, ret = file->f_op->aio_read(req, buf,
iocb->aio_nbytes, iocb->aio_offset); iocb->aio_nbytes, req->ki_pos);
break; break;
case IOCB_CMD_PWRITE: case IOCB_CMD_PWRITE:
ret = -EBADF; ret = -EBADF;
...@@ -961,7 +962,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb, ...@@ -961,7 +962,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
ret = -EINVAL; ret = -EINVAL;
if (file->f_op->aio_write) if (file->f_op->aio_write)
ret = file->f_op->aio_write(req, buf, ret = file->f_op->aio_write(req, buf,
iocb->aio_nbytes, iocb->aio_offset); iocb->aio_nbytes, req->ki_pos);
break; break;
case IOCB_CMD_FDSYNC: case IOCB_CMD_FDSYNC:
ret = -EINVAL; ret = -EINVAL;
......
...@@ -131,7 +131,7 @@ asmlinkage long sys_uselib(const char * library) ...@@ -131,7 +131,7 @@ asmlinkage long sys_uselib(const char * library)
goto out; goto out;
error = -ENOEXEC; error = -ENOEXEC;
if(file->f_op && file->f_op->read) { if(file->f_op) {
struct linux_binfmt * fmt; struct linux_binfmt * fmt;
read_lock(&binfmt_lock); read_lock(&binfmt_lock);
...@@ -452,19 +452,16 @@ struct file *open_exec(const char *name) ...@@ -452,19 +452,16 @@ struct file *open_exec(const char *name)
} }
int kernel_read(struct file *file, unsigned long offset, int kernel_read(struct file *file, unsigned long offset,
char * addr, unsigned long count) char *addr, unsigned long count)
{ {
mm_segment_t old_fs; mm_segment_t old_fs;
loff_t pos = offset; loff_t pos = offset;
int result = -ENOSYS; int result;
if (!file->f_op->read)
goto fail;
old_fs = get_fs(); old_fs = get_fs();
set_fs(get_ds()); set_fs(get_ds());
result = file->f_op->read(file, addr, count, &pos); result = vfs_read(file, addr, count, &pos);
set_fs(old_fs); set_fs(old_fs);
fail:
return result; return result;
} }
......
...@@ -41,6 +41,8 @@ struct file_operations ext2_file_operations = { ...@@ -41,6 +41,8 @@ struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_file_read, .read = generic_file_read,
.write = generic_file_write, .write = generic_file_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.ioctl = ext2_ioctl, .ioctl = ext2_ioctl,
.mmap = generic_file_mmap, .mmap = generic_file_mmap,
.open = generic_file_open, .open = generic_file_open,
......
...@@ -58,8 +58,9 @@ static int ext3_open_file (struct inode * inode, struct file * filp) ...@@ -58,8 +58,9 @@ static int ext3_open_file (struct inode * inode, struct file * filp)
*/ */
static ssize_t static ssize_t
ext3_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ext3_file_write(struct kiocb *iocb, const char *buf, size_t count, loff_t pos)
{ {
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = file->f_dentry->d_inode;
/* /*
...@@ -72,13 +73,15 @@ ext3_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -72,13 +73,15 @@ ext3_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
if (IS_SYNC(inode) || (file->f_flags & O_SYNC)) if (IS_SYNC(inode) || (file->f_flags & O_SYNC))
mark_inode_dirty(inode); mark_inode_dirty(inode);
return generic_file_write(file, buf, count, ppos); return generic_file_aio_write(iocb, buf, count, pos);
} }
struct file_operations ext3_file_operations = { struct file_operations ext3_file_operations = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_file_read, .read = do_sync_read,
.write = ext3_file_write, .write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = ext3_file_write,
.readv = generic_file_readv, .readv = generic_file_readv,
.writev = generic_file_writev, .writev = generic_file_writev,
.ioctl = ext3_ioctl, .ioctl = ext3_ioctl,
......
...@@ -35,15 +35,17 @@ ...@@ -35,15 +35,17 @@
#define NFSDBG_FACILITY NFSDBG_FILE #define NFSDBG_FACILITY NFSDBG_FILE
static int nfs_file_mmap(struct file *, struct vm_area_struct *); static int nfs_file_mmap(struct file *, struct vm_area_struct *);
static ssize_t nfs_file_read(struct file *, char *, size_t, loff_t *); static ssize_t nfs_file_read(struct kiocb *, char *, size_t, loff_t);
static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *); static ssize_t nfs_file_write(struct kiocb *, const char *, size_t, loff_t);
static int nfs_file_flush(struct file *); static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
struct file_operations nfs_file_operations = { struct file_operations nfs_file_operations = {
.llseek = remote_llseek, .llseek = remote_llseek,
.read = nfs_file_read, .read = do_sync_read,
.write = nfs_file_write, .write = do_sync_write,
.aio_read = nfs_file_read,
.aio_write = nfs_file_write,
.mmap = nfs_file_mmap, .mmap = nfs_file_mmap,
.open = nfs_open, .open = nfs_open,
.flush = nfs_file_flush, .flush = nfs_file_flush,
...@@ -89,19 +91,19 @@ nfs_file_flush(struct file *file) ...@@ -89,19 +91,19 @@ nfs_file_flush(struct file *file)
} }
static ssize_t static ssize_t
nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos) nfs_file_read(struct kiocb *iocb, char * buf, size_t count, loff_t pos)
{ {
struct dentry * dentry = file->f_dentry; struct dentry * dentry = iocb->ki_filp->f_dentry;
struct inode * inode = dentry->d_inode; struct inode * inode = dentry->d_inode;
ssize_t result; ssize_t result;
dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n", dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long) *ppos); (unsigned long) count, (unsigned long) pos);
result = nfs_revalidate_inode(NFS_SERVER(inode), inode); result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
if (!result) if (!result)
result = generic_file_read(file, buf, count, ppos); result = generic_file_aio_read(iocb, buf, count, pos);
return result; return result;
} }
...@@ -206,15 +208,15 @@ struct address_space_operations nfs_file_aops = { ...@@ -206,15 +208,15 @@ struct address_space_operations nfs_file_aops = {
* Write to a file (through the page cache). * Write to a file (through the page cache).
*/ */
static ssize_t static ssize_t
nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) nfs_file_write(struct kiocb *iocb, const char *buf, size_t count, loff_t pos)
{ {
struct dentry * dentry = file->f_dentry; struct dentry * dentry = iocb->ki_filp->f_dentry;
struct inode * inode = dentry->d_inode; struct inode * inode = dentry->d_inode;
ssize_t result; ssize_t result;
dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n", dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n",
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name,
inode->i_ino, (unsigned long) count, (unsigned long) *ppos); inode->i_ino, (unsigned long) count, (unsigned long) pos);
result = -EBUSY; result = -EBUSY;
if (IS_SWAPFILE(inode)) if (IS_SWAPFILE(inode))
...@@ -227,7 +229,7 @@ nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) ...@@ -227,7 +229,7 @@ nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
if (!count) if (!count)
goto out; goto out;
result = generic_file_write(file, buf, count, ppos); result = generic_file_aio_write(iocb, buf, count, pos);
out: out:
return result; return result;
......
...@@ -176,6 +176,20 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, ...@@ -176,6 +176,20 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
} }
#endif #endif
ssize_t do_sync_read(struct file *filp, char *buf, size_t len, loff_t *ppos)
{
struct kiocb kiocb;
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
return ret;
}
ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos) ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos)
{ {
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = file->f_dentry->d_inode;
...@@ -183,14 +197,17 @@ ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos) ...@@ -183,14 +197,17 @@ ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos)
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))
return -EBADF; return -EBADF;
if (!file->f_op || !file->f_op->read) if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
return -EINVAL; return -EINVAL;
ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count); ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count);
if (!ret) { if (!ret) {
ret = security_ops->file_permission (file, MAY_READ); ret = security_ops->file_permission (file, MAY_READ);
if (!ret) { if (!ret) {
if (file->f_op->read)
ret = file->f_op->read(file, buf, count, pos); ret = file->f_op->read(file, buf, count, pos);
else
ret = do_sync_read(file, buf, count, pos);
if (ret > 0) if (ret > 0)
dnotify_parent(file->f_dentry, DN_ACCESS); dnotify_parent(file->f_dentry, DN_ACCESS);
} }
...@@ -199,6 +216,20 @@ ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos) ...@@ -199,6 +216,20 @@ ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos)
return ret; return ret;
} }
ssize_t do_sync_write(struct file *filp, const char *buf, size_t len, loff_t *ppos)
{
struct kiocb kiocb;
ssize_t ret;
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
return ret;
}
ssize_t vfs_write(struct file *file, const char *buf, size_t count, loff_t *pos) ssize_t vfs_write(struct file *file, const char *buf, size_t count, loff_t *pos)
{ {
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = file->f_dentry->d_inode;
...@@ -206,14 +237,17 @@ ssize_t vfs_write(struct file *file, const char *buf, size_t count, loff_t *pos) ...@@ -206,14 +237,17 @@ ssize_t vfs_write(struct file *file, const char *buf, size_t count, loff_t *pos)
if (!(file->f_mode & FMODE_WRITE)) if (!(file->f_mode & FMODE_WRITE))
return -EBADF; return -EBADF;
if (!file->f_op || !file->f_op->write) if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
return -EINVAL; return -EINVAL;
ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count); ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count);
if (!ret) { if (!ret) {
ret = security_ops->file_permission (file, MAY_WRITE); ret = security_ops->file_permission (file, MAY_WRITE);
if (!ret) { if (!ret) {
if (file->f_op->write)
ret = file->f_op->write(file, buf, count, pos); ret = file->f_op->write(file, buf, count, pos);
else
ret = do_sync_write(file, buf, count, pos);
if (ret > 0) if (ret > 0)
dnotify_parent(file->f_dentry, DN_MODIFY); dnotify_parent(file->f_dentry, DN_MODIFY);
} }
......
...@@ -37,6 +37,7 @@ struct kiocb { ...@@ -37,6 +37,7 @@ struct kiocb {
void *ki_data; /* for use by the the file */ void *ki_data; /* for use by the the file */
void *ki_user_obj; /* pointer to userland's iocb */ void *ki_user_obj; /* pointer to userland's iocb */
__u64 ki_user_data; /* user's data for completion */ __u64 ki_user_data; /* user's data for completion */
loff_t ki_pos;
long private[KIOCB_PRIVATE_SIZE/sizeof(long)]; long private[KIOCB_PRIVATE_SIZE/sizeof(long)];
}; };
......
...@@ -751,7 +751,7 @@ struct file_operations { ...@@ -751,7 +751,7 @@ struct file_operations {
ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, char *, size_t, loff_t); ssize_t (*aio_read) (struct kiocb *, char *, size_t, loff_t);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
ssize_t (*aio_write) (struct kiocb *, char *, size_t, loff_t); ssize_t (*aio_write) (struct kiocb *, const char *, size_t, loff_t);
int (*readdir) (struct file *, void *, filldir_t); int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *); unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
...@@ -1243,6 +1243,10 @@ extern int generic_file_mmap(struct file *, struct vm_area_struct *); ...@@ -1243,6 +1243,10 @@ extern int generic_file_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_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *); extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *); extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
extern ssize_t generic_file_aio_read(struct kiocb *, char *, size_t, loff_t);
extern ssize_t generic_file_aio_write(struct kiocb *, const char *, size_t, loff_t);
extern ssize_t do_sync_read(struct file *filp, char *buf, size_t len, loff_t *ppos);
extern ssize_t do_sync_write(struct file *filp, const char *buf, size_t len, loff_t *ppos);
ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov, ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *ppos); unsigned long nr_segs, loff_t *ppos);
extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t); extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t);
......
...@@ -1206,11 +1206,12 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, ...@@ -1206,11 +1206,12 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
} }
ssize_t ssize_t
generic_file_aio_read(struct kiocb *iocb, char *buf, size_t count, loff_t *ppos) generic_file_aio_read(struct kiocb *iocb, char *buf, size_t count, loff_t pos)
{ {
struct iovec local_iov = { .iov_base = buf, .iov_len = count }; struct iovec local_iov = { .iov_base = buf, .iov_len = count };
return __generic_file_aio_read(iocb, &local_iov, 1, ppos); BUG_ON(iocb->ki_pos != pos);
return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
} }
ssize_t ssize_t
...@@ -1966,6 +1967,12 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov, ...@@ -1966,6 +1967,12 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
return err; return err;
} }
ssize_t generic_file_aio_write(struct kiocb *iocb, const char *buf,
size_t count, loff_t pos)
{
return generic_file_write(iocb->ki_filp, buf, count, &iocb->ki_pos);
}
ssize_t generic_file_write(struct file *file, const char *buf, ssize_t generic_file_write(struct file *file, const char *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment