From: Mike Kravetz <[email protected]>

commit 79aa925bf239c234be8586780e482872dc4690dd upstream.

Michal Privoznik was using "free page reporting" in QEMU/virtio-balloon
with hugetlbfs and hit the warning below.  QEMU with free page hinting
uses fallocate(FALLOC_FL_PUNCH_HOLE) to discard pages that are reported
as free by a VM.  The reporting granularity is in pageblock granularity.
So when the guest reports 2M chunks, we fallocate(FALLOC_FL_PUNCH_HOLE)
one huge page in QEMU.

  WARNING: CPU: 7 PID: 6636 at mm/page_counter.c:57 
page_counter_uncharge+0x4b/0x50
  Modules linked in: ...
  CPU: 7 PID: 6636 Comm: qemu-system-x86 Not tainted 5.9.0 #137
  Hardware name: Gigabyte Technology Co., Ltd. X570 AORUS PRO/X570 AORUS PRO, 
BIOS F21 07/31/2020
  RIP: 0010:page_counter_uncharge+0x4b/0x50
  ...
  Call Trace:
    hugetlb_cgroup_uncharge_file_region+0x4b/0x80
    region_del+0x1d3/0x300
    hugetlb_unreserve_pages+0x39/0xb0
    remove_inode_hugepages+0x1a8/0x3d0
    hugetlbfs_fallocate+0x3c4/0x5c0
    vfs_fallocate+0x146/0x290
    __x64_sys_fallocate+0x3e/0x70
    do_syscall_64+0x33/0x40
    entry_SYSCALL_64_after_hwframe+0x44/0xa9

Investigation of the issue uncovered bugs in hugetlb cgroup reservation
accounting.  This patch addresses the found issues.

Fixes: 075a61d07a8e ("hugetlb_cgroup: add accounting for shared mappings")
Reported-by: Michal Privoznik <[email protected]>
Co-developed-by: David Hildenbrand <[email protected]>
Signed-off-by: David Hildenbrand <[email protected]>
Signed-off-by: Mike Kravetz <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Tested-by: Michal Privoznik <[email protected]>
Reviewed-by: Mina Almasry <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Cc: <[email protected]>
Cc: David Hildenbrand <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Muchun Song <[email protected]>
Cc: "Aneesh Kumar K . V" <[email protected]>
Cc: Tejun Heo <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 mm/hugetlb.c |   20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -655,6 +655,8 @@ retry:
                        }
 
                        del += t - f;
+                       hugetlb_cgroup_uncharge_file_region(
+                               resv, rg, t - f);
 
                        /* New entry for end of split region */
                        nrg->from = t;
@@ -667,9 +669,6 @@ retry:
                        /* Original entry is trimmed */
                        rg->to = f;
 
-                       hugetlb_cgroup_uncharge_file_region(
-                               resv, rg, nrg->to - nrg->from);
-
                        list_add(&nrg->link, &rg->link);
                        nrg = NULL;
                        break;
@@ -685,17 +684,17 @@ retry:
                }
 
                if (f <= rg->from) {    /* Trim beginning of region */
-                       del += t - rg->from;
-                       rg->from = t;
-
                        hugetlb_cgroup_uncharge_file_region(resv, rg,
                                                            t - rg->from);
-               } else {                /* Trim end of region */
-                       del += rg->to - f;
-                       rg->to = f;
 
+                       del += t - rg->from;
+                       rg->from = t;
+               } else {                /* Trim end of region */
                        hugetlb_cgroup_uncharge_file_region(resv, rg,
                                                            rg->to - f);
+
+                       del += rg->to - f;
+                       rg->to = f;
                }
        }
 
@@ -2454,6 +2453,9 @@ struct page *alloc_huge_page(struct vm_a
 
                rsv_adjust = hugepage_subpool_put_pages(spool, 1);
                hugetlb_acct_memory(h, -rsv_adjust);
+               if (deferred_reserve)
+                       hugetlb_cgroup_uncharge_page_rsvd(hstate_index(h),
+                                       pages_per_huge_page(h), page);
        }
        return page;
 


Reply via email to