Skip to content

Commit ea1f5f3

Browse files
Pavel Tatashintorvalds
authored andcommitted
mm: define memblock_virt_alloc_try_nid_raw
* A new variant of memblock_virt_alloc_* allocations: memblock_virt_alloc_try_nid_raw() - Does not zero the allocated memory - Does not panic if request cannot be satisfied * optimize early system hash allocations Clients can call alloc_large_system_hash() with flag: HASH_ZERO to specify that memory that was allocated for system hash needs to be zeroed, otherwise the memory does not need to be zeroed, and client will initialize it. If memory does not need to be zero'd, call the new memblock_virt_alloc_raw() interface, and thus improve the boot performance. * debug for raw alloctor When CONFIG_DEBUG_VM is enabled, this patch sets all the memory that is returned by memblock_virt_alloc_try_nid_raw() to ones to ensure that no places excpect zeroed memory. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Pavel Tatashin <[email protected]> Reviewed-by: Steven Sistare <[email protected]> Reviewed-by: Daniel Jordan <[email protected]> Reviewed-by: Bob Picco <[email protected]> Tested-by: Bob Picco <[email protected]> Acked-by: Michal Hocko <[email protected]> Cc: Alexander Potapenko <[email protected]> Cc: Andrey Ryabinin <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Christian Borntraeger <[email protected]> Cc: David S. Miller <[email protected]> Cc: Dmitry Vyukov <[email protected]> Cc: Heiko Carstens <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Mel Gorman <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Sam Ravnborg <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Will Deacon <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent df8ee57 commit ea1f5f3

File tree

3 files changed

+87
-15
lines changed

3 files changed

+87
-15
lines changed

include/linux/bootmem.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
161161
#define BOOTMEM_ALLOC_ANYWHERE (~(phys_addr_t)0)
162162

163163
/* FIXME: Move to memblock.h at a point where we remove nobootmem.c */
164+
void *memblock_virt_alloc_try_nid_raw(phys_addr_t size, phys_addr_t align,
165+
phys_addr_t min_addr,
166+
phys_addr_t max_addr, int nid);
164167
void *memblock_virt_alloc_try_nid_nopanic(phys_addr_t size,
165168
phys_addr_t align, phys_addr_t min_addr,
166169
phys_addr_t max_addr, int nid);
@@ -177,6 +180,14 @@ static inline void * __init memblock_virt_alloc(
177180
NUMA_NO_NODE);
178181
}
179182

