mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'mm-stable-2025-10-03-16-49' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull more MM updates from Andrew Morton:
"Only two patch series in this pull request:
- "mm/memory_hotplug: fixup crash during uevent handling" from Hannes
Reinecke fixes a race that was causing udev to trigger a crash in
the memory hotplug code
- "mm_slot: following fixup for usage of mm_slot_entry()" from Wei
Yang adds some touchups to the just-merged mm_slot changes"
* tag 'mm-stable-2025-10-03-16-49' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
mm/khugepaged: use KMEM_CACHE()
mm/ksm: cleanup mm_slot_entry() invocation
Documentation/mm: drop pxx_mkdevmap() descriptions from page table helpers
mm: clean up is_guard_pte_marker()
drivers/base: move memory_block_add_nid() into the caller
mm/memory_hotplug: activate node before adding new memory blocks
drivers/base/memory: add node id parameter to add_memory_block()
This commit is contained in:
@@ -52,8 +52,6 @@ PTE Page Table Helpers
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pte_mkspecial | Creates a special PTE |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pte_mkdevmap | Creates a ZONE_DEVICE mapped PTE |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pte_mksoft_dirty | Creates a soft dirty PTE |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pte_clear_soft_dirty | Clears a soft dirty PTE |
|
||||
@@ -124,8 +122,6 @@ PMD Page Table Helpers
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pmd_mkspecial | Creates a special PMD |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pmd_mkdevmap | Creates a ZONE_DEVICE mapped PMD |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pmd_mksoft_dirty | Creates a soft dirty PMD |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pmd_clear_soft_dirty | Clears a soft dirty PMD |
|
||||
@@ -185,8 +181,6 @@ PUD Page Table Helpers
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pud_wrprotect | Creates a write protected PUD |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pud_mkdevmap | Creates a ZONE_DEVICE mapped PUD |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
| pud_mkinvalid | Invalidates a present PUD; do not call for |
|
||||
| | non-present PUD [1] |
|
||||
+---------------------------+--------------------------------------------------+
|
||||
|
||||
@@ -769,21 +769,22 @@ static struct zone *early_node_zone_for_memory_block(struct memory_block *mem,
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
/**
|
||||
* memory_block_add_nid() - Indicate that system RAM falling into this memory
|
||||
* block device (partially) belongs to the given node.
|
||||
* memory_block_add_nid_early() - Indicate that early system RAM falling into
|
||||
* this memory block device (partially) belongs
|
||||
* to the given node.
|
||||
* @mem: The memory block device.
|
||||
* @nid: The node id.
|
||||
* @context: The memory initialization context.
|
||||
*
|
||||
* Indicate that system RAM falling into this memory block (partially) belongs
|
||||
* to the given node. If the context indicates ("early") that we are adding the
|
||||
* node during node device subsystem initialization, this will also properly
|
||||
* set/adjust mem->zone based on the zone ranges of the given node.
|
||||
* Indicate that early system RAM falling into this memory block (partially)
|
||||
* belongs to the given node. This will also properly set/adjust mem->zone based
|
||||
* on the zone ranges of the given node.
|
||||
*
|
||||
* Memory hotplug handles this on memory block creation, where we can only have
|
||||
* a single nid span a memory block.
|
||||
*/
|
||||
void memory_block_add_nid(struct memory_block *mem, int nid,
|
||||
enum meminit_context context)
|
||||
void memory_block_add_nid_early(struct memory_block *mem, int nid)
|
||||
{
|
||||
if (context == MEMINIT_EARLY && mem->nid != nid) {
|
||||
if (mem->nid != nid) {
|
||||
/*
|
||||
* For early memory we have to determine the zone when setting
|
||||
* the node id and handle multiple nodes spanning a single
|
||||
@@ -797,19 +798,18 @@ void memory_block_add_nid(struct memory_block *mem, int nid,
|
||||
mem->zone = early_node_zone_for_memory_block(mem, nid);
|
||||
else
|
||||
mem->zone = NULL;
|
||||
/*
|
||||
* If this memory block spans multiple nodes, we only indicate
|
||||
* the last processed node. If we span multiple nodes (not applicable
|
||||
* to hotplugged memory), zone == NULL will prohibit memory offlining
|
||||
* and consequently unplug.
|
||||
*/
|
||||
mem->nid = nid;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this memory block spans multiple nodes, we only indicate
|
||||
* the last processed node. If we span multiple nodes (not applicable
|
||||
* to hotplugged memory), zone == NULL will prohibit memory offlining
|
||||
* and consequently unplug.
|
||||
*/
|
||||
mem->nid = nid;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int add_memory_block(unsigned long block_id, unsigned long state,
|
||||
static int add_memory_block(unsigned long block_id, int nid, unsigned long state,
|
||||
struct vmem_altmap *altmap,
|
||||
struct memory_group *group)
|
||||
{
|
||||
@@ -827,7 +827,7 @@ static int add_memory_block(unsigned long block_id, unsigned long state,
|
||||
|
||||
mem->start_section_nr = block_id * sections_per_block;
|
||||
mem->state = state;
|
||||
mem->nid = NUMA_NO_NODE;
|
||||
mem->nid = nid;
|
||||
mem->altmap = altmap;
|
||||
INIT_LIST_HEAD(&mem->group_next);
|
||||
|
||||
@@ -854,13 +854,6 @@ static int add_memory_block(unsigned long block_id, unsigned long state,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_hotplug_memory_block(unsigned long block_id,
|
||||
struct vmem_altmap *altmap,
|
||||
struct memory_group *group)
|
||||
{
|
||||
return add_memory_block(block_id, MEM_OFFLINE, altmap, group);
|
||||
}
|
||||
|
||||
static void remove_memory_block(struct memory_block *memory)
|
||||
{
|
||||
if (WARN_ON_ONCE(memory->dev.bus != &memory_subsys))
|
||||
@@ -886,7 +879,7 @@ static void remove_memory_block(struct memory_block *memory)
|
||||
* Called under device_hotplug_lock.
|
||||
*/
|
||||
int create_memory_block_devices(unsigned long start, unsigned long size,
|
||||
struct vmem_altmap *altmap,
|
||||
int nid, struct vmem_altmap *altmap,
|
||||
struct memory_group *group)
|
||||
{
|
||||
const unsigned long start_block_id = pfn_to_block_id(PFN_DOWN(start));
|
||||
@@ -900,7 +893,7 @@ int create_memory_block_devices(unsigned long start, unsigned long size,
|
||||
return -EINVAL;
|
||||
|
||||
for (block_id = start_block_id; block_id != end_block_id; block_id++) {
|
||||
ret = add_hotplug_memory_block(block_id, altmap, group);
|
||||
ret = add_memory_block(block_id, nid, MEM_OFFLINE, altmap, group);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
@@ -1005,7 +998,7 @@ void __init memory_dev_init(void)
|
||||
continue;
|
||||
|
||||
block_id = memory_block_id(nr);
|
||||
ret = add_memory_block(block_id, MEM_ONLINE, NULL, NULL);
|
||||
ret = add_memory_block(block_id, NUMA_NO_NODE, MEM_ONLINE, NULL, NULL);
|
||||
if (ret) {
|
||||
panic("%s() failed to add memory block: %d\n",
|
||||
__func__, ret);
|
||||
|
||||
@@ -819,13 +819,10 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
static void do_register_memory_block_under_node(int nid,
|
||||
struct memory_block *mem_blk,
|
||||
enum meminit_context context)
|
||||
struct memory_block *mem_blk)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memory_block_add_nid(mem_blk, nid, context);
|
||||
|
||||
ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
|
||||
&mem_blk->dev.kobj,
|
||||
kobject_name(&mem_blk->dev.kobj));
|
||||
@@ -853,7 +850,7 @@ static int register_mem_block_under_node_hotplug(struct memory_block *mem_blk,
|
||||
{
|
||||
int nid = *(int *)arg;
|
||||
|
||||
do_register_memory_block_under_node(nid, mem_blk, MEMINIT_HOTPLUG);
|
||||
do_register_memory_block_under_node(nid, mem_blk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -893,7 +890,8 @@ static void register_memory_blocks_under_nodes(void)
|
||||
if (!mem)
|
||||
continue;
|
||||
|
||||
do_register_memory_block_under_node(nid, mem, MEMINIT_EARLY);
|
||||
memory_block_add_nid_early(mem, nid);
|
||||
do_register_memory_block_under_node(nid, mem);
|
||||
put_device(&mem->dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ static inline unsigned long memory_block_advised_max_size(void)
|
||||
extern int register_memory_notifier(struct notifier_block *nb);
|
||||
extern void unregister_memory_notifier(struct notifier_block *nb);
|
||||
int create_memory_block_devices(unsigned long start, unsigned long size,
|
||||
struct vmem_altmap *altmap,
|
||||
int nid, struct vmem_altmap *altmap,
|
||||
struct memory_group *group);
|
||||
void remove_memory_block_devices(unsigned long start, unsigned long size);
|
||||
extern void memory_dev_init(void);
|
||||
@@ -202,8 +202,7 @@ static inline unsigned long phys_to_block_id(unsigned long phys)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
void memory_block_add_nid(struct memory_block *mem, int nid,
|
||||
enum meminit_context context);
|
||||
void memory_block_add_nid_early(struct memory_block *mem, int nid);
|
||||
#endif /* CONFIG_NUMA */
|
||||
int memory_block_advise_max_size(unsigned long size);
|
||||
unsigned long memory_block_advised_max_size(void);
|
||||
|
||||
@@ -376,10 +376,7 @@ int hugepage_madvise(struct vm_area_struct *vma,
|
||||
|
||||
int __init khugepaged_init(void)
|
||||
{
|
||||
mm_slot_cache = kmem_cache_create("khugepaged_mm_slot",
|
||||
sizeof(struct mm_slot),
|
||||
__alignof__(struct mm_slot),
|
||||
0, NULL);
|
||||
mm_slot_cache = KMEM_CACHE(mm_slot, 0);
|
||||
if (!mm_slot_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
27
mm/ksm.c
27
mm/ksm.c
@@ -2921,7 +2921,7 @@ int __ksm_enter(struct mm_struct *mm)
|
||||
|
||||
void __ksm_exit(struct mm_struct *mm)
|
||||
{
|
||||
struct ksm_mm_slot *mm_slot;
|
||||
struct ksm_mm_slot *mm_slot = NULL;
|
||||
struct mm_slot *slot;
|
||||
int easy_to_free = 0;
|
||||
|
||||
@@ -2936,19 +2936,20 @@ void __ksm_exit(struct mm_struct *mm)
|
||||
|
||||
spin_lock(&ksm_mmlist_lock);
|
||||
slot = mm_slot_lookup(mm_slots_hash, mm);
|
||||
if (slot) {
|
||||
mm_slot = mm_slot_entry(slot, struct ksm_mm_slot, slot);
|
||||
if (ksm_scan.mm_slot != mm_slot) {
|
||||
if (!mm_slot->rmap_list) {
|
||||
hash_del(&slot->hash);
|
||||
list_del(&slot->mm_node);
|
||||
easy_to_free = 1;
|
||||
} else {
|
||||
list_move(&slot->mm_node,
|
||||
&ksm_scan.mm_slot->slot.mm_node);
|
||||
}
|
||||
}
|
||||
if (!slot)
|
||||
goto unlock;
|
||||
mm_slot = mm_slot_entry(slot, struct ksm_mm_slot, slot);
|
||||
if (ksm_scan.mm_slot == mm_slot)
|
||||
goto unlock;
|
||||
if (!mm_slot->rmap_list) {
|
||||
hash_del(&slot->hash);
|
||||
list_del(&slot->mm_node);
|
||||
easy_to_free = 1;
|
||||
} else {
|
||||
list_move(&slot->mm_node,
|
||||
&ksm_scan.mm_slot->slot.mm_node);
|
||||
}
|
||||
unlock:
|
||||
spin_unlock(&ksm_mmlist_lock);
|
||||
|
||||
if (easy_to_free) {
|
||||
|
||||
@@ -1071,8 +1071,8 @@ static bool is_valid_guard_vma(struct vm_area_struct *vma, bool allow_locked)
|
||||
|
||||
static bool is_guard_pte_marker(pte_t ptent)
|
||||
{
|
||||
return is_pte_marker(ptent) &&
|
||||
is_guard_swp_entry(pte_to_swp_entry(ptent));
|
||||
return is_swap_pte(ptent) &&
|
||||
is_guard_swp_entry(pte_to_swp_entry(ptent));
|
||||
}
|
||||
|
||||
static int guard_install_pud_entry(pud_t *pud, unsigned long addr,
|
||||
|
||||
@@ -1477,7 +1477,7 @@ static int create_altmaps_and_memory_blocks(int nid, struct memory_group *group,
|
||||
}
|
||||
|
||||
/* create memory block devices after memory was added */
|
||||
ret = create_memory_block_devices(cur_start, memblock_size,
|
||||
ret = create_memory_block_devices(cur_start, memblock_size, nid,
|
||||
params.altmap, group);
|
||||
if (ret) {
|
||||
arch_remove_memory(cur_start, memblock_size, NULL);
|
||||
@@ -1539,8 +1539,16 @@ int add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags)
|
||||
|
||||
ret = __try_online_node(nid, false);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
new_node = ret;
|
||||
goto error_memblock_remove;
|
||||
if (ret) {
|
||||
node_set_online(nid);
|
||||
ret = register_one_node(nid);
|
||||
if (WARN_ON(ret)) {
|
||||
node_set_offline(nid);
|
||||
goto error_memblock_remove;
|
||||
}
|
||||
new_node = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Self hosted memmap array
|
||||
@@ -1556,24 +1564,13 @@ int add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags)
|
||||
goto error;
|
||||
|
||||
/* create memory block devices after memory was added */
|
||||
ret = create_memory_block_devices(start, size, NULL, group);
|
||||
ret = create_memory_block_devices(start, size, nid, NULL, group);
|
||||
if (ret) {
|
||||
arch_remove_memory(start, size, params.altmap);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_node) {
|
||||
/* If sysfs file of new node can't be created, cpu on the node
|
||||
* can't be hot-added. There is no rollback way now.
|
||||
* So, check by BUG_ON() to catch it reluctantly..
|
||||
* We online node here. We can't roll back from here.
|
||||
*/
|
||||
node_set_online(nid);
|
||||
ret = register_one_node(nid);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
register_memory_blocks_under_node_hotplug(nid, PFN_DOWN(start),
|
||||
PFN_UP(start + size - 1));
|
||||
|
||||
@@ -1597,6 +1594,11 @@ int add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags)
|
||||
|
||||
return ret;
|
||||
error:
|
||||
if (new_node) {
|
||||
node_set_offline(nid);
|
||||
unregister_one_node(nid);
|
||||
}
|
||||
error_memblock_remove:
|
||||
if (IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK))
|
||||
memblock_remove(start, size);
|
||||
error_mem_hotplug_end:
|
||||
|
||||
Reference in New Issue
Block a user