diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/vmalloc.c | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 21ec16b7e6e1..2faaa2976447 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -765,7 +765,7 @@ struct vmap_block { | |||
765 | spinlock_t lock; | 765 | spinlock_t lock; |
766 | struct vmap_area *va; | 766 | struct vmap_area *va; |
767 | unsigned long free, dirty; | 767 | unsigned long free, dirty; |
768 | DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS); | 768 | unsigned long dirty_min, dirty_max; /*< dirty range */ |
769 | struct list_head free_list; | 769 | struct list_head free_list; |
770 | struct rcu_head rcu_head; | 770 | struct rcu_head rcu_head; |
771 | struct list_head purge; | 771 | struct list_head purge; |
@@ -851,7 +851,8 @@ static void *new_vmap_block(unsigned int order, gfp_t gfp_mask) | |||
851 | BUG_ON(VMAP_BBMAP_BITS <= (1UL << order)); | 851 | BUG_ON(VMAP_BBMAP_BITS <= (1UL << order)); |
852 | vb->free = VMAP_BBMAP_BITS - (1UL << order); | 852 | vb->free = VMAP_BBMAP_BITS - (1UL << order); |
853 | vb->dirty = 0; | 853 | vb->dirty = 0; |
854 | bitmap_zero(vb->dirty_map, VMAP_BBMAP_BITS); | 854 | vb->dirty_min = VMAP_BBMAP_BITS; |
855 | vb->dirty_max = 0; | ||
855 | INIT_LIST_HEAD(&vb->free_list); | 856 | INIT_LIST_HEAD(&vb->free_list); |
856 | 857 | ||
857 | vb_idx = addr_to_vb_idx(va->va_start); | 858 | vb_idx = addr_to_vb_idx(va->va_start); |
@@ -902,7 +903,8 @@ static void purge_fragmented_blocks(int cpu) | |||
902 | if (vb->free + vb->dirty == VMAP_BBMAP_BITS && vb->dirty != VMAP_BBMAP_BITS) { | 903 | if (vb->free + vb->dirty == VMAP_BBMAP_BITS && vb->dirty != VMAP_BBMAP_BITS) { |
903 | vb->free = 0; /* prevent further allocs after releasing lock */ | 904 | vb->free = 0; /* prevent further allocs after releasing lock */ |
904 | vb->dirty = VMAP_BBMAP_BITS; /* prevent purging it again */ | 905 | vb->dirty = VMAP_BBMAP_BITS; /* prevent purging it again */ |
905 | bitmap_fill(vb->dirty_map, VMAP_BBMAP_BITS); | 906 | vb->dirty_min = 0; |
907 | vb->dirty_max = VMAP_BBMAP_BITS; | ||
906 | spin_lock(&vbq->lock); | 908 | spin_lock(&vbq->lock); |
907 | list_del_rcu(&vb->free_list); | 909 | list_del_rcu(&vb->free_list); |
908 | spin_unlock(&vbq->lock); | 910 | spin_unlock(&vbq->lock); |
@@ -995,6 +997,7 @@ static void vb_free(const void *addr, unsigned long size) | |||
995 | order = get_order(size); | 997 | order = get_order(size); |
996 | 998 | ||
997 | offset = (unsigned long)addr & (VMAP_BLOCK_SIZE - 1); | 999 | offset = (unsigned long)addr & (VMAP_BLOCK_SIZE - 1); |
1000 | offset >>= PAGE_SHIFT; | ||
998 | 1001 | ||
999 | vb_idx = addr_to_vb_idx((unsigned long)addr); | 1002 | vb_idx = addr_to_vb_idx((unsigned long)addr); |
1000 | rcu_read_lock(); | 1003 | rcu_read_lock(); |
@@ -1005,7 +1008,10 @@ static void vb_free(const void *addr, unsigned long size) | |||
1005 | vunmap_page_range((unsigned long)addr, (unsigned long)addr + size); | 1008 | vunmap_page_range((unsigned long)addr, (unsigned long)addr + size); |
1006 | 1009 | ||
1007 | spin_lock(&vb->lock); | 1010 | spin_lock(&vb->lock); |
1008 | BUG_ON(bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order)); | 1011 | |
1012 | /* Expand dirty range */ | ||
1013 | vb->dirty_min = min(vb->dirty_min, offset); | ||
1014 | vb->dirty_max = max(vb->dirty_max, offset + (1UL << order)); | ||
1009 | 1015 | ||
1010 | vb->dirty += 1UL << order; | 1016 | vb->dirty += 1UL << order; |
1011 | if (vb->dirty == VMAP_BBMAP_BITS) { | 1017 | if (vb->dirty == VMAP_BBMAP_BITS) { |
@@ -1044,25 +1050,18 @@ void vm_unmap_aliases(void) | |||
1044 | 1050 | ||
1045 | rcu_read_lock(); | 1051 | rcu_read_lock(); |
1046 | list_for_each_entry_rcu(vb, &vbq->free, free_list) { | 1052 | list_for_each_entry_rcu(vb, &vbq->free, free_list) { |
1047 | int i, j; | ||
1048 | |||
1049 | spin_lock(&vb->lock); | 1053 | spin_lock(&vb->lock); |
1050 | i = find_first_bit(vb->dirty_map, VMAP_BBMAP_BITS); | 1054 | if (vb->dirty) { |
1051 | if (i < VMAP_BBMAP_BITS) { | 1055 | unsigned long va_start = vb->va->va_start; |
1052 | unsigned long s, e; | 1056 | unsigned long s, e; |
1053 | 1057 | ||
1054 | j = find_last_bit(vb->dirty_map, | 1058 | s = va_start + (vb->dirty_min << PAGE_SHIFT); |
1055 | VMAP_BBMAP_BITS); | 1059 | e = va_start + (vb->dirty_max << PAGE_SHIFT); |
1056 | j = j + 1; /* need exclusive index */ | ||
1057 | 1060 | ||
1058 | s = vb->va->va_start + (i << PAGE_SHIFT); | 1061 | start = min(s, start); |
1059 | e = vb->va->va_start + (j << PAGE_SHIFT); | 1062 | end = max(e, end); |
1060 | flush = 1; | ||
1061 | 1063 | ||
1062 | if (s < start) | 1064 | flush = 1; |
1063 | start = s; | ||
1064 | if (e > end) | ||
1065 | end = e; | ||
1066 | } | 1065 | } |
1067 | spin_unlock(&vb->lock); | 1066 | spin_unlock(&vb->lock); |
1068 | } | 1067 | } |