]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
aio: add support for IOCB_CMD_POLL via aio thread helper
authorBenjamin LaHaise <bcrl@kvack.org>
Sun, 10 Jan 2016 23:00:10 +0000 (18:00 -0500)
committerBenjamin LaHaise <bcrl@kvack.org>
Sun, 10 Jan 2016 23:00:10 +0000 (18:00 -0500)
Applications that require a unified event loop occasionally have a need
to interface with libaries or other code that require notification on a
file descriptor becoming ready for read or write via poll.  Add support
for the aio poll operation to enable these use-cases by way of the thread
based aio helpers.

Signed-off-by: Benjamin LaHaise <ben.lahaise@solacesystems.com>
Signed-off-by: Benjamin LaHaise <bcrl@kvack.org>
fs/aio.c
include/uapi/linux/aio_abi.h

index a6427ef481fa936410d90871b517b031337c933c..56bcdf4105f4c76706bb4407cceca49698ef115b 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -200,6 +200,7 @@ struct aio_kiocb {
        struct task_struct      *ki_submit_task;
 #if IS_ENABLED(CONFIG_AIO_THREAD)
        struct task_struct      *ki_cancel_task;
+       unsigned long           ki_data;
        unsigned long           ki_rlimit_fsize;
        aio_thread_work_fn_t    ki_work_fn;
        struct work_struct      ki_work;
@@ -1662,6 +1663,40 @@ ssize_t generic_async_fsync(struct kiocb *iocb, int datasync)
                                                   : aio_thread_op_fsync, 0);
 }
 EXPORT_SYMBOL(generic_async_fsync);
+
+static long aio_thread_op_poll(struct aio_kiocb *iocb)
+{
+       struct file *file = iocb->common.ki_filp;
+       short events = iocb->ki_data;
+       struct poll_wqueues table;
+       unsigned int mask;
+       ssize_t ret = 0;
+
+       poll_initwait(&table);
+       events |= POLLERR | POLLHUP;
+
+       for (;;) {
+               mask = DEFAULT_POLLMASK;
+               if (file->f_op && file->f_op->poll) {
+                       table.pt._key = events;
+                       mask = file->f_op->poll(file, &table.pt);
+               }
+               /* Mask out unneeded events. */
+               mask &= events;
+               ret = mask;
+               if (mask)
+                       break;
+
+               ret = -EINTR;
+               if (signal_pending(current))
+                       break;
+
+               poll_schedule_timeout(&table, TASK_INTERRUPTIBLE, NULL, 0);
+       }
+
+       poll_freewait(&table);
+       return ret;
+}
 #endif /* IS_ENABLED(CONFIG_AIO_THREAD) */
 
 /*
@@ -1759,6 +1794,13 @@ rw_common:
 #endif
                break;
 
+       case IOCB_CMD_POLL:
+#if IS_ENABLED(CONFIG_AIO_THREAD)
+               if (aio_auto_threads & 1)
+                       ret = aio_thread_queue_iocb(req, aio_thread_op_poll, 0);
+#endif
+               break;
+
        default:
                pr_debug("EINVAL: no operation provided\n");
                break;
index bb2554f7fbd12a677015d48703ccf681357e84c6..7639fb14a9079066e5cf30482bdf578de5c5a5a1 100644 (file)
@@ -39,8 +39,8 @@ enum {
        IOCB_CMD_FDSYNC = 3,
        /* These two are experimental.
         * IOCB_CMD_PREADX = 4,
-        * IOCB_CMD_POLL = 5,
         */
+       IOCB_CMD_POLL = 5,
        IOCB_CMD_NOOP = 6,
        IOCB_CMD_PREADV = 7,
        IOCB_CMD_PWRITEV = 8,