static void io_poll_complete_work(struct io_wq_work **workptr)
{
	struct io_wq_work *work = *workptr;
	struct io_kiocb *req = container_of(work, struct io_kiocb, work);
	struct io_poll_iocb *poll = &req->poll;
	struct poll_table_struct pt = { ._key = poll->events };
	struct io_ring_ctx *ctx = req->ctx;
	struct io_kiocb *nxt = NULL;
	__poll_t mask = 0;
	int ret = 0;

	if (work->flags & IO_WQ_WORK_CANCEL) {
		WRITE_ONCE(poll->canceled, true);
		ret = -ECANCELED;
	} else if (READ_ONCE(poll->canceled)) {
		ret = -ECANCELED;
	}

	if (ret != -ECANCELED)
		mask = vfs_poll(poll->file, &pt) & poll->events;

	/*
	 * Note that ->ki_cancel callers also delete iocb from active_reqs after
	 * calling ->ki_cancel.  We need the ctx_lock roundtrip here to
	 * synchronize with them.  In the cancellation case the list_del_init
	 * itself is not actually needed, but harmless so we keep it in to
	 * avoid further branches in the fast path.
	 */
	spin_lock_irq(&ctx->completion_lock);
	if (!mask && ret != -ECANCELED) {
		add_wait_queue(poll->head, &poll->wait);
		spin_unlock_irq(&ctx->completion_lock);
		return;
	}
	hash_del(&req->hash_node);
	io_poll_complete(req, mask, ret);
	spin_unlock_irq(&ctx->completion_lock);

	io_cqring_ev_posted(ctx);

	if (ret < 0)
		req_set_fail_links(req);
	io_put_req_find_next(req, &nxt);
	if (nxt)
		io_wq_assign_next(workptr, nxt);
}
static void io_poll_complete_work(struct io_wq_work **workptr)
{
	struct io_wq_work *work = *workptr;
	struct io_kiocb *req = container_of(work, struct io_kiocb, work);
	struct io_poll_iocb *poll = &req->poll;
	struct poll_table_struct pt = { ._key = poll->events };
	struct io_ring_ctx *ctx = req->ctx;
	struct io_kiocb *nxt = NULL;
	__poll_t mask = 0;
	int ret = 0;

	if (work->flags & IO_WQ_WORK_CANCEL) {
		WRITE_ONCE(poll->canceled, true);
		ret = -ECANCELED;
	} else if (READ_ONCE(poll->canceled)) {
		ret = -ECANCELED;
	}

	if (ret != -ECANCELED)
		mask = vfs_poll(poll->file, &pt) & poll->events;

	 
	spin_lock_irq(&ctx->completion_lock);
	if (!mask && ret != -ECANCELED) {
		add_wait_queue(poll->head, &poll->wait);
		spin_unlock_irq(&ctx->completion_lock);
		return;
	}
	hash_del(&req->hash_node);
	io_poll_complete(req, mask, ret);
	spin_unlock_irq(&ctx->completion_lock);

	io_cqring_ev_posted(ctx);

	if (ret < 0)
		req_set_fail_links(req);
	io_put_req_find_next(req, &nxt);
	if (nxt)
		io_wq_assign_next(workptr, nxt);
}