11
11
#include "io_uring.h"
12
12
#include "rsrc.h"
13
13
#include "filetable.h"
14
+ #include "alloc_cache.h"
14
15
#include "msg_ring.h"
15
16
16
-
17
17
/* All valid masks for MSG_RING */
18
18
#define IORING_MSG_RING_MASK (IORING_MSG_RING_CQE_SKIP | \
19
19
IORING_MSG_RING_FLAGS_PASS)
@@ -68,59 +68,65 @@ void io_msg_ring_cleanup(struct io_kiocb *req)
68
68
69
69
static inline bool io_msg_need_remote (struct io_ring_ctx * target_ctx )
70
70
{
71
- if (!target_ctx -> task_complete )
72
- return false;
73
- return current != target_ctx -> submitter_task ;
71
+ return target_ctx -> task_complete ;
74
72
}
75
73
76
- static int io_msg_exec_remote (struct io_kiocb * req , task_work_func_t func )
74
+ static void io_msg_tw_complete (struct io_kiocb * req , struct io_tw_state * ts )
77
75
{
78
- struct io_ring_ctx * ctx = req -> file -> private_data ;
79
- struct io_msg * msg = io_kiocb_to_cmd (req , struct io_msg );
80
- struct task_struct * task = READ_ONCE (ctx -> submitter_task );
76
+ struct io_ring_ctx * ctx = req -> ctx ;
81
77
82
- if (unlikely (!task ))
83
- return - EOWNERDEAD ;
78
+ io_add_aux_cqe (ctx , req -> cqe .user_data , req -> cqe .res , req -> cqe .flags );
79
+ if (spin_trylock (& ctx -> msg_lock )) {
80
+ if (io_alloc_cache_put (& ctx -> msg_cache , req ))
81
+ req = NULL ;
82
+ spin_unlock (& ctx -> msg_lock );
83
+ }
84
+ if (req )
85
+ kfree (req );
86
+ percpu_ref_put (& ctx -> refs );
87
+ }
84
88
85
- init_task_work (& msg -> tw , func );
86
- if (task_work_add (task , & msg -> tw , TWA_SIGNAL ))
87
- return - EOWNERDEAD ;
89
+ static void io_msg_remote_post (struct io_ring_ctx * ctx , struct io_kiocb * req ,
90
+ int res , u32 cflags , u64 user_data )
91
+ {
92
+ req -> cqe .user_data = user_data ;
93
+ io_req_set_res (req , res , cflags );
94
+ percpu_ref_get (& ctx -> refs );
95
+ req -> ctx = ctx ;
96
+ req -> task = READ_ONCE (ctx -> submitter_task );
97
+ req -> io_task_work .func = io_msg_tw_complete ;
98
+ io_req_task_work_add_remote (req , ctx , IOU_F_TWQ_LAZY_WAKE );
99
+ }
88
100
89
- return IOU_ISSUE_SKIP_COMPLETE ;
101
+ static struct io_kiocb * io_msg_get_kiocb (struct io_ring_ctx * ctx )
102
+ {
103
+ struct io_kiocb * req = NULL ;
104
+
105
+ if (spin_trylock (& ctx -> msg_lock )) {
106
+ req = io_alloc_cache_get (& ctx -> msg_cache );
107
+ spin_unlock (& ctx -> msg_lock );
108
+ }
109
+ if (req )
110
+ return req ;
111
+ return kmem_cache_alloc (req_cachep , GFP_KERNEL | __GFP_NOWARN );
90
112
}
91
113
92
- static void io_msg_tw_complete (struct callback_head * head )
114
+ static int io_msg_data_remote (struct io_kiocb * req )
93
115
{
94
- struct io_msg * msg = container_of (head , struct io_msg , tw );
95
- struct io_kiocb * req = cmd_to_io_kiocb (msg );
96
116
struct io_ring_ctx * target_ctx = req -> file -> private_data ;
97
- int ret = 0 ;
98
-
99
- if (current -> flags & PF_EXITING ) {
100
- ret = - EOWNERDEAD ;
101
- } else {
102
- u32 flags = 0 ;
103
-
104
- if (msg -> flags & IORING_MSG_RING_FLAGS_PASS )
105
- flags = msg -> cqe_flags ;
106
-
107
- /*
108
- * If the target ring is using IOPOLL mode, then we need to be
109
- * holding the uring_lock for posting completions. Other ring
110
- * types rely on the regular completion locking, which is
111
- * handled while posting.
112
- */
113
- if (target_ctx -> flags & IORING_SETUP_IOPOLL )
114
- mutex_lock (& target_ctx -> uring_lock );
115
- if (!io_post_aux_cqe (target_ctx , msg -> user_data , msg -> len , flags ))
116
- ret = - EOVERFLOW ;
117
- if (target_ctx -> flags & IORING_SETUP_IOPOLL )
118
- mutex_unlock (& target_ctx -> uring_lock );
119
- }
117
+ struct io_msg * msg = io_kiocb_to_cmd (req , struct io_msg );
118
+ struct io_kiocb * target ;
119
+ u32 flags = 0 ;
120
120
121
- if (ret < 0 )
122
- req_set_fail (req );
123
- io_req_queue_tw_complete (req , ret );
121
+ target = io_msg_get_kiocb (req -> ctx );
122
+ if (unlikely (!target ))
123
+ return - ENOMEM ;
124
+
125
+ if (msg -> flags & IORING_MSG_RING_FLAGS_PASS )
126
+ flags = msg -> cqe_flags ;
127
+
128
+ io_msg_remote_post (target_ctx , target , msg -> len , flags , msg -> user_data );
129
+ return 0 ;
124
130
}
125
131
126
132
static int io_msg_ring_data (struct io_kiocb * req , unsigned int issue_flags )
@@ -138,7 +144,7 @@ static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags)
138
144
return - EBADFD ;
139
145
140
146
if (io_msg_need_remote (target_ctx ))
141
- return io_msg_exec_remote (req , io_msg_tw_complete );
147
+ return io_msg_data_remote (req );
142
148
143
149
if (msg -> flags & IORING_MSG_RING_FLAGS_PASS )
144
150
flags = msg -> cqe_flags ;
@@ -218,6 +224,22 @@ static void io_msg_tw_fd_complete(struct callback_head *head)
218
224
io_req_queue_tw_complete (req , ret );
219
225
}
220
226
227
+ static int io_msg_fd_remote (struct io_kiocb * req )
228
+ {
229
+ struct io_ring_ctx * ctx = req -> file -> private_data ;
230
+ struct io_msg * msg = io_kiocb_to_cmd (req , struct io_msg );
231
+ struct task_struct * task = READ_ONCE (ctx -> submitter_task );
232
+
233
+ if (unlikely (!task ))
234
+ return - EOWNERDEAD ;
235
+
236
+ init_task_work (& msg -> tw , io_msg_tw_fd_complete );
237
+ if (task_work_add (task , & msg -> tw , TWA_SIGNAL ))
238
+ return - EOWNERDEAD ;
239
+
240
+ return IOU_ISSUE_SKIP_COMPLETE ;
241
+ }
242
+
221
243
static int io_msg_send_fd (struct io_kiocb * req , unsigned int issue_flags )
222
244
{
223
245
struct io_ring_ctx * target_ctx = req -> file -> private_data ;
@@ -240,7 +262,7 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
240
262
}
241
263
242
264
if (io_msg_need_remote (target_ctx ))
243
- return io_msg_exec_remote (req , io_msg_tw_fd_complete );
265
+ return io_msg_fd_remote (req );
244
266
return io_msg_install_complete (req , issue_flags );
245
267
}
246
268
@@ -294,3 +316,10 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags)
294
316
io_req_set_res (req , ret , 0 );
295
317
return IOU_OK ;
296
318
}
319
+
320
+ void io_msg_cache_free (const void * entry )
321
+ {
322
+ struct io_kiocb * req = (struct io_kiocb * ) entry ;
323
+
324
+ kmem_cache_free (req_cachep , req );
325
+ }
0 commit comments