diff options
| author | Benjamin LaHaise <bcrl@toomuch.toronto.redhat.com> | 2002-09-24 13:29:22 -0400 |
|---|---|---|
| committer | Benjamin LaHaise <bcrl@toomuch.toronto.redhat.com> | 2002-09-24 13:29:22 -0400 |
| commit | e828d70905ec36f915f98de213e0abe8a64dc3bf (patch) | |
| tree | 9c6ff3f5dc5d6af475b3ca3b05cd50d9602ccc3a | |
| parent | d3eee8ac7ef0d88f2d3d312991850848d57f1e49 (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.c | 5 | ||||
| -rw-r--r-- | fs/exec.c | 11 | ||||
| -rw-r--r-- | fs/ext2/file.c | 2 | ||||
| -rw-r--r-- | fs/ext3/file.c | 11 | ||||
| -rw-r--r-- | fs/nfs/file.c | 26 | ||||
| -rw-r--r-- | fs/read_write.c | 42 | ||||
| -rw-r--r-- | include/linux/aio.h | 1 | ||||
| -rw-r--r-- | include/linux/fs.h | 6 | ||||
| -rw-r--r-- | mm/filemap.c | 11 |
9 files changed, 83 insertions, 32 deletions
@@ -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) { |
