blktap: don't use vma->vm_start to calculate offset. struct vma can be split by partial munmap(), we can't depend on vm_start. Instead, use tap_blkif_t::rings_vstart. Signed-off-by: Isaku Yamahata diff --git a/drivers/xen/blktap/blktap.c b/drivers/xen/blktap/blktap.c --- a/drivers/xen/blktap/blktap.c +++ b/drivers/xen/blktap/blktap.c @@ -317,7 +317,7 @@ static pte_t blktap_clear_pte(struct vm_ pte_t copy; tap_blkif_t *info; int offset, seg, usr_idx, pending_idx, mmap_idx; - unsigned long uvstart = vma->vm_start + (RING_PAGES << PAGE_SHIFT); + unsigned long uvstart; unsigned long kvaddr; struct tap_vma_priv *priv; struct page *pg; @@ -329,11 +329,15 @@ static pte_t blktap_clear_pte(struct vm_ * If the address is before the start of the grant mapped region or * if vm_file is NULL (meaning mmap failed and we have nothing to do) */ - if (uvaddr < uvstart || vma->vm_file == NULL) + if (vma->vm_file != NULL) { + info = vma->vm_file->private_data; + uvstart = info->rings_vstart + (RING_PAGES << PAGE_SHIFT); + } else + uvstart = uvaddr; /* make the following if clause true */ + if (uvaddr < uvstart) return ptep_get_and_clear_full(vma->vm_mm, uvaddr, ptep, is_fullmm); - info = vma->vm_file->private_data; priv = vma->vm_private_data; /* TODO Should these be changed to if statements? */ @@ -1200,8 +1204,7 @@ static int blktap_read_ufe_ring(tap_blki pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); ClearPageReserved(pg); - offset = (uvaddr - info->vma->vm_start) - >> PAGE_SHIFT; + offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT; priv->map[offset] = NULL; } fast_flush_area(pending_req, pending_idx, usr_idx, info->minor); @@ -1492,7 +1495,7 @@ static void dispatch_rw_block_io(blkif_t set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT)); - offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; + offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT; pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); priv->map[offset] = pg; } @@ -1519,7 +1522,7 @@ static void dispatch_rw_block_io(blkif_t if (ret) continue; - offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; + offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT; pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); priv->map[offset] = pg; }