> -static int bio_map_user_iov(struct request *rq, struct iov_iter *iter, > +static struct bio *bio_map_get(struct request *rq, unsigned int nr_vecs, > gfp_t gfp_mask) bio_map_get is a very confusing name. And I also still think this is the wrong way to go. If plain slab allocations don't use proper per-cpu caches we have a MM problem and need to talk to the slab maintainers and not use the overkill bio_set here. > +/* Prepare bio for passthrough IO given an existing bvec iter */ > +int blk_rq_map_user_bvec(struct request *rq, struct iov_iter *iter) I'm a little confused about the interface we're trying to present from the block layer to the driver here. blk_rq_map_user_iov really should be able to detect that it is called on a bvec iter and just do the right thing rather than needing different helpers. > + /* > + * If the queue doesn't support SG gaps and adding this > + * offset would create a gap, disallow it. > + */ > + if (bvprvp && bvec_gap_to_prev(lim, bvprvp, bv->bv_offset)) > + goto out_err; So now you limit the input that is accepted? That's not really how iov_iters are used. We can either try to reshuffle the bvecs, or just fall back to the copy data version as blk_rq_map_user_iov does for 'weird' iters˙ > + > + /* check full condition */ > + if (nsegs >= nr_segs || bytes > UINT_MAX - bv->bv_len) > + goto out_err; > + > + if (bytes + bv->bv_len <= nr_iter && > + bv->bv_offset + bv->bv_len <= PAGE_SIZE) { > + nsegs++; > + bytes += bv->bv_len; > + } else > + goto out_err; Nit: This would read much better as: if (bytes + bv->bv_len > nr_iter) goto out_err; if (bv->bv_offset + bv->bv_len > PAGE_SIZE) goto out_err; bytes += bv->bv_len; nsegs++;