Skip to content

Commit 5835d96

Browse files
committed
percpu: implement [__]alloc_percpu_gfp()
Now that pcpu_alloc_area() can allocate only from populated areas, it's easy to add atomic allocation support to [__]alloc_percpu(). Update pcpu_alloc() so that it accepts @gfp and skips all the blocking operations and allocates only from the populated areas if @gfp doesn't contain GFP_KERNEL. New interface functions [__]alloc_percpu_gfp() are added. While this means that atomic allocations are possible, this isn't complete yet as there's no mechanism to ensure that certain amount of populated areas is kept available and atomic allocations may keep failing under certain conditions. Signed-off-by: Tejun Heo <[email protected]>
1 parent e04d320 commit 5835d96

File tree

2 files changed

+46
-27
lines changed

2 files changed

+46
-27
lines changed

include/linux/percpu.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,16 @@ extern void __init setup_per_cpu_areas(void);
122122
#endif
123123
extern void __init percpu_init_late(void);
124124

125+
extern void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp);
125126
extern void __percpu *__alloc_percpu(size_t size, size_t align);
126127
extern void free_percpu(void __percpu *__pdata);
127128
extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
128129

129-
#define alloc_percpu(type) \
130-
(typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type))
130+
#define alloc_percpu_gfp(type, gfp) \
131+
(typeof(type) __percpu *)__alloc_percpu_gfp(sizeof(type), \
132+
__alignof__(type), gfp)
133+
#define alloc_percpu(type) \
134+
(typeof(type) __percpu *)__alloc_percpu(sizeof(type), \
135+
__alignof__(type))
131136

132137
#endif /* __LINUX_PERCPU_H */

mm/percpu.c

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,6 @@ static struct pcpu_chunk *pcpu_first_chunk;
151151
static struct pcpu_chunk *pcpu_reserved_chunk;
152152
static int pcpu_reserved_chunk_limit;
153153

154-
/*
155-
* Free path accesses and alters only the index data structures and can be
156-
* safely called from atomic context. When memory needs to be returned to
157-
* the system, free path schedules reclaim_work.
158-
*/
159154
static DEFINE_SPINLOCK(pcpu_lock); /* all internal data structures */
160155
static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop */
161156

