fix: count huge pages
This commit is contained in:
@@ -2838,23 +2838,53 @@ class TestCpSharedL2EightRankReserveDeterminism(unittest.TestCase):
|
||||
|
||||
class TestCpSharedL2HugetlbfsCapacity(unittest.TestCase):
|
||||
"""The hugetlbfs capacity check fails LOUD on insufficient hugepages (clean message vs a cryptic mmap
|
||||
ENOMEM). statvfs works on any mount, so the logic is exercised here against a tmpdir; the real hugetlbfs
|
||||
semantics (f_frsize = hugepage size, f_bavail = free hugepages) validate on the live server."""
|
||||
ENOMEM). The FREE COUNT comes from sysfs (`hugepages-NkB/free_hugepages`), NOT statvfs.f_bavail -- the
|
||||
latter is 0 for an unlimited mount with no size= quota (the false "0 GB free" the live server hit). Here we
|
||||
inject a fake sysfs pool via `sysfs_root=`; the real sysfs validates on the server."""
|
||||
|
||||
def test_free_bytes_and_capacity_check(self):
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
free_bytes_fn = _cp_shared_l2_pool.cp_shared_l2_hugetlbfs_free_bytes
|
||||
check_fn = _cp_shared_l2_pool.check_cp_shared_l2_hugetlbfs_capacity
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
free, pages, page_bytes = free_bytes_fn(d)
|
||||
self.assertGreater(free, 0)
|
||||
self.assertGreater(page_bytes, 0)
|
||||
self.assertEqual(free, pages * page_bytes)
|
||||
check_fn(d, 4096) # tiny request fits -> no raise
|
||||
pool = _cp_shared_l2_pool
|
||||
free_bytes_fn = pool.cp_shared_l2_hugetlbfs_free_bytes
|
||||
check_fn = pool.check_cp_shared_l2_hugetlbfs_capacity
|
||||
with tempfile.TemporaryDirectory() as d, tempfile.TemporaryDirectory() as sysfs:
|
||||
# Build a fake sysfs pool whose dir name matches this mount's hugepage size so the lookup resolves
|
||||
# (the page size still comes from statvfs/meminfo; only the free COUNT is read from sysfs).
|
||||
page_bytes = pool._hugetlbfs_page_bytes(d)
|
||||
name = f"hugepages-{page_bytes // 1024}kB"
|
||||
os.makedirs(os.path.join(sysfs, name))
|
||||
with open(os.path.join(sysfs, name, "free_hugepages"), "w") as f:
|
||||
f.write("100\n")
|
||||
|
||||
free, pages, pb = free_bytes_fn(d, sysfs_root=sysfs)
|
||||
self.assertEqual(pages, 100)
|
||||
self.assertEqual(pb, page_bytes)
|
||||
self.assertEqual(free, 100 * page_bytes)
|
||||
|
||||
check_fn(d, page_bytes, sysfs_root=sysfs) # 1 page fits in 100 -> no raise
|
||||
with self.assertRaises(ValueError): # exceeds free capacity -> fail loud
|
||||
check_fn(d, free + 10**12)
|
||||
check_fn(d, free + page_bytes, sysfs_root=sysfs)
|
||||
|
||||
def test_skips_check_when_free_count_unreadable(self):
|
||||
# When the free count can't be read (unreadable sysfs root + a hugepage size that won't match any real
|
||||
# per-NUMA pool), the helper returns None and the check is SKIPPED -- never false-fails (the bug the
|
||||
# live server hit, where statvfs.f_bavail==0 wrongly reported "0 GB free").
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
pool = _cp_shared_l2_pool
|
||||
with tempfile.TemporaryDirectory() as empty_sysfs, tempfile.TemporaryDirectory() as d:
|
||||
# 7 MiB is not a real hugepage size, so the per-NUMA glob fallback finds nothing either.
|
||||
self.assertIsNone(pool._hugepage_free_pages(7 << 20, sysfs_root=empty_sysfs))
|
||||
free, pages, pb = pool.cp_shared_l2_hugetlbfs_free_bytes(d, sysfs_root=empty_sysfs)
|
||||
# Page size is still resolvable; free count is None iff this mount's size isn't in the empty root.
|
||||
self.assertGreater(pb, 0)
|
||||
if free is None:
|
||||
self.assertIsNone(pages)
|
||||
# An impossibly large request must NOT raise when the free count is unknown.
|
||||
pool.check_cp_shared_l2_hugetlbfs_capacity(d, 10**18, sysfs_root=empty_sysfs)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user