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

Badari Pulavarty (pbadari@us.ibm.com)
Tue, 5 Nov 2002 17:01:42 -0800 (PST)


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/