On 2/7/19 3:12 PM, Jeff Moyer wrote: > Hi, Jens, > >> +static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe) >> +{ > > [...] > >> + /* one for removal from waitqueue, one for this function */ >> + refcount_set(&req->refs, 2); >> + >> + mask = vfs_poll(poll->file, &ipt.pt) & poll->events; >> + if (unlikely(!poll->head)) { >> + /* we did not manage to set up a waitqueue, done */ >> + goto out; >> + } >> + >> + spin_lock_irq(&ctx->completion_lock); >> + spin_lock(&poll->head->lock); >> + if (poll->woken) { >> + /* wake_up context handles the rest */ >> + mask = 0; >> + ipt.error = 0; >> + } else if (mask || ipt.error) { >> + /* if we get an error or a mask we are done */ >> + WARN_ON_ONCE(list_empty(&poll->wait.entry)); >> + list_del_init(&poll->wait.entry); >> + } else { >> + /* actually waiting for an event */ >> + list_add_tail(&req->list, &ctx->cancel_list); >> + } >> + spin_unlock(&poll->head->lock); >> + spin_unlock_irq(&ctx->completion_lock); >> + >> +out: >> + if (unlikely(ipt.error)) { >> + if (!(flags & IOSQE_FIXED_FILE)) >> + fput(poll->file); >> + return ipt.error; >> + } > > You need to drop the reference count on the req inside that if block. Ah good point, because it's elevated. Fixed, thanks Jeff. -- Jens Axboe