On Sat, Oct 23, 2021 at 05:21:34PM +0100, Pavel Begunkov wrote: > --- a/block/fops.c > +++ b/block/fops.c > @@ -352,11 +352,21 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb, > bio->bi_end_io = blkdev_bio_end_io_async; > bio->bi_ioprio = iocb->ki_ioprio; > > - ret = bio_iov_iter_get_pages(bio, iter); > - if (unlikely(ret)) { > - bio->bi_status = BLK_STS_IOERR; > - bio_endio(bio); > - return ret; > + if (!iov_iter_is_bvec(iter)) { > + ret = bio_iov_iter_get_pages(bio, iter); > + if (unlikely(ret)) { > + bio->bi_status = BLK_STS_IOERR; > + bio_endio(bio); > + return ret; > + } Nit: I generally find it much nicer to read if simple if statements don't use pointless negations. > + } else { > + /* > + * Users don't rely on the iterator being in any particular > + * state for async I/O returning -EIOCBQUEUED, hence we can > + * avoid expensive iov_iter_advance(). Bypass > + * bio_iov_iter_get_pages() and set the bvec directly. > + */ > + bio_iov_bvec_set(bio, iter); So if this optimization is so useful, please also do it for non-bvec iov_iters, which is what 99% of the applications actually use.