From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oi1-f176.google.com (mail-oi1-f176.google.com [209.85.167.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EDBF4281530 for ; Tue, 23 Jun 2026 19:44:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.176 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782243858; cv=none; b=CRt+qtKG9kuO5me/CjkNrLxsWGyxYhVOndVH5fWEwlFgXJCzN6TEg8xonnBq61DMuh3aBc95TbkhqLx/m3oTyTw60+0ulsCRNAeV9HwOw3Y/weqHT8QZJDUITdjVJ5NjbEeP7EgZoY7RlyEg6ScN0hwvf7w1FG2jMvTCIzabRxs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782243858; c=relaxed/simple; bh=xGVfyeI5sgath3f7A8Ib7TtW7dbRKz4tYmjY4Aso30A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uh+HrLWLdrxKAr3TRdBJaogjNvSttWMsuMBhMpULdJNQV9wkXHZI+EJ/kOjIzw0XpWJOQUqXiOE/NWE3H6iCsh8aH96KcW7Py3naaZopKfCJV9EJEvoF7J68HC1YheG8vo0MV8N+7uWTzIQVc4uxmgKyIJBMm7Ic70Xeac7w9FM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=LknncH9i; arc=none smtp.client-ip=209.85.167.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="LknncH9i" Received: by mail-oi1-f176.google.com with SMTP id 5614622812f47-48bd982d04bso171413b6e.1 for ; Tue, 23 Jun 2026 12:44:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1782243851; x=1782848651; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Lgm2YIBlwTOJsnhELmj9Lon+JAOK9Kqtj3LT2AgOXNE=; b=LknncH9i1IlGMW459T2dPMT02JhJeGu/xjMSQSpi4zWO2aK9Xq/UoCWTk3slr5XO6y K6RgpyeD7K3BvO26tBeneaCvEXKTKB6TmPy0Ghdqs6U7Flz2cQs+G+flmYtY/tuQ+Cwd PMIZf0O6DVAJlKVo06jSFMCorMrcQYKVGBt9yNwhJc2qE86A9B9lr8RA+PToBRYM/003 okaQ2s0cnw0PL7pRdazWYUDgzrt0nMW3L1sMN0iSJjj0+z+OCgRPrwdFhuY/VdtNYY5q WJk8qkM0K4DbJJ06pw4qYCuQtN922gqEAJ8NwETbOEggD6J6kKA4Aa1/m3isPjZD8rZb QvUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782243851; x=1782848651; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Lgm2YIBlwTOJsnhELmj9Lon+JAOK9Kqtj3LT2AgOXNE=; b=RvjvfmEdiHpCircZe0yREKJ8COjuWmKffHQ3nBdOZWqzHpYslmdsVXZPQrVM7GVPSG Hksc/3wfASfvRDdbeomi3agFvtugiSuOC6U3y/YrSkSJ3Kt+AlRuaGamSi+WiuWOO4f3 Q575Rm9ypXwA+6oowfdTK6G3a+XD+zVCG5zMOdgdcjsTlRo3U9lA4/kouuRAtdUyvD/l MphOcgwqfj5I3ccSVssgDZAMoF9HeI3nkfqOhvHrLGBVjacm2g12oGTKeDMr7Wy2Csn5 d//hEYXTEuDVjW+rWR1lrkOi3CJX8YOKO5+1I4OG19dPhZ2Kn5nzffa8TlaWEGwPzvFO +s/Q== X-Forwarded-Encrypted: i=1; AFNElJ/velMagnJ/cvGJu5mrVUVSrymJzTwDg10+JC6+CGUkqPdpYyWF6Nn+PqRrFsPSLVWc/mRQs3Z1BWp/FTI=@vger.kernel.org X-Gm-Message-State: AOJu0YxgoltXMV+46MyhdLGqjp91YOFq4quF83JOmyMzV4e0JB4pnIcc iq5h3QvaNrehHlnVHxAchnsIBVT4HwF3n+ykhWBsDQ/Hj/7/UOysmm5W X-Gm-Gg: AfdE7cmsvCQpr0+/WDsvj5Y6vwY9uvJT7DKi435yrM6NuH/SJS+DQEtQrudH35Vn8f/ SE0e20jncb7R2DcTX6FSsIxfTiFQhvByk8MQ2hvHptL2U4OLSiDXXlsY0pbtKnyCDIRUCJ0zZ9d +uCXoRKV7se7SDaggvENJnHFIO5qnnl+pCG8eVnYZJ4JvlSR3cYmZmM2GGmce9GLXu8jutfJtTM R0NTkdquOjjSshkQgwhTGiySWP7fVZ+LzBNfDTYQrfqeIVuMGRVLhZbAfpOggszvs+/deFAoxbj aAT5q6v8Wz213t3Q7o9UDoCgNGoafzoYrNf1KYnkaT3JvKJLxcmMZuz1gQbN1SWuLJ5pdJVxL8B 8N4t+q/hTN4ug9Swb864qTcHBYRlWuxDxOa6w31zLScnFgM3kMyguJMECcVkuzWdLrUwe83imz4 TSsxr5hoqd9yJMHnJHtEh0YEUwyKo7R4bgfA/7inxK1/g= X-Received: by 2002:a05:6808:3a0e:b0:48a:b42c:6f08 with SMTP id 5614622812f47-48ee2f53500mr3588132b6e.10.1782243850984; Tue, 23 Jun 2026 12:44:10 -0700 (PDT) Received: from localhost ([2a03:2880:10ff:41::]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7e944007d7fsm9481926a34.2.2026.06.23.12.44.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jun 2026 12:44:10 -0700 (PDT) From: Joshua Hahn To: Charles Haithcock Cc: muchun.song@linux.dev, osalvador@suse.de, akpm@linux-foundation.org, david@kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, arozansk@redhat.com Subject: Re: [PATCH v2] Respect mempolicy when calculating surplus huge pages. Date: Tue, 23 Jun 2026 12:44:08 -0700 Message-ID: <20260623194409.2034390-1-joshua.hahnjy@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260623184548.1245488-1-chaithco@redhat.com> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit > Presently, when calculating how many huge pages are needed when > reserving surplus huge pages, the global count of free huge pages > are used. When reserving with a mempolicy, the global count of free huge > pages is used even if some/all of those free huge pages are on numa > nodes outside of the mempolicy. > > Reserving surplus huge pages is ultimately best effort even without a > mempolicy. Restrictions from cpusets and mempolicies further complicate > calculating correct numbers of surplus huge pages to reserve and > maintaining which nodes those reservations belong to (see the comment in > `hugetlb_acct_memory`). > > However, we can do a little better when reserving surplus huge pages > with a mempolicy. This patch changes how to calculate the necessary > amount of surplus huge pages to reserve by considering the max of either > the amount of free huge pages on nodes in the mempolicy or the global > amount of free huge pages. We may still attempt to reserve huge pages > outside the mempolicy, however, we end up being more likely to reserve > from nodes in the mempolicy. > > Signed-off-by: Charles Haithcock > --- > > - v1: Modified `needed` calculation to use `allowed_mems_nr(h)` in order > to consider free hugetlb pages in our mempolicy. > - v2: Folded in Joshua Hahn's recommendation [1] to further modify > `needed` calculation to take the max of either the available hugetlb > pages in the mempolicy or the globally available hugetlb pages. Allows > allocations to prioritize nodes in the mempolicy but can still fall > back to offnode allocations. Also added selftests to check only for > the edgecase which caused this to initially be reported and sanity > checks. > > [1] https://lore.kernel.org/all/20260602152022.2673803-1-joshua.hahnjy@gmail.com/ > > mm/hugetlb.c | 42 +- > tools/testing/selftests/mm/Makefile | 3 + > .../selftests/mm/hugetlb_surplus_mempolicy.c | 472 ++++++++++++++++++ > tools/testing/selftests/mm/run_vmtests.sh | 1 + > 4 files changed, 498 insertions(+), 20 deletions(-) > create mode 100644 tools/testing/selftests/mm/hugetlb_surplus_mempolicy.c Hi Charles, Thanks for following up with a v2! The change to hugetlb.c looks good to me, I left a small stylistic nit below. One request I have is that we might separate this commit into two, one for the mm/hugetlb.c change, and one for the selftests & related scripts/Makefile change. That way, reviewers can sign off and review the change separately from the selftests that are being introduced! > diff --git a/mm/hugetlb.c b/mm/hugetlb.c > index f24bf49be0..bd97f0f434 100644 > --- a/mm/hugetlb.c > +++ b/mm/hugetlb.c > @@ -2255,6 +2255,23 @@ static nodemask_t *policy_mbind_nodemask(gfp_t gfp) > return NULL; > } > > +static unsigned int allowed_mems_nr(struct hstate *h) > +{ > + int node; > + unsigned int nr = 0; > + nodemask_t *mbind_nodemask; > + unsigned int *array = h->free_huge_pages_node; > + gfp_t gfp_mask = htlb_alloc_mask(h); > + > + mbind_nodemask = policy_mbind_nodemask(gfp_mask); > + for_each_node_mask(node, cpuset_current_mems_allowed) { > + if (!mbind_nodemask || node_isset(node, *mbind_nodemask)) > + nr += array[node]; > + } > + > + return nr; > +} > + > /* > * Increase the hugetlb pool such that it can accommodate a reservation > * of size 'delta'. > @@ -2277,7 +2294,8 @@ static int gather_surplus_pages(struct hstate *h, long delta) > alloc_nodemask = cpuset_current_mems_allowed; > > lockdep_assert_held(&hugetlb_lock); > - needed = (h->resv_huge_pages + delta) - h->free_huge_pages; > + needed = max((long) (delta - allowed_mems_nr(h)), > + (long) ((h->resv_huge_pages + delta) - h->free_huge_pages)); > if (needed <= 0) { > h->resv_huge_pages += delta; > return 0; > @@ -2311,8 +2329,9 @@ static int gather_surplus_pages(struct hstate *h, long delta) > * because either resv_huge_pages or free_huge_pages may have changed. > */ > spin_lock_irq(&hugetlb_lock); > - needed = (h->resv_huge_pages + delta) - > - (h->free_huge_pages + allocated); > + needed = max((long) ((delta - allowed_mems_nr(h)) - allocated), > + (long) ((h->resv_huge_pages + delta) - > + (h->free_huge_pages + allocated))); What if instead of casting each argument separately, we use max_t(long, (...), (...)) instead? I think we could make this part look a bit better : -) The logic itself looks good to me. And thanks for catching the + allocated part, I think I missed that in my original response from v1. I'll take a look at the selftests in the future, just wanted to get these comments out first. Thanks again, I hope you have a great day! Joshua > if (needed > 0) { > if (alloc_ok) > goto retry;