Skip to content

Commit 0760fa3

Browse files
rgushchindennisszhou
authored andcommitted
percpu: make pcpu_nr_empty_pop_pages per chunk type
nr_empty_pop_pages is used to guarantee that there are some free populated pages to satisfy atomic allocations. Accounted and non-accounted allocations are using separate sets of chunks, so both need to have a surplus of empty pages. This commit makes pcpu_nr_empty_pop_pages and the corresponding logic per chunk type. [Dennis] This issue came up as I was reviewing [1] and realized I missed this. Simultaneously, it was reported btrfs was seeing failed atomic allocations in fsstress tests [2] and [3]. [1] https://lore.kernel.org/linux-mm/[email protected]/ [2] https://lore.kernel.org/linux-mm/[email protected]/ [3] https://lore.kernel.org/linux-mm/CAL3q7H5RNBjCi708GH7jnczAOe0BLnacT9C+OBgA-Dx9jhB6SQ@mail.gmail.com/ Fixes: 3c7be18 ("mm: memcg/percpu: account percpu memory to memory cgroups") Cc: [email protected] # 5.9+ Signed-off-by: Roman Gushchin <[email protected]> Tested-by: Filipe Manana <[email protected]> Signed-off-by: Dennis Zhou <[email protected]>
1 parent e49d033 commit 0760fa3

File tree

3 files changed

+15
-10
lines changed

3 files changed

+15
-10
lines changed

mm/percpu-internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ extern spinlock_t pcpu_lock;
8787

8888
extern struct list_head *pcpu_chunk_lists;
8989
extern int pcpu_nr_slots;
90-
extern int pcpu_nr_empty_pop_pages;
90+
extern int pcpu_nr_empty_pop_pages[];
9191

9292
extern struct pcpu_chunk *pcpu_first_chunk;
9393
extern struct pcpu_chunk *pcpu_reserved_chunk;

mm/percpu-stats.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ static int percpu_stats_show(struct seq_file *m, void *v)
145145
int slot, max_nr_alloc;
146146
int *buffer;
147147
enum pcpu_chunk_type type;
148+
int nr_empty_pop_pages;
148149

149150
alloc_buffer:
150151
spin_lock_irq(&pcpu_lock);
@@ -165,7 +166,11 @@ static int percpu_stats_show(struct seq_file *m, void *v)
165166
goto alloc_buffer;
166167
}
167168

168-
#define PL(X) \
169+
nr_empty_pop_pages = 0;
170+
for (type = 0; type < PCPU_NR_CHUNK_TYPES; type++)
171+
nr_empty_pop_pages += pcpu_nr_empty_pop_pages[type];
172+
173+
#define PL(X) \
169174
seq_printf(m, " %-20s: %12lld\n", #X, (long long int)pcpu_stats_ai.X)
170175

171176
seq_printf(m,
@@ -196,7 +201,7 @@ static int percpu_stats_show(struct seq_file *m, void *v)
196201
PU(nr_max_chunks);
197202
PU(min_alloc_size);
198203
PU(max_alloc_size);
199-
P("empty_pop_pages", pcpu_nr_empty_pop_pages);
204+
P("empty_pop_pages", nr_empty_pop_pages);
200205
seq_putc(m, '\n');
201206

202207
#undef PU

mm/percpu.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,10 @@ struct list_head *pcpu_chunk_lists __ro_after_init; /* chunk list slots */
173173
static LIST_HEAD(pcpu_map_extend_chunks);
174174

175175
/*
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.
178178
*/
179-
int pcpu_nr_empty_pop_pages;
179+
int pcpu_nr_empty_pop_pages[PCPU_NR_CHUNK_TYPES];
180180

181181
/*
182182
* The number of populated pages in use by the allocator, protected by
@@ -556,7 +556,7 @@ static inline void pcpu_update_empty_pages(struct pcpu_chunk *chunk, int nr)
556556
{
557557
chunk->nr_empty_pop_pages += nr;
558558
if (chunk != pcpu_reserved_chunk)
559-
pcpu_nr_empty_pop_pages += nr;
559+
pcpu_nr_empty_pop_pages[pcpu_chunk_type(chunk)] += nr;
560560
}
561561

562562
/*
@@ -1832,7 +1832,7 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
18321832
mutex_unlock(&pcpu_alloc_mutex);
18331833
}
18341834

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)
18361836
pcpu_schedule_balance_work();
18371837

18381838
/* clear the areas and return address relative to base address */
@@ -2000,7 +2000,7 @@ static void __pcpu_balance_workfn(enum pcpu_chunk_type type)
20002000
pcpu_atomic_alloc_failed = false;
20012001
} else {
20022002
nr_to_pop = clamp(PCPU_EMPTY_POP_PAGES_HIGH -
2003-
pcpu_nr_empty_pop_pages,
2003+
pcpu_nr_empty_pop_pages[type],
20042004
0, PCPU_EMPTY_POP_PAGES_HIGH);
20052005
}
20062006

@@ -2580,7 +2580,7 @@ void __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
25802580

25812581
/* link the first chunk in */
25822582
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;
25842584
pcpu_chunk_relocate(pcpu_first_chunk, -1);
25852585

25862586
/* include all regions of the first chunk */

0 commit comments

Comments
 (0)