Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-5.12-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/dennis/percpu

Pull percpu fix from Dennis Zhou:
"This contains a fix for sporadically failing atomic percpu
allocations.

I only caught it recently while I was reviewing a new series [1] and
simultaneously saw reports by btrfs in xfstests [2] and [3].

In v5.9, memcg accounting was extended to percpu done by adding a
second type of chunk. I missed an interaction with the free page float
count used to ensure we can support atomic allocations. If one type of
chunk has no free pages, but the other has enough to satisfy the free
page float requirement, we will not repopulate the free pages for the
former type of chunk. This led to the sporadically failing atomic
allocations"

Link: https://lore.kernel.org/linux-mm/20210324190626.564297-1-guro@fb.com/ [1]
Link: https://lore.kernel.org/linux-mm/20210401185158.3275.409509F4@e16-tech.com/ [2]
Link: https://lore.kernel.org/linux-mm/CAL3q7H5RNBjCi708GH7jnczAOe0BLnacT9C+OBgA-Dx9jhB6SQ@mail.gmail.com/ [3]

* 'for-5.12-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/dennis/percpu:
percpu: make pcpu_nr_empty_pop_pages per chunk type

+15 -10
+1 -1
mm/percpu-internal.h
··· 87 87 88 88 extern struct list_head *pcpu_chunk_lists; 89 89 extern int pcpu_nr_slots; 90 - extern int pcpu_nr_empty_pop_pages; 90 + extern int pcpu_nr_empty_pop_pages[]; 91 91 92 92 extern struct pcpu_chunk *pcpu_first_chunk; 93 93 extern struct pcpu_chunk *pcpu_reserved_chunk;
+7 -2
mm/percpu-stats.c
··· 145 145 int slot, max_nr_alloc; 146 146 int *buffer; 147 147 enum pcpu_chunk_type type; 148 + int nr_empty_pop_pages; 148 149 149 150 alloc_buffer: 150 151 spin_lock_irq(&pcpu_lock); ··· 166 165 goto alloc_buffer; 167 166 } 168 167 169 - #define PL(X) \ 168 + nr_empty_pop_pages = 0; 169 + for (type = 0; type < PCPU_NR_CHUNK_TYPES; type++) 170 + nr_empty_pop_pages += pcpu_nr_empty_pop_pages[type]; 171 + 172 + #define PL(X) \ 170 173 seq_printf(m, " %-20s: %12lld\n", #X, (long long int)pcpu_stats_ai.X) 171 174 172 175 seq_printf(m, ··· 201 196 PU(nr_max_chunks); 202 197 PU(min_alloc_size); 203 198 PU(max_alloc_size); 204 - P("empty_pop_pages", pcpu_nr_empty_pop_pages); 199 + P("empty_pop_pages", nr_empty_pop_pages); 205 200 seq_putc(m, '\n'); 206 201 207 202 #undef PU
+7 -7
mm/percpu.c
··· 173 173 static LIST_HEAD(pcpu_map_extend_chunks); 174 174 175 175 /* 176 - * The number of empty populated pages, protected by pcpu_lock. The 177 - * reserved chunk doesn't contribute to the count. 176 + * The number of empty populated pages by chunk type, protected by pcpu_lock. 177 + * The reserved chunk doesn't contribute to the count. 178 178 */ 179 - int pcpu_nr_empty_pop_pages; 179 + int pcpu_nr_empty_pop_pages[PCPU_NR_CHUNK_TYPES]; 180 180 181 181 /* 182 182 * The number of populated pages in use by the allocator, protected by ··· 556 556 { 557 557 chunk->nr_empty_pop_pages += nr; 558 558 if (chunk != pcpu_reserved_chunk) 559 - pcpu_nr_empty_pop_pages += nr; 559 + pcpu_nr_empty_pop_pages[pcpu_chunk_type(chunk)] += nr; 560 560 } 561 561 562 562 /* ··· 1832 1832 mutex_unlock(&pcpu_alloc_mutex); 1833 1833 } 1834 1834 1835 - if (pcpu_nr_empty_pop_pages < PCPU_EMPTY_POP_PAGES_LOW) 1835 + if (pcpu_nr_empty_pop_pages[type] < PCPU_EMPTY_POP_PAGES_LOW) 1836 1836 pcpu_schedule_balance_work(); 1837 1837 1838 1838 /* clear the areas and return address relative to base address */ ··· 2000 2000 pcpu_atomic_alloc_failed = false; 2001 2001 } else { 2002 2002 nr_to_pop = clamp(PCPU_EMPTY_POP_PAGES_HIGH - 2003 - pcpu_nr_empty_pop_pages, 2003 + pcpu_nr_empty_pop_pages[type], 2004 2004 0, PCPU_EMPTY_POP_PAGES_HIGH); 2005 2005 } 2006 2006 ··· 2580 2580 2581 2581 /* link the first chunk in */ 2582 2582 pcpu_first_chunk = chunk; 2583 - pcpu_nr_empty_pop_pages = pcpu_first_chunk->nr_empty_pop_pages; 2583 + pcpu_nr_empty_pop_pages[PCPU_CHUNK_ROOT] = pcpu_first_chunk->nr_empty_pop_pages; 2584 2584 pcpu_chunk_relocate(pcpu_first_chunk, -1); 2585 2585 2586 2586 /* include all regions of the first chunk */