1,内核对mutil-page bvec 的 map
如果是在虚拟机 guest 中,其可以通过半虚拟化前端驱动 virtio-blk 发送 IO 请求,将上层下发的IO 请求 request->bio 的bvec(可能是multi-page的bvec) 先通过如下map函数转化为sglist,然后将sglist转化为 virtio-ring的表示形式:desc.addr, desc.len。如果是multi-page的bvec,那么desc.len > PAGE_SIZE.
static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio,
struct scatterlist *sglist,
struct scatterlist **sg)
{
struct bio_vec bvec, bvprv = { NULL };
struct bvec_iter iter;
int nsegs = 0;
bool new_bio = false;
for_each_bio(bio) {
bio_for_each_bvec(bvec, bio, iter) {
/*
* Only try to merge bvecs from two bios given we
* have done bio internal merge when adding pages
* to bio
*/
if (new_bio &&
__blk_segment_map_sg_merge(q, &bvec, &bvprv, sg))
goto next_bvec;
// 单page bvec的处理
if (bvec.bv_offset + bvec.bv_len <= PAGE_SIZE)
nsegs &