@@ -191,6 +191,9 @@ struct aio_kiocb {
struct iov_iter ki_iter;
struct iovec *ki_iovec;
struct iovec ki_inline_vecs[UIO_FASTIOV];
+
+ /* Fields used for threaded aio helper. */
+ struct task_struct *ki_submit_task;
};
/*------ sysctl variables----*/
@@ -586,6 +589,17 @@ struct mm_struct *aio_get_mm(struct kiocb *req)
return NULL;
}
+struct task_struct *aio_get_task(struct kiocb *req)
+{
+ if (req->ki_complete == aio_complete) {
+ struct aio_kiocb *iocb;
+
+ iocb = container_of(req, struct aio_kiocb, common);
+ return iocb->ki_submit_task;
+ }
+ return current;
+}
+
static void free_ioctx(struct work_struct *work)
{
struct kioctx *ctx = container_of(work, struct kioctx, free_work);
@@ -1045,6 +1059,8 @@ static void kiocb_free(struct aio_kiocb *req)
eventfd_ctx_put(req->ki_eventfd);
if (req->ki_iovec != req->ki_inline_vecs)
kfree(req->ki_iovec);
+ if (req->ki_submit_task)
+ put_task_struct(req->ki_submit_task);
kmem_cache_free(kiocb_cachep, req);
}
@@ -18,6 +18,7 @@ extern long do_io_submit(aio_context_t ctx_id, long nr,
struct iocb __user *__user *iocbpp, bool compat);
void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
struct mm_struct *aio_get_mm(struct kiocb *req);
+struct task_struct *aio_get_task(struct kiocb *req);
#else
static inline void exit_aio(struct mm_struct *mm) { }
static inline long do_io_submit(aio_context_t ctx_id, long nr,
@@ -26,6 +27,8 @@ static inline long do_io_submit(aio_context_t ctx_id, long nr,
static inline void kiocb_set_cancel_fn(struct kiocb *req,
kiocb_cancel_fn *cancel) { }
static inline struct mm_struct *aio_get_mm(struct kiocb *req) { return NULL; }
+static inline struct task_struct *aio_get_task(struct kiocb *req)
+{ return current; }
#endif /* CONFIG_AIO */
/* for sysctl: */
@@ -1633,6 +1633,11 @@ struct task_struct {
/* journalling filesystem info */
void *journal_info;
+/* threaded aio info */
+#if IS_ENABLED(CONFIG_AIO)
+ struct kiocb *kiocb;
+#endif
+
/* stacked block device info */
struct bio_list *bio_list;
@@ -34,6 +34,7 @@
#include <linux/compat.h>
#include <linux/cn_proc.h>
#include <linux/compiler.h>
+#include <linux/aio.h>
#define CREATE_TRACE_POINTS
#include <trace/events/signal.h>
@@ -1432,7 +1433,12 @@ int send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
*/
int io_send_sig(int sig)
{
- return send_sig(sig, current, 0);
+ struct task_struct *task = current;
+#if IS_ENABLED(CONFIG_AIO)
+ if (task->kiocb)
+ task = aio_get_task(task->kiocb);
+#endif
+ return send_sig(sig, task, 0);
}
EXPORT_SYMBOL(io_send_sig);