@@ -113,6 +113,7 @@ struct pcpu_chunk {
113113 void * data ; /* chunk data */
114114 int first_free ; /* no free below this */
115115 bool immutable ; /* no [de]population allowed */
116+ int nr_populated ; /* # of populated pages */
116117 unsigned long populated []; /* populated bitmap */
117118};
118119
@@ -161,6 +162,12 @@ static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop */
161162
162163static struct list_head * pcpu_slot __read_mostly ; /* chunk list slots */
163164
165+ /*
166+ * The number of empty populated pages, protected by pcpu_lock. The
167+ * reserved chunk doesn't contribute to the count.
168+ */
169+ static int pcpu_nr_empty_pop_pages ;
170+
164171/* reclaim work to release fully free chunks, scheduled from free path */
165172static void pcpu_reclaim (struct work_struct * work );
166173static DECLARE_WORK (pcpu_reclaim_work , pcpu_reclaim );
@@ -295,6 +302,38 @@ static void pcpu_mem_free(void *ptr, size_t size)
295302 vfree (ptr );
296303}
297304
305+ /**
306+ * pcpu_count_occupied_pages - count the number of pages an area occupies
307+ * @chunk: chunk of interest
308+ * @i: index of the area in question
309+ *
310+ * Count the number of pages chunk's @i'th area occupies. When the area's
311+ * start and/or end address isn't aligned to page boundary, the straddled
312+ * page is included in the count iff the rest of the page is free.
313+ */
314+ static int pcpu_count_occupied_pages (struct pcpu_chunk * chunk , int i )
315+ {
316+ int off = chunk -> map [i ] & ~1 ;
317+ int end = chunk -> map [i + 1 ] & ~1 ;
318+
319+ if (!PAGE_ALIGNED (off ) && i > 0 ) {
320+ int prev = chunk -> map [i - 1 ];
321+
322+ if (!(prev & 1 ) && prev <= round_down (off , PAGE_SIZE ))
323+ off = round_down (off , PAGE_SIZE );
324+ }
325+
326+ if (!PAGE_ALIGNED (end ) && i + 1 < chunk -> map_used ) {
327+ int next = chunk -> map [i + 1 ];
328+ int nend = chunk -> map [i + 2 ] & ~1 ;
329+
330+ if (!(next & 1 ) && nend >= round_up (end , PAGE_SIZE ))
331+ end = round_up (end , PAGE_SIZE );
332+ }
333+
334+ return max_t (int , PFN_DOWN (end ) - PFN_UP (off ), 0 );
335+ }
336+
298337/**
299338 * pcpu_chunk_relocate - put chunk in the appropriate chunk slot
300339 * @chunk: chunk of interest
@@ -483,6 +522,7 @@ static int pcpu_fit_in_area(struct pcpu_chunk *chunk, int off, int this_size,
483522 * @size: wanted size in bytes
484523 * @align: wanted align
485524 * @pop_only: allocate only from the populated area
525+ * @occ_pages_p: out param for the number of pages the area occupies
486526 *
487527 * Try to allocate @size bytes area aligned at @align from @chunk.
488528 * Note that this function only allocates the offset. It doesn't
@@ -498,7 +538,7 @@ static int pcpu_fit_in_area(struct pcpu_chunk *chunk, int off, int this_size,
498538 * found.
499539 */
500540static int pcpu_alloc_area (struct pcpu_chunk * chunk , int size , int align ,
501- bool pop_only )
541+ bool pop_only , int * occ_pages_p )
502542{
503543 int oslot = pcpu_chunk_slot (chunk );
504544 int max_contig = 0 ;
@@ -587,6 +627,7 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align,
587627 chunk -> free_size -= size ;
588628 * p |= 1 ;
589629
630+ * occ_pages_p = pcpu_count_occupied_pages (chunk , i );
590631 pcpu_chunk_relocate (chunk , oslot );
591632 return off ;
592633 }
@@ -602,6 +643,7 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align,
602643 * pcpu_free_area - free area to a pcpu_chunk
603644 * @chunk: chunk of interest
604645 * @freeme: offset of area to free
646+ * @occ_pages_p: out param for the number of pages the area occupies
605647 *
606648 * Free area starting from @freeme to @chunk. Note that this function
607649 * only modifies the allocation map. It doesn't depopulate or unmap
@@ -610,7 +652,8 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align,
610652 * CONTEXT:
611653 * pcpu_lock.
612654 */
613- static void pcpu_free_area (struct pcpu_chunk * chunk , int freeme )
655+ static void pcpu_free_area (struct pcpu_chunk * chunk , int freeme ,
656+ int * occ_pages_p )
614657{
615658 int oslot = pcpu_chunk_slot (chunk );
616659 int off = 0 ;
@@ -641,6 +684,8 @@ static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme)
641684 * p = off &= ~1 ;
642685 chunk -> free_size += (p [1 ] & ~1 ) - off ;
643686
687+ * occ_pages_p = pcpu_count_occupied_pages (chunk , i );
688+
644689 /* merge with next? */
645690 if (!(p [1 ] & 1 ))
646691 to_free ++ ;
@@ -696,6 +741,50 @@ static void pcpu_free_chunk(struct pcpu_chunk *chunk)
696741 pcpu_mem_free (chunk , pcpu_chunk_struct_size );
697742}
698743
744+ /**
745+ * pcpu_chunk_populated - post-population bookkeeping
746+ * @chunk: pcpu_chunk which got populated
747+ * @page_start: the start page
748+ * @page_end: the end page
749+ *
750+ * Pages in [@page_start,@page_end) have been populated to @chunk. Update
751+ * the bookkeeping information accordingly. Must be called after each
752+ * successful population.
753+ */
754+ static void pcpu_chunk_populated (struct pcpu_chunk * chunk ,
755+ int page_start , int page_end )
756+ {
757+ int nr = page_end - page_start ;
758+
759+ lockdep_assert_held (& pcpu_lock );
760+
761+ bitmap_set (chunk -> populated , page_start , nr );
762+ chunk -> nr_populated += nr ;
763+ pcpu_nr_empty_pop_pages += nr ;
764+ }
765+
766+ /**
767+ * pcpu_chunk_depopulated - post-depopulation bookkeeping
768+ * @chunk: pcpu_chunk which got depopulated
769+ * @page_start: the start page
770+ * @page_end: the end page
771+ *
772+ * Pages in [@page_start,@page_end) have been depopulated from @chunk.
773+ * Update the bookkeeping information accordingly. Must be called after
774+ * each successful depopulation.
775+ */
776+ static void pcpu_chunk_depopulated (struct pcpu_chunk * chunk ,
777+ int page_start , int page_end )
778+ {
779+ int nr = page_end - page_start ;
780+
781+ lockdep_assert_held (& pcpu_lock );
782+
783+ bitmap_clear (chunk -> populated , page_start , nr );
784+ chunk -> nr_populated -= nr ;
785+ pcpu_nr_empty_pop_pages -= nr ;
786+ }
787+
699788/*
700789 * Chunk management implementation.
701790 *
@@ -772,6 +861,7 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
772861 struct pcpu_chunk * chunk ;
773862 const char * err ;
774863 bool is_atomic = !(gfp & GFP_KERNEL );
864+ int occ_pages = 0 ;
775865 int slot , off , new_alloc , cpu , ret ;
776866 unsigned long flags ;
777867 void __percpu * ptr ;
@@ -812,7 +902,8 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
812902 spin_lock_irqsave (& pcpu_lock , flags );
813903 }
814904
815- off = pcpu_alloc_area (chunk , size , align , is_atomic );
905+ off = pcpu_alloc_area (chunk , size , align , is_atomic ,
906+ & occ_pages );
816907 if (off >= 0 )
817908 goto area_found ;
818909
@@ -845,7 +936,8 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
845936 goto restart ;
846937 }
847938
848- off = pcpu_alloc_area (chunk , size , align , is_atomic );
939+ off = pcpu_alloc_area (chunk , size , align , is_atomic ,
940+ & occ_pages );
849941 if (off >= 0 )
850942 goto area_found ;
851943 }
@@ -899,17 +991,20 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
899991 spin_lock_irqsave (& pcpu_lock , flags );
900992 if (ret ) {
901993 mutex_unlock (& pcpu_alloc_mutex );
902- pcpu_free_area (chunk , off );
994+ pcpu_free_area (chunk , off , & occ_pages );
903995 err = "failed to populate" ;
904996 goto fail_unlock ;
905997 }
906- bitmap_set (chunk -> populated , rs , re - rs );
998+ pcpu_chunk_populated (chunk , rs , re );
907999 spin_unlock_irqrestore (& pcpu_lock , flags );
9081000 }
9091001
9101002 mutex_unlock (& pcpu_alloc_mutex );
9111003 }
9121004
1005+ if (chunk != pcpu_reserved_chunk )
1006+ pcpu_nr_empty_pop_pages -= occ_pages ;
1007+
9131008 /* clear the areas and return address relative to base address */
9141009 for_each_possible_cpu (cpu )
9151010 memset ((void * )pcpu_chunk_addr (chunk , cpu , 0 ) + off , 0 , size );
@@ -1019,7 +1114,9 @@ static void pcpu_reclaim(struct work_struct *work)
10191114
10201115 pcpu_for_each_pop_region (chunk , rs , re , 0 , pcpu_unit_pages ) {
10211116 pcpu_depopulate_chunk (chunk , rs , re );
1022- bitmap_clear (chunk -> populated , rs , re - rs );
1117+ spin_lock_irq (& pcpu_lock );
1118+ pcpu_chunk_depopulated (chunk , rs , re );
1119+ spin_unlock_irq (& pcpu_lock );
10231120 }
10241121 pcpu_destroy_chunk (chunk );
10251122 }
@@ -1041,7 +1138,7 @@ void free_percpu(void __percpu *ptr)
10411138 void * addr ;
10421139 struct pcpu_chunk * chunk ;
10431140 unsigned long flags ;
1044- int off ;
1141+ int off , occ_pages ;
10451142
10461143 if (!ptr )
10471144 return ;
@@ -1055,7 +1152,10 @@ void free_percpu(void __percpu *ptr)
10551152 chunk = pcpu_chunk_addr_search (addr );
10561153 off = addr - chunk -> base_addr ;
10571154
1058- pcpu_free_area (chunk , off );
1155+ pcpu_free_area (chunk , off , & occ_pages );
1156+
1157+ if (chunk != pcpu_reserved_chunk )
1158+ pcpu_nr_empty_pop_pages += occ_pages ;
10591159
10601160 /* if there are more than one fully free chunks, wake up grim reaper */
10611161 if (chunk -> free_size == pcpu_unit_size ) {
@@ -1459,6 +1559,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
14591559 schunk -> map_alloc = ARRAY_SIZE (smap );
14601560 schunk -> immutable = true;
14611561 bitmap_fill (schunk -> populated , pcpu_unit_pages );
1562+ schunk -> nr_populated = pcpu_unit_pages ;
14621563
14631564 if (ai -> reserved_size ) {
14641565 schunk -> free_size = ai -> reserved_size ;
@@ -1488,6 +1589,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
14881589 dchunk -> map_alloc = ARRAY_SIZE (dmap );
14891590 dchunk -> immutable = true;
14901591 bitmap_fill (dchunk -> populated , pcpu_unit_pages );
1592+ dchunk -> nr_populated = pcpu_unit_pages ;
14911593
14921594 dchunk -> contig_hint = dchunk -> free_size = dyn_size ;
14931595 dchunk -> map [0 ] = 1 ;
@@ -1498,6 +1600,8 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
14981600
14991601 /* link the first chunk in */
15001602 pcpu_first_chunk = dchunk ?: schunk ;
1603+ pcpu_nr_empty_pop_pages +=
1604+ pcpu_count_occupied_pages (pcpu_first_chunk , 1 );
15011605 pcpu_chunk_relocate (pcpu_first_chunk , -1 );
15021606
15031607 /* we're done */
0 commit comments