lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Wed, 6 Jan 2021 16:47:37 +0800 From: Muchun Song <songmuchun@...edance.com> To: mike.kravetz@...cle.com, akpm@...ux-foundation.org Cc: n-horiguchi@...jp.nec.com, ak@...ux.intel.com, mhocko@...e.cz, linux-mm@...ck.org, linux-kernel@...r.kernel.org, Muchun Song <songmuchun@...edance.com> Subject: [PATCH v2 4/6] mm: hugetlb: add return -EAGAIN for dissolve_free_huge_page When dissolve_free_huge_page() races with __free_huge_page(), we can do a retry. Because the race window is small. Signed-off-by: Muchun Song <songmuchun@...edance.com> --- mm/hugetlb.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 8ff138c17129..bf02e81e3953 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1775,10 +1775,11 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed, * nothing for in-use hugepages and non-hugepages. * This function returns values like below: * - * -EBUSY: failed to dissolved free hugepages or the hugepage is in-use - * (allocated or reserved.) - * 0: successfully dissolved free hugepages or the page is not a - * hugepage (considered as already dissolved) + * -EAGAIN: race with __free_huge_page() and can do a retry + * -EBUSY: failed to dissolved free hugepages or the hugepage is in-use + * (allocated or reserved.) + * 0: successfully dissolved free hugepages or the page is not a + * hugepage (considered as already dissolved) */ int dissolve_free_huge_page(struct page *page) { @@ -1805,8 +1806,10 @@ int dissolve_free_huge_page(struct page *page) * We should make sure that the page is already on the free list * when it is dissolved. */ - if (unlikely(!PageHugeFreed(head))) + if (unlikely(!PageHugeFreed(head))) { + rc = -EAGAIN; goto out; + } /* * Move PageHWPoison flag from head page to the raw error page, @@ -1825,6 +1828,14 @@ int dissolve_free_huge_page(struct page *page) } out: spin_unlock(&hugetlb_lock); + + /* + * If the freeing of the HugeTLB page is put on a work queue, we should + * flush the work before retrying. + */ + if (unlikely(rc == -EAGAIN)) + flush_work(&free_hpage_work); + return rc; } @@ -1847,7 +1858,12 @@ int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn) for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order) { page = pfn_to_page(pfn); +retry: rc = dissolve_free_huge_page(page); + if (rc == -EAGAIN) { + cpu_relax(); + goto retry; + } if (rc) break; } -- 2.11.0
Powered by blists - more mailing lists