--- x/include/linux/io_uring_types.h +++ y/include/linux/io_uring_types.h @@ -578,6 +578,7 @@ struct io_kiocb { struct io_kiocb *link; /* custom credentials, valid IFF REQ_F_CREDS is set */ const struct cred *creds; + struct file *poll_file; struct io_wq_work work; }; --- x/io_uring/io_uring.c +++ y/io_uring/io_uring.c @@ -976,6 +976,8 @@ static void __io_req_complete_post(struc io_put_kbuf_comp(req); io_dismantle_req(req); io_put_task(req->task, 1); + if (req->poll_file) + fput(req->poll_file); wq_list_add_head(&req->comp_list, &ctx->locked_free_list); ctx->locked_free_nr++; } @@ -1099,6 +1101,8 @@ __cold void io_free_req(struct io_kiocb io_req_put_rsrc(req); io_dismantle_req(req); io_put_task(req->task, 1); + if (req->poll_file) + fput(req->poll_file); spin_lock(&ctx->completion_lock); wq_list_add_head(&req->comp_list, &ctx->locked_free_list); @@ -2140,6 +2144,7 @@ static int io_init_req(struct io_ring_ct req->flags = sqe_flags = READ_ONCE(sqe->flags); req->cqe.user_data = READ_ONCE(sqe->user_data); req->file = NULL; + req->poll_file = NULL; req->rsrc_node = NULL; req->task = current; --- x/io_uring/poll.c +++ y/io_uring/poll.c @@ -714,6 +714,8 @@ int io_arm_poll_handler(struct io_kiocb io_kbuf_recycle(req, issue_flags); + get_file(req->file); + req->poll_file = req->file; ret = __io_arm_poll_handler(req, &apoll->poll, &ipt, mask, issue_flags); if (ret) return ret > 0 ? IO_APOLL_READY : IO_APOLL_ABORTED; @@ -943,6 +945,8 @@ int io_poll_add(struct io_kiocb *req, un if (req->ctx->flags & (IORING_SETUP_SQPOLL|IORING_SETUP_SINGLE_ISSUER)) req->flags |= REQ_F_HASH_LOCKED; + get_file(req->file); + req->poll_file = req->file; ret = __io_arm_poll_handler(req, poll, &ipt, poll->events, issue_flags); if (ret > 0) { io_req_set_res(req, ipt.result_mask, 0);