static int iotlb_translate()

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;
}