aboutsummaryrefslogtreecommitdiffstats
path: root/mm/zsmalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/zsmalloc.c')
-rw-r--r--mm/zsmalloc.c180
1 files changed, 134 insertions, 46 deletions
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 839a48c3ca27..4d0a063145ec 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -155,8 +155,6 @@
155 * (reason above) 155 * (reason above)
156 */ 156 */
157#define ZS_SIZE_CLASS_DELTA (PAGE_SIZE >> 8) 157#define ZS_SIZE_CLASS_DELTA (PAGE_SIZE >> 8)
158#define ZS_SIZE_CLASSES ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \
159 ZS_SIZE_CLASS_DELTA + 1)
160 158
161/* 159/*
162 * We do not maintain any list for completely empty or full pages 160 * We do not maintain any list for completely empty or full pages
@@ -171,6 +169,11 @@ enum fullness_group {
171}; 169};
172 170
173/* 171/*
172 * number of size_classes
173 */
174static int zs_size_classes;
175
176/*
174 * We assign a page to ZS_ALMOST_EMPTY fullness group when: 177 * We assign a page to ZS_ALMOST_EMPTY fullness group when:
175 * n <= N / f, where 178 * n <= N / f, where
176 * n = number of allocated objects 179 * n = number of allocated objects
@@ -214,7 +217,7 @@ struct link_free {
214}; 217};
215 218
216struct zs_pool { 219struct zs_pool {
217 struct size_class size_class[ZS_SIZE_CLASSES]; 220 struct size_class **size_class;
218 221
219 gfp_t flags; /* allocation flags used when growing pool */ 222 gfp_t flags; /* allocation flags used when growing pool */
220 atomic_long_t pages_allocated; 223 atomic_long_t pages_allocated;
@@ -468,7 +471,7 @@ static enum fullness_group fix_fullness_group(struct zs_pool *pool,
468 if (newfg == currfg) 471 if (newfg == currfg)
469 goto out; 472 goto out;
470 473
471 class = &pool->size_class[class_idx]; 474 class = pool->size_class[class_idx];
472 remove_zspage(page, class, currfg); 475 remove_zspage(page, class, currfg);
473 insert_zspage(page, class, newfg); 476 insert_zspage(page, class, newfg);
474 set_zspage_mapping(page, class_idx, newfg); 477 set_zspage_mapping(page, class_idx, newfg);
@@ -629,6 +632,7 @@ static void init_zspage(struct page *first_page, struct size_class *class)
629 struct page *next_page; 632 struct page *next_page;
630 struct link_free *link; 633 struct link_free *link;
631 unsigned int i = 1; 634 unsigned int i = 1;
635 void *vaddr;
632 636
633 /* 637 /*
634 * page->index stores offset of first object starting 638 * page->index stores offset of first object starting
@@ -639,8 +643,8 @@ static void init_zspage(struct page *first_page, struct size_class *class)
639 if (page != first_page) 643 if (page != first_page)
640 page->index = off; 644 page->index = off;
641 645
642 link = (struct link_free *)kmap_atomic(page) + 646 vaddr = kmap_atomic(page);
643 off / sizeof(*link); 647 link = (struct link_free *)vaddr + off / sizeof(*link);
644 648
645 while ((off += class->size) < PAGE_SIZE) { 649 while ((off += class->size) < PAGE_SIZE) {
646 link->next = obj_location_to_handle(page, i++); 650 link->next = obj_location_to_handle(page, i++);
@@ -654,7 +658,7 @@ static void init_zspage(struct page *first_page, struct size_class *class)
654 */ 658 */
655 next_page = get_next_page(page); 659 next_page = get_next_page(page);
656 link->next = obj_location_to_handle(next_page, 0); 660 link->next = obj_location_to_handle(next_page, 0);
657 kunmap_atomic(link); 661 kunmap_atomic(vaddr);
658 page = next_page; 662 page = next_page;
659 off %= PAGE_SIZE; 663 off %= PAGE_SIZE;
660 } 664 }
@@ -784,7 +788,7 @@ static inline int __zs_cpu_up(struct mapping_area *area)
784 */ 788 */
785 if (area->vm_buf) 789 if (area->vm_buf)
786 return 0; 790 return 0;
787 area->vm_buf = (char *)__get_free_page(GFP_KERNEL); 791 area->vm_buf = kmalloc(ZS_MAX_ALLOC_SIZE, GFP_KERNEL);
788 if (!area->vm_buf) 792 if (!area->vm_buf)
789 return -ENOMEM; 793 return -ENOMEM;
790 return 0; 794 return 0;
@@ -792,8 +796,7 @@ static inline int __zs_cpu_up(struct mapping_area *area)
792 796
793static inline void __zs_cpu_down(struct mapping_area *area) 797static inline void __zs_cpu_down(struct mapping_area *area)
794{ 798{
795 if (area->vm_buf) 799 kfree(area->vm_buf);
796 free_page((unsigned long)area->vm_buf);
797 area->vm_buf = NULL; 800 area->vm_buf = NULL;
798} 801}
799 802
@@ -881,14 +884,10 @@ static struct notifier_block zs_cpu_nb = {
881 .notifier_call = zs_cpu_notifier 884 .notifier_call = zs_cpu_notifier
882}; 885};
883 886
884static void zs_exit(void) 887static void zs_unregister_cpu_notifier(void)
885{ 888{
886 int cpu; 889 int cpu;
887 890
888#ifdef CONFIG_ZPOOL
889 zpool_unregister_driver(&zs_zpool_driver);
890#endif
891
892 cpu_notifier_register_begin(); 891 cpu_notifier_register_begin();
893 892
894 for_each_online_cpu(cpu) 893 for_each_online_cpu(cpu)
@@ -898,31 +897,74 @@ static void zs_exit(void)
898 cpu_notifier_register_done(); 897 cpu_notifier_register_done();
899} 898}
900 899
901static int zs_init(void) 900static int zs_register_cpu_notifier(void)
902{ 901{
903 int cpu, ret; 902 int cpu, uninitialized_var(ret);
904 903
905 cpu_notifier_register_begin(); 904 cpu_notifier_register_begin();
906 905
907 __register_cpu_notifier(&zs_cpu_nb); 906 __register_cpu_notifier(&zs_cpu_nb);
908 for_each_online_cpu(cpu) { 907 for_each_online_cpu(cpu) {
909 ret = zs_cpu_notifier(NULL, CPU_UP_PREPARE, (void *)(long)cpu); 908 ret = zs_cpu_notifier(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
910 if (notifier_to_errno(ret)) { 909 if (notifier_to_errno(ret))
911 cpu_notifier_register_done(); 910 break;
912 goto fail;
913 }
914 } 911 }
915 912
916 cpu_notifier_register_done(); 913 cpu_notifier_register_done();
914 return notifier_to_errno(ret);
915}
916
917static void init_zs_size_classes(void)
918{
919 int nr;
917 920
921 nr = (ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / ZS_SIZE_CLASS_DELTA + 1;
922 if ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) % ZS_SIZE_CLASS_DELTA)
923 nr += 1;
924
925 zs_size_classes = nr;
926}
927
928static void __exit zs_exit(void)
929{
918#ifdef CONFIG_ZPOOL 930#ifdef CONFIG_ZPOOL
919 zpool_register_driver(&zs_zpool_driver); 931 zpool_unregister_driver(&zs_zpool_driver);
920#endif 932#endif
933 zs_unregister_cpu_notifier();
934}
921 935
936static int __init zs_init(void)
937{
938 int ret = zs_register_cpu_notifier();
939
940 if (ret) {
941 zs_unregister_cpu_notifier();
942 return ret;
943 }
944
945 init_zs_size_classes();
946
947#ifdef CONFIG_ZPOOL
948 zpool_register_driver(&zs_zpool_driver);
949#endif
922 return 0; 950 return 0;
923fail: 951}
924 zs_exit(); 952
925 return notifier_to_errno(ret); 953static unsigned int get_maxobj_per_zspage(int size, int pages_per_zspage)
954{
955 return pages_per_zspage * PAGE_SIZE / size;
956}
957
958static bool can_merge(struct size_class *prev, int size, int pages_per_zspage)
959{
960 if (prev->pages_per_zspage != pages_per_zspage)
961 return false;
962
963 if (get_maxobj_per_zspage(prev->size, prev->pages_per_zspage)
964 != get_maxobj_per_zspage(size, pages_per_zspage))
965 return false;
966
967 return true;
926} 968}
927 969
928/** 970/**
@@ -937,33 +979,71 @@ fail:
937 */ 979 */
938struct zs_pool *zs_create_pool(gfp_t flags) 980struct zs_pool *zs_create_pool(gfp_t flags)
939{ 981{
940 int i, ovhd_size; 982 int i;
941 struct zs_pool *pool; 983 struct zs_pool *pool;
984 struct size_class *prev_class = NULL;
942 985
943 ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); 986 pool = kzalloc(sizeof(*pool), GFP_KERNEL);
944 pool = kzalloc(ovhd_size, GFP_KERNEL);
945 if (!pool) 987 if (!pool)
946 return NULL; 988 return NULL;
947 989
948 for (i = 0; i < ZS_SIZE_CLASSES; i++) { 990 pool->size_class = kcalloc(zs_size_classes, sizeof(struct size_class *),
991 GFP_KERNEL);
992 if (!pool->size_class) {
993 kfree(pool);
994 return NULL;
995 }
996
997 /*
998 * Iterate reversly, because, size of size_class that we want to use
999 * for merging should be larger or equal to current size.
1000 */
1001 for (i = zs_size_classes - 1; i >= 0; i--) {
949 int size; 1002 int size;
1003 int pages_per_zspage;
950 struct size_class *class; 1004 struct size_class *class;
951 1005
952 size = ZS_MIN_ALLOC_SIZE + i * ZS_SIZE_CLASS_DELTA; 1006 size = ZS_MIN_ALLOC_SIZE + i * ZS_SIZE_CLASS_DELTA;
953 if (size > ZS_MAX_ALLOC_SIZE) 1007 if (size > ZS_MAX_ALLOC_SIZE)
954 size = ZS_MAX_ALLOC_SIZE; 1008 size = ZS_MAX_ALLOC_SIZE;
1009 pages_per_zspage = get_pages_per_zspage(size);
1010
1011 /*
1012 * size_class is used for normal zsmalloc operation such
1013 * as alloc/free for that size. Although it is natural that we
1014 * have one size_class for each size, there is a chance that we
1015 * can get more memory utilization if we use one size_class for
1016 * many different sizes whose size_class have same
1017 * characteristics. So, we makes size_class point to
1018 * previous size_class if possible.
1019 */
1020 if (prev_class) {
1021 if (can_merge(prev_class, size, pages_per_zspage)) {
1022 pool->size_class[i] = prev_class;
1023 continue;
1024 }
1025 }
1026
1027 class = kzalloc(sizeof(struct size_class), GFP_KERNEL);
1028 if (!class)
1029 goto err;
955 1030
956 class = &pool->size_class[i];
957 class->size = size; 1031 class->size = size;
958 class->index = i; 1032 class->index = i;
1033 class->pages_per_zspage = pages_per_zspage;
959 spin_lock_init(&class->lock); 1034 spin_lock_init(&class->lock);
960 class->pages_per_zspage = get_pages_per_zspage(size); 1035 pool->size_class[i] = class;
961 1036
1037 prev_class = class;
962 } 1038 }
963 1039
964 pool->flags = flags; 1040 pool->flags = flags;
965 1041
966 return pool; 1042 return pool;
1043
1044err:
1045 zs_destroy_pool(pool);
1046 return NULL;
967} 1047}
968EXPORT_SYMBOL_GPL(zs_create_pool); 1048EXPORT_SYMBOL_GPL(zs_create_pool);
969 1049
@@ -971,9 +1051,15 @@ void zs_destroy_pool(struct zs_pool *pool)
971{ 1051{
972 int i; 1052 int i;
973 1053
974 for (i = 0; i < ZS_SIZE_CLASSES; i++) { 1054 for (i = 0; i < zs_size_classes; i++) {
975 int fg; 1055 int fg;
976 struct size_class *class = &pool->size_class[i]; 1056 struct size_class *class = pool->size_class[i];
1057
1058 if (!class)
1059 continue;
1060
1061 if (class->index != i)
1062 continue;
977 1063
978 for (fg = 0; fg < _ZS_NR_FULLNESS_GROUPS; fg++) { 1064 for (fg = 0; fg < _ZS_NR_FULLNESS_GROUPS; fg++) {
979 if (class->fullness_list[fg]) { 1065 if (class->fullness_list[fg]) {
@@ -981,7 +1067,10 @@ void zs_destroy_pool(struct zs_pool *pool)
981 class->size, fg); 1067 class->size, fg);
982 } 1068 }
983 } 1069 }
1070 kfree(class);
984 } 1071 }
1072
1073 kfree(pool->size_class);
985 kfree(pool); 1074 kfree(pool);
986} 1075}
987EXPORT_SYMBOL_GPL(zs_destroy_pool); 1076EXPORT_SYMBOL_GPL(zs_destroy_pool);
@@ -999,8 +1088,8 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size)
999{ 1088{
1000 unsigned long obj; 1089 unsigned long obj;
1001 struct link_free *link; 1090 struct link_free *link;
1002 int class_idx;
1003 struct size_class *class; 1091 struct size_class *class;
1092 void *vaddr;
1004 1093
1005 struct page *first_page, *m_page; 1094 struct page *first_page, *m_page;
1006 unsigned long m_objidx, m_offset; 1095 unsigned long m_objidx, m_offset;
@@ -1008,9 +1097,7 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size)
1008 if (unlikely(!size || size > ZS_MAX_ALLOC_SIZE)) 1097 if (unlikely(!size || size > ZS_MAX_ALLOC_SIZE))
1009 return 0; 1098 return 0;
1010 1099
1011 class_idx = get_size_class_index(size); 1100 class = pool->size_class[get_size_class_index(size)];
1012 class = &pool->size_class[class_idx];
1013 BUG_ON(class_idx != class->index);
1014 1101
1015 spin_lock(&class->lock); 1102 spin_lock(&class->lock);
1016 first_page = find_get_zspage(class); 1103 first_page = find_get_zspage(class);
@@ -1031,11 +1118,11 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size)
1031 obj_handle_to_location(obj, &m_page, &m_objidx); 1118 obj_handle_to_location(obj, &m_page, &m_objidx);
1032 m_offset = obj_idx_to_offset(m_page, m_objidx, class->size); 1119 m_offset = obj_idx_to_offset(m_page, m_objidx, class->size);
1033 1120
1034 link = (struct link_free *)kmap_atomic(m_page) + 1121 vaddr = kmap_atomic(m_page);
1035 m_offset / sizeof(*link); 1122 link = (struct link_free *)vaddr + m_offset / sizeof(*link);
1036 first_page->freelist = link->next; 1123 first_page->freelist = link->next;
1037 memset(link, POISON_INUSE, sizeof(*link)); 1124 memset(link, POISON_INUSE, sizeof(*link));
1038 kunmap_atomic(link); 1125 kunmap_atomic(vaddr);
1039 1126
1040 first_page->inuse++; 1127 first_page->inuse++;
1041 /* Now move the zspage to another fullness group, if required */ 1128 /* Now move the zspage to another fullness group, if required */
@@ -1051,6 +1138,7 @@ void zs_free(struct zs_pool *pool, unsigned long obj)
1051 struct link_free *link; 1138 struct link_free *link;
1052 struct page *first_page, *f_page; 1139 struct page *first_page, *f_page;
1053 unsigned long f_objidx, f_offset; 1140 unsigned long f_objidx, f_offset;
1141 void *vaddr;
1054 1142
1055 int class_idx; 1143 int class_idx;
1056 struct size_class *class; 1144 struct size_class *class;
@@ -1063,16 +1151,16 @@ void zs_free(struct zs_pool *pool, unsigned long obj)
1063 first_page = get_first_page(f_page); 1151 first_page = get_first_page(f_page);
1064 1152
1065 get_zspage_mapping(first_page, &class_idx, &fullness); 1153 get_zspage_mapping(first_page, &class_idx, &fullness);
1066 class = &pool->size_class[class_idx]; 1154 class = pool->size_class[class_idx];
1067 f_offset = obj_idx_to_offset(f_page, f_objidx, class->size); 1155 f_offset = obj_idx_to_offset(f_page, f_objidx, class->size);
1068 1156
1069 spin_lock(&class->lock); 1157 spin_lock(&class->lock);
1070 1158
1071 /* Insert this object in containing zspage's freelist */ 1159 /* Insert this object in containing zspage's freelist */
1072 link = (struct link_free *)((unsigned char *)kmap_atomic(f_page) 1160 vaddr = kmap_atomic(f_page);
1073 + f_offset); 1161 link = (struct link_free *)(vaddr + f_offset);
1074 link->next = first_page->freelist; 1162 link->next = first_page->freelist;
1075 kunmap_atomic(link); 1163 kunmap_atomic(vaddr);
1076 first_page->freelist = (void *)obj; 1164 first_page->freelist = (void *)obj;
1077 1165
1078 first_page->inuse--; 1166 first_page->inuse--;
@@ -1124,7 +1212,7 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle,
1124 1212
1125 obj_handle_to_location(handle, &page, &obj_idx); 1213 obj_handle_to_location(handle, &page, &obj_idx);
1126 get_zspage_mapping(get_first_page(page), &class_idx, &fg); 1214 get_zspage_mapping(get_first_page(page), &class_idx, &fg);
1127 class = &pool->size_class[class_idx]; 1215 class = pool->size_class[class_idx];
1128 off = obj_idx_to_offset(page, obj_idx, class->size); 1216 off = obj_idx_to_offset(page, obj_idx, class->size);
1129 1217
1130 area = &get_cpu_var(zs_map_area); 1218 area = &get_cpu_var(zs_map_area);
@@ -1158,7 +1246,7 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
1158 1246
1159 obj_handle_to_location(handle, &page, &obj_idx); 1247 obj_handle_to_location(handle, &page, &obj_idx);
1160 get_zspage_mapping(get_first_page(page), &class_idx, &fg); 1248 get_zspage_mapping(get_first_page(page), &class_idx, &fg);
1161 class = &pool->size_class[class_idx]; 1249 class = pool->size_class[class_idx];
1162 off = obj_idx_to_offset(page, obj_idx, class->size); 1250 off = obj_idx_to_offset(page, obj_idx, class->size);
1163 1251
1164 area = this_cpu_ptr(&zs_map_area); 1252 area = this_cpu_ptr(&zs_map_area);