LCOV - code coverage report
Current view: top level - mm - percpu-internal.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 3 100.0 %
Date: 2022-12-09 01:23:36 Functions: 0 0 -

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : #ifndef _MM_PERCPU_INTERNAL_H
       3             : #define _MM_PERCPU_INTERNAL_H
       4             : 
       5             : #include <linux/types.h>
       6             : #include <linux/percpu.h>
       7             : 
       8             : /*
       9             :  * pcpu_block_md is the metadata block struct.
      10             :  * Each chunk's bitmap is split into a number of full blocks.
      11             :  * All units are in terms of bits.
      12             :  *
      13             :  * The scan hint is the largest known contiguous area before the contig hint.
      14             :  * It is not necessarily the actual largest contig hint though.  There is an
      15             :  * invariant that the scan_hint_start > contig_hint_start iff
      16             :  * scan_hint == contig_hint.  This is necessary because when scanning forward,
      17             :  * we don't know if a new contig hint would be better than the current one.
      18             :  */
      19             : struct pcpu_block_md {
      20             :         int                     scan_hint;      /* scan hint for block */
      21             :         int                     scan_hint_start; /* block relative starting
      22             :                                                     position of the scan hint */
      23             :         int                     contig_hint;    /* contig hint for block */
      24             :         int                     contig_hint_start; /* block relative starting
      25             :                                                       position of the contig hint */
      26             :         int                     left_free;      /* size of free space along
      27             :                                                    the left side of the block */
      28             :         int                     right_free;     /* size of free space along
      29             :                                                    the right side of the block */
      30             :         int                     first_free;     /* block position of first free */
      31             :         int                     nr_bits;        /* total bits responsible for */
      32             : };
      33             : 
      34             : struct pcpu_chunk {
      35             : #ifdef CONFIG_PERCPU_STATS
      36             :         int                     nr_alloc;       /* # of allocations */
      37             :         size_t                  max_alloc_size; /* largest allocation size */
      38             : #endif
      39             : 
      40             :         struct list_head        list;           /* linked to pcpu_slot lists */
      41             :         int                     free_bytes;     /* free bytes in the chunk */
      42             :         struct pcpu_block_md    chunk_md;
      43             :         void                    *base_addr;     /* base address of this chunk */
      44             : 
      45             :         unsigned long           *alloc_map;     /* allocation map */
      46             :         unsigned long           *bound_map;     /* boundary map */
      47             :         struct pcpu_block_md    *md_blocks;     /* metadata blocks */
      48             : 
      49             :         void                    *data;          /* chunk data */
      50             :         bool                    immutable;      /* no [de]population allowed */
      51             :         bool                    isolated;       /* isolated from active chunk
      52             :                                                    slots */
      53             :         int                     start_offset;   /* the overlap with the previous
      54             :                                                    region to have a page aligned
      55             :                                                    base_addr */
      56             :         int                     end_offset;     /* additional area required to
      57             :                                                    have the region end page
      58             :                                                    aligned */
      59             : #ifdef CONFIG_MEMCG_KMEM
      60             :         struct obj_cgroup       **obj_cgroups;  /* vector of object cgroups */
      61             : #endif
      62             : 
      63             :         int                     nr_pages;       /* # of pages served by this chunk */
      64             :         int                     nr_populated;   /* # of populated pages */
      65             :         int                     nr_empty_pop_pages; /* # of empty populated pages */
      66             :         unsigned long           populated[];    /* populated bitmap */
      67             : };
      68             : 
      69             : extern spinlock_t pcpu_lock;
      70             : 
      71             : extern struct list_head *pcpu_chunk_lists;
      72             : extern int pcpu_nr_slots;
      73             : extern int pcpu_sidelined_slot;
      74             : extern int pcpu_to_depopulate_slot;
      75             : extern int pcpu_nr_empty_pop_pages;
      76             : 
      77             : extern struct pcpu_chunk *pcpu_first_chunk;
      78             : extern struct pcpu_chunk *pcpu_reserved_chunk;
      79             : 
      80             : /**
      81             :  * pcpu_chunk_nr_blocks - converts nr_pages to # of md_blocks
      82             :  * @chunk: chunk of interest
      83             :  *
      84             :  * This conversion is from the number of physical pages that the chunk
      85             :  * serves to the number of bitmap blocks used.
      86             :  */
      87             : static inline int pcpu_chunk_nr_blocks(struct pcpu_chunk *chunk)
      88             : {
      89        1575 :         return chunk->nr_pages * PAGE_SIZE / PCPU_BITMAP_BLOCK_SIZE;
      90             : }
      91             : 
      92             : /**
      93             :  * pcpu_nr_pages_to_map_bits - converts the pages to size of bitmap
      94             :  * @pages: number of physical pages
      95             :  *
      96             :  * This conversion is from physical pages to the number of bits
      97             :  * required in the bitmap.
      98             :  */
      99             : static inline int pcpu_nr_pages_to_map_bits(int pages)
     100             : {
     101        1143 :         return pages * PAGE_SIZE / PCPU_MIN_ALLOC_SIZE;
     102             : }
     103             : 
     104             : /**
     105             :  * pcpu_chunk_map_bits - helper to convert nr_pages to size of bitmap
     106             :  * @chunk: chunk of interest
     107             :  *
     108             :  * This conversion is from the number of physical pages that the chunk
     109             :  * serves to the number of bits in the bitmap.
     110             :  */
     111             : static inline int pcpu_chunk_map_bits(struct pcpu_chunk *chunk)
     112             : {
     113        2286 :         return pcpu_nr_pages_to_map_bits(chunk->nr_pages);
     114             : }
     115             : 
     116             : #ifdef CONFIG_MEMCG_KMEM
     117             : /**
     118             :  * pcpu_obj_full_size - helper to calculate size of each accounted object
     119             :  * @size: size of area to allocate in bytes
     120             :  *
     121             :  * For each accounted object there is an extra space which is used to store
     122             :  * obj_cgroup membership. Charge it too.
     123             :  */
     124             : static inline size_t pcpu_obj_full_size(size_t size)
     125             : {
     126             :         size_t extra_size;
     127             : 
     128             :         extra_size = size / PCPU_MIN_ALLOC_SIZE * sizeof(struct obj_cgroup *);
     129             : 
     130             :         return size * num_possible_cpus() + extra_size;
     131             : }
     132             : #endif /* CONFIG_MEMCG_KMEM */
     133             : 
     134             : #ifdef CONFIG_PERCPU_STATS
     135             : 
     136             : #include <linux/spinlock.h>
     137             : 
     138             : struct percpu_stats {
     139             :         u64 nr_alloc;           /* lifetime # of allocations */
     140             :         u64 nr_dealloc;         /* lifetime # of deallocations */
     141             :         u64 nr_cur_alloc;       /* current # of allocations */
     142             :         u64 nr_max_alloc;       /* max # of live allocations */
     143             :         u32 nr_chunks;          /* current # of live chunks */
     144             :         u32 nr_max_chunks;      /* max # of live chunks */
     145             :         size_t min_alloc_size;  /* min allocation size */
     146             :         size_t max_alloc_size;  /* max allocation size */
     147             : };
     148             : 
     149             : extern struct percpu_stats pcpu_stats;
     150             : extern struct pcpu_alloc_info pcpu_stats_ai;
     151             : 
     152             : /*
     153             :  * For debug purposes. We don't care about the flexible array.
     154             :  */
     155             : static inline void pcpu_stats_save_ai(const struct pcpu_alloc_info *ai)
     156             : {
     157             :         memcpy(&pcpu_stats_ai, ai, sizeof(struct pcpu_alloc_info));
     158             : 
     159             :         /* initialize min_alloc_size to unit_size */
     160             :         pcpu_stats.min_alloc_size = pcpu_stats_ai.unit_size;
     161             : }
     162             : 
     163             : /*
     164             :  * pcpu_stats_area_alloc - increment area allocation stats
     165             :  * @chunk: the location of the area being allocated
     166             :  * @size: size of area to allocate in bytes
     167             :  *
     168             :  * CONTEXT:
     169             :  * pcpu_lock.
     170             :  */
     171             : static inline void pcpu_stats_area_alloc(struct pcpu_chunk *chunk, size_t size)
     172             : {
     173             :         lockdep_assert_held(&pcpu_lock);
     174             : 
     175             :         pcpu_stats.nr_alloc++;
     176             :         pcpu_stats.nr_cur_alloc++;
     177             :         pcpu_stats.nr_max_alloc =
     178             :                 max(pcpu_stats.nr_max_alloc, pcpu_stats.nr_cur_alloc);
     179             :         pcpu_stats.min_alloc_size =
     180             :                 min(pcpu_stats.min_alloc_size, size);
     181             :         pcpu_stats.max_alloc_size =
     182             :                 max(pcpu_stats.max_alloc_size, size);
     183             : 
     184             :         chunk->nr_alloc++;
     185             :         chunk->max_alloc_size = max(chunk->max_alloc_size, size);
     186             : }
     187             : 
     188             : /*
     189             :  * pcpu_stats_area_dealloc - decrement allocation stats
     190             :  * @chunk: the location of the area being deallocated
     191             :  *
     192             :  * CONTEXT:
     193             :  * pcpu_lock.
     194             :  */
     195             : static inline void pcpu_stats_area_dealloc(struct pcpu_chunk *chunk)
     196             : {
     197             :         lockdep_assert_held(&pcpu_lock);
     198             : 
     199             :         pcpu_stats.nr_dealloc++;
     200             :         pcpu_stats.nr_cur_alloc--;
     201             : 
     202             :         chunk->nr_alloc--;
     203             : }
     204             : 
     205             : /*
     206             :  * pcpu_stats_chunk_alloc - increment chunk stats
     207             :  */
     208             : static inline void pcpu_stats_chunk_alloc(void)
     209             : {
     210             :         unsigned long flags;
     211             :         spin_lock_irqsave(&pcpu_lock, flags);
     212             : 
     213             :         pcpu_stats.nr_chunks++;
     214             :         pcpu_stats.nr_max_chunks =
     215             :                 max(pcpu_stats.nr_max_chunks, pcpu_stats.nr_chunks);
     216             : 
     217             :         spin_unlock_irqrestore(&pcpu_lock, flags);
     218             : }
     219             : 
     220             : /*
     221             :  * pcpu_stats_chunk_dealloc - decrement chunk stats
     222             :  */
     223             : static inline void pcpu_stats_chunk_dealloc(void)
     224             : {
     225             :         unsigned long flags;
     226             :         spin_lock_irqsave(&pcpu_lock, flags);
     227             : 
     228             :         pcpu_stats.nr_chunks--;
     229             : 
     230             :         spin_unlock_irqrestore(&pcpu_lock, flags);
     231             : }
     232             : 
     233             : #else
     234             : 
     235             : static inline void pcpu_stats_save_ai(const struct pcpu_alloc_info *ai)
     236             : {
     237             : }
     238             : 
     239             : static inline void pcpu_stats_area_alloc(struct pcpu_chunk *chunk, size_t size)
     240             : {
     241             : }
     242             : 
     243             : static inline void pcpu_stats_area_dealloc(struct pcpu_chunk *chunk)
     244             : {
     245             : }
     246             : 
     247             : static inline void pcpu_stats_chunk_alloc(void)
     248             : {
     249             : }
     250             : 
     251             : static inline void pcpu_stats_chunk_dealloc(void)
     252             : {
     253             : }
     254             : 
     255             : #endif /* !CONFIG_PERCPU_STATS */
     256             : 
     257             : #endif

Generated by: LCOV version 1.14