From nobody Sat Feb 7 17:20:17 2026 Received: from mail-dy1-f172.google.com (mail-dy1-f172.google.com [74.125.82.172]) (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 37AB9207A32 for ; Wed, 7 Jan 2026 02:22:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767752548; cv=none; b=u2ZI50j9nl4eC1SPHIRmXjFh/p6y2yz62I/RP9qz+8nkzYHAMDf0FTAjjxGZifRUs0hlu4A/kRQFYLkSxxpv38k0orrgHmOcW8u8/K+TI6U6qMTcRJi95OLQcxWO4w5wWAJ0pkR/Vo3KdaYd25cNDbV1dzGfnh0vHSje3/dysLU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767752548; c=relaxed/simple; bh=8SYFwo/boI3SmOD9mmlGdc/tMJSs3M7ul1skNdTl9IQ=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=G94MzcqCoWc2L1CGFvR4OiQTni4WarGFRa80nKqlR6pVA5OO1SDRHIZqbolBYCQ6GhvkDxzWTP7HQ0YFlmP9Vnw+/zCbBQyMUcUOYWFY5vo695YuEVl7YtBNWhpY+u9vLjtIqGsvmHZ0OjEnYyoRKFBJ+HWe5HvpW6eGNT9IIMk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=roeck-us.net; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bDh4KXYp; arc=none smtp.client-ip=74.125.82.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=roeck-us.net 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="bDh4KXYp" Received: by mail-dy1-f172.google.com with SMTP id 5a478bee46e88-2b053ec7d90so884170eec.0 for ; Tue, 06 Jan 2026 18:22:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1767752545; x=1768357345; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:sender:from:to:cc:subject:date:message-id:reply-to; bh=+pY3++RoIvY9aLRkJUNxdKswch5gwSrkeohy6VF0XP8=; b=bDh4KXYpLdmpHCN6nq9N53Q2pZ6GAFydJ6z+WIZ76/+8f0i2NTL7U9hC1p0YovX158 hyNRHcSMmJcoyBBSl2DvJEsR1CqviTmH3ALwFp21P2Ct2NUAKdUKGLjh2OxyTe30BIYF WwuengOHwV2Us82fXSeuT3jY7dU9nivJQ1iV8CA/7k2o3RmOdOT+qqM9uGA5KSkfLR3M lV5RycMihLxIY9JdLM7yMuR0WcGODOWWL3NhC99zCtx2HXJKzzNx+JEPrtu6tKnxJo2Y b50EYBMnko0qQYPM1Gt6W5nAR5ExBWu+XX/oc2Olh/RNcAU+3sLHA/MkMW9DISKDrsX8 inQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767752545; x=1768357345; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:sender:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=+pY3++RoIvY9aLRkJUNxdKswch5gwSrkeohy6VF0XP8=; b=Mjyv+ZpJ4tFAH2qn7Hfye+EQ4NJmDofd8wflryL7fmQWgRSiJR4XZagxu5ri7Wk/MT 0x3b0ZszRxSPUxcrPHgKVyxQwVeORoqNjz3NhbWiMY19Gt9G7fQ9PlaxoI3zclRah/gt 47cT+jpbpnRZIwe/S+DBNHEqNAyPtBmzZshCg4HXcHBY/0LVkQ/yTPUwJHLSSG2geuYy S3dE1f6avXuiOlM9LiO5oc81SfpM7/SpeoBe65N2u5Rhoa/tgRkm5j+XdKywr67JhHEM S+JCGme+L87r8ttSLLkLE+sYIA0TmgNpuwbC1C3dnq+AOw9AOG/mnjWcBqATyM2ObkVS uPyQ== X-Forwarded-Encrypted: i=1; AJvYcCXkyZ2XWi/9GFfsJuhCOiRobzBkDcqHby4qN6N/MjJWTVz/qQW5DxYc/q26LHwAH1hsHe3/gOLmLD2R5GU=@vger.kernel.org X-Gm-Message-State: AOJu0YycFX1iOTBRL7r+SQlVA9LREBdf05PZpRICn8kHRzpdWeUy31Is z8nQ/QNNsut3wsicATmniK1im0hJs+aq19TXMVTeLYWRch1t3SmLH36by6u0iA== X-Gm-Gg: AY/fxX7JZE/UbvlfAK/TJaXCOOcBC9XRhPf5XQjsbONezSxUmIOC9MvmxUz9Vd81v9R 5r1mfxoQlLF4V+bn1lT2LMwiBTlaN8Qo9Wf4idkV0/5V8tv4lXFiaNmotW4PRUhq7MLbHpDQf/6 jvSOvYSQAuRzWI+prsz+7OTMlQp3csXZGU93ncHLA6nacgWkZDMp5Rn3hcjgbvZjUgm+nddYThX tpbWE64jlXlPq+epGut7/p7GkLtLNThsC9XpGhGBBtPwWNQ7d6uAUE7iG3Xp59WSn9luH8vEcC3 NhASH9UfAyyulsn2YNMk7SNEMA3CGz9ZZbT5Wp6ay/pkOAi/aAIs4KjvovPk5lN/VQ4tBU1+ofl Z8RAkAJdtf0ZVYzBWUMY9r49S5W6HHrnFrYjDWziHmgT8oA4iAytXIJXA8cVmR7C3OlEQZwUFe8 0PqvgNuO+T+P+D4/hgnihwMx7n X-Google-Smtp-Source: AGHT+IHZti3mnv8gmCGd0QAiWAd3nZiv7YmKqZBeP56OJEuXwRFyMkXjh8gyhHfXutXJFnWxAhGyYQ== X-Received: by 2002:a05:7300:8622:b0:2ae:5b71:d226 with SMTP id 5a478bee46e88-2b17d1fa677mr829927eec.3.1767752544956; Tue, 06 Jan 2026 18:22:24 -0800 (PST) Received: from server.roeck-us.net ([2600:1700:e321:62f0:da43:aeff:fecc:bfd5]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2b17078d818sm5445604eec.21.2026.01.06.18.22.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 18:22:24 -0800 (PST) Sender: Guenter Roeck From: Guenter Roeck To: Steven Rostedt Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, Guenter Roeck Subject: [PATCH v3] ftrace: Do not over-allocate ftrace memory Date: Tue, 6 Jan 2026 18:22:21 -0800 Message-ID: <20260107022221.2907717-1-linux@roeck-us.net> X-Mailer: git-send-email 2.45.2 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The pg_remaining calculation in ftrace_process_locs() assumes that ENTRIES_PER_PAGE multiplied by 2^order equals the actual capacity of the allocated page group. However, ENTRIES_PER_PAGE is PAGE_SIZE / ENTRY_SIZE (integer division). When PAGE_SIZE is not a multiple of ENTRY_SIZE (e.g. 4096 / 24 =3D 170 with remainder 16), high-order allocations (like 256 page= s) have significantly more capacity than 256 * 170. This leads to pg_remaining being underestimated, which in turn makes skip (derived from skipped - pg_remaining) larger than expected, causing the WARN(skip !=3D remaining) to trigger. Extra allocated pages for ftrace: 2 with 654 skipped WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:7295 ftrace_process_locs+0x= 5bf/0x5e0 A similar problem in ftrace_allocate_records() can result in allocating too many pages. This can trigger the second warning in ftrace_process_locs(). Extra allocated pages for ftrace WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:7276 ftrace_process_locs+0x= 548/0x580 Use the actual capacity of a page group to determine the number of pages to allocate. Have ftrace_allocate_pages() return the number of allocated pages to avoid having to calculate it. Use the actual page group capacity when validating the number of unused pages due to skipped entries. Drop the definition of ENTRIES_PER_PAGE since it is no longer used. Fixes: 4a3efc6baff93 ("ftrace: Update the mcount_loc check of skipped entri= es") Cc: Steven Rostedt Signed-off-by: Guenter Roeck --- v3: Restore the code calculating the number of unused pages due to skipped entries. Use the actual number of entries per page group when calculating the number of entries in unused page groups. v2: Have ftrace_allocate_pages() return the number of allocated pages, and drop the page count calculation code as well as the associated warnings from ftrace_process_locs(). kernel/trace/ftrace.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index ef2d5dca6f70..2c9692b45215 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1148,7 +1148,6 @@ struct ftrace_page { }; =20 #define ENTRY_SIZE sizeof(struct dyn_ftrace) -#define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE) =20 static struct ftrace_page *ftrace_pages_start; static struct ftrace_page *ftrace_pages; @@ -3834,7 +3833,8 @@ static int ftrace_update_code(struct module *mod, str= uct ftrace_page *new_pgs) return 0; } =20 -static int ftrace_allocate_records(struct ftrace_page *pg, int count) +static int ftrace_allocate_records(struct ftrace_page *pg, int count, + unsigned long *num_pages) { int order; int pages; @@ -3844,7 +3844,7 @@ static int ftrace_allocate_records(struct ftrace_page= *pg, int count) return -EINVAL; =20 /* We want to fill as much as possible, with no empty pages */ - pages =3D DIV_ROUND_UP(count, ENTRIES_PER_PAGE); + pages =3D DIV_ROUND_UP(count * ENTRY_SIZE, PAGE_SIZE); order =3D fls(pages) - 1; =20 again: @@ -3859,6 +3859,7 @@ static int ftrace_allocate_records(struct ftrace_page= *pg, int count) } =20 ftrace_number_of_pages +=3D 1 << order; + *num_pages +=3D 1 << order; ftrace_number_of_groups++; =20 cnt =3D (PAGE_SIZE << order) / ENTRY_SIZE; @@ -3887,12 +3888,14 @@ static void ftrace_free_pages(struct ftrace_page *p= ages) } =20 static struct ftrace_page * -ftrace_allocate_pages(unsigned long num_to_init) +ftrace_allocate_pages(unsigned long num_to_init, unsigned long *pages) { struct ftrace_page *start_pg; struct ftrace_page *pg; int cnt; =20 + *pages =3D 0; + if (!num_to_init) return NULL; =20 @@ -3906,7 +3909,7 @@ ftrace_allocate_pages(unsigned long num_to_init) * waste as little space as possible. */ for (;;) { - cnt =3D ftrace_allocate_records(pg, num_to_init); + cnt =3D ftrace_allocate_records(pg, num_to_init, pages); if (cnt < 0) goto free_pages; =20 @@ -7192,8 +7195,6 @@ static int ftrace_process_locs(struct module *mod, if (!count) return 0; =20 - pages =3D DIV_ROUND_UP(count, ENTRIES_PER_PAGE); - /* * Sorting mcount in vmlinux at build time depend on * CONFIG_BUILDTIME_MCOUNT_SORT, while mcount loc in @@ -7206,7 +7207,7 @@ static int ftrace_process_locs(struct module *mod, test_is_sorted(start, count); } =20 - start_pg =3D ftrace_allocate_pages(count); + start_pg =3D ftrace_allocate_pages(count, &pages); if (!start_pg) return -ENOMEM; =20 @@ -7305,27 +7306,27 @@ static int ftrace_process_locs(struct module *mod, /* We should have used all pages unless we skipped some */ if (pg_unuse) { unsigned long pg_remaining, remaining =3D 0; - unsigned long skip; + long skip; =20 /* Count the number of entries unused and compare it to skipped. */ - pg_remaining =3D (ENTRIES_PER_PAGE << pg->order) - pg->index; + pg_remaining =3D (PAGE_SIZE << pg->order) / ENTRY_SIZE - pg->index; =20 if (!WARN(skipped < pg_remaining, "Extra allocated pages for ftrace")) { =20 skip =3D skipped - pg_remaining; =20 - for (pg =3D pg_unuse; pg; pg =3D pg->next) + for (pg =3D pg_unuse; pg && skip > 0; pg =3D pg->next) { remaining +=3D 1 << pg->order; + skip -=3D (PAGE_SIZE << pg->order) / ENTRY_SIZE; + } =20 pages -=3D remaining; =20 - skip =3D DIV_ROUND_UP(skip, ENTRIES_PER_PAGE); - /* * Check to see if the number of pages remaining would * just fit the number of entries skipped. */ - WARN(skip !=3D remaining, "Extra allocated pages for ftrace: %lu with %= lu skipped", + WARN(pg || skip > 0, "Extra allocated pages for ftrace: %lu with %lu sk= ipped", remaining, skipped); } /* Need to synchronize with ftrace_location_range() */ --=20 2.45.2