in vringh.c [1091:1134]
static int iotlb_translate(const struct vringh *vrh,
u64 addr, u64 len, struct bio_vec iov[],
int iov_size, u32 perm)
{
struct vhost_iotlb_map *map;
struct vhost_iotlb *iotlb = vrh->iotlb;
int ret = 0;
u64 s = 0;
spin_lock(vrh->iotlb_lock);
while (len > s) {
u64 size, pa, pfn;
if (unlikely(ret >= iov_size)) {
ret = -ENOBUFS;
break;
}
map = vhost_iotlb_itree_first(iotlb, addr,
addr + len - 1);
if (!map || map->start > addr) {
ret = -EINVAL;
break;
} else if (!(map->perm & perm)) {
ret = -EPERM;
break;
}
size = map->size - addr + map->start;
pa = map->addr + addr - map->start;
pfn = pa >> PAGE_SHIFT;
iov[ret].bv_page = pfn_to_page(pfn);
iov[ret].bv_len = min(len - s, size);
iov[ret].bv_offset = pa & (PAGE_SIZE - 1);
s += size;
addr += size;
++ret;
}
spin_unlock(vrh->iotlb_lock);
return ret;
}