History

mm/huge_memory: replace can_split_folio() with direct refcount calculation

can_split_folio() is just a refcount comparison, making sure only the split caller holds an extra pin. Open code it with folio_expected_ref_count() != folio_ref_count() - 1. For the extra_pins used by folio_ref_freeze(), add folio_cache_ref_count() to calculate it. Also replace folio_expected_ref_count() with folio_cache_ref_count() used by folio_ref_unfreeze(), since they are returning the same values when a folio is frozen and folio_cache_ref_count() does not have unnecessary folio_mapcount() in its implementation.

Zi Yan committed 11 months ago

Commit 5842bcb1 parent bdd0d693 files · +22 −34Browse files

Unified · Split

3 files
  1. include/linux/huge_mm.h +0 −1
  2. mm/huge_memory.c +20 −32
  3. mm/vmscan.c +2 −1
include/linux/huge_mm.h+0−1
@@ -369,7 +369,6 @@ enum split_type { · 368 unmodified lines
369 SPLIT_TYPE_NON_UNIFORM,369 SPLIT_TYPE_NON_UNIFORM,
370};370};
371 371
372bool can_split_folio(struct folio *folio, int caller_pins, int *pextra_pins);
373int __split_huge_page_to_list_to_order(struct page *page, struct list_head *list,372int __split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
374 unsigned int new_order);373 unsigned int new_order);
375int folio_split_unmapped(struct folio *folio, unsigned int new_order);374int folio_split_unmapped(struct folio *folio, unsigned int new_order);
mm/huge_memory.c+20−32
@@ -3455,23 +3455,6 @@ static void lru_add_split_folio(struct folio *folio, struct folio *new_folio, · 3454 unmodified lines
3455 }3455 }
3456}3456}
3457 3457
3458/* Racy check whether the huge page can be split */
3459bool can_split_folio(struct folio *folio, int caller_pins, int *pextra_pins)
3460{
3461 int extra_pins;
3462
3463 /* Additional pins from page cache */
3464 if (folio_test_anon(folio))
3465 extra_pins = folio_test_swapcache(folio) ?
3466 folio_nr_pages(folio) : 0;
3467 else
3468 extra_pins = folio_nr_pages(folio);
3469 if (pextra_pins)
3470 *pextra_pins = extra_pins;
3471 return folio_mapcount(folio) == folio_ref_count(folio) - extra_pins -
3472 caller_pins;
3473}
3474
3475static bool page_range_has_hwpoisoned(struct page *page, long nr_pages)3458static bool page_range_has_hwpoisoned(struct page *page, long nr_pages)
3476{3459{
3477 for (; nr_pages; page++, nr_pages--)3460 for (; nr_pages; page++, nr_pages--)
@@ -3767,11 +3750,19 @@ int folio_check_splittable(struct folio *folio, unsigned int new_order, · 289 unmodified lines
3767 return 0;3750 return 0;
3768}3751}
3769 3752
3753/* Number of folio references from the pagecache or the swapcache. */
3754static unsigned int folio_cache_ref_count(const struct folio *folio)
3755{
3756 if (folio_test_anon(folio) && !folio_test_swapcache(folio))
3757 return 0;
3758 return folio_nr_pages(folio);
3759}
3760
3770static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int new_order,3761static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int new_order,
3771 struct page *split_at, struct xa_state *xas,3762 struct page *split_at, struct xa_state *xas,
3772 struct address_space *mapping, bool do_lru,3763 struct address_space *mapping, bool do_lru,
3773 struct list_head *list, enum split_type split_type,3764 struct list_head *list, enum split_type split_type,
3774 pgoff_t end, int *nr_shmem_dropped, int extra_pins)3765 pgoff_t end, int *nr_shmem_dropped)
3775{3766{
3776 struct folio *end_folio = folio_next(folio);3767 struct folio *end_folio = folio_next(folio);
3777 struct folio *new_folio, *next;3768 struct folio *new_folio, *next;
@@ -3782,10 +3773,9 @@ static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int n · 4 unmodified lines
3782 VM_WARN_ON_ONCE(!mapping && end);3773 VM_WARN_ON_ONCE(!mapping && end);
3783 /* Prevent deferred_split_scan() touching ->_refcount */3774 /* Prevent deferred_split_scan() touching ->_refcount */
3784 ds_queue = folio_split_queue_lock(folio);3775 ds_queue = folio_split_queue_lock(folio);
3785 if (folio_ref_freeze(folio, 1 + extra_pins)) {3776 if (folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) {
3786 struct swap_cluster_info *ci = NULL;3777 struct swap_cluster_info *ci = NULL;
3787 struct lruvec *lruvec;3778 struct lruvec *lruvec;
3788 int expected_refs;
3789 3779
3790 if (old_order > 1) {3780 if (old_order > 1) {
3791 if (!list_empty(&folio->_deferred_list)) {3781 if (!list_empty(&folio->_deferred_list)) {
@@ -3853,8 +3843,8 @@ static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int n · 61 unmodified lines
3853 3843
3854 zone_device_private_split_cb(folio, new_folio);3844 zone_device_private_split_cb(folio, new_folio);
3855 3845
3856 expected_refs = folio_expected_ref_count(new_folio) + 1;3846 folio_ref_unfreeze(new_folio,
3857 folio_ref_unfreeze(new_folio, expected_refs);3847 folio_cache_ref_count(new_folio) + 1);
3858 3848
3859 if (do_lru)3849 if (do_lru)
3860 lru_add_split_folio(folio, new_folio, lruvec, list);3850 lru_add_split_folio(folio, new_folio, lruvec, list);
@@ -3897,8 +3887,7 @@ static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int n · 36 unmodified lines
3897 * Otherwise, a parallel folio_try_get() can grab @folio3887 * Otherwise, a parallel folio_try_get() can grab @folio
3898 * and its caller can see stale page cache entries.3888 * and its caller can see stale page cache entries.
3899 */3889 */
3900 expected_refs = folio_expected_ref_count(folio) + 1;3890 folio_ref_unfreeze(folio, folio_cache_ref_count(folio) + 1);
3901 folio_ref_unfreeze(folio, expected_refs);
3902 3891
3903 if (do_lru)3892 if (do_lru)
3904 unlock_page_lruvec(lruvec);3893 unlock_page_lruvec(lruvec);
@@ -3947,7 +3936,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, · 42 unmodified lines
3947 struct folio *new_folio, *next;3936 struct folio *new_folio, *next;
3948 int nr_shmem_dropped = 0;3937 int nr_shmem_dropped = 0;
3949 int remap_flags = 0;3938 int remap_flags = 0;
3950 int extra_pins, ret;3939 int ret;
3951 pgoff_t end = 0;3940 pgoff_t end = 0;
3952 3941
3953 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);3942 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
@@ -4028,7 +4017,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, · 74 unmodified lines
4028 * Racy check if we can split the page, before unmap_folio() will4017 * Racy check if we can split the page, before unmap_folio() will
4029 * split PMDs4018 * split PMDs
4030 */4019 */
4031 if (!can_split_folio(folio, 1, &extra_pins)) {4020 if (folio_expected_ref_count(folio) != folio_ref_count(folio) - 1) {
4032 ret = -EAGAIN;4021 ret = -EAGAIN;
4033 goto out_unlock;4022 goto out_unlock;
4034 }4023 }
@@ -4051,8 +4040,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, · 16 unmodified lines
4051 }4040 }
4052 4041
4053 ret = __folio_freeze_and_split_unmapped(folio, new_order, split_at, &xas, mapping,4042 ret = __folio_freeze_and_split_unmapped(folio, new_order, split_at, &xas, mapping,
4054 true, list, split_type, end, &nr_shmem_dropped,4043 true, list, split_type, end, &nr_shmem_dropped);
4055 extra_pins);
4056fail:4044fail:
4057 if (mapping)4045 if (mapping)
4058 xas_unlock(&xas);4046 xas_unlock(&xas);
@@ -4126,20 +4114,20 @@ out: · 67 unmodified lines
4126 */4114 */
4127int folio_split_unmapped(struct folio *folio, unsigned int new_order)4115int folio_split_unmapped(struct folio *folio, unsigned int new_order)
4128{4116{
4129 int extra_pins, ret = 0;4117 int ret = 0;
4130 4118
4131 VM_WARN_ON_ONCE_FOLIO(folio_mapped(folio), folio);4119 VM_WARN_ON_ONCE_FOLIO(folio_mapped(folio), folio);
4132 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);4120 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
4133 VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);4121 VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
4134 VM_WARN_ON_ONCE_FOLIO(!folio_test_anon(folio), folio);4122 VM_WARN_ON_ONCE_FOLIO(!folio_test_anon(folio), folio);
4135 4123
4136 if (!can_split_folio(folio, 1, &extra_pins))4124 if (folio_expected_ref_count(folio) != folio_ref_count(folio) - 1)
4137 return -EAGAIN;4125 return -EAGAIN;
4138 4126
4139 local_irq_disable();4127 local_irq_disable();
4140 ret = __folio_freeze_and_split_unmapped(folio, new_order, &folio->page, NULL,4128 ret = __folio_freeze_and_split_unmapped(folio, new_order, &folio->page, NULL,
4141 NULL, false, NULL, SPLIT_TYPE_UNIFORM,4129 NULL, false, NULL, SPLIT_TYPE_UNIFORM,
4142 0, NULL, extra_pins);4130 0, NULL);
4143 local_irq_enable();4131 local_irq_enable();
4144 return ret;4132 return ret;
4145}4133}
@@ -4632,7 +4620,7 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start, · 486 unmodified lines
4632 * can be split or not. So skip the check here.4620 * can be split or not. So skip the check here.
4633 */4621 */
4634 if (!folio_test_private(folio) &&4622 if (!folio_test_private(folio) &&
4635 !can_split_folio(folio, 0, NULL))4623 folio_expected_ref_count(folio) != folio_ref_count(folio))
4636 goto next;4624 goto next;
4637 4625
4638 if (!folio_trylock(folio))4626 if (!folio_trylock(folio))
mm/vmscan.c+2−1
@@ -1284,7 +1284,8 @@ retry: · 1283 unmodified lines
1284 goto keep_locked;1284 goto keep_locked;
1285 if (folio_test_large(folio)) {1285 if (folio_test_large(folio)) {
1286 /* cannot split folio, skip it */1286 /* cannot split folio, skip it */
1287 if (!can_split_folio(folio, 1, NULL))1287 if (folio_expected_ref_count(folio) !=
1288 folio_ref_count(folio) - 1)
1288 goto activate_locked;1289 goto activate_locked;
1289 /*1290 /*
1290 * Split partially mapped folios right away.1291 * Split partially mapped folios right away.