On Sat, Mar 02, 2019 at 01:55:54PM +0000, Peng Fan wrote: > Hi Dennis, > > > -----Original Message----- > > From: owner-linux-mm@xxxxxxxxx [mailto:owner-linux-mm@xxxxxxxxx] On > > Behalf Of Dennis Zhou > > Sent: 2019年2月28日 10:19 > > To: Dennis Zhou <dennis@xxxxxxxxxx>; Tejun Heo <tj@xxxxxxxxxx>; Christoph > > Lameter <cl@xxxxxxxxx> > > Cc: Vlad Buslov <vladbu@xxxxxxxxxxxx>; kernel-team@xxxxxx; > > linux-mm@xxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx > > Subject: [PATCH 05/12] percpu: relegate chunks unusable when failing small > > allocations > > > > In certain cases, requestors of percpu memory may want specific alignments. > > However, it is possible to end up in situations where the contig_hint matches, > > but the alignment does not. This causes excess scanning of chunks that will fail. > > To prevent this, if a small allocation fails (< 32B), the chunk is moved to the > > empty list. Once an allocation is freed from that chunk, it is placed back into > > rotation. > > > > Signed-off-by: Dennis Zhou <dennis@xxxxxxxxxx> > > --- > > mm/percpu.c | 35 ++++++++++++++++++++++++++--------- > > 1 file changed, 26 insertions(+), 9 deletions(-) > > > > diff --git a/mm/percpu.c b/mm/percpu.c > > index c996bcffbb2a..3d7deece9556 100644 > > --- a/mm/percpu.c > > +++ b/mm/percpu.c > > @@ -94,6 +94,8 @@ > > > > /* the slots are sorted by free bytes left, 1-31 bytes share the same slot */ > > #define PCPU_SLOT_BASE_SHIFT 5 > > +/* chunks in slots below this are subject to being sidelined on failed alloc */ > > +#define PCPU_SLOT_FAIL_THRESHOLD 3 > > > > #define PCPU_EMPTY_POP_PAGES_LOW 2 > > #define PCPU_EMPTY_POP_PAGES_HIGH 4 > > @@ -488,6 +490,22 @@ static void pcpu_mem_free(void *ptr) > > kvfree(ptr); > > } > > > > +static void __pcpu_chunk_move(struct pcpu_chunk *chunk, int slot, > > + bool move_front) > > +{ > > + if (chunk != pcpu_reserved_chunk) { > > + if (move_front) > > + list_move(&chunk->list, &pcpu_slot[slot]); > > + else > > + list_move_tail(&chunk->list, &pcpu_slot[slot]); > > + } > > +} > > + > > +static void pcpu_chunk_move(struct pcpu_chunk *chunk, int slot) { > > + __pcpu_chunk_move(chunk, slot, true); > > +} > > + > > /** > > * pcpu_chunk_relocate - put chunk in the appropriate chunk slot > > * @chunk: chunk of interest > > @@ -505,12 +523,8 @@ static void pcpu_chunk_relocate(struct pcpu_chunk > > *chunk, int oslot) { > > int nslot = pcpu_chunk_slot(chunk); > > > > - if (chunk != pcpu_reserved_chunk && oslot != nslot) { > > - if (oslot < nslot) > > - list_move(&chunk->list, &pcpu_slot[nslot]); > > - else > > - list_move_tail(&chunk->list, &pcpu_slot[nslot]); > > - } > > + if (oslot != nslot) > > + __pcpu_chunk_move(chunk, nslot, oslot < nslot); > > } > > > > /** > > @@ -1381,7 +1395,7 @@ static void __percpu *pcpu_alloc(size_t size, size_t > > align, bool reserved, > > bool is_atomic = (gfp & GFP_KERNEL) != GFP_KERNEL; > > bool do_warn = !(gfp & __GFP_NOWARN); > > static int warn_limit = 10; > > - struct pcpu_chunk *chunk; > > + struct pcpu_chunk *chunk, *next; > > const char *err; > > int slot, off, cpu, ret; > > unsigned long flags; > > @@ -1443,11 +1457,14 @@ static void __percpu *pcpu_alloc(size_t size, > > size_t align, bool reserved, > > restart: > > /* search through normal chunks */ > > for (slot = pcpu_size_to_slot(size); slot < pcpu_nr_slots; slot++) { > > - list_for_each_entry(chunk, &pcpu_slot[slot], list) { > > + list_for_each_entry_safe(chunk, next, &pcpu_slot[slot], list) { > > off = pcpu_find_block_fit(chunk, bits, bit_align, > > is_atomic); > > - if (off < 0) > > + if (off < 0) { > > + if (slot < PCPU_SLOT_FAIL_THRESHOLD) > > + pcpu_chunk_move(chunk, 0); > > continue; > > + } > > > > off = pcpu_alloc_area(chunk, bits, bit_align, off); > > if (off >= 0) > > For the code: Reviewed-by: Peng Fan <peng.fan@xxxxxxx> > > But I did not understand well why choose 32B? If there are > more information, better put in commit log. > There isn't I just picked a small allocation size. Thanks, Dennis