[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] blktap2: make blktap2 work for auto translated mode with hvm domain.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1248427713 -3600 # Node ID 899d28ee5c7d445737f976b6cf69a7d9bed452b8 # Parent 5a2b46dfeef8a8b0dd82e036e6ca95099ecd0a36 blktap2: make blktap2 work for auto translated mode with hvm domain. This patch makes blktap2 work for hvm domain with auto translated mode. (I.e. IA64 HVM domain case as Kuwamura reported its bug.) blktap2 has introduces new feature that pages from the self domain can be handled. However it doesn't work for auto translated mode because blktap2 relies on p2m table manipulation. But the p2m doesn't make sense for auto translated mode. So self grant mapping is used instead. Just passing same page to blktap2 daemon doesn't work because when doing io, the page is locked, so the given page from blktap2 block device is already locked. When blktap2 daemon issues IO on the page, it tries to lock it resulting in dead lock. So resorted to self grant. Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx> --- drivers/xen/blktap2/device.c | 86 +++++++++++++++++++++++++++++++++++-------- 1 files changed, 71 insertions(+), 15 deletions(-) diff -r 5a2b46dfeef8 -r 899d28ee5c7d drivers/xen/blktap2/device.c --- a/drivers/xen/blktap2/device.c Mon Jul 20 10:11:23 2009 +0100 +++ b/drivers/xen/blktap2/device.c Fri Jul 24 10:28:33 2009 +0100 @@ -225,6 +225,8 @@ blktap_device_fast_flush(struct blktap * struct grant_handle_pair *khandle; unsigned long kvaddr, uvaddr, offset; struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST * 2]; + grant_handle_t self_gref[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int self_gref_nr = 0; cnt = 0; ring = &tap->ring; @@ -283,6 +285,10 @@ blktap_device_fast_flush(struct blktap * if (PageBlkback(page)) { ClearPageBlkback(page); set_page_private(page, 0); + } else if ( + xen_feature(XENFEAT_auto_translated_physmap)) { + self_gref[self_gref_nr] = khandle->kernel; + self_gref_nr++; } } map[offset] = NULL; @@ -301,6 +307,11 @@ blktap_device_fast_flush(struct blktap * zap_page_range(ring->vma, MMAP_VADDR(ring->user_vstart, usr_idx, 0), request->nr_pages << PAGE_SHIFT, NULL); + else { + for (i = 0; i < self_gref_nr; i++) { + gnttab_end_foreign_access_ref(self_gref[i]); + } + } } /* @@ -323,7 +334,8 @@ blktap_unmap(struct blktap *tap, struct MMAP_VADDR(tap->ring.user_vstart, usr_idx, i), request->handles[i].user); - if (request->handles[i].kernel == INVALID_GRANT_HANDLE) { + if (!xen_feature(XENFEAT_auto_translated_physmap) && + request->handles[i].kernel == INVALID_GRANT_HANDLE) { kvaddr = request_to_kaddr(request, i); blktap_umap_uaddr(&init_mm, kvaddr); flush_tlb_kernel_page(kvaddr); @@ -540,7 +552,7 @@ blktap_map_foreign(struct blktap *tap, return err; } -static void +static int blktap_map(struct blktap *tap, struct blktap_request *request, unsigned int seg, struct page *page) @@ -549,25 +561,68 @@ blktap_map(struct blktap *tap, int usr_idx; struct blktap_ring *ring; unsigned long uvaddr, kvaddr; + int err = 0; ring = &tap->ring; usr_idx = request->usr_idx; uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, seg); kvaddr = request_to_kaddr(request, seg); - pte = mk_pte(page, ring->vma->vm_page_prot); - blktap_map_uaddr(ring->vma->vm_mm, uvaddr, pte_mkwrite(pte)); - flush_tlb_page(ring->vma, uvaddr); - blktap_map_uaddr(&init_mm, kvaddr, mk_pte(page, PAGE_KERNEL)); - flush_tlb_kernel_page(kvaddr); - - set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, pte_mfn(pte)); - request->handles[seg].kernel = INVALID_GRANT_HANDLE; - request->handles[seg].user = INVALID_GRANT_HANDLE; + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + pte = mk_pte(page, ring->vma->vm_page_prot); + blktap_map_uaddr(ring->vma->vm_mm, uvaddr, pte_mkwrite(pte)); + flush_tlb_page(ring->vma, uvaddr); + blktap_map_uaddr(&init_mm, kvaddr, mk_pte(page, PAGE_KERNEL)); + flush_tlb_kernel_page(kvaddr); + + set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, pte_mfn(pte)); + request->handles[seg].kernel = INVALID_GRANT_HANDLE; + } else { + /* grant this page access to self domain and map it. */ + domid_t domid = 0; /* XXX my domian id: grant table hypercall + doesn't understand DOMID_SELF */ + int gref; + uint32_t flags; + struct gnttab_map_grant_ref map; + struct page *tap_page; + + gref = gnttab_grant_foreign_access( + domid, page_to_pfn(page), + (request->operation == BLKIF_OP_WRITE)? + GTF_readonly: 0); + + flags = GNTMAP_host_map | + (request->operation == BLKIF_OP_WRITE ? + GNTMAP_readonly : 0); + + gnttab_set_map_op(&map, kvaddr, flags, gref, domid); + + /* enable chained tap devices */ + tap_page = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + set_page_private(tap_page, page_private(page)); + SetPageBlkback(tap_page); + + err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, + &map, 1); + BUG_ON(err); + + err = vm_insert_page(ring->vma, uvaddr, tap_page); + if (err) { + struct gnttab_unmap_grant_ref unmap; + gnttab_set_unmap_op(&unmap, kvaddr, + GNTMAP_host_map, gref); + (void)HYPERVISOR_grant_table_op( + GNTTABOP_unmap_grant_ref, &unmap, 1); + } else + request->handles[seg].kernel = gref; + } + request->handles[seg].user = INVALID_GRANT_HANDLE; BTDBG("pending_req: %p, seg: %d, page: %p, kvaddr: 0x%08lx, " "uvaddr: 0x%08lx\n", request, seg, page, kvaddr, uvaddr); + + return err; } static int @@ -630,10 +685,11 @@ blktap_device_process_request(struct blk goto out; } else { /* do it the old fashioned way */ - blktap_map(tap, - request, - i, - sg->page); + if (blktap_map(tap, + request, + i, + sg->page)) + goto out; } uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |