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/