From: jbeulich@novell.com Subject: fix c/s 863 Patch-mainline: obsolete (superceded by c/s 867) get_user_pages() expects vma->vm_private_data of VM_FOREIGN vma-s to point to an array of struct page *, hence blktap must not alter the meaning of that field. Found-by: Isaku Yamahata --- sle11-2009-04-20.orig/drivers/xen/blktap/blktap.c 2009-04-20 11:41:53.000000000 +0200 +++ sle11-2009-04-20/drivers/xen/blktap/blktap.c 2009-04-29 09:36:57.000000000 +0200 @@ -320,7 +320,7 @@ static pte_t blktap_clear_pte(struct vm_ int offset, seg, usr_idx, pending_idx, mmap_idx; unsigned long uvstart = vma->vm_start + (RING_PAGES << PAGE_SHIFT); unsigned long kvaddr; - struct tap_vma_priv *priv; + struct page **map; struct page *pg; struct grant_handle_pair *khandle; struct gnttab_unmap_grant_ref unmap[2]; @@ -335,12 +335,12 @@ static pte_t blktap_clear_pte(struct vm_ is_fullmm); info = vma->vm_file->private_data; - priv = vma->vm_private_data; + map = vma->vm_private_data; /* TODO Should these be changed to if statements? */ BUG_ON(!info); BUG_ON(!info->idx_map); - BUG_ON(!priv); + BUG_ON(!map); offset = (int) ((uvaddr - uvstart) >> PAGE_SHIFT); usr_idx = OFFSET_TO_USR_IDX(offset); @@ -352,7 +352,7 @@ static pte_t blktap_clear_pte(struct vm_ kvaddr = idx_to_kaddr(mmap_idx, pending_idx, seg); pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); ClearPageReserved(pg); - priv->map[offset + RING_PAGES] = NULL; + map[offset + RING_PAGES] = NULL; khandle = &pending_handle(mmap_idx, pending_idx, seg); @@ -395,9 +395,11 @@ static pte_t blktap_clear_pte(struct vm_ static void blktap_vma_close(struct vm_area_struct *vma) { - struct tap_vma_priv *priv = vma->vm_private_data; + if (vma->vm_private_data) { + struct tap_vma_priv *priv = container_of(vma->vm_private_data, + struct tap_vma_priv, + map); - if (priv) { priv->info->vma = NULL; kfree(priv); } @@ -708,7 +710,7 @@ static int blktap_mmap(struct file *filp } priv->info = info; - vma->vm_private_data = priv; + vma->vm_private_data = priv->map; vma->vm_flags |= VM_FOREIGN; vma->vm_flags |= VM_DONTCOPY; @@ -1189,7 +1191,7 @@ static int blktap_read_ufe_ring(tap_blki for (j = 0; j < pending_req->nr_pages; j++) { unsigned long kvaddr, uvaddr; - struct tap_vma_priv *priv = info->vma->vm_private_data; + struct page **map = info->vma->vm_private_data; struct page *pg; int offset; @@ -1200,7 +1202,7 @@ static int blktap_read_ufe_ring(tap_blki ClearPageReserved(pg); offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; - priv->map[offset] = NULL; + map[offset] = NULL; } fast_flush_area(pending_req, pending_idx, usr_idx, info->minor); info->idx_map[usr_idx] = INVALID_REQ; @@ -1366,7 +1368,7 @@ static void dispatch_rw_block_io(blkif_t unsigned int nseg; int ret, i, nr_sects = 0; tap_blkif_t *info; - struct tap_vma_priv *priv; + struct page **pgmap; blkif_request_t *target; int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx); int usr_idx; @@ -1432,7 +1434,6 @@ static void dispatch_rw_block_io(blkif_t pending_req->status = BLKIF_RSP_OKAY; pending_req->nr_pages = nseg; op = 0; - priv = info->vma->vm_private_data; mm = info->vma->vm_mm; if (!xen_feature(XENFEAT_auto_translated_physmap)) down_write(&mm->mmap_sem); @@ -1477,6 +1478,8 @@ static void dispatch_rw_block_io(blkif_t ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op); BUG_ON(ret); + pgmap = info->vma->vm_private_data; + if (!xen_feature(XENFEAT_auto_translated_physmap)) { up_write(&mm->mmap_sem); @@ -1516,7 +1519,7 @@ static void dispatch_rw_block_io(blkif_t >> PAGE_SHIFT)); offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); - priv->map[offset] = pg; + pgmap[offset] = pg; } } else { for (i = 0; i < nseg; i++) { @@ -1543,7 +1546,7 @@ static void dispatch_rw_block_io(blkif_t offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); - priv->map[offset] = pg; + pgmap[offset] = pg; } }