Message ID | 6efef5316d7468d13ed5f344452a0b872481972b.1727148662.git.zhengqi.arch@bytedance.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | introduce pte_offset_map_{ro|rw}_nolock() | expand |
On 24.09.24 08:10, Qi Zheng wrote: > In walk_pte_range(), we may modify the pte entry after holding the ptl, so > convert it to using pte_offset_map_rw_nolock(). At this time, the > pte_same() check is not performed after the ptl held, so we should get > pmdval and do pmd_same() check to ensure the stability of pmd entry. > > Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> > Reviewed-by: Muchun Song <muchun.song@linux.dev> > --- > mm/vmscan.c | 9 ++++++++- > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/mm/vmscan.c b/mm/vmscan.c > index 749cdc110c745..bdca94e663bc5 100644 > --- a/mm/vmscan.c > +++ b/mm/vmscan.c > @@ -3375,8 +3375,10 @@ static bool walk_pte_range(pmd_t *pmd, unsigned long start, unsigned long end, > struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); > DEFINE_MAX_SEQ(walk->lruvec); > int old_gen, new_gen = lru_gen_from_seq(max_seq); > + pmd_t pmdval; > > - pte = pte_offset_map_nolock(args->mm, pmd, start & PMD_MASK, &ptl); > + pte = pte_offset_map_rw_nolock(args->mm, pmd, start & PMD_MASK, &pmdval, > + &ptl); > if (!pte) > return false; > if (!spin_trylock(ptl)) { > @@ -3384,6 +3386,11 @@ static bool walk_pte_range(pmd_t *pmd, unsigned long start, unsigned long end, > return false; > } > > + if (unlikely(!pmd_same(pmdval, pmdp_get_lockless(pmd)))) { > + pte_unmap_unlock(pte, ptl); > + return false; > + } Acked-by: David Hildenbrand <david@redhat.com>
diff --git a/mm/vmscan.c b/mm/vmscan.c index 749cdc110c745..bdca94e663bc5 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3375,8 +3375,10 @@ static bool walk_pte_range(pmd_t *pmd, unsigned long start, unsigned long end, struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); DEFINE_MAX_SEQ(walk->lruvec); int old_gen, new_gen = lru_gen_from_seq(max_seq); + pmd_t pmdval; - pte = pte_offset_map_nolock(args->mm, pmd, start & PMD_MASK, &ptl); + pte = pte_offset_map_rw_nolock(args->mm, pmd, start & PMD_MASK, &pmdval, + &ptl); if (!pte) return false; if (!spin_trylock(ptl)) { @@ -3384,6 +3386,11 @@ static bool walk_pte_range(pmd_t *pmd, unsigned long start, unsigned long end, return false; } + if (unlikely(!pmd_same(pmdval, pmdp_get_lockless(pmd)))) { + pte_unmap_unlock(pte, ptl); + return false; + } + arch_enter_lazy_mmu_mode(); restart: for (i = pte_index(start), addr = start; addr != end; i++, addr += PAGE_SIZE) {