From: Zach Brown <zach.brown@oracle.com>
To: linux-fsdevel@vger.kernel.org
Subject: [PATCH 8/8] loop: use aio to perform io on the underlying file
Date: Thu, 22 Oct 2009 13:25:57 -0700 [thread overview]
Message-ID: <1256243157-16667-9-git-send-email-zach.brown@oracle.com> (raw)
In-Reply-To: <1256243157-16667-8-git-send-email-zach.brown@oracle.com>
This uses the new kernel aio interface to process loopback IO by submitting
concurrent direct aio. Previously loop's IO was serialized by synchronus
processing in a thread. It specifies io memory by directly referencing the
pages in the incoming bios rather than kmapping them.
This patch lets us start testing, but we should fix the following before its
merged:
* We might want to fall back to non-vectored ops if the file doesn't support
vectored ops.
* Talk to Jens about cleverly translating bio flags (like barriers?) down
to the bios that fs/direct-io.c is building based on our pages?
* More carefully discover support for and enable o_direct.
* Call into fs/aio.c to discover if aio is supported.
Signed-off-by: Zach Brown <zach.brown@oracle.com>
---
drivers/block/loop.c | 62 +++++++++++++++++++++++++++++++++++++++++++------
include/linux/loop.h | 1 +
2 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index edda9ea..1180808 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -267,6 +267,41 @@ fail:
goto out;
}
+void lo_rw_aio_complete(u64 data, long res)
+{
+ struct bio *bio = (struct bio *)data;
+
+ if (res > 0)
+ res = 0;
+ else if (res < 0)
+ res = -EIO;
+
+ bio_endio(bio, res);
+}
+
+static int lo_rw_aio(struct loop_device *lo, struct bio *bio, loff_t pos)
+{
+ struct file *file = lo->lo_backing_file;
+ struct kiocb *iocb;
+ unsigned short op;
+
+ iocb = aio_kernel_alloc(mapping_gfp_mask(file->f_mapping));
+ if (!iocb)
+ return -ENOMEM;
+
+ if (bio_rw(bio) & WRITE)
+ op = IOCB_CMD_PWRITEP;
+ else
+ op = IOCB_CMD_PREADP;
+
+ /* XXX can we just reference the bvec array like this? */
+ aio_kernel_init_rw(iocb, file, op, bio_iovec_idx(bio, bio->bi_idx),
+ bio_segments(bio), pos);
+ aio_kernel_init_callback(iocb, lo_rw_aio_complete, (u64)bio);
+
+ return aio_kernel_submit(iocb);
+}
+
/**
* __do_lo_send_write - helper for writing data to a loop device
*
@@ -467,13 +502,22 @@ lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
return ret;
}
-static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
+static void do_bio_filebacked(struct loop_device *lo, struct bio *bio)
{
loff_t pos;
int ret;
pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
+ if (lo->lo_flags & LO_FLAGS_USE_AIO && lo->transfer == transfer_none) {
+ ret = lo_rw_aio(lo, bio, pos);
+ if (ret) {
+ ret = -EIO;
+ goto out;
+ }
+ return;
+ }
+
if (bio_rw(bio) == WRITE) {
bool barrier = bio_rw_flagged(bio, BIO_RW_BARRIER);
struct file *file = lo->lo_backing_file;
@@ -502,7 +546,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
ret = lo_receive(lo, bio, lo->lo_blocksize, pos);
out:
- return ret;
+ bio_endio(bio, ret);
}
/*
@@ -570,10 +614,8 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
if (unlikely(!bio->bi_bdev)) {
do_loop_switch(lo, bio->bi_private);
bio_put(bio);
- } else {
- int ret = do_bio_filebacked(lo, bio);
- bio_endio(bio, ret);
- }
+ } else
+ do_bio_filebacked(lo, bio);
}
/*
@@ -784,9 +826,13 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
const struct address_space_operations *aops = mapping->a_ops;
- if (aops->write_begin)
+ if (file->f_op->aio_write_pages && file->f_op->aio_read_pages){
+ /* XXX dangerous hack */
+ file->f_flags |= O_DIRECT;
+ lo_flags |= LO_FLAGS_USE_AIO;
+ } else if (aops->write_begin)
lo_flags |= LO_FLAGS_USE_AOPS;
- if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
+ else if (!file->f_op->write)
lo_flags |= LO_FLAGS_READ_ONLY;
lo_blocksize = S_ISBLK(inode->i_mode) ?
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 66c194e..97a955c 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -76,6 +76,7 @@ enum {
LO_FLAGS_READ_ONLY = 1,
LO_FLAGS_USE_AOPS = 2,
LO_FLAGS_AUTOCLEAR = 4,
+ LO_FLAGS_USE_AIO = 8,
};
#include <asm/posix_types.h> /* for __kernel_old_dev_t */
--
1.6.2.5
next prev parent 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 ` [PATCH 7/8] block: provide aio_read_pages and aio_write_pages Zach Brown
2009-10-22 20:25 ` Zach Brown [this message]
2009-10-27 16:01 ` [PATCH 8/8] loop: use aio to perform io on the underlying file 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-9-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).