Skip to content

Commit ff93026

Browse files
committed
Merge branch 'for-4.14-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu
Pull percpu fixes from Tejun Heo: "Rather important fixes this time. - The new percpu area allocator had a subtle bug in how it iterates the memory regions and could skip viable areas, which led to allocation failures for module static percpu variables. Dennis fixed the bug and another non-critical one in stat calculation. - Mark noticed that the generic implementations of percpu local atomic reads aren't properly protected against irqs and there's a (slim) chance for split reads on some 32bit systems. Generic implementations are updated to disable irq when read size is larger than ulong size. This may have made some 32bit archs which can do atomic local 64bit accesses generate sub-optimal code. We need to find them out and implement arch-specific overrides" * 'for-4.14-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu: percpu: fix iteration to prevent skipping over block percpu: fix starting offset for chunk statistics traversal percpu: make this_cpu_generic_read() atomic w.r.t. interrupts
2 parents c1de159 + 1fa4df3 commit ff93026

File tree

3 files changed

+27
-3
lines changed

3 files changed

+27
-3
lines changed

include/asm-generic/percpu.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,35 @@ do { \
115115
(__ret); \
116116
})
117117

118-
#define this_cpu_generic_read(pcp) \
118+
#define __this_cpu_generic_read_nopreempt(pcp) \
119119
({ \
120120
typeof(pcp) __ret; \
121121
preempt_disable_notrace(); \
122-
__ret = raw_cpu_generic_read(pcp); \
122+
__ret = READ_ONCE(*raw_cpu_ptr(&(pcp))); \
123123
preempt_enable_notrace(); \
124124
__ret; \
125125
})
126126

127+
#define __this_cpu_generic_read_noirq(pcp) \
128+
({ \
129+
typeof(pcp) __ret; \
130+
unsigned long __flags; \
131+
raw_local_irq_save(__flags); \
132+
__ret = raw_cpu_generic_read(pcp); \
133+
raw_local_irq_restore(__flags); \
134+
__ret; \
135+
})
136+
137+
#define this_cpu_generic_read(pcp) \
138+
({ \
139+
typeof(pcp) __ret; \
140+
if (__native_word(pcp)) \
141+
__ret = __this_cpu_generic_read_nopreempt(pcp); \
142+
else \
143+
__ret = __this_cpu_generic_read_noirq(pcp); \
144+
__ret; \
145+
})
146+
127147
#define this_cpu_generic_to_op(pcp, val, op) \
128148
do { \
129149
unsigned long __flags; \

mm/percpu-stats.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ static void chunk_map_stats(struct seq_file *m, struct pcpu_chunk *chunk,
7373
last_alloc + 1 : 0;
7474

7575
as_len = 0;
76-
start = chunk->start_offset;
76+
start = chunk->start_offset / PCPU_MIN_ALLOC_SIZE;
7777

7878
/*
7979
* If a bit is set in the allocation map, the bound_map identifies

mm/percpu.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ static void pcpu_next_md_free_region(struct pcpu_chunk *chunk, int *bit_off,
353353
block->contig_hint_start);
354354
return;
355355
}
356+
/* reset to satisfy the second predicate above */
357+
block_off = 0;
356358

357359
*bits = block->right_free;
358360
*bit_off = (i + 1) * PCPU_BITMAP_BLOCK_BITS - block->right_free;
@@ -407,6 +409,8 @@ static void pcpu_next_fit_region(struct pcpu_chunk *chunk, int alloc_bits,
407409
*bit_off = pcpu_block_off_to_off(i, block->first_free);
408410
return;
409411
}
412+
/* reset to satisfy the second predicate above */
413+
block_off = 0;
410414

411415
*bit_off = ALIGN(PCPU_BITMAP_BLOCK_BITS - block->right_free,
412416
align);

0 commit comments

Comments
 (0)