summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin LaHaise <bcrl@toomuch.toronto.redhat.com>2002-09-24 13:29:22 -0400
committerBenjamin LaHaise <bcrl@toomuch.toronto.redhat.com>2002-09-24 13:29:22 -0400
commite828d70905ec36f915f98de213e0abe8a64dc3bf (patch)
tree9c6ff3f5dc5d6af475b3ca3b05cd50d9602ccc3a
parentd3eee8ac7ef0d88f2d3d312991850848d57f1e49 (diff)
several updates for testing aio_{read,write}
support for file descriptors with only async ops in vfs_{read,write}
-rw-r--r--fs/aio.c5
-rw-r--r--fs/exec.c11
-rw-r--r--fs/ext2/file.c2
-rw-r--r--fs/ext3/file.c11
-rw-r--r--fs/nfs/file.c26
-rw-r--r--fs/read_write.c42
-rw-r--r--include/linux/aio.h1
-rw-r--r--include/linux/fs.h6
-rw-r--r--mm/filemap.c11
9 files changed, 83 insertions, 32 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 8ea30ef3c906..5a58beceffe7 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -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_data = iocb->aio_data;
+ req->ki_pos = iocb->aio_offset;
buf = (char *)(unsigned long)iocb->aio_buf;
@@ -949,7 +950,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
ret = -EINVAL;
if (file->f_op->aio_read)
ret = file->f_op->aio_read(req, buf,
- iocb->aio_nbytes, iocb->aio_offset);
+ iocb->aio_nbytes, req->ki_pos);
break;
case IOCB_CMD_PWRITE:
ret = -EBADF;
@@ -961,7 +962,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
ret = -EINVAL;
if (file->f_op->aio_write)
ret = file->f_op->aio_write(req, buf,
- iocb->aio_nbytes, iocb->aio_offset);
+ iocb->aio_nbytes, req->ki_pos);
break;
case IOCB_CMD_FDSYNC:
ret = -EINVAL;
diff --git a/fs/exec.c b/fs/exec.c
index 21222017549d..dff548c08e5a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -131,7 +131,7 @@ asmlinkage long sys_uselib(const char * library)
goto out;
error = -ENOEXEC;
- if(file->f_op && file->f_op->read) {
+ if(file->f_op) {
struct linux_binfmt * fmt;
read_lock(&binfmt_lock);
@@ -452,19 +452,16 @@ out:
}
int kernel_read(struct file *file, unsigned long offset,
- char * addr, unsigned long count)
+ char *addr, unsigned long count)
{
mm_segment_t old_fs;
loff_t pos = offset;
- int result = -ENOSYS;
+ int result;
- if (!file->f_op->read)
- goto fail;
old_fs = get_fs();
set_fs(get_ds());
- result = file->f_op->read(file, addr, count, &pos);
+ result = vfs_read(file, addr, count, &pos);
set_fs(old_fs);
-fail:
return result;
}
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index aff333ae8e5a..2722dc183286 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -41,6 +41,8 @@ struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
+ .aio_read = generic_file_aio_read,
+ .aio_write = generic_file_aio_write,
.ioctl = ext2_ioctl,
.mmap = generic_file_mmap,
.open = generic_file_open,
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 6ea4b8a091b8..72f58cab014f 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -58,8 +58,9 @@ static int ext3_open_file (struct inode * inode, struct file * filp)
*/
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;
/*
@@ -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))
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 = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = ext3_file_write,
+ .read = do_sync_read,
+ .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,
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index b127eba61974..fcd18b4747eb 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -35,15 +35,17 @@
#define NFSDBG_FACILITY NFSDBG_FILE
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_write(struct file *, const 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 kiocb *, const char *, size_t, loff_t);
static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
struct file_operations nfs_file_operations = {
.llseek = remote_llseek,
- .read = nfs_file_read,
- .write = nfs_file_write,
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .aio_read = nfs_file_read,
+ .aio_write = nfs_file_write,
.mmap = nfs_file_mmap,
.open = nfs_open,
.flush = nfs_file_flush,
@@ -89,19 +91,19 @@ nfs_file_flush(struct file *file)
}
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;
ssize_t result;
dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
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);
if (!result)
- result = generic_file_read(file, buf, count, ppos);
+ result = generic_file_aio_read(iocb, buf, count, pos);
return result;
}
@@ -206,15 +208,15 @@ struct address_space_operations nfs_file_aops = {
* Write to a file (through the page cache).
*/
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;
ssize_t result;
dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n",
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;
if (IS_SWAPFILE(inode))
@@ -227,7 +229,7 @@ nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
if (!count)
goto out;
- result = generic_file_write(file, buf, count, ppos);
+ result = generic_file_aio_write(iocb, buf, count, pos);
out:
return result;
diff --git a/fs/read_write.c b/fs/read_write.c
index f7e525ce2cb5..2c2cc69465bb 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -176,6 +176,20 @@ bad:
}
#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)
{
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)
if (!(file->f_mode & FMODE_READ))
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;
ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count);
if (!ret) {
ret = security_ops->file_permission (file, MAY_READ);
if (!ret) {
- ret = file->f_op->read(file, buf, count, pos);
+ if (file->f_op->read)
+ ret = file->f_op->read(file, buf, count, pos);
+ else
+ ret = do_sync_read(file, buf, count, pos);
if (ret > 0)
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)
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)
{
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)
if (!(file->f_mode & FMODE_WRITE))
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;
ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count);
if (!ret) {
ret = security_ops->file_permission (file, MAY_WRITE);
if (!ret) {
- ret = file->f_op->write(file, buf, count, pos);
+ if (file->f_op->write)
+ ret = file->f_op->write(file, buf, count, pos);
+ else
+ ret = do_sync_write(file, buf, count, pos);
if (ret > 0)
dnotify_parent(file->f_dentry, DN_MODIFY);
}
diff --git a/include/linux/aio.h b/include/linux/aio.h
index c819f731e4a2..d4178237ed62 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -37,6 +37,7 @@ struct kiocb {
void *ki_data; /* for use by the the file */
void *ki_user_obj; /* pointer to userland's iocb */
__u64 ki_user_data; /* user's data for completion */
+ loff_t ki_pos;
long private[KIOCB_PRIVATE_SIZE/sizeof(long)];
};
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 56f2bab87d7f..ec3db44319e2 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -751,7 +751,7 @@ struct file_operations {
ssize_t (*read) (struct file *, 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 (*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);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
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 *);
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_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,
unsigned long nr_segs, loff_t *ppos);
extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t);
diff --git a/mm/filemap.c b/mm/filemap.c
index 9118a5794f27..3629b28e9e71 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1206,11 +1206,12 @@ out:
}
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 };
- 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
@@ -1966,6 +1967,12 @@ out:
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,
size_t count, loff_t *ppos)
{