summaryrefslogtreecommitdiff
path: root/mm/huge_memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r--mm/huge_memory.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 8e2746ea74ad..b298cba853ab 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2797,7 +2797,8 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
_dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma);
} else {
src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd);
- _dst_pmd = folio_mk_pmd(src_folio, dst_vma->vm_page_prot);
+ _dst_pmd = move_soft_dirty_pmd(src_pmdval);
+ _dst_pmd = clear_uffd_wp_pmd(_dst_pmd);
}
set_pmd_at(mm, dst_addr, dst_pmd, _dst_pmd);
@@ -3631,6 +3632,7 @@ static int __split_unmapped_folio(struct folio *folio, int new_order,
const bool is_anon = folio_test_anon(folio);
int old_order = folio_order(folio);
int start_order = split_type == SPLIT_TYPE_UNIFORM ? new_order : old_order - 1;
+ struct folio *old_folio = folio;
int split_order;
/*
@@ -3651,12 +3653,16 @@ static int __split_unmapped_folio(struct folio *folio, int new_order,
* uniform split has xas_split_alloc() called before
* irq is disabled to allocate enough memory, whereas
* non-uniform split can handle ENOMEM.
+ * Use the to-be-split folio, so that a parallel
+ * folio_try_get() waits on it until xarray is updated
+ * with after-split folios and the original one is
+ * unfrozen.
*/
- if (split_type == SPLIT_TYPE_UNIFORM)
- xas_split(xas, folio, old_order);
- else {
+ if (split_type == SPLIT_TYPE_UNIFORM) {
+ xas_split(xas, old_folio, old_order);
+ } else {
xas_set_order(xas, folio->index, split_order);
- xas_try_split(xas, folio, old_order);
+ xas_try_split(xas, old_folio, old_order);
if (xas_error(xas))
return xas_error(xas);
}