On 11/22/18 4:13 AM, Jan Kara wrote: > > On Tue 20-11-18 10:19:53, Jens Axboe wrote: >> +/* >> + * We can't just wait for polled events to come to us, we have to actively >> + * find and complete them. >> + */ >> +static void aio_iopoll_reap_events(struct kioctx *ctx) >> +{ >> + if (!(ctx->flags & IOCTX_FLAG_IOPOLL)) >> + return; >> + >> + while (!list_empty_careful(&ctx->poll_submitted) || >> + !list_empty(&ctx->poll_completing)) { >> + unsigned int nr_events = 0; >> + >> + __aio_iopoll_check(ctx, NULL, &nr_events, 1, UINT_MAX); >> + } >> +} >> + >> +static int aio_iopoll_check(struct kioctx *ctx, long min_nr, long nr, >> + struct io_event __user *event) >> +{ >> + unsigned int nr_events = 0; >> + int ret = 0; >> + >> + /* * Only allow one thread polling at a time */ >> + if (test_and_set_bit(0, &ctx->getevents_busy)) >> + return -EBUSY; >> + >> + while (!nr_events || !need_resched()) { >> + int tmin = 0; >> + >> + if (nr_events < min_nr) >> + tmin = min_nr - nr_events; >> + >> + ret = __aio_iopoll_check(ctx, event, &nr_events, tmin, nr); >> + if (ret <= 0) >> + break; >> + ret = 0; >> + } >> + >> + clear_bit(0, &ctx->getevents_busy); >> + return nr_events ? nr_events : ret; >> +} > > Hum, what if userspace calls io_destroy() while another process is polling > for events on the same kioctx? It seems we'd be reaping events from two > processes in parallel in that case which will result in various > "interesting" effects like ctx->poll_completing list corruption...
I've replaced the ->getevents_busy with a mutex, and we also protect the ->dead check inside that mutex. That ensures that destroy can't proceed before a potential caller is inside getevents(), and that getevents() sees if the ctx is being destroyed. -- Jens Axboe