[PATCH RFC 05/13] mm/huge_memory: consolidate irq and locking for folio split
Kairui Song <[email protected]>
| Newsgroups | org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
Let each split helper handle its own locking instead of relying on the caller, so both paths follow the same convention and __folio_split() can drop its local irq handling and fail label, preparing for further cleanup. Signed-off-by: Kairui Song <[email protected]> --- mm/huge_memory.c | 52 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 56a356c30f30..ca9430a6f8d1 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3947,6 +3947,8 @@ static int __folio_freeze_split_unmapped_anon(struct folio *folio, unsigned int bool dequeue_deferred; int ret = 0; + local_irq_disable(); + /* * If this folio can be on the deferred split queue, lock out * the shrinker before freezing the ref. If the shrinker sees @@ -3969,6 +3971,7 @@ static int __folio_freeze_split_unmapped_anon(struct folio *folio, unsigned int list_lru_unlock(lru); rcu_read_unlock(); } + local_irq_enable(); return -EAGAIN; } @@ -4020,6 +4023,7 @@ static int __folio_freeze_split_unmapped_anon(struct folio *folio, unsigned int lruvec_unlock(lruvec); if (ci) swap_cluster_unlock(ci); + local_irq_enable(); return ret; } @@ -4035,8 +4039,21 @@ static int __folio_freeze_split_unmapped_file(struct folio *folio, unsigned int struct lruvec *lruvec; int ret; - if (!folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) - return -EAGAIN; + xas_lock_irq(xas); + + /* + * Check if the folio is present in page cache. + * We assume all tail are present too, if folio is there. + */ + if (xas_load(xas) != folio) { + ret = -EAGAIN; + goto fail; + } + + if (!folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) { + ret = -EAGAIN; + goto fail; + } if (folio_test_pmd_mappable(folio) && new_order < HPAGE_PMD_ORDER) { @@ -4107,6 +4124,8 @@ static int __folio_freeze_split_unmapped_file(struct folio *folio, unsigned int if (do_lru) lruvec_unlock(lruvec); +fail: + xas_unlock_irq(xas); return ret; } @@ -4246,19 +4265,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, unmap_folio(folio); - /* block interrupt reentry in xa_lock and spinlock */ - local_irq_disable(); - if (mapping) { - /* - * Check if the folio is present in page cache. - * We assume all tail are present too, if folio is there. - */ - xas_lock(&xas); - xas_reset(&xas); - if (xas_load(&xas) != folio) { - ret = -EAGAIN; - goto fail; - } + if (!is_anon) { ret = __folio_freeze_split_unmapped_file(folio, new_order, split_at, &xas, mapping, true, list, split_type, end, &nr_shmem_dropped); @@ -4267,12 +4274,6 @@ static int __folio_split(struct folio *folio, unsigned int new_order, list, split_type); } -fail: - if (mapping) - xas_unlock(&xas); - - local_irq_enable(); - if (nr_shmem_dropped) shmem_uncharge(mapping->host, nr_shmem_dropped); @@ -4355,8 +4356,6 @@ static int __folio_split(struct folio *folio, unsigned int new_order, */ int folio_split_unmapped(struct folio *folio, unsigned int new_order) { - int ret = 0; - VM_WARN_ON_ONCE_FOLIO(folio_mapped(folio), folio); VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio); VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio); @@ -4365,11 +4364,8 @@ int folio_split_unmapped(struct folio *folio, unsigned int new_order) if (folio_expected_ref_count(folio) != folio_ref_count(folio) - 1) return -EAGAIN; - local_irq_disable(); - ret = __folio_freeze_split_unmapped_anon(folio, new_order, &folio->page, - false, NULL, SPLIT_TYPE_UNIFORM); - local_irq_enable(); - return ret; + return __folio_freeze_split_unmapped_anon(folio, new_order, &folio->page, + false, NULL, SPLIT_TYPE_UNIFORM); } /* -- 2.55.0