]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.git/commitdiff
patch CA-20346-blktap-vma-unmap
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Tue, 30 Jun 2009 11:55:47 +0000 (12:55 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Tue, 30 Jun 2009 11:55:47 +0000 (12:55 +0100)
drivers/xen/blktap/blktap.c
include/linux/mm.h
mm/mmap.c

index d58531eb94a7cdf3b8a26bbb14535e67e99e5cd7..a70d5027761dba6ec9714acbc1404e3156e5eb56 100644 (file)
@@ -95,6 +95,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,
        fault:    blktap_fault,
        zap_pte:  blktap_clear_pte,
@@ -534,6 +548,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;
 
@@ -944,6 +959,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
index 0de95218c526bd23ca6e2cbd1e9cf57eeb3d6714..ed56414eeb3afb4bc8ea2967cd31c6840950ed62 100644 (file)
@@ -196,6 +196,10 @@ struct vm_operations_struct {
        pte_t (*zap_pte)(struct vm_area_struct *vma,
                         unsigned long addr, pte_t *ptep, int is_fullmm);
 #endif
+
+       /* called before close() to indicate no more pages should be mapped */
+       void (*unmap)(struct vm_area_struct *area);
+
 #ifdef CONFIG_NUMA
        /*
         * set_policy() op must add a reference to any non-NULL @new mempolicy
index 2e5d6f15320c59f74dfb1e496e0cad0a426e695d..2d4950a40714e096d667f5cb8235e5d7da625527 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1835,6 +1835,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..
@@ -1850,6 +1856,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;
@@ -2117,7 +2124,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;
 
@@ -2125,6 +2132,9 @@ void exit_mmap(struct mm_struct *mm)
        arch_exit_mmap(mm);
        mmu_notifier_release(mm);
 
+       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);