3.7. Redeeming#

After the buddy allocator returned the pages for the allocation, redeem_claims_for_allocation() redeems claims up to the size of the allocation in the same critical region that updates the free-page counters.

The function performs the following steps to redeem the matching claims for this allocation. It ensures that the domain’s total memory allocation as domain_tot_pages() plus its outstanding claims as domain.outstanding_pages remain within the domain’s limits, defined by domain.max_pages:

3.7.1. Steps to redeem claims for an allocation#

Step 1:

Redeem claims from domain.claims[alloc_node] on the allocation node, up to the size of that claim.

Step 2:

If the allocation exceeds domain.claims[alloc_node], redeem the remaining pages from the host-wide claims (domain.outstanding_pages - domain.node_claims), up to the size of the host-wide claims.

Step 3:

If the allocation exceeds the combination of those claims, redeem the remaining pages from other per-node claims so that the domain’s total allocation plus claims remain within the domain’s domain.max_pages limit.

3.7.2. Enforcing the domain’s max_pages limit#

domain_tot_pages() + domain.outstanding_pages must not exceed the domain.max_pages limit, otherwise the domain could exceed its memory entitlement.

At claim installation time, domain_install_claim_set() performs this check.

At memory allocation time

If (unexpectedly) a domain builder ends up allocating memory from different nodes than it claimed from, the domain’s total allocation plus claims could exceed the domain’s domain.max_pages limit, unless the page allocator redeems claims from other nodes to ensure the sum of the domain’s claims and populated pages remains within the domain.max_pages limit.

redeem_claims_for_allocation() cannot reliably check domain.max_pages race-free because domain.max_pages is not protected by the heap_lock taken by the page allocator during allocation.

To check the domain’s limits, it would have to take the domain.page_alloc_lock to inspect the domain’s limits and its current allocation. However, taking that lock while holding the heap_lock would invert the locking order and could lead to deadlocks.

Therefore, redeem_claims_for_allocation() redeems the remaining allocation from other-node claims in Step 3.