|
@@ -30,6 +30,7 @@
|
|
|
#include <linux/highmem.h>
|
|
|
#include <linux/workqueue.h>
|
|
|
#include <linux/security.h>
|
|
|
+#include <linux/eventfd.h>
|
|
|
|
|
|
#include <asm/kmap_types.h>
|
|
|
#include <asm/uaccess.h>
|
|
@@ -417,6 +418,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
|
|
|
req->private = NULL;
|
|
|
req->ki_iovec = NULL;
|
|
|
INIT_LIST_HEAD(&req->ki_run_list);
|
|
|
+ req->ki_eventfd = ERR_PTR(-EINVAL);
|
|
|
|
|
|
/* Check if the completion queue has enough free space to
|
|
|
* accept an event from this io.
|
|
@@ -458,6 +460,8 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
|
|
|
{
|
|
|
assert_spin_locked(&ctx->ctx_lock);
|
|
|
|
|
|
+ if (!IS_ERR(req->ki_eventfd))
|
|
|
+ fput(req->ki_eventfd);
|
|
|
if (req->ki_dtor)
|
|
|
req->ki_dtor(req);
|
|
|
if (req->ki_iovec != &req->ki_inline_vec)
|
|
@@ -942,6 +946,14 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Check if the user asked us to deliver the result through an
|
|
|
+ * eventfd. The eventfd_signal() function is safe to be called
|
|
|
+ * from IRQ context.
|
|
|
+ */
|
|
|
+ if (!IS_ERR(iocb->ki_eventfd))
|
|
|
+ eventfd_signal(iocb->ki_eventfd, 1);
|
|
|
+
|
|
|
info = &ctx->ring_info;
|
|
|
|
|
|
/* add a completion event to the ring buffer.
|
|
@@ -1526,8 +1538,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
|
|
|
ssize_t ret;
|
|
|
|
|
|
/* enforce forwards compatibility on users */
|
|
|
- if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
|
|
|
- iocb->aio_reserved3)) {
|
|
|
+ if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2)) {
|
|
|
pr_debug("EINVAL: io_submit: reserve field set\n");
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -1551,6 +1562,19 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
|
|
|
fput(file);
|
|
|
return -EAGAIN;
|
|
|
}
|
|
|
+ if (iocb->aio_flags & IOCB_FLAG_RESFD) {
|
|
|
+ /*
|
|
|
+ * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
|
|
|
+ * instance of the file* now. The file descriptor must be
|
|
|
+ * an eventfd() fd, and will be signaled for each completed
|
|
|
+ * event using the eventfd_signal() function.
|
|
|
+ */
|
|
|
+ req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd);
|
|
|
+ if (unlikely(IS_ERR(req->ki_eventfd))) {
|
|
|
+ ret = PTR_ERR(req->ki_eventfd);
|
|
|
+ goto out_put_req;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
req->ki_filp = file;
|
|
|
ret = put_user(req->ki_key, &user_iocb->aio_key);
|