linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Zach Brown <zach.brown@oracle.com>
To: linux-fsdevel@vger.kernel.org
Subject: [PATCH 7/8] block: provide aio_read_pages and aio_write_pages
Date: Thu, 22 Oct 2009 13:25:56 -0700	[thread overview]
Message-ID: <1256243157-16667-8-git-send-email-zach.brown@oracle.com> (raw)
In-Reply-To: <1256243157-16667-7-git-send-email-zach.brown@oracle.com>

This adds functions which perform direct aio read and write on the specified
pages.  This is just a hack to prototype the surrounding code without having to
start with file systems.  It just copies the generic paths which are needed for
direct io to block devices.  It calls the __blockdev_direct_IO_pages() directly
instead of changing the ->direct_IO() prototype.

To do this properly we're going to have to weave support for specifying memory
with pages into the generic paths.  We could have one entry point which takes
an abstract memory argument and conditionals in the path for working on iovecs
or pages.  Or we could have entry points for each memory argument that call
helpers.

Signed-off-by: Zach Brown <zach.brown@oracle.com>
---
 fs/block_dev.c |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 9cf4b92..1a07574 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1436,6 +1436,117 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
 }
 EXPORT_SYMBOL_GPL(blkdev_aio_write);
 
+/* XXX did I miss an existing helper? _length() like iov_length().. */
+static ssize_t bvec_length(const struct bio_vec *bvec, unsigned long bvec_len)
+{
+	ssize_t bytes = 0;
+	BUG_ON(bvec_len == 0);
+	while (bvec_len--)
+		bytes += (bvec++)->bv_len;
+	return bytes;
+}
+
+/*
+ * A quick prototype for testing.  This has copied the direct reading path of
+ * raw_fops.aio_read which doesn't use iovecs.
+ */
+ssize_t blkdev_aio_read_pages(struct kiocb *iocb, const struct bio_vec *bvec,
+			      unsigned long bvec_len, loff_t pos)
+{
+	struct file *file = iocb->ki_filp;
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t ret;
+	size_t count;
+
+	BUG_ON(iocb->ki_pos != pos);
+
+	if (!(file->f_flags & O_DIRECT))
+		return -EINVAL;
+
+	if (pos >= i_size_read(inode))
+		return 0;
+
+	count = bvec_length(bvec, bvec_len);
+	if (!count)
+		return 0;
+
+	ret = filemap_write_and_wait_range(mapping, pos, pos + count - 1);
+	if (ret)
+		return ret;
+
+	ret = __blockdev_direct_IO_pages(READ, iocb, inode, I_BDEV(inode),
+					 bvec, bvec_len, pos,
+					 blkdev_get_blocks, NULL,
+					 DIO_NO_LOCKING);
+	if (ret)
+		file_accessed(file);
+	return ret;
+}
+
+/*
+ * A quick prototype for testing.  This has copied the direct writing path of
+ * raw_fops.aio_write which doesn't use iovecs.
+ */
+ssize_t blkdev_aio_write_pages(struct kiocb *iocb, const struct bio_vec *bvec,
+			       unsigned long bvec_len, loff_t pos)
+{
+	struct file *file = iocb->ki_filp;
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t ret;
+	size_t count;
+
+	BUG_ON(iocb->ki_pos != pos);
+
+	if (!(file->f_flags & O_DIRECT))
+		return -EINVAL;
+
+	vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+
+	count = bvec_length(bvec, bvec_len);
+
+	ret = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+	if (ret)
+		goto out;
+
+	if (!count)
+		return 0;
+
+	ret = file_remove_suid(file);
+	if (ret)
+		goto out;
+
+	file_update_time(file);
+
+	ret = filemap_write_and_wait_range(mapping, pos, pos + count - 1);
+	if (ret)
+		goto out;
+
+	if (mapping->nrpages) {
+		ret = invalidate_inode_pages2_range(mapping,
+					pos >> PAGE_CACHE_SHIFT, 
+					(pos + count - 1) >> PAGE_CACHE_SHIFT);
+		/* XXX this'll return -EBUSY when a page can't be validated
+		 * as we're not falling back to buffered */
+		if (ret)
+			goto out;
+	}
+
+	ret = __blockdev_direct_IO_pages(WRITE, iocb, inode, I_BDEV(inode),
+					 bvec, bvec_len, pos, blkdev_get_blocks,
+					 NULL, DIO_NO_LOCKING);
+	if (ret > 0 || ret == -EIOCBQUEUED) {
+		ssize_t err; 
+		
+		err = generic_write_sync(file, pos, ret > 0 ? ret : count);
+		if (err < 0 && ret > 0)
+			ret = err;
+	}
+out:
+	return ret;
+}
+
 /*
  * Try to release a page associated with block device when the system
  * is under memory pressure.
@@ -1477,6 +1588,8 @@ const struct file_operations def_blk_fops = {
 #endif
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
+  	.aio_read_pages	= blkdev_aio_read_pages,
+	.aio_write_pages	= blkdev_aio_write_pages,
 };
 
 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
-- 
1.6.2.5


  reply	other threads:[~2009-10-22 20:47 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-22 20:25 [RFC] loop: issue aio with pages Zach Brown
2009-10-22 20:25 ` [PATCH 1/8] gadgetfs: use schedule_work() instead of EIOCBRETRY Zach Brown
2009-10-22 20:25   ` [PATCH 2/8] aio: disable retry Zach Brown
2009-10-22 20:25     ` [PATCH 3/8] aio: add an interface to submit aio from the kernel Zach Brown
2009-10-22 20:25       ` [PATCH 4/8] aio: add aio_read_pages and aio_write_pages Zach Brown
2009-10-22 20:25         ` [PATCH 5/8] dio: refactor __blockdev_direct_IO() Zach Brown
2009-10-22 20:25           ` [PATCH 6/8] dio: add an entry point which takes pages Zach Brown
2009-10-22 20:25             ` Zach Brown [this message]
2009-10-22 20:25               ` [PATCH 8/8] loop: use aio to perform io on the underlying file Zach Brown
2009-10-27 16:01                 ` Jeff Moyer
2009-10-27 15:49             ` [PATCH 6/8] dio: add an entry point which takes pages Jeff Moyer
2009-10-27 17:50               ` Zach Brown
2009-10-27 15:39           ` [PATCH 5/8] dio: refactor __blockdev_direct_IO() Jeff Moyer
2009-10-26 16:17         ` [PATCH 4/8] aio: add aio_read_pages and aio_write_pages Jeff Moyer
2009-10-26 17:08           ` Jeff Moyer
2009-10-26 22:22             ` Zach Brown
2009-10-26 16:10       ` [PATCH 3/8] aio: add an interface to submit aio from the kernel Jeff Moyer
2009-10-26 22:21         ` Zach Brown
2009-10-25  7:37     ` [PATCH 2/8] aio: disable retry Christoph Hellwig
2009-10-26 22:15       ` Zach Brown
2009-10-26 16:00     ` Jeff Moyer
2009-10-26 15:57   ` [PATCH 1/8] gadgetfs: use schedule_work() instead of EIOCBRETRY Jeff Moyer
2009-10-25  7:36 ` [RFC] loop: issue aio with pages Christoph Hellwig
2009-10-26 22:13   ` Zach Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1256243157-16667-8-git-send-email-zach.brown@oracle.com \
    --to=zach.brown@oracle.com \
    --cc=linux-fsdevel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).