diff --git a/mm/memfd.c b/mm/memfd.c index 2bb5e257080e9..5859705dafe19 100644 --- a/mm/memfd.c +++ b/mm/memfd.c @@ -34,11 +34,12 @@ static void memfd_tag_pins(struct address_space *mapping) void __rcu **slot; pgoff_t start; struct page *page; + unsigned int tagged = 0; lru_add_drain(); start = 0; - rcu_read_lock(); + xa_lock_irq(&mapping->i_pages); radix_tree_for_each_slot(slot, &mapping->i_pages, &iter, start) { page = radix_tree_deref_slot(slot); if (!page || radix_tree_exception(page)) { @@ -47,18 +48,19 @@ static void memfd_tag_pins(struct address_space *mapping) continue; } } else if (page_count(page) - page_mapcount(page) > 1) { - xa_lock_irq(&mapping->i_pages); radix_tree_tag_set(&mapping->i_pages, iter.index, MEMFD_TAG_PINNED); - xa_unlock_irq(&mapping->i_pages); } - if (need_resched()) { - slot = radix_tree_iter_resume(slot, &iter); - cond_resched_rcu(); - } + if (++tagged % 1024) + continue; + + slot = radix_tree_iter_resume(slot, &iter); + xa_unlock_irq(&mapping->i_pages); + cond_resched(); + xa_lock_irq(&mapping->i_pages); } - rcu_read_unlock(); + xa_unlock_irq(&mapping->i_pages); } /*