There are two paths that hit the done_unlock label in io_futex_wait(): the ENOMEM error path allocating ifd (via goto done_unlock) and the futex_wait_setup() error path (via a fallthrough). In the ENOMEM path, ifd is always NULL; in the futex_wait_setup() error path, it's always non-NULL. Move the done_unlock label so the goto skips the ifd freeing and the success path can free it unconditionally. This also avoids the need to initialize ifd before the io_cache_alloc() call, as it's only used if io_cache_alloc() succeeds. Signed-off-by: Caleb Sander Mateos --- io_uring/futex.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/io_uring/futex.c b/io_uring/futex.c index 9c7d384bab9b..e0cb815fd37a 100644 --- a/io_uring/futex.c +++ b/io_uring/futex.c @@ -317,11 +317,11 @@ int io_futexv_wait(struct io_kiocb *req, unsigned int issue_flags) int io_futex_wait(struct io_kiocb *req, unsigned int issue_flags) { struct io_futex *iof = io_kiocb_to_cmd(req, struct io_futex); struct io_ring_ctx *ctx = req->ctx; - struct io_futex_data *ifd = NULL; + struct io_futex_data *ifd; int ret; if (!iof->futex_mask) { ret = -EINVAL; goto done; @@ -349,16 +349,14 @@ int io_futex_wait(struct io_kiocb *req, unsigned int issue_flags) io_ring_submit_unlock(ctx, issue_flags); return IOU_ISSUE_SKIP_COMPLETE; } + /* As in io_futex_complete(), or failed arms would drain it. */ + io_cache_free(&ctx->futex_cache, ifd); + io_req_async_data_clear(req, 0); done_unlock: - if (ifd) { - /* As in io_futex_complete(), or failed arms would drain it. */ - io_cache_free(&ctx->futex_cache, ifd); - io_req_async_data_clear(req, 0); - } io_ring_submit_unlock(ctx, issue_flags); done: if (ret < 0) req_set_fail(req); io_req_set_res(req, ret, 0); -- 2.56.0