diff options
-rw-r--r-- | mm/huge_memory.c | 2 | ||||
-rw-r--r-- | mm/memcontrol.c | 11 |
2 files changed, 12 insertions, 1 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 4f542444a91f..86ee29b5c39c 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2823,7 +2823,7 @@ void folio_undo_large_rmappable(struct folio *folio) spin_lock_irqsave(&ds_queue->split_queue_lock, flags); if (!list_empty(&folio->_deferred_list)) { ds_queue->split_queue_len--; - list_del(&folio->_deferred_list); + list_del_init(&folio->_deferred_list); } spin_unlock_irqrestore(&ds_queue->split_queue_lock, flags); } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index b226090fd906..651b86ff03dd 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -7543,6 +7543,17 @@ void mem_cgroup_migrate(struct folio *old, struct folio *new) /* Transfer the charge and the css ref */ commit_charge(new, memcg); + /* + * If the old folio is a large folio and is in the split queue, it needs + * to be removed from the split queue now, in case getting an incorrect + * split queue in destroy_large_folio() after the memcg of the old folio + * is cleared. + * + * In addition, the old folio is about to be freed after migration, so + * removing from the split queue a bit earlier seems reasonable. + */ + if (folio_test_large(old) && folio_test_large_rmappable(old)) + folio_undo_large_rmappable(old); old->memcg_data = 0; } |