[PATCH 1/2] 2.5.46 AIO support for raw/O_DIRECT

From: Badari Pulavarty (pbadari@us.ibm.com)
Date: Tue Nov 05 2002 - 20:01:42 EST


Hi,

Here is (part 1/2) 2.5.46 patch to support AIO for raw/O_DIRECT.

This patch adds the infrastructure only. It does not make
DIO code Async. (part 2/2 does). Here is summary of what this
patch does:

1) Adds generic_file_aio_write_nolock() and makes all other
   generic_file_*_write() to use it.

2) Modifies generic_file_direct_IO() and ->direct_IO() functions
   to take "kiocb *" instead of "file *".

3) Renames generic_direct_IO() to blockdev_direct_IO().
        (Andrew's suggestion)

4) Moves generic_file_direct_IO() to mm/filemap.c
        (Andrew's suggestion)

5) Adds AIO read/write support for raw driver.

Any suggestions/comments ?

Thanks,
Badari

diff -Naur -X dontdiff linux-2.5.46/drivers/char/raw.c linux-2.5.46.aio/drivers/char/raw.c
--- linux-2.5.46/drivers/char/raw.c Mon Nov 4 14:30:33 2002
+++ linux-2.5.46.aio/drivers/char/raw.c Tue Nov 5 12:21:11 2002
@@ -213,9 +213,20 @@
         return generic_file_write_nolock(file, &local_iov, 1, ppos);
 }
 
+static ssize_t raw_file_aio_write(struct kiocb *iocb, const char *buf,
+ size_t count, loff_t pos)
+{
+ struct iovec local_iov = { .iov_base = (void *)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,
         .open = raw_open,
         .release= raw_release,
         .ioctl = raw_ioctl,
diff -Naur -X dontdiff linux-2.5.46/fs/block_dev.c linux-2.5.46.aio/fs/block_dev.c
--- linux-2.5.46/fs/block_dev.c Mon Nov 4 14:30:57 2002
+++ linux-2.5.46.aio/fs/block_dev.c Tue Nov 5 12:21:11 2002
@@ -115,12 +115,13 @@
 }
 
 static int
-blkdev_direct_IO(int rw, struct file *file, const struct iovec *iov,
+blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                         loff_t offset, unsigned long nr_segs)
 {
+ struct file *file = iocb->ki_filp;
         struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 
- return generic_direct_IO(rw, inode, inode->i_bdev, iov, offset,
+ return blockdev_direct_IO(rw, iocb, inode, inode->i_bdev, iov, offset,
                                 nr_segs, blkdev_get_blocks);
 }
 
diff -Naur -X dontdiff linux-2.5.46/fs/direct-io.c linux-2.5.46.aio/fs/direct-io.c
--- linux-2.5.46/fs/direct-io.c Mon Nov 4 14:30:31 2002
+++ linux-2.5.46.aio/fs/direct-io.c Tue Nov 5 12:21:11 2002
@@ -842,9 +842,9 @@
  * This is a library function for use by filesystem drivers.
  */
 int
-generic_direct_IO(int rw, struct inode *inode, struct block_device *bdev,
- const struct iovec *iov, loff_t offset, unsigned long nr_segs,
- get_blocks_t get_blocks)
+blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
+ struct block_device *bdev, const struct iovec *iov, loff_t offset,
+ unsigned long nr_segs, get_blocks_t get_blocks)
 {
         int seg;
         size_t size;
@@ -883,25 +883,3 @@
 out:
         return retval;
 }
-
-ssize_t
-generic_file_direct_IO(int rw, struct file *file, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
-{
- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
- ssize_t retval;
-
- if (mapping->nrpages) {
- retval = filemap_fdatawrite(mapping);
- if (retval == 0)
- retval = filemap_fdatawait(mapping);
- if (retval)
- goto out;
- }
-
- retval = mapping->a_ops->direct_IO(rw, file, iov, offset, nr_segs);
- if (rw == WRITE && mapping->nrpages)
- invalidate_inode_pages2(mapping);
-out:
- return retval;
-}
diff -Naur -X dontdiff linux-2.5.46/fs/ext2/inode.c linux-2.5.46.aio/fs/ext2/inode.c
--- linux-2.5.46/fs/ext2/inode.c Mon Nov 4 14:30:06 2002
+++ linux-2.5.46.aio/fs/ext2/inode.c Tue Nov 5 12:21:11 2002
@@ -630,12 +630,13 @@
 }
 
 static int
-ext2_direct_IO(int rw, struct file *file, const struct iovec *iov,
+ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                         loff_t offset, unsigned long nr_segs)
 {
+ struct file *file = iocb->ki_filp;
         struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 
- return generic_direct_IO(rw, inode, inode->i_sb->s_bdev, iov,
+ return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                 offset, nr_segs, ext2_get_blocks);
 }
 
diff -Naur -X dontdiff linux-2.5.46/fs/ext3/inode.c linux-2.5.46.aio/fs/ext3/inode.c
--- linux-2.5.46/fs/ext3/inode.c Mon Nov 4 14:30:36 2002
+++ linux-2.5.46.aio/fs/ext3/inode.c Tue Nov 5 12:21:11 2002
@@ -1411,10 +1411,11 @@
  * If the O_DIRECT write is intantiating holes inside i_size and the machine
  * crashes then stale disk data _may_ be exposed inside the file.
  */
-static int ext3_direct_IO(int rw, struct file *file,
+static int ext3_direct_IO(int rw, struct kiocb *iocb,
                         const struct iovec *iov, loff_t offset,
                         unsigned long nr_segs)
 {
+ struct file *file = iocb->ki_filp;
         struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
         struct ext3_inode_info *ei = EXT3_I(inode);
         handle_t *handle = NULL;
@@ -1443,8 +1444,8 @@
                 }
         }
 
- ret = generic_direct_IO(rw, inode, inode->i_sb->s_bdev, iov, offset,
- nr_segs, ext3_direct_io_get_blocks);
+ ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+ offset, nr_segs, ext3_direct_io_get_blocks);
 
 out_stop:
         if (handle) {
diff -Naur -X dontdiff linux-2.5.46/fs/jfs/inode.c linux-2.5.46.aio/fs/jfs/inode.c
--- linux-2.5.46/fs/jfs/inode.c Mon Nov 4 14:30:03 2002
+++ linux-2.5.46.aio/fs/jfs/inode.c Tue Nov 5 12:21:11 2002
@@ -310,12 +310,13 @@
         return generic_block_bmap(mapping, block, jfs_get_block);
 }
 
