Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

io_uring: add async data clear/free helpers

Futex recently had an issue where it mishandled how ->async_data and
REQ_F_ASYNC_DATA is handled. To avoid future issues like that, add a set
of helpers that either clear or clear-and-free the async data assigned
to a struct io_kiocb.

Convert existing manual handling of that to use the helpers. No intended
functional changes in this patch.

Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

+23 -22
+4 -9
io_uring/futex.c
··· 43 43 44 44 static void __io_futex_complete(struct io_kiocb *req, io_tw_token_t tw) 45 45 { 46 - req->async_data = NULL; 47 46 hlist_del_init(&req->hash_node); 48 47 io_req_task_complete(req, tw); 49 48 } ··· 53 54 54 55 io_tw_lock(ctx, tw); 55 56 io_cache_free(&ctx->futex_cache, req->async_data); 57 + io_req_async_data_clear(req, 0); 56 58 __io_futex_complete(req, tw); 57 59 } 58 60 ··· 72 72 io_req_set_res(req, res, 0); 73 73 } 74 74 75 - kfree(req->async_data); 76 - req->flags &= ~REQ_F_ASYNC_DATA; 75 + io_req_async_data_free(req); 77 76 __io_futex_complete(req, tw); 78 77 } 79 78 ··· 231 232 io_ring_submit_unlock(ctx, issue_flags); 232 233 req_set_fail(req); 233 234 io_req_set_res(req, ret, 0); 234 - kfree(futexv); 235 - req->async_data = NULL; 236 - req->flags &= ~REQ_F_ASYNC_DATA; 235 + io_req_async_data_free(req); 237 236 return IOU_COMPLETE; 238 237 } 239 238 ··· 307 310 if (ret < 0) 308 311 req_set_fail(req); 309 312 io_req_set_res(req, ret, 0); 310 - req->async_data = NULL; 311 - req->flags &= ~REQ_F_ASYNC_DATA; 312 - kfree(ifd); 313 + io_req_async_data_free(req); 313 314 return IOU_COMPLETE; 314 315 } 315 316
+13
io_uring/io_uring.h
··· 281 281 return req->flags & REQ_F_ASYNC_DATA; 282 282 } 283 283 284 + static inline void io_req_async_data_clear(struct io_kiocb *req, 285 + io_req_flags_t extra_flags) 286 + { 287 + req->flags &= ~(REQ_F_ASYNC_DATA|extra_flags); 288 + req->async_data = NULL; 289 + } 290 + 291 + static inline void io_req_async_data_free(struct io_kiocb *req) 292 + { 293 + kfree(req->async_data); 294 + io_req_async_data_clear(req, 0); 295 + } 296 + 284 297 static inline void io_put_file(struct io_kiocb *req) 285 298 { 286 299 if (!(req->flags & REQ_F_FIXED_FILE) && req->file)
+2 -4
io_uring/net.c
··· 178 178 if (hdr->vec.nr > IO_VEC_CACHE_SOFT_CAP) 179 179 io_vec_free(&hdr->vec); 180 180 181 - if (io_alloc_cache_put(&req->ctx->netmsg_cache, hdr)) { 182 - req->async_data = NULL; 183 - req->flags &= ~(REQ_F_ASYNC_DATA|REQ_F_NEED_CLEANUP); 184 - } 181 + if (io_alloc_cache_put(&req->ctx->netmsg_cache, hdr)) 182 + io_req_async_data_clear(req, REQ_F_NEED_CLEANUP); 185 183 } 186 184 187 185 static struct io_async_msghdr *io_msg_alloc_async(struct io_kiocb *req)
+2 -4
io_uring/rw.c
··· 154 154 if (rw->vec.nr > IO_VEC_CACHE_SOFT_CAP) 155 155 io_vec_free(&rw->vec); 156 156 157 - if (io_alloc_cache_put(&req->ctx->rw_cache, rw)) { 158 - req->async_data = NULL; 159 - req->flags &= ~REQ_F_ASYNC_DATA; 160 - } 157 + if (io_alloc_cache_put(&req->ctx->rw_cache, rw)) 158 + io_req_async_data_clear(req, 0); 161 159 } 162 160 163 161 static void io_req_rw_cleanup(struct io_kiocb *req, unsigned int issue_flags)
+1 -2
io_uring/uring_cmd.c
··· 37 37 38 38 if (io_alloc_cache_put(&req->ctx->cmd_cache, ac)) { 39 39 ioucmd->sqe = NULL; 40 - req->async_data = NULL; 41 - req->flags &= ~(REQ_F_ASYNC_DATA|REQ_F_NEED_CLEANUP); 40 + io_req_async_data_clear(req, REQ_F_NEED_CLEANUP); 42 41 } 43 42 } 44 43
+1 -3
io_uring/waitid.c
··· 37 37 struct io_waitid_async *iwa = req->async_data; 38 38 39 39 put_pid(iwa->wo.wo_pid); 40 - kfree(req->async_data); 41 - req->async_data = NULL; 42 - req->flags &= ~REQ_F_ASYNC_DATA; 40 + io_req_async_data_free(req); 43 41 } 44 42 45 43 static bool io_waitid_compat_copy_si(struct io_waitid *iw, int signo)