aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r--mm/vmalloc.c95
1 files changed, 55 insertions, 40 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index a5bbdd3b5d67..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;
@@ -796,13 +796,31 @@ static unsigned long addr_to_vb_idx(unsigned long addr)
796 return addr; 796 return addr;
797} 797}
798 798
799static struct vmap_block *new_vmap_block(gfp_t gfp_mask) 799static void *vmap_block_vaddr(unsigned long va_start, unsigned long pages_off)
800{
801 unsigned long addr;
802
803 addr = va_start + (pages_off << PAGE_SHIFT);
804 BUG_ON(addr_to_vb_idx(addr) != addr_to_vb_idx(va_start));
805 return (void *)addr;
806}
807
808/**
809 * new_vmap_block - allocates new vmap_block and occupies 2^order pages in this
810 * block. Of course pages number can't exceed VMAP_BBMAP_BITS
811 * @order: how many 2^order pages should be occupied in newly allocated block
812 * @gfp_mask: flags for the page level allocator
813 *
814 * Returns: virtual address in a newly allocated block or ERR_PTR(-errno)
815 */
816static void *new_vmap_block(unsigned int order, gfp_t gfp_mask)
800{ 817{
801 struct vmap_block_queue *vbq; 818 struct vmap_block_queue *vbq;
802 struct vmap_block *vb; 819 struct vmap_block *vb;
803 struct vmap_area *va; 820 struct vmap_area *va;
804 unsigned long vb_idx; 821 unsigned long vb_idx;
805 int node, err; 822 int node, err;
823 void *vaddr;
806 824
807 node = numa_node_id(); 825 node = numa_node_id();
808 826
@@ -826,11 +844,15 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask)
826 return ERR_PTR(err); 844 return ERR_PTR(err);
827 } 845 }
828 846
847 vaddr = vmap_block_vaddr(va->va_start, 0);
829 spin_lock_init(&vb->lock); 848 spin_lock_init(&vb->lock);
830 vb->va = va; 849 vb->va = va;
831 vb->free = VMAP_BBMAP_BITS; 850 /* At least something should be left free */
851 BUG_ON(VMAP_BBMAP_BITS <= (1UL << order));
852 vb->free = VMAP_BBMAP_BITS - (1UL << order);
832 vb->dirty = 0; 853 vb->dirty = 0;
833 bitmap_zero(vb->dirty_map, VMAP_BBMAP_BITS); 854 vb->dirty_min = VMAP_BBMAP_BITS;
855 vb->dirty_max = 0;
834 INIT_LIST_HEAD(&vb->free_list); 856 INIT_LIST_HEAD(&vb->free_list);
835 857
836 vb_idx = addr_to_vb_idx(va->va_start); 858 vb_idx = addr_to_vb_idx(va->va_start);
@@ -842,11 +864,11 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask)
842 864
843 vbq = &get_cpu_var(vmap_block_queue); 865 vbq = &get_cpu_var(vmap_block_queue);
844 spin_lock(&vbq->lock); 866 spin_lock(&vbq->lock);
845 list_add_rcu(&vb->free_list, &vbq->free); 867 list_add_tail_rcu(&vb->free_list, &vbq->free);
846 spin_unlock(&vbq->lock); 868 spin_unlock(&vbq->lock);
847 put_cpu_var(vmap_block_queue); 869 put_cpu_var(vmap_block_queue);
848 870
849 return vb; 871 return vaddr;
850} 872}
851 873
852static void free_vmap_block(struct vmap_block *vb) 874static void free_vmap_block(struct vmap_block *vb)
@@ -881,7 +903,8 @@ static void purge_fragmented_blocks(int cpu)
881 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) {
882 vb->free = 0; /* prevent further allocs after releasing lock */ 904 vb->free = 0; /* prevent further allocs after releasing lock */
883 vb->dirty = VMAP_BBMAP_BITS; /* prevent purging it again */ 905 vb->dirty = VMAP_BBMAP_BITS; /* prevent purging it again */
884 bitmap_fill(vb->dirty_map, VMAP_BBMAP_BITS); 906 vb->dirty_min = 0;
907 vb->dirty_max = VMAP_BBMAP_BITS;
885 spin_lock(&vbq->lock); 908 spin_lock(&vbq->lock);
886 list_del_rcu(&vb->free_list); 909 list_del_rcu(&vb->free_list);
887 spin_unlock(&vbq->lock); 910 spin_unlock(&vbq->lock);
@@ -910,7 +933,7 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask)
910{ 933{
911 struct vmap_block_queue *vbq; 934 struct vmap_block_queue *vbq;
912 struct vmap_block *vb; 935 struct vmap_block *vb;
913 unsigned long addr = 0; 936 void *vaddr = NULL;
914 unsigned int order; 937 unsigned int order;
915 938
916 BUG_ON(size & ~PAGE_MASK); 939 BUG_ON(size & ~PAGE_MASK);
@@ -925,43 +948,38 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask)
925 } 948 }
926 order = get_order(size); 949 order = get_order(size);
927 950
928again:
929 rcu_read_lock(); 951 rcu_read_lock();
930 vbq = &get_cpu_var(vmap_block_queue); 952 vbq = &get_cpu_var(vmap_block_queue);
931 list_for_each_entry_rcu(vb, &vbq->free, free_list) { 953 list_for_each_entry_rcu(vb, &vbq->free, free_list) {
932 int i; 954 unsigned long pages_off;
933 955
934 spin_lock(&vb->lock); 956 spin_lock(&vb->lock);
935 if (vb->free < 1UL << order) 957 if (vb->free < (1UL << order)) {
936 goto next; 958 spin_unlock(&vb->lock);
959 continue;
960 }
937 961
938 i = VMAP_BBMAP_BITS - vb->free; 962 pages_off = VMAP_BBMAP_BITS - vb->free;
939 addr = vb->va->va_start + (i << PAGE_SHIFT); 963 vaddr = vmap_block_vaddr(vb->va->va_start, pages_off);
940 BUG_ON(addr_to_vb_idx(addr) !=
941 addr_to_vb_idx(vb->va->va_start));
942 vb->free -= 1UL << order; 964 vb->free -= 1UL << order;
943 if (vb->free == 0) { 965 if (vb->free == 0) {
944 spin_lock(&vbq->lock); 966 spin_lock(&vbq->lock);
945 list_del_rcu(&vb->free_list); 967 list_del_rcu(&vb->free_list);
946 spin_unlock(&vbq->lock); 968 spin_unlock(&vbq->lock);
947 } 969 }
970
948 spin_unlock(&vb->lock); 971 spin_unlock(&vb->lock);
949 break; 972 break;
950next:
951 spin_unlock(&vb->lock);
952 } 973 }
953 974
954 put_cpu_var(vmap_block_queue); 975 put_cpu_var(vmap_block_queue);
955 rcu_read_unlock(); 976 rcu_read_unlock();
956 977
957 if (!addr) { 978 /* Allocate new block if nothing was found */
958 vb = new_vmap_block(gfp_mask); 979 if (!vaddr)
959 if (IS_ERR(vb)) 980 vaddr = new_vmap_block(order, gfp_mask);
960 return vb;
961 goto again;
962 }
963 981
964 return (void *)addr; 982 return vaddr;
965} 983}
966 984
967static void vb_free(const void *addr, unsigned long size) 985static void vb_free(const void *addr, unsigned long size)
@@ -979,6 +997,7 @@ static void vb_free(const void *addr, unsigned long size)
979 order = get_order(size); 997 order = get_order(size);
980 998
981 offset = (unsigned long)addr & (VMAP_BLOCK_SIZE - 1); 999 offset = (unsigned long)addr & (VMAP_BLOCK_SIZE - 1);
1000 offset >>= PAGE_SHIFT;
982 1001
983 vb_idx = addr_to_vb_idx((unsigned long)addr); 1002 vb_idx = addr_to_vb_idx((unsigned long)addr);
984 rcu_read_lock(); 1003 rcu_read_lock();
@@ -989,7 +1008,10 @@ static void vb_free(const void *addr, unsigned long size)
989 vunmap_page_range((unsigned long)addr, (unsigned long)addr + size); 1008 vunmap_page_range((unsigned long)addr, (unsigned long)addr + size);
990 1009
991 spin_lock(&vb->lock); 1010 spin_lock(&vb->lock);
992 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));
993 1015
994 vb->dirty += 1UL << order; 1016 vb->dirty += 1UL << order;
995 if (vb->dirty == VMAP_BBMAP_BITS) { 1017 if (vb->dirty == VMAP_BBMAP_BITS) {
@@ -1028,25 +1050,18 @@ void vm_unmap_aliases(void)
1028 1050
1029 rcu_read_lock(); 1051 rcu_read_lock();
1030 list_for_each_entry_rcu(vb, &vbq->free, free_list) { 1052 list_for_each_entry_rcu(vb, &vbq->free, free_list) {
1031 int i, j;
1032
1033 spin_lock(&vb->lock); 1053 spin_lock(&vb->lock);
1034 i = find_first_bit(vb->dirty_map, VMAP_BBMAP_BITS); 1054 if (vb->dirty) {
1035 if (i < VMAP_BBMAP_BITS) { 1055 unsigned long va_start = vb->va->va_start;
1036 unsigned long s, e; 1056 unsigned long s, e;
1037 1057
1038 j = find_last_bit(vb->dirty_map, 1058 s = va_start + (vb->dirty_min << PAGE_SHIFT);
1039 VMAP_BBMAP_BITS); 1059 e = va_start + (vb->dirty_max << PAGE_SHIFT);
1040 j = j + 1; /* need exclusive index */
1041 1060
1042 s = vb->va->va_start + (i << PAGE_SHIFT); 1061 start = min(s, start);
1043 e = vb->va->va_start + (j << PAGE_SHIFT); 1062 end = max(e, end);
1044 flush = 1;
1045 1063
1046 if (s < start) 1064 flush = 1;
1047 start = s;
1048 if (e > end)
1049 end = e;
1050 } 1065 }
1051 spin_unlock(&vb->lock); 1066 spin_unlock(&vb->lock);
1052 } 1067 }