183+
static inline void * __init memblock_virt_alloc_raw(
184+
phys_addr_t size, phys_addr_t align)
185+
{
186+
return memblock_virt_alloc_try_nid_raw(size, align, BOOTMEM_LOW_LIMIT,
187+
BOOTMEM_ALLOC_ACCESSIBLE,
188+
NUMA_NO_NODE);
189+
}
190+
180191
static inline void * __init memblock_virt_alloc_nopanic(
181192
phys_addr_t size, phys_addr_t align)
182193
{
@@ -258,6 +269,14 @@ static inline void * __init memblock_virt_alloc(
258269
return __alloc_bootmem(size, align, BOOTMEM_LOW_LIMIT);
259270
}
260271

272+
static inline void * __init memblock_virt_alloc_raw(
273+
phys_addr_t size, phys_addr_t align)
274+
{
275+
if (!align)
276+
align = SMP_CACHE_BYTES;
277+
return __alloc_bootmem_nopanic(size, align, BOOTMEM_LOW_LIMIT);
278+
}
279+
261280
static inline void * __init memblock_virt_alloc_nopanic(
262281
phys_addr_t size, phys_addr_t align)
263282
{
@@ -310,6 +329,14 @@ static inline void * __init memblock_virt_alloc_try_nid(phys_addr_t size,
310329
min_addr);
311330
}
312331

332+
static inline void * __init memblock_virt_alloc_try_nid_raw(
333+
phys_addr_t size, phys_addr_t align,
334+
phys_addr_t min_addr, phys_addr_t max_addr, int nid)
335+
{
336+
return ___alloc_bootmem_node_nopanic(NODE_DATA(nid), size, align,
337+
min_addr, max_addr);
338+
}
339+
313340
static inline void * __init memblock_virt_alloc_try_nid_nopanic(
314341
phys_addr_t size, phys_addr_t align,
315342
phys_addr_t min_addr, phys_addr_t max_addr, int nid)

mm/memblock.c

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,6 @@ static void * __init memblock_virt_alloc_internal(
13271327
return NULL;
13281328
done:
13291329
ptr = phys_to_virt(alloc);
1330-
memset(ptr, 0, size);
13311330

13321331
/*
13331332
* The min_count is set to 0 so that bootmem allocated blocks
@@ -1340,6 +1339,45 @@ static void * __init memblock_virt_alloc_internal(
13401339
return ptr;
13411340
}
13421341

1342+
/**
1343+
* memblock_virt_alloc_try_nid_raw - allocate boot memory block without zeroing
1344+
* memory and without panicking
1345+
* @size: size of memory block to be allocated in bytes
1346+
* @align: alignment of the region and block's size
1347+
* @min_addr: the lower bound of the memory region from where the allocation
1348+
* is preferred (phys address)
1349+
* @max_addr: the upper bound of the memory region from where the allocation
1350+
* is preferred (phys address), or %BOOTMEM_ALLOC_ACCESSIBLE to
1351+
* allocate only from memory limited by memblock.current_limit value
1352+
* @nid: nid of the free area to find, %NUMA_NO_NODE for any node
1353+
*
1354+
* Public function, provides additional debug information (including caller
1355+
* info), if enabled. Does not zero allocated memory, does not panic if request
1356+
* cannot be satisfied.
1357+
*
1358+
* RETURNS:
1359+
* Virtual address of allocated memory block on success, NULL on failure.
1360+
*/
1361+
void * __init memblock_virt_alloc_try_nid_raw(
1362+
phys_addr_t size, phys_addr_t align,
1363+
phys_addr_t min_addr, phys_addr_t max_addr,
1364+
int nid)
1365+
{
1366+
void *ptr;
1367+
1368+
memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF\n",
1369+
__func__, (u64)size, (u64)align, nid, (u64)min_addr,
1370+
(u64)max_addr, (void *)_RET_IP_);
1371+
1372+
ptr = memblock_virt_alloc_internal(size, align,
1373+
min_addr, max_addr, nid);
1374+
#ifdef CONFIG_DEBUG_VM
1375+
if (ptr && size > 0)
1376+
memset(ptr, 0xff, size);
1377+
#endif
1378+
return ptr;
1379+
}
1380+
13431381
/**
13441382
* memblock_virt_alloc_try_nid_nopanic - allocate boot memory block
13451383
* @size: size of memory block to be allocated in bytes
@@ -1351,8 +1389,8 @@ static void * __init memblock_virt_alloc_internal(
13511389
* allocate only from memory limited by memblock.current_limit value
13521390
* @nid: nid of the free area to find, %NUMA_NO_NODE for any node
13531391
*
1354-
* Public version of _memblock_virt_alloc_try_nid_nopanic() which provides
1355-
* additional debug information (including caller info), if enabled.
1392+
* Public function, provides additional debug information (including caller
1393+
* info), if enabled. This function zeroes the allocated memory.
13561394
*
13571395
* RETURNS:
13581396
* Virtual address of allocated memory block on success, NULL on failure.
@@ -1362,11 +1400,17 @@ void * __init memblock_virt_alloc_try_nid_nopanic(
13621400
phys_addr_t min_addr, phys_addr_t max_addr,
13631401
int nid)
13641402
{
1403+
void *ptr;
1404+
13651405
memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF\n",
13661406
__func__, (u64)size, (u64)align, nid, (u64)min_addr,
13671407
(u64)max_addr, (void *)_RET_IP_);
1368-
return memblock_virt_alloc_internal(size, align, min_addr,
1369-
max_addr, nid);
1408+
1409+
ptr = memblock_virt_alloc_internal(size, align,
1410+
min_addr, max_addr, nid);
1411+
if (ptr)
1412+
memset(ptr, 0, size);
1413+
return ptr;
13701414
}
13711415

13721416
/**
@@ -1380,7 +1424,7 @@ void * __init memblock_virt_alloc_try_nid_nopanic(
13801424
* allocate only from memory limited by memblock.current_limit value
13811425
* @nid: nid of the free area to find, %NUMA_NO_NODE for any node
13821426
*
1383-
* Public panicking version of _memblock_virt_alloc_try_nid_nopanic()
1427+
* Public panicking version of memblock_virt_alloc_try_nid_nopanic()
13841428
* which provides debug information (including caller info), if enabled,
13851429
* and panics if the request can not be satisfied.
13861430
*
@@ -1399,8 +1443,10 @@ void * __init memblock_virt_alloc_try_nid(
13991443
(u64)max_addr, (void *)_RET_IP_);
14001444
ptr = memblock_virt_alloc_internal(size, align,
14011445
min_addr, max_addr, nid);
1402-
if (ptr)
1446+
if (ptr) {
1447+
memset(ptr, 0, size);
14031448
return ptr;
1449+
}
14041450

14051451
panic("%s: Failed to allocate %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx\n",
14061452
__func__, (u64)size, (u64)align, nid, (u64)min_addr,

mm/page_alloc.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7313,18 +7313,17 @@ void *__init alloc_large_system_hash(const char *tablename,
73137313

73147314
log2qty = ilog2(numentries);
73157315

7316-
/*
7317-
* memblock allocator returns zeroed memory already, so HASH_ZERO is
7318-
* currently not used when HASH_EARLY is specified.
7319-
*/
73207316
gfp_flags = (flags & HASH_ZERO) ? GFP_ATOMIC | __GFP_ZERO : GFP_ATOMIC;
73217317
do {
73227318
size = bucketsize << log2qty;
7323-
if (flags & HASH_EARLY)
7324-
table = memblock_virt_alloc_nopanic(size, 0);
7325-
else if (hashdist)
7319+
if (flags & HASH_EARLY) {
7320+
if (flags & HASH_ZERO)
7321+
table = memblock_virt_alloc_nopanic(size, 0);
7322+
else
7323+
table = memblock_virt_alloc_raw(size, 0);
7324+
} else if (hashdist) {
73267325
table = __vmalloc(size, gfp_flags, PAGE_KERNEL);
7327-
else {
7326+
} else {
73287327
/*
73297328
* If bucketsize is not a power-of-two, we may free
73307329
* some pages at the end of hash table which

0 commit comments

Comments
 (0)