From 3fa1c4a69c8d7611a32dab7f519c321ced28c644 Mon Sep 17 00:00:00 2001 From: t_jeang Date: Tue, 6 Jan 2009 12:06:01 +0000 Subject: [PATCH] imported patch CA-20346-blktap-vma-unmap --- drivers/xen/blktap/blktap.c | 25 +++++++++++++++++++++++-- include/linux/mm.h | 4 ++++ mm/mmap.c | 12 +++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/drivers/xen/blktap/blktap.c b/drivers/xen/blktap/blktap.c index 3729c160..87cb9df9 100644 --- a/drivers/xen/blktap/blktap.c +++ b/drivers/xen/blktap/blktap.c @@ -93,6 +93,12 @@ static unsigned short mmap_alloc = 0; static unsigned short mmap_lock = 0; static unsigned short mmap_inuse = 0; +#define BLKTAP_VMA_MAPPED 5 +static inline int blktap_vma_mapped(struct tap_blkif *info) +{ + return test_bit(BLKTAP_VMA_MAPPED, &info->dev_inuse); +} + /****************************************************************** * GRANT HANDLES */ @@ -236,13 +242,20 @@ static pte_t blktap_clear_pte(struct vm_area_struct *vma, return copy; } -static void blktap_vm_close(struct vm_area_struct *vma) +static void blktap_vm_unmap(struct vm_area_struct *vma) { struct tap_blkif *info = vma->vm_private_data; down_write(&info->vm_update_sem); + clear_bit(BLKTAP_VMA_MAPPED, &info->dev_inuse); + up_write(&info->vm_update_sem); +} - zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, NULL); +static void blktap_vm_close(struct vm_area_struct *vma) +{ + struct tap_blkif *info = vma->vm_private_data; + + down_write(&info->vm_update_sem); kfree(info->foreign_map.map); @@ -260,6 +273,7 @@ static void blktap_vm_close(struct vm_area_struct *vma) static struct vm_operations_struct blktap_vm_ops = { + unmap: blktap_vm_unmap, close: blktap_vm_close, nopage: blktap_nopage, zap_pte: blktap_clear_pte, @@ -535,6 +549,7 @@ static int blktap_mmap(struct file *filp, struct vm_area_struct *vma) info->pid = current->pid; DPRINTK("blktap: mapping pid is %d\n", info->pid); + set_bit(BLKTAP_VMA_MAPPED, &info->dev_inuse); info->vma = vma; return 0; @@ -945,6 +960,12 @@ int tap_blkif_schedule(void *arg) break; } + if (!blktap_vma_mapped(info)) { + WPRINTK("vma unmapped but not closed\n"); + up_read(&info->vm_update_sem); + continue; + } + if (do_block_io_op(info)) blkif->waiting_reqs = 1; else diff --git a/include/linux/mm.h b/include/linux/mm.h index b5c8fc76..f0c8c3ff 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -220,6 +220,10 @@ struct vm_operations_struct { * original value of @ptep. */ pte_t (*zap_pte)(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, int is_fullmm); + + /* called before close() to indicate no more pages should be mapped */ + void (*unmap)(struct vm_area_struct *area); + #ifdef CONFIG_NUMA int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new); struct mempolicy *(*get_policy)(struct vm_area_struct *vma, diff --git a/mm/mmap.c b/mm/mmap.c index dabff0b8..4b7c04cd 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1787,6 +1787,12 @@ static void unmap_region(struct mm_struct *mm, tlb_finish_mmu(tlb, start, end); } +static inline void unmap_vma(struct vm_area_struct *vma) +{ + if (unlikely(vma->vm_ops && vma->vm_ops->unmap)) + vma->vm_ops->unmap(vma); +} + /* * Create a list of vma's touched by the unmap, removing them from the mm's * vma list as we go.. @@ -1802,6 +1808,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, insertion_point = (prev ? &prev->vm_next : &mm->mmap); do { rb_erase(&vma->vm_rb, &mm->mm_rb); + unmap_vma(vma); mm->map_count--; tail_vma = vma; vma = vma->vm_next; @@ -2068,7 +2075,7 @@ EXPORT_SYMBOL(do_brk); void exit_mmap(struct mm_struct *mm) { struct mmu_gather *tlb; - struct vm_area_struct *vma = mm->mmap; + struct vm_area_struct *vma_tmp, *vma = mm->mmap; unsigned long nr_accounted = 0; unsigned long end; @@ -2076,6 +2083,9 @@ void exit_mmap(struct mm_struct *mm) arch_exit_mmap(mm); #endif + for (vma_tmp = mm->mmap; vma_tmp; vma_tmp = vma_tmp->vm_next) + unmap_vma(vma_tmp); + lru_add_drain(); flush_cache_mm(mm); tlb = tlb_gather_mmu(mm, 1); -- 2.39.5