On Tue, 2018-11-27 at 08:24 -0700, Jens Axboe wrote:
> On 11/27/18 2:53 AM, Benny Halevy wrote:
> > > @@ -818,11 +853,15 @@ static int kill_ioctx(struct mm_struct *mm, struct 
> > > kioctx *ctx,
> > >  {
> > >   struct kioctx_table *table;
> > >  
> > > + mutex_lock(&ctx->getevents_lock);
> > >   spin_lock(&mm->ioctx_lock);
> > >   if (atomic_xchg(&ctx->dead, 1)) {
> > >           spin_unlock(&mm->ioctx_lock);
> > > +         mutex_unlock(&ctx->getevents_lock);
> > >           return -EINVAL;
> > >   }
> > > + aio_iopoll_reap_events(ctx);
> > > + mutex_unlock(&ctx->getevents_lock);
> > 
> > Is it worth handling the mutex lock and calling aio_iopoll_reap_events
> > only if (ctx->flags & IOCTX_FLAG_IOPOLL)?  If so, testing it can be
> > removed from aio_iopoll_reap_events() (and maybe it could even
> > be open coded
> > here since this is its only call site apparently)
> 
> I don't think it really matters, this only happens when you tear down an
> io_context. FWIW, I think it's cleaner to retain the test in the
> function, not outside it.
> 
> > > @@ -1072,6 +1112,15 @@ static inline void iocb_put(struct aio_kiocb *iocb)
> > >   }
> > >  }
> > >  
> > > +static void iocb_put_many(struct kioctx *ctx, void **iocbs, int *nr)
> > > +{
> > > + if (nr) {
> > 
> > How can nr by NULL?
> > And what's the point of supporting this case?
> > Did you mean: if (*nr)?
> > (In this case, if safe to call the functions below with *nr==0,
> > I'm not sure it's worth optimizing... especially since this is a static
> > function and its callers make sure to call it only when *nr > 0)
> 
> Indeed, that should be if (*nr), thanks! The slub implementation of the
> bulk free complains if you pass in nr == 0. Outside of that, a single
> check should be better than checking in multiple spots.
> 

Cool. The compiler might also optimize it away when inlining this function
if the caller tests *nr for being non-zero too.

> > > @@ -1261,6 +1310,166 @@ static bool aio_read_events(struct kioctx *ctx, 
> > > long min_nr, long nr,
> > >   return ret < 0 || *i >= min_nr;
> > >  }
> > >  
> > > +#define AIO_IOPOLL_BATCH 8
> > > +
> > > +/*
> > > + * Process completed iocb iopoll entries, copying the result to 
> > > userspace.
> > > + */
> > > +static long aio_iopoll_reap(struct kioctx *ctx, struct io_event __user 
> > > *evs,
> > > +                     unsigned int *nr_events, long max)
> > > +{
> > > + void *iocbs[AIO_IOPOLL_BATCH];
> > > + struct aio_kiocb *iocb, *n;
> > > + int to_free = 0, ret = 0;
> > > +
> > > + list_for_each_entry_safe(iocb, n, &ctx->poll_completing, ki_list) {
> > > +         if (*nr_events == max)
> > 
> > *nr_events >= max would be safer.
> 
> I don't see how we can get there with it being larger than already, that
> would be a big bug if we fill more events than userspace asked for.
> 

Currently we indeed can't, but if the code changes in the future
and we do, this will reduce the damage - hence being safer (and it costs nothing
in terms of performance).

> > > @@ -1570,17 +1829,43 @@ static inline void aio_rw_done(struct kiocb *req, 
> > > ssize_t ret)
> > >   default:
> > >           req->ki_complete(req, ret, 0);
> > >   }
> > > +
> > 
> > nit: this hunk is probably unintentional
> 
> Looks like it, I'll kill it.
> 
> 

Reply via email to