From: Thomas Hellstrom <thellstrom@xxxxxxxxxx> We always do dirty tracking on the PTE level. This means that any huge pmds we encounter should be read-only and not dirty: We can just skip those. Write-enabled huge pmds should not exist. They should have been split when made write-enabled. Warn and attempt to split them. Signed-off-by: Thomas Hellstrom <thellstrom@xxxxxxxxxx> --- mm/mapping_dirty_helpers.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mm/mapping_dirty_helpers.c b/mm/mapping_dirty_helpers.c index 799b9154b48f..f61bb9de1530 100644 --- a/mm/mapping_dirty_helpers.c +++ b/mm/mapping_dirty_helpers.c @@ -115,11 +115,18 @@ static int clean_record_pte(pte_t *pte, unsigned long addr, static int wp_clean_pmd_entry(pmd_t *pmd, unsigned long addr, unsigned long end, struct mm_walk *walk) { - /* Dirty-tracking should be handled on the pte level */ pmd_t pmdval = pmd_read_atomic(pmd); - if (pmd_trans_huge(pmdval) || pmd_devmap(pmdval)) - WARN_ON(pmd_write(pmdval) || pmd_dirty(pmdval)); + /* + * Dirty-tracking should be handled on the pte level, and write- + * enabled huge PMDS should never have been created. Warn on those. + * Read-only huge PMDS can't be dirty so we just skip them. + */ + if (pmd_trans_huge(pmdval) || pmd_devmap(pmdval)) { + if (WARN_ON(pmd_write(pmdval) || pmd_dirty(pmdval))) + return 0; + return PAGE_WALK_CONTINUE; + } return 0; } -- 2.21.0