7474 */
7575#define ZS_ALIGN 8
7676
77- /*
78- * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single)
79- * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N.
80- */
81- #define ZS_MAX_ZSPAGE_ORDER 2
82- #define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER)
77+ #define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_PAGE_ORDER)
8378
8479#define ZS_HANDLE_SIZE (sizeof(unsigned long))
8580
124119#define ISOLATED_BITS 3
125120#define MAGIC_VAL_BITS 8
126121
127- #define MAX (a , b ) ((a) >= (b) ? (a) : (b))
128- /* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */
129- #define ZS_MIN_ALLOC_SIZE \
130- MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
122+ #define ZS_MIN_ALLOC_SIZE 32U
123+
131124/* each chunk includes extra space to keep handle */
132125#define ZS_MAX_ALLOC_SIZE PAGE_SIZE
133126
141134 * determined). NOTE: all those class sizes must be set as multiple of
142135 * ZS_ALIGN to make sure link_free itself never has to span 2 pages.
143136 *
144- * ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN
145- * (reason above)
137+ * pool->min_alloc_size ( ZS_MIN_ALLOC_SIZE) and ZS_SIZE_CLASS_DELTA must
138+ * be multiple of ZS_ALIGN (reason above)
146139 */
147140#define ZS_SIZE_CLASS_DELTA (PAGE_SIZE >> CLASS_BITS)
148- #define ZS_SIZE_CLASSES (DIV_ROUND_UP(ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE, \
149- ZS_SIZE_CLASS_DELTA) + 1)
150141
151142enum fullness_group {
152143 ZS_EMPTY ,
@@ -230,12 +221,15 @@ struct link_free {
230221struct zs_pool {
231222 const char * name ;
232223
233- struct size_class * size_class [ ZS_SIZE_CLASSES ] ;
224+ struct size_class * * size_class ;
234225 struct kmem_cache * handle_cachep ;
235226 struct kmem_cache * zspage_cachep ;
236227
237228 atomic_long_t pages_allocated ;
238229
230+ u32 num_size_classes ;
231+ u32 min_alloc_size ;
232+
239233 struct zs_pool_stats stats ;
240234
241235 /* Compact classes */
@@ -523,15 +517,15 @@ static void set_zspage_mapping(struct zspage *zspage,
523517 * classes depending on its size. This function returns index of the
524518 * size class which has chunk size big enough to hold the given size.
525519 */
526- static int get_size_class_index (int size )
520+ static int get_size_class_index (struct zs_pool * pool , int size )
527521{
528522 int idx = 0 ;
529523
530- if (likely (size > ZS_MIN_ALLOC_SIZE ))
531- idx = DIV_ROUND_UP (size - ZS_MIN_ALLOC_SIZE ,
524+ if (likely (size > pool -> min_alloc_size ))
525+ idx = DIV_ROUND_UP (size - pool -> min_alloc_size ,
532526 ZS_SIZE_CLASS_DELTA );
533527
534- return min_t (int , ZS_SIZE_CLASSES - 1 , idx );
528+ return min_t (int , pool -> num_size_classes - 1 , idx );
535529}
536530
537531/* type can be of enum type class_stat_type or fullness_group */
@@ -591,7 +585,7 @@ static int zs_stats_size_show(struct seq_file *s, void *v)
591585 "obj_allocated" , "obj_used" , "pages_used" ,
592586 "pages_per_zspage" , "freeable" );
593587
594- for (i = 0 ; i < ZS_SIZE_CLASSES ; i ++ ) {
588+ for (i = 0 ; i < pool -> num_size_classes ; i ++ ) {
595589 class = pool -> size_class [i ];
596590
597591 if (class -> index != i )
@@ -777,13 +771,13 @@ static enum fullness_group fix_fullness_group(struct size_class *class,
777771 * link together 3 PAGE_SIZE sized pages to form a zspage
778772 * since then we can perfectly fit in 8 such objects.
779773 */
780- static int get_pages_per_zspage (int class_size )
774+ static int get_pages_per_zspage (u32 class_size , u32 num_pages )
781775{
782776 int i , max_usedpc = 0 ;
783777 /* zspage order which gives maximum used size per KB */
784778 int max_usedpc_order = 1 ;
785779
786- for (i = 1 ; i <= ZS_MAX_PAGES_PER_ZSPAGE ; i ++ ) {
780+ for (i = 1 ; i <= num_pages ; i ++ ) {
787781 int zspage_size ;
788782 int waste , usedpc ;
789783
@@ -1220,7 +1214,7 @@ unsigned int zs_lookup_class_index(struct zs_pool *pool, unsigned int size)
12201214{
12211215 struct size_class * class ;
12221216
1223- class = pool -> size_class [get_size_class_index (size )];
1217+ class = pool -> size_class [get_size_class_index (pool , size )];
12241218
12251219 return class -> index ;
12261220}
@@ -1431,7 +1425,7 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp)
14311425
14321426 /* extra space in chunk to keep the handle */
14331427 size += ZS_HANDLE_SIZE ;
1434- class = pool -> size_class [get_size_class_index (size )];
1428+ class = pool -> size_class [get_size_class_index (pool , size )];
14351429
14361430 /* class->lock effectively protects the zpage migration */
14371431 spin_lock (& class -> lock );
@@ -1980,7 +1974,7 @@ static void async_free_zspage(struct work_struct *work)
19801974 struct zs_pool * pool = container_of (work , struct zs_pool ,
19811975 free_work );
19821976
1983- for (i = 0 ; i < ZS_SIZE_CLASSES ; i ++ ) {
1977+ for (i = 0 ; i < pool -> num_size_classes ; i ++ ) {
19841978 class = pool -> size_class [i ];
19851979 if (class -> index != i )
19861980 continue ;
@@ -2129,7 +2123,7 @@ unsigned long zs_compact(struct zs_pool *pool)
21292123 struct size_class * class ;
21302124 unsigned long pages_freed = 0 ;
21312125
2132- for (i = ZS_SIZE_CLASSES - 1 ; i >= 0 ; i -- ) {
2126+ for (i = pool -> num_size_classes - 1 ; i >= 0 ; i -- ) {
21332127 class = pool -> size_class [i ];
21342128 if (class -> index != i )
21352129 continue ;
@@ -2173,7 +2167,7 @@ static unsigned long zs_shrinker_count(struct shrinker *shrinker,
21732167 struct zs_pool * pool = container_of (shrinker , struct zs_pool ,
21742168 shrinker );
21752169
2176- for (i = ZS_SIZE_CLASSES - 1 ; i >= 0 ; i -- ) {
2170+ for (i = pool -> num_size_classes - 1 ; i >= 0 ; i -- ) {
21772171 class = pool -> size_class [i ];
21782172 if (class -> index != i )
21792173 continue ;
@@ -2215,11 +2209,27 @@ struct zs_pool *zs_create_pool(const char *name)
22152209 int i ;
22162210 struct zs_pool * pool ;
22172211 struct size_class * prev_class = NULL ;
2212+ unsigned long num_pages ;
22182213
22192214 pool = kzalloc (sizeof (* pool ), GFP_KERNEL );
22202215 if (!pool )
22212216 return NULL ;
22222217
2218+ num_pages = 1UL << ZS_DEFAULT_PAGE_ORDER ;
2219+ /* min_alloc_size must be multiple of ZS_ALIGN */
2220+ pool -> min_alloc_size = num_pages << PAGE_SHIFT >> OBJ_INDEX_BITS ;
2221+ pool -> min_alloc_size = max (pool -> min_alloc_size , ZS_MIN_ALLOC_SIZE );
2222+
2223+ pool -> num_size_classes =
2224+ DIV_ROUND_UP (ZS_MAX_ALLOC_SIZE - pool -> min_alloc_size ,
2225+ ZS_SIZE_CLASS_DELTA ) + 1 ;
2226+
2227+ pool -> size_class = kmalloc_array (pool -> num_size_classes ,
2228+ sizeof (struct size_class * ),
2229+ GFP_KERNEL | __GFP_ZERO );
2230+ if (!pool -> size_class )
2231+ goto err ;
2232+
22232233 init_deferred_free (pool );
22242234 rwlock_init (& pool -> migrate_lock );
22252235
@@ -2234,17 +2244,17 @@ struct zs_pool *zs_create_pool(const char *name)
22342244 * Iterate reversely, because, size of size_class that we want to use
22352245 * for merging should be larger or equal to current size.
22362246 */
2237- for (i = ZS_SIZE_CLASSES - 1 ; i >= 0 ; i -- ) {
2247+ for (i = pool -> num_size_classes - 1 ; i >= 0 ; i -- ) {
22382248 int size ;
22392249 int pages_per_zspage ;
22402250 int objs_per_zspage ;
22412251 struct size_class * class ;
22422252 int fullness = 0 ;
22432253
2244- size = ZS_MIN_ALLOC_SIZE + i * ZS_SIZE_CLASS_DELTA ;
2254+ size = pool -> min_alloc_size + i * ZS_SIZE_CLASS_DELTA ;
22452255 if (size > ZS_MAX_ALLOC_SIZE )
22462256 size = ZS_MAX_ALLOC_SIZE ;
2247- pages_per_zspage = get_pages_per_zspage (size );
2257+ pages_per_zspage = get_pages_per_zspage (size , num_pages );
22482258 objs_per_zspage = pages_per_zspage * PAGE_SIZE / size ;
22492259
22502260 /*
@@ -2328,7 +2338,7 @@ void zs_destroy_pool(struct zs_pool *pool)
23282338 zs_flush_migration (pool );
23292339 zs_pool_stat_destroy (pool );
23302340
2331- for (i = 0 ; i < ZS_SIZE_CLASSES ; i ++ ) {
2341+ for (i = 0 ; i < pool -> num_size_classes ; i ++ ) {
23322342 int fg ;
23332343 struct size_class * class = pool -> size_class [i ];
23342344
@@ -2348,6 +2358,7 @@ void zs_destroy_pool(struct zs_pool *pool)
23482358 }
23492359
23502360 destroy_cache (pool );
2361+ kfree (pool -> size_class );
23512362 kfree (pool -> name );
23522363 kfree (pool );
23532364}
0 commit comments