[PATCH v5 0/8] make hugetlb put_page safe for all calling contexts

From: Mike Kravetz
Date: Fri Apr 09 2021 - 16:54:21 EST


IMPORTANT NOTE FOR REVIEWERS: Andrew has removed Oscar Salvador's series
"Make alloc_contig_range handle Hugetlb pages" so that this series can
go in first. Most issues discussed in v4 of this series do not apply
until Oscar's series is added and will be addressed then. This could be
more accurately described as v3.2. Changes from v3 only include:
- Trivial context changes
- Oscar's suggestions to move some VM_BUG_ON_PAGE calls and remove
unnecessary HPage flag clearing in remove_hugetlb_page.
- Add a missing spin_lock to spin_lock_irq conversion in
set_max_huge_pages.
- Acked-by: and Reviewed-by: tags from v3 remain with those from v4 that
also apply.

Original cover letter follows:
This effort is the result a recent bug report [1]. Syzbot found a
potential deadlock in the hugetlb put_page/free_huge_page_path.
WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected
Since the free_huge_page_path already has code to 'hand off' page
free requests to a workqueue, a suggestion was proposed to make
the in_irq() detection accurate by always enabling PREEMPT_COUNT [2].
The outcome of that discussion was that the hugetlb put_page path
(free_huge_page) path should be properly fixed and safe for all calling
contexts.

This series is based on v5.12-rc3-mmotm-2021-03-17-22-24. At a high
level, the series provides:
- Patches 1 & 2 change CMA bitmap mutex to an irq safe spinlock
- Patch 3 adds a mutex for proc/sysfs interfaces changing hugetlb counts
- Patches 4, 5 & 6 are aimed at reducing lock hold times. To be clear
the goal is to eliminate single lock hold times of a long duration.
Overall lock hold time is not addressed.
- Patch 7 makes hugetlb_lock and subpool lock IRQ safe. It also reverts
the code which defers calls to a workqueue if !in_task.
- Patch 8 adds some lockdep_assert_held() calls

[1] https://lore.kernel.org/linux-mm/000000000000f1c03b05bc43aadc@xxxxxxxxxx/
[2] http://lkml.kernel.org/r/20210311021321.127500-1-mike.kravetz@xxxxxxxxxx

v4 -> v5
- Do not take the series "Make alloc_contig_range handle Hugetlb pages"
into account. It will be added after this series.
- In remove_hugetlb_page, move VM_BUG_ON_PAGE calls and remove
unnecessary HPage flag clearing as suggested by Oscar.
- Add all collected Acked-by: and Reviewed-by:

v3 -> v4
- Add changes needed for the series "Make alloc_contig_range handle
Hugetlb pages"

v2 -> v3
- Update commit message in patch 1 as suggested by Michal
- Do not use spin_lock_irqsave/spin_unlock_irqrestore when we know we
are in task context as suggested by Michal
- Remove unnecessary INIT_LIST_HEAD() as suggested by Muchun

v1 -> v2
- Drop Roman's cma_release_nowait() patches and just change CMA mutex
to an IRQ safe spinlock.
- Cleanups to variable names, commets and commit messages as suggested
by Michal, Oscar, Miaohe and Muchun.
- Dropped unnecessary INIT_LIST_HEAD as suggested by Michal and list_del
as suggested by Muchun.
- Created update_and_free_pages_bulk helper as suggested by Michal.
- Rebased on v5.12-rc4-mmotm-2021-03-28-16-37
- Added Acked-by: and Reviewed-by: from v1

RFC -> v1
- Add Roman's cma_release_nowait() patches. This eliminated the need
to do a workqueue handoff in hugetlb code.
- Use Michal's suggestion to batch pages for freeing. This eliminated
the need to recalculate loop control variables when dropping the lock.
- Added lockdep_assert_held() calls
- Rebased to v5.12-rc3-mmotm-2021-03-17-22-24

Mike Kravetz (8):
mm/cma: change cma mutex to irq safe spinlock
hugetlb: no need to drop hugetlb_lock to call cma_release
hugetlb: add per-hstate mutex to synchronize user adjustments
hugetlb: create remove_hugetlb_page() to separate functionality
hugetlb: call update_and_free_page without hugetlb_lock
hugetlb: change free_pool_huge_page to remove_pool_huge_page
hugetlb: make free_huge_page irq safe
hugetlb: add lockdep_assert_held() calls for hugetlb_lock

include/linux/hugetlb.h | 1 +
mm/cma.c | 18 +--
mm/cma.h | 2 +-
mm/cma_debug.c | 8 +-
mm/hugetlb.c | 337 +++++++++++++++++++++-------------------
mm/hugetlb_cgroup.c | 8 +-
6 files changed, 194 insertions(+), 180 deletions(-)

--
2.30.2