7373 */
7474#define ZS_ALIGN 8
7575
76- /*
77- * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single)
78- * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N.
79- */
80- #define ZS_MAX_ZSPAGE_ORDER 2
81- #define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER)
76+ #define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_PAGE_ORDER)
8277
8378#define ZS_HANDLE_SIZE (sizeof(unsigned long))
8479
123118#define ISOLATED_BITS 3
124119#define MAGIC_VAL_BITS 8
125120
126- #define MAX (a , b ) ((a) >= (b) ? (a) : (b))
127- /* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */
128- #define ZS_MIN_ALLOC_SIZE \
129- MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
121+ #define ZS_MIN_ALLOC_SIZE 32U
122+
130123/* each chunk includes extra space to keep handle */
131124#define ZS_MAX_ALLOC_SIZE PAGE_SIZE
132125
140133 * determined). NOTE: all those class sizes must be set as multiple of
141134 * ZS_ALIGN to make sure link_free itself never has to span 2 pages.
142135 *
143- * ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN
144- * (reason above)
136+ * pool->min_alloc_size ( ZS_MIN_ALLOC_SIZE) and ZS_SIZE_CLASS_DELTA must
137+ * be multiple of ZS_ALIGN (reason above)
145138 */
146139#define ZS_SIZE_CLASS_DELTA (PAGE_SIZE >> CLASS_BITS)
147- #define ZS_SIZE_CLASSES (DIV_ROUND_UP(ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE, \
148- ZS_SIZE_CLASS_DELTA) + 1)
149140
150141enum fullness_group {
151142 ZS_EMPTY ,
@@ -234,12 +225,15 @@ struct zs_ops {
234225struct zs_pool {
235226 const char * name ;
236227
237- struct size_class * size_class [ ZS_SIZE_CLASSES ] ;
228+ struct size_class * * size_class ;
238229 struct kmem_cache * handle_cachep ;
239230 struct kmem_cache * zspage_cachep ;
240231
241232 atomic_long_t pages_allocated ;
242233
234+ u32 num_size_classes ;
235+ u32 min_alloc_size ;
236+
243237 struct zs_pool_stats stats ;
244238
245239 /* Compact classes */
@@ -595,15 +589,15 @@ static void set_zspage_mapping(struct zspage *zspage,
595589 * classes depending on its size. This function returns index of the
596590 * size class which has chunk size big enough to hold the given size.
597591 */
598- static int get_size_class_index (int size )
592+ static int get_size_class_index (struct zs_pool * pool , int size )
599593{
600594 int idx = 0 ;
601595
602- if (likely (size > ZS_MIN_ALLOC_SIZE ))
603- idx = DIV_ROUND_UP (size - ZS_MIN_ALLOC_SIZE ,
596+ if (likely (size > pool -> min_alloc_size ))
597+ idx = DIV_ROUND_UP (size - pool -> min_alloc_size ,
604598 ZS_SIZE_CLASS_DELTA );
605599
606- return min_t (int , ZS_SIZE_CLASSES - 1 , idx );
600+ return min_t (int , pool -> num_size_classes - 1 , idx );
607601}
608602
609603/* type can be of enum type class_stat_type or fullness_group */
@@ -663,7 +657,7 @@ static int zs_stats_size_show(struct seq_file *s, void *v)
663657 "obj_allocated" , "obj_used" , "pages_used" ,
664658 "pages_per_zspage" , "freeable" );
665659
666- for (i = 0 ; i < ZS_SIZE_CLASSES ; i ++ ) {
660+ for (i = 0 ; i < pool -> num_size_classes ; i ++ ) {
667661 class = pool -> size_class [i ];
668662
669663 if (class -> index != i )
@@ -849,13 +843,13 @@ static enum fullness_group fix_fullness_group(struct size_class *class,
849843 * link together 3 PAGE_SIZE sized pages to form a zspage
850844 * since then we can perfectly fit in 8 such objects.
851845 */
852- static int get_pages_per_zspage (int class_size )
846+ static int get_pages_per_zspage (u32 class_size , u32 num_pages )
853847{
854848 int i , max_usedpc = 0 ;
855849 /* zspage order which gives maximum used size per KB */
856850 int max_usedpc_order = 1 ;
857851
858- for (i = 1 ; i <= ZS_MAX_PAGES_PER_ZSPAGE ; i ++ ) {
852+ for (i = 1 ; i <= num_pages ; i ++ ) {
859853 int zspage_size ;
860854 int waste , usedpc ;
861855
@@ -1315,7 +1309,7 @@ unsigned int zs_lookup_class_index(struct zs_pool *pool, unsigned int size)
13151309{
13161310 struct size_class * class ;
13171311
1318- class = pool -> size_class [get_size_class_index (size )];
1312+ class = pool -> size_class [get_size_class_index (pool , size )];
13191313
13201314 return class -> index ;
13211315}
@@ -1526,7 +1520,7 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp)
15261520
15271521 /* extra space in chunk to keep the handle */
15281522 size += ZS_HANDLE_SIZE ;
1529- class = pool -> size_class [get_size_class_index (size )];
1523+ class = pool -> size_class [get_size_class_index (pool , size )];
15301524
15311525 /* pool->lock effectively protects the zpage migration */
15321526 spin_lock (& pool -> lock );
@@ -2102,7 +2096,7 @@ static void async_free_zspage(struct work_struct *work)
21022096 struct zs_pool * pool = container_of (work , struct zs_pool ,
21032097 free_work );
21042098
2105- for (i = 0 ; i < ZS_SIZE_CLASSES ; i ++ ) {
2099+ for (i = 0 ; i < pool -> num_size_classes ; i ++ ) {
21062100 class = pool -> size_class [i ];
21072101 if (class -> index != i )
21082102 continue ;
@@ -2250,7 +2244,7 @@ unsigned long zs_compact(struct zs_pool *pool)
22502244 struct size_class * class ;
22512245 unsigned long pages_freed = 0 ;
22522246
2253- for (i = ZS_SIZE_CLASSES - 1 ; i >= 0 ; i -- ) {
2247+ for (i = pool -> num_size_classes - 1 ; i >= 0 ; i -- ) {
22542248 class = pool -> size_class [i ];
22552249 if (class -> index != i )
22562250 continue ;
@@ -2294,7 +2288,7 @@ static unsigned long zs_shrinker_count(struct shrinker *shrinker,
22942288 struct zs_pool * pool = container_of (shrinker , struct zs_pool ,
22952289 shrinker );
22962290
2297- for (i = ZS_SIZE_CLASSES - 1 ; i >= 0 ; i -- ) {
2291+ for (i = pool -> num_size_classes - 1 ; i >= 0 ; i -- ) {
22982292 class = pool -> size_class [i ];
22992293 if (class -> index != i )
23002294 continue ;
@@ -2336,11 +2330,27 @@ struct zs_pool *zs_create_pool(const char *name)
23362330 int i ;
23372331 struct zs_pool * pool ;
23382332 struct size_class * prev_class = NULL ;
2333+ unsigned long num_pages ;
23392334
23402335 pool = kzalloc (sizeof (* pool ), GFP_KERNEL );
23412336 if (!pool )
23422337 return NULL ;
23432338
2339+ num_pages = 1UL << ZS_DEFAULT_PAGE_ORDER ;
2340+ /* min_alloc_size must be multiple of ZS_ALIGN */
2341+ pool -> min_alloc_size = num_pages << PAGE_SHIFT >> OBJ_INDEX_BITS ;
2342+ pool -> min_alloc_size = max (pool -> min_alloc_size , ZS_MIN_ALLOC_SIZE );
2343+
2344+ pool -> num_size_classes =
2345+ DIV_ROUND_UP (ZS_MAX_ALLOC_SIZE - pool -> min_alloc_size ,
2346+ ZS_SIZE_CLASS_DELTA ) + 1 ;
2347+
2348+ pool -> size_class = kmalloc_array (pool -> num_size_classes ,
2349+ sizeof (struct size_class * ),
2350+ GFP_KERNEL | __GFP_ZERO );
2351+ if (!pool -> size_class )
2352+ goto err ;
2353+
23442354 init_deferred_free (pool );
23452355 spin_lock_init (& pool -> lock );
23462356
@@ -2355,17 +2365,17 @@ struct zs_pool *zs_create_pool(const char *name)
23552365 * Iterate reversely, because, size of size_class that we want to use
23562366 * for merging should be larger or equal to current size.
23572367 */
2358- for (i = ZS_SIZE_CLASSES - 1 ; i >= 0 ; i -- ) {
2368+ for (i = pool -> num_size_classes - 1 ; i >= 0 ; i -- ) {
23592369 int size ;
23602370 int pages_per_zspage ;
23612371 int objs_per_zspage ;
23622372 struct size_class * class ;
23632373 int fullness = 0 ;
23642374
2365- size = ZS_MIN_ALLOC_SIZE + i * ZS_SIZE_CLASS_DELTA ;
2375+ size = pool -> min_alloc_size + i * ZS_SIZE_CLASS_DELTA ;
23662376 if (size > ZS_MAX_ALLOC_SIZE )
23672377 size = ZS_MAX_ALLOC_SIZE ;
2368- pages_per_zspage = get_pages_per_zspage (size );
2378+ pages_per_zspage = get_pages_per_zspage (size , num_pages );
23692379 objs_per_zspage = pages_per_zspage * PAGE_SIZE / size ;
23702380
23712381 /*
@@ -2450,7 +2460,7 @@ void zs_destroy_pool(struct zs_pool *pool)
24502460 zs_flush_migration (pool );
24512461 zs_pool_stat_destroy (pool );
24522462
2453- for (i = 0 ; i < ZS_SIZE_CLASSES ; i ++ ) {
2463+ for (i = 0 ; i < pool -> num_size_classes ; i ++ ) {
24542464 int fg ;
24552465 struct size_class * class = pool -> size_class [i ];
24562466
@@ -2470,6 +2480,7 @@ void zs_destroy_pool(struct zs_pool *pool)
24702480 }
24712481
24722482 destroy_cache (pool );
2483+ kfree (pool -> size_class );
24732484 kfree (pool -> name );
24742485 kfree (pool );
24752486}
0 commit comments