Both post-insertion allocation failures remove the folio from the swap cache, restore its shadow and drop the folio references. Factor the common cleanup into one error path so additional checks can use it. Signed-off-by: Usama Arif --- mm/swap_state.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/mm/swap_state.c b/mm/swap_state.c index da65d75ceead1..a8a486b0403ab 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -484,24 +484,14 @@ static struct folio *__swap_cache_alloc(struct swap_cluster_info *ci, if (mem_cgroup_swapin_charge_folio(folio, memcg_id, vmf ? vmf->vma->vm_mm : NULL, gfp)) { - spin_lock(&ci->lock); - __swap_cache_do_del_folio(ci, folio, entry, shadow); - spin_unlock(&ci->lock); - folio_unlock(folio); - /* nr_pages refs from swap cache, 1 from allocation */ - folio_put_refs(folio, nr_pages + 1); + err = -ENOMEM; count_mthp_stat(order, MTHP_STAT_SWPIN_FALLBACK_CHARGE); - return ERR_PTR(-ENOMEM); + goto delete_folio; } if (order > 1 && folio_memcg_alloc_deferred(folio)) { - spin_lock(&ci->lock); - __swap_cache_do_del_folio(ci, folio, entry, shadow); - spin_unlock(&ci->lock); - folio_unlock(folio); - /* nr_pages refs from swap cache, 1 from allocation */ - folio_put_refs(folio, nr_pages + 1); - return ERR_PTR(-ENOMEM); + err = -ENOMEM; + goto delete_folio; } /* memsw uncharges swap when folio is added to swap cache */ @@ -513,6 +503,15 @@ static struct folio *__swap_cache_alloc(struct swap_cluster_info *ci, lruvec_stat_mod_folio(folio, NR_SWAPCACHE, nr_pages); return folio; + +delete_folio: + spin_lock(&ci->lock); + __swap_cache_do_del_folio(ci, folio, entry, shadow); + spin_unlock(&ci->lock); + folio_unlock(folio); + /* nr_pages refs from swap cache, 1 from allocation */ + folio_put_refs(folio, nr_pages + 1); + return ERR_PTR(err); } /** -- 2.53.0-Meta