-static int jfs_direct_IO(int rw, struct file *file, const struct iovec *iov,
+static int jfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                         loff_t offset, unsigned long nr_segs)
 {
+ struct file *file = iocb->ki_filp;
         struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 
- return generic_direct_IO(rw, inode, inode->i_sb->s_bdev, iov,
+ return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                 offset, nr_segs, jfs_get_blocks);
 }
 
diff -Naur -X dontdiff linux-2.5.46/fs/xfs/linux/xfs_aops.c linux-2.5.46.aio/fs/xfs/linux/xfs_aops.c
--- linux-2.5.46/fs/xfs/linux/xfs_aops.c Mon Nov 4 14:30:50 2002
+++ linux-2.5.46.aio/fs/xfs/linux/xfs_aops.c Tue Nov 5 12:21:11 2002
@@ -600,14 +600,15 @@
 STATIC int
 linvfs_direct_IO(
         int rw,
- struct file *file,
+ struct kiocb *iocb,
         const struct iovec *iov,
         loff_t offset,
         unsigned long nr_segs)
 {
+ struct file *file = iocb->ki_filp;
         struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
 
- return generic_direct_IO(rw, inode, NULL,
+ return blockdev_direct_IO(rw, iocb, inode, NULL,
                         iov, offset, nr_segs, linvfs_get_blocks_direct);
 }
 
diff -Naur -X dontdiff linux-2.5.46/include/linux/fs.h linux-2.5.46.aio/include/linux/fs.h
--- linux-2.5.46/include/linux/fs.h Mon Nov 4 14:30:15 2002
+++ linux-2.5.46.aio/include/linux/fs.h Tue Nov 5 12:21:11 2002
@@ -282,6 +282,7 @@
 struct page;
 struct address_space;
 struct writeback_control;
+struct kiocb;
 
 struct address_space_operations {
         int (*writepage)(struct page *);
@@ -310,7 +311,7 @@
         sector_t (*bmap)(struct address_space *, sector_t);
         int (*invalidatepage) (struct page *, unsigned long);
         int (*releasepage) (struct page *, int);
- int (*direct_IO)(int, struct file *, const struct iovec *iov,
+ int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                         loff_t offset, unsigned long nr_segs);
 };
 
@@ -740,7 +741,6 @@
  * read, write, poll, fsync, readv, writev can be called
  * without the big kernel lock held in all filesystems.
  */
-struct kiocb;
 struct file_operations {
         struct module *owner;
         loff_t (*llseek) (struct file *, loff_t, int);
@@ -1250,6 +1250,8 @@
 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 generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
+ unsigned long, 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,
@@ -1259,10 +1261,11 @@
                                     loff_t *, read_descriptor_t *, read_actor_t);
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
-extern ssize_t generic_file_direct_IO(int rw, struct file *file,
+extern ssize_t generic_file_direct_IO(int rw, struct kiocb *iocb,
         const struct iovec *iov, loff_t offset, unsigned long nr_segs);
-extern int generic_direct_IO(int rw, struct inode *inode, struct block_device *bdev,
- const struct iovec *iov, loff_t offset, unsigned long nr_segs, get_blocks_t *get_blocks);
+extern int blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
+ struct block_device *bdev, const struct iovec *iov, loff_t offset,
+ unsigned long nr_segs, get_blocks_t *get_blocks);
 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,
diff -Naur -X dontdiff linux-2.5.46/kernel/ksyms.c linux-2.5.46.aio/kernel/ksyms.c
--- linux-2.5.46/kernel/ksyms.c Mon Nov 4 14:30:04 2002
+++ linux-2.5.46.aio/kernel/ksyms.c Tue Nov 5 12:21:11 2002
@@ -215,7 +215,7 @@
 EXPORT_SYMBOL(submit_bh);
 EXPORT_SYMBOL(unlock_buffer);
 EXPORT_SYMBOL(__wait_on_buffer);
-EXPORT_SYMBOL(generic_direct_IO);
+EXPORT_SYMBOL(blockdev_direct_IO);
 EXPORT_SYMBOL(block_write_full_page);
 EXPORT_SYMBOL(block_read_full_page);
 EXPORT_SYMBOL(block_prepare_write);
diff -Naur -X dontdiff linux-2.5.46/mm/filemap.c linux-2.5.46.aio/mm/filemap.c
--- linux-2.5.46/mm/filemap.c Mon Nov 4 14:30:18 2002
+++ linux-2.5.46.aio/mm/filemap.c Tue Nov 5 12:21:11 2002
@@ -812,7 +812,7 @@
                                 nr_segs = iov_shorten((struct iovec *)iov,
                                                         nr_segs, count);
                         }
