linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dave Kleikamp <dave.kleikamp@oracle.com>
To: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	Zach Brown <zab@zabbo.net>,
	"Maxim V. Patlasov" <mpatlasov@parallels.com>,
	Dave Kleikamp <dave.kleikamp@oracle.com>
Subject: [PATCH V6 12/30] aio: add aio_kernel_() interface
Date: Tue, 29 Jan 2013 10:23:25 -0600	[thread overview]
Message-ID: <1359476623-10544-13-git-send-email-dave.kleikamp@oracle.com> (raw)
In-Reply-To: <1359476623-10544-1-git-send-email-dave.kleikamp@oracle.com>

From: Zach Brown <zab@zabbo.net>

This adds an interface that lets kernel callers submit aio iocbs without
going through the user space syscalls.  This lets kernel callers avoid
the management limits and overhead of the context.  It will also let us
integrate aio operations with other kernel apis that the user space
interface doesn't have access to.

Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
Cc: Zach Brown <zab@zabbo.net>
---
 fs/aio.c            | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/aio.h | 15 +++++++++
 2 files changed, 107 insertions(+)

diff --git a/fs/aio.c b/fs/aio.c
index 71f613c..9a1a6fc 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -912,6 +912,10 @@ int aio_complete(struct kiocb *iocb, long res, long res2)
 		iocb->ki_users = 0;
 		wake_up_process(iocb->ki_obj.tsk);
 		return 1;
+	} else if (is_kernel_kiocb(iocb)) {
+		iocb->ki_obj.complete(iocb->ki_user_data, res);
+		aio_kernel_free(iocb);
+		return 0;
 	}
 
 	info = &ctx->ring_info;
@@ -1504,6 +1508,94 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
 	return 0;
 }
 
+ /*
+ * This allocates an iocb that will be used to submit and track completion of
+ * an IO that is issued from kernel space.
+ *
+ * The caller is expected to call the appropriate aio_kernel_init_() functions
+ * and then call aio_kernel_submit().  From that point forward progress is
+ * guaranteed by the file system aio method.  Eventually the caller's
+ * completion callback will be called.
+ *
+ * These iocbs are special.  They don't have a context, we don't limit the
+ * number pending, they can't be canceled, and can't be retried.  In the short
+ * term callers need to be careful not to call operations which might retry by
+ * only calling new ops which never add retry support.  In the long term
+ * retry-based AIO should be removed.
+ */
+struct kiocb *aio_kernel_alloc(gfp_t gfp)
+{
+	struct kiocb *iocb = kzalloc(sizeof(struct kiocb), gfp);
+	if (iocb)
+		iocb->ki_key = KIOCB_KERNEL_KEY;
+	return iocb;
+}
+EXPORT_SYMBOL_GPL(aio_kernel_alloc);
+
+void aio_kernel_free(struct kiocb *iocb)
+{
+	kfree(iocb);
+}
+EXPORT_SYMBOL_GPL(aio_kernel_free);
+
+/*
+ * ptr and count can be a buff and bytes or an iov and segs.
+ */
+void aio_kernel_init_rw(struct kiocb *iocb, struct file *filp,
+			unsigned short op, void *ptr, size_t nr, loff_t off)
+{
+	iocb->ki_filp = filp;
+	iocb->ki_opcode = op;
+	iocb->ki_buf = (char __user *)(unsigned long)ptr;
+	iocb->ki_left = nr;
+	iocb->ki_nbytes = nr;
+	iocb->ki_pos = off;
+}
+EXPORT_SYMBOL_GPL(aio_kernel_init_rw);
+
+void aio_kernel_init_callback(struct kiocb *iocb,
+			      void (*complete)(u64 user_data, long res),
+			      u64 user_data)
+{
+	iocb->ki_obj.complete = complete;
+	iocb->ki_user_data = user_data;
+}
+EXPORT_SYMBOL_GPL(aio_kernel_init_callback);
+
+/*
+ * The iocb is our responsibility once this is called.  The caller must not
+ * reference it.  This comes from aio_setup_iocb() modifying the iocb.
+ *
+ * Callers must be prepared for their iocb completion callback to be called the
+ * moment they enter this function.  The completion callback may be called from
+ * any context.
+ *
+ * Returns: 0: the iocb completion callback will be called with the op result
+ * negative errno: the operation was not submitted and the iocb was freed
+ */
+int aio_kernel_submit(struct kiocb *iocb)
+{
+	int ret;
+
+	BUG_ON(!is_kernel_kiocb(iocb));
+	BUG_ON(!iocb->ki_obj.complete);
+	BUG_ON(!iocb->ki_filp);
+
+	ret = aio_setup_iocb(iocb, 0);
+	if (ret) {
+		aio_kernel_free(iocb);
+		return ret;
+	}
+
+	ret = iocb->ki_retry(iocb);
+	BUG_ON(ret == -EIOCBRETRY);
+	if (ret != -EIOCBQUEUED)
+		aio_complete(iocb, ret, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(aio_kernel_submit);
+
 static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 			 struct iocb *iocb, struct kiocb_batch *batch,
 			 bool compat)
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 31ff6db..f9e0292 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -24,6 +24,7 @@ struct kioctx;
 #define KIOCB_C_COMPLETE	0x02
 
 #define KIOCB_SYNC_KEY		(~0U)
+#define KIOCB_KERNEL_KEY		(~1U)
 
 /* ki_flags bits */
 /*
@@ -99,6 +100,7 @@ struct kiocb {
 	union {
 		void __user		*user;
 		struct task_struct	*tsk;
+		void			(*complete)(u64 user_data, long res);
 	} ki_obj;
 
 	__u64			ki_user_data;	/* user's data for completion */
@@ -131,6 +133,11 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb)
 	return kiocb->ki_key == KIOCB_SYNC_KEY;
 }
 