@@ -727,20 +722,21 @@ static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr)
727722
* @size: size of area to allocate in bytes
728723
* @align: alignment of area (max PAGE_SIZE)
729724
* @reserved: allocate from the reserved chunk if available
725+
* @gfp: allocation flags
730726
*
731-
* Allocate percpu area of @size bytes aligned at @align.
732-
*
733-
* CONTEXT:
734-
* Does GFP_KERNEL allocation.
727+
* Allocate percpu area of @size bytes aligned at @align. If @gfp doesn't
728+
* contain %GFP_KERNEL, the allocation is atomic.
735729
*
736730
* RETURNS:
737731
* Percpu pointer to the allocated area on success, NULL on failure.
738732
*/
739-
static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
733+
static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
734+
gfp_t gfp)
740735
{
741736
static int warn_limit = 10;
742737
struct pcpu_chunk *chunk;
743738
const char *err;
739+
bool is_atomic = !(gfp & GFP_KERNEL);
744740
int slot, off, new_alloc, cpu, ret;
745741
unsigned long flags;
746742
void __percpu *ptr;
@@ -773,14 +769,15 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
773769

774770
while ((new_alloc = pcpu_need_to_extend(chunk))) {
775771
spin_unlock_irqrestore(&pcpu_lock, flags);
776-
if (pcpu_extend_area_map(chunk, new_alloc) < 0) {
772+
if (is_atomic ||
773+
pcpu_extend_area_map(chunk, new_alloc) < 0) {
777774
err = "failed to extend area map of reserved chunk";
778775
goto fail;
779776
}
780777
spin_lock_irqsave(&pcpu_lock, flags);
781778
}
782779

783-
off = pcpu_alloc_area(chunk, size, align, false);
780+
off = pcpu_alloc_area(chunk, size, align, is_atomic);
784781
if (off >= 0)
785782
goto area_found;
786783

@@ -797,6 +794,8 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
797794

798795
new_alloc = pcpu_need_to_extend(chunk);
799796
if (new_alloc) {
797+
if (is_atomic)
798+
continue;
800799
spin_unlock_irqrestore(&pcpu_lock, flags);
801800
if (pcpu_extend_area_map(chunk,
802801
new_alloc) < 0) {
@@ -811,7 +810,7 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
811810
goto restart;
812811
}
813812

814-
off = pcpu_alloc_area(chunk, size, align, false);
813+
off = pcpu_alloc_area(chunk, size, align, is_atomic);
815814
if (off >= 0)
816815
goto area_found;
817816
}
@@ -824,6 +823,9 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
824823
* tasks to create chunks simultaneously. Serialize and create iff
825824
* there's still no empty chunk after grabbing the mutex.
826825
*/
826+
if (is_atomic)
827+
goto fail;
828+
827829
mutex_lock(&pcpu_alloc_mutex);
828830

829831
if (list_empty(&pcpu_slot[pcpu_nr_slots - 1])) {
@@ -846,7 +848,7 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
846848
spin_unlock_irqrestore(&pcpu_lock, flags);
847849

848850
/* populate if not all pages are already there */
849-
if (true) {
851+
if (!is_atomic) {
850852
int page_start, page_end, rs, re;
851853

852854
mutex_lock(&pcpu_alloc_mutex);
@@ -884,9 +886,9 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
884886
fail_unlock:
885887
spin_unlock_irqrestore(&pcpu_lock, flags);
886888
fail:
887-
if (warn_limit) {
888-
pr_warning("PERCPU: allocation failed, size=%zu align=%zu, "
889-
"%s\n", size, align, err);
889+
if (!is_atomic && warn_limit) {
890+
pr_warning("PERCPU: allocation failed, size=%zu align=%zu atomic=%d, %s\n",
891+
size, align, is_atomic, err);
890892
dump_stack();
891893
if (!--warn_limit)
892894
pr_info("PERCPU: limit reached, disable warning\n");
@@ -895,22 +897,34 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
895897
}
896898

897899
/**
898-
* __alloc_percpu - allocate dynamic percpu area
900+
* __alloc_percpu_gfp - allocate dynamic percpu area
899901
* @size: size of area to allocate in bytes
900902
* @align: alignment of area (max PAGE_SIZE)
903+
* @gfp: allocation flags
901904
*
902-
* Allocate zero-filled percpu area of @size bytes aligned at @align.
903-
* Might sleep. Might trigger writeouts.
904-
*
905-
* CONTEXT:
906-
* Does GFP_KERNEL allocation.
905+
* Allocate zero-filled percpu area of @size bytes aligned at @align. If
906+
* @gfp doesn't contain %GFP_KERNEL, the allocation doesn't block and can
907+
* be called from any context but is a lot more likely to fail.
907908
*
908909
* RETURNS:
909910
* Percpu pointer to the allocated area on success, NULL on failure.
910911
*/
912+
void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp)
913+
{
914+
return pcpu_alloc(size, align, false, gfp);
915+
}
916+
EXPORT_SYMBOL_GPL(__alloc_percpu_gfp);
917+
918+
/**
919+
* __alloc_percpu - allocate dynamic percpu area
920+
* @size: size of area to allocate in bytes
921+
* @align: alignment of area (max PAGE_SIZE)
922+
*
923+
* Equivalent to __alloc_percpu_gfp(size, align, %GFP_KERNEL).
924+
*/
911925
void __percpu *__alloc_percpu(size_t size, size_t align)
912926
{
913-
return pcpu_alloc(size, align, false);
927+
return pcpu_alloc(size, align, false, GFP_KERNEL);
914928
}
915929
EXPORT_SYMBOL_GPL(__alloc_percpu);
916930

@@ -932,7 +946,7 @@ EXPORT_SYMBOL_GPL(__alloc_percpu);
932946
*/
933947
void __percpu *__alloc_reserved_percpu(size_t size, size_t align)
934948
{
935-
return pcpu_alloc(size, align, true);
949+
return pcpu_alloc(size, align, true, GFP_KERNEL);
936950
}
937951

938952
/**

0 commit comments

Comments
 (0)