- retval = generic_file_direct_IO(READ, filp,
+ retval = generic_file_direct_IO(READ, iocb,
                                         iov, pos, nr_segs);
                         if (retval > 0)
                                 *ppos = pos + retval;
@@ -1539,9 +1539,10 @@
  * okir@monad.swb.de
  */
 ssize_t
-generic_file_write_nolock(struct file *file, const struct iovec *iov,
+generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
                                 unsigned long nr_segs, loff_t *ppos)
 {
+ struct file *file = iocb->ki_filp;
         struct address_space * mapping = file->f_dentry->d_inode->i_mapping;
         struct address_space_operations *a_ops = mapping->a_ops;
         size_t ocount; /* original count */
@@ -1686,7 +1687,7 @@
                 if (count != ocount)
                         nr_segs = iov_shorten((struct iovec *)iov,
                                                 nr_segs, count);
- written = generic_file_direct_IO(WRITE, file,
+ written = generic_file_direct_IO(WRITE, iocb,
                                         iov, pos, nr_segs);
                 if (written > 0) {
                         loff_t end = pos + written;
@@ -1797,12 +1798,39 @@
         return err;
 }
 
+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);
+ 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_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);
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+ int err;
+ struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
+
+ BUG_ON(iocb->ki_pos != pos);
+
+ down(&inode->i_sem);
+ err = generic_file_aio_write_nolock(iocb, &local_iov, 1,
+ &iocb->ki_pos);
+ up(&inode->i_sem);
+
+ return err;
 }
 EXPORT_SYMBOL(generic_file_aio_write);
+EXPORT_SYMBOL(generic_file_aio_write_nolock);
 
 ssize_t generic_file_write(struct file *file, const char *buf,
                            size_t count, loff_t *ppos)
@@ -1842,3 +1870,26 @@
         up(&inode->i_sem);
         return ret;
 }
+
+ssize_t
+generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs)
+{
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+ ssize_t retval;
+
+ if (mapping->nrpages) {
+ retval = filemap_fdatawrite(mapping);
+ if (retval == 0)
+ retval = filemap_fdatawait(mapping);
+ if (retval)
+ goto out;
+ }
+
+ retval = mapping->a_ops->direct_IO(rw, iocb, iov, offset, nr_segs);
+ if (rw == WRITE && mapping->nrpages)
+ invalidate_inode_pages2(mapping);
+out:
+ return retval;
+}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Nov 07 2002 - 22:00:40 EST