]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
imported patch CA-20346-blktap-vma-unmap blk-latency-stats
authort_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:01 +0000 (12:06 +0000)
committert_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:01 +0000 (12:06 +0000)
drivers/xen/blktap/blktap.c
include/linux/mm.h
mm/mmap.c

index 3729c16020a4439f40f3e789b4ee6b2a11cf463b..87cb9df9df05cb654f449096b0fb1e90b11ae9ee 100644 (file)
@@ -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
index b5c8fc76fdeb6eaa85e3dbcd6f1a688f3ce488b8..f0c8c3ff79ade2388558e293aca274d711fb9ee9 100644 (file)
@@ -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,
index dabff0b8a527e9c39c0cd031f70a9733aec40e7c..4b7c04cd647c34151683d630fc572138441b1972 100644 (file)
--- 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);