+static inline bool is_kernel_kiocb(struct kiocb *kiocb)
+{
+	return kiocb->ki_key == KIOCB_KERNEL_KEY;
+}
+
 static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
 {
 	*kiocb = (struct kiocb) {
@@ -218,6 +225,14 @@ struct mm_struct;
 extern void exit_aio(struct mm_struct *mm);
 extern long do_io_submit(aio_context_t ctx_id, long nr,
 			 struct iocb __user *__user *iocbpp, bool compat);
+struct kiocb *aio_kernel_alloc(gfp_t gfp);
+void aio_kernel_free(struct kiocb *iocb);
+void aio_kernel_init_rw(struct kiocb *iocb, struct file *filp,
+			unsigned short op, void *ptr, size_t nr, loff_t off);
+void aio_kernel_init_callback(struct kiocb *iocb,
+			      void (*complete)(u64 user_data, long res),
+			      u64 user_data);
+int aio_kernel_submit(struct kiocb *iocb);
 #else
 static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
 static inline int aio_put_req(struct kiocb *iocb) { return 0; }
-- 
1.8.1.1


  parent reply	other threads:[~2013-01-29 16:24 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-29 16:23 [PATCH V6 00/30] loop: Issue O_DIRECT aio using bio_vec Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 01/30] iov_iter: move into its own file Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 02/30] iov_iter: iov_iter_copy_from_user() should use non-atomic copy Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 03/30] iov_iter: add copy_to_user support Dave Kleikamp
     [not found] ` <1359476623-10544-1-git-send-email-dave.kleikamp-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
2013-01-29 16:23   ` [PATCH V6 04/30] fuse: convert fuse to use iov_iter_copy_[to|from]_user Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 05/30] iov_iter: hide iovec details behind ops function pointers Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 06/30] iov_iter: add bvec support Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 07/30] iov_iter: add a shorten call Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 08/30] iov_iter: let callers extract iovecs and bio_vecs Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 09/30] dio: Convert direct_IO to use iov_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 10/30] dio: add bio_vec support to __blockdev_direct_IO() Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 11/30] fs: pull iov_iter use higher up the stack Dave Kleikamp
2013-01-29 16:23 ` Dave Kleikamp [this message]
2013-01-29 16:23 ` [PATCH V6 13/30] aio: add aio support for iov_iter arguments Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 14/30] bio: add bvec_length(), like iov_length() Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 15/30] loop: use aio to perform io on the underlying file Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 16/30] fs: create file_readable() and file_writable() functions Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 17/30] fs: use read_iter and write_iter rather than aio_read and aio_write Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 18/30] fs: add read_iter and write_iter to several file systems Dave Kleikamp
2013-02-01  7:51   ` Artem Bityutskiy
2013-02-01 20:40     ` Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 19/30] ocfs2: add support for read_iter, write_iter, and direct_IO_bvec Dave Kleikamp
2013-01-30  0:59   ` Joel Becker
2013-01-29 16:23 ` [PATCH V6 20/30] ext4: add support for read_iter and write_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 21/30] nfs: add support for read_iter, write_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 22/30] nfs: simplify swap Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 23/30] btrfs: add support for read_iter and write_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 24/30] block_dev: add support for read_iter, write_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 25/30] xfs: add support for read_iter and write_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 26/30] gfs2: Convert aio_read/write ops to read/write_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 27/30] udf: convert file ops from aio_read/write " Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 28/30] afs: add support for read_iter and write_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 29/30] ecrpytfs: Convert aio_read/write ops to read/write_iter Dave Kleikamp
2013-01-29 16:23 ` [PATCH V6 30/30] ubifs: convert file ops from aio_read/write " Dave Kleikamp
2013-01-29 18:42 ` [PATCH V6 00/30] loop: Issue O_DIRECT aio using bio_vec Jeff Moyer
2013-01-29 18:45   ` Dave Kleikamp
2013-01-30  3:22   ` Dave Kleikamp
2013-01-30 19:23     ` Jeff Moyer
2013-01-30 19:26       ` Dave Kleikamp
2013-02-18 21:42         ` Sedat Dilek
2013-02-18 22:14           ` Dave Kleikamp
2013-01-29 23:38 ` [PATCH V6 18/30] fs: add read_iter and write_iter to several file systems Dave Kleikamp
2013-01-30  0:52 ` Dave Kleikamp

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=1359476623-10544-13-git-send-email-dave.kleikamp@oracle.com \
    --to=dave.kleikamp@oracle.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpatlasov@parallels.com \
    --cc=viro@zeniv.linux.org.uk \
    --cc=zab@zabbo.net \
    /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).