From nobody Mon Jun 8 22:51:24 2026 Received: from out-172.mta1.migadu.com (out-172.mta1.migadu.com [95.215.58.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BAFA73451AF for ; Mon, 25 May 2026 22:40:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779748811; cv=none; b=A4EnYNb55zxao9lsdu072gFCjBHZPQioG+BMk/Bm7jAn7WroKpnh0Imdk6aZxCj2o86lwbCpWCuxDgAT1T3n9YGhtpBjVV4X8hIWE09vGMQKVbr3Pwz6SnVbLqn2u5MlPm2RWapBOnk2aPaGgIgG1VFKa9gtIVfd+AV4TQoL1m0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779748811; c=relaxed/simple; bh=Jr9lcIbXLq4LE+XYFj8sp3KUpS6T1W/u6KkSV5Q3PFs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=StJfRADtXca53Xq9PhZnsaoCV4qlcLHyZVU1B/egegbbcW8YhIOQLQbyURXPRr1DZLBBVpRRSGuT4jeScKoPmBGvEU+Gw1LwtYHiXQpLXKefo46uB4l7qvaSE8jeGbLbqZMpEgnkIHvvsqmwFB72RPMEEeXV1w+flqDFJSmBA9w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=qSP7oJYM; arc=none smtp.client-ip=95.215.58.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="qSP7oJYM" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1779748807; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GVrvzy9clah8EtD+v/2ouiX/NekgcIxxRRED2Tw7R3w=; b=qSP7oJYM64isI/RnAp8IUkaDX0elXGA5tQCQJUsP1ZwSwwMsIx45Qvi0arEURyvepEuuS4 mZHnd2VO/7lhE4i3hgi6CKehhgmAqvyHqzEpKAN1yb7qmfzEBZQy8yQCsOxdKW/UzMqY1V VN9tFQazhsZdsrXZR4pcdxr5DJ5kU+Q= From: Ihor Solodrai To: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Eduard Zingerman , Kumar Kartikeya Dwivedi Cc: Puranjay Mohan , Shakeel Butt , Mykyta Yatsenko , bpf@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-team@meta.com Subject: [PATCH bpf-next v7 1/3] bpf: Factor out stack_map build ID helpers Date: Mon, 25 May 2026 15:39:46 -0700 Message-ID: <20260525223948.1920986-2-ihor.solodrai@linux.dev> In-Reply-To: <20260525223948.1920986-1-ihor.solodrai@linux.dev> References: <20260525223948.1920986-1-ihor.solodrai@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Factor out helpers from stack_map_get_build_id_offset() in preparation for adding a sleepable build ID resolution path: stack_map_build_id_set_ip(), stack_map_build_id_offset(), and stack_map_build_id_set_valid(). While here, refactor stack_map_get_build_id_offset(): * use continue-driven control flow in the main loop and remove build_id_valid label * update prev_vma and prev_build_id on the fall-back-to-IP branch so the cache reflects the actual VMA seen on the previous IP [1] * guard fetch_build_id() with vma_is_anonymous() [2] to skip parse attempts that would otherwise fail the ELF magic check [1] https://lore.kernel.org/bpf/CAEf4Bzac9uWWqBvzH0iFzKvJcq3vxscZ3pKm0sUHmN= -F-z9wVQ@mail.gmail.com/ [2] https://lore.kernel.org/bpf/226398c1ff3f2b686c0aeb010408d85fb15df13f9ff= 60a045bee31e79b9e41e9@mail.kernel.org/ Acked-by: Mykyta Yatsenko Signed-off-by: Ihor Solodrai --- kernel/bpf/stackmap.c | 57 ++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index da3d328f5c15..e23be7d44503 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -152,6 +152,28 @@ static int fetch_build_id(struct vm_area_struct *vma, = unsigned char *build_id, b : build_id_parse_nofault(vma, build_id, NULL); } =20 +static inline void stack_map_build_id_set_ip(struct bpf_stack_build_id *id) +{ + id->status =3D BPF_STACK_BUILD_ID_IP; + memset(id->build_id, 0, BUILD_ID_SIZE_MAX); +} + +static inline u64 stack_map_build_id_offset(unsigned long vm_pgoff, + unsigned long vm_start, u64 ip) +{ + return (vm_pgoff << PAGE_SHIFT) + ip - vm_start; +} + +static inline void stack_map_build_id_set_valid(struct bpf_stack_build_id = *id, + u64 offset, + const unsigned char *build_id) +{ + id->status =3D BPF_STACK_BUILD_ID_VALID; + id->offset =3D offset; + if (id->build_id !=3D build_id) + memcpy(id->build_id, build_id, BUILD_ID_SIZE_MAX); +} + /* * Expects all id_offs[i].ip values to be set to correct initial IPs. * They will be subsequently: @@ -165,44 +187,45 @@ static int fetch_build_id(struct vm_area_struct *vma,= unsigned char *build_id, b static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_of= fs, u32 trace_nr, bool user, bool may_fault) { - int i; struct mmap_unlock_irq_work *work =3D NULL; bool irq_work_busy =3D bpf_mmap_unlock_get_irq_work(&work); + bool has_user_ctx =3D user && current && current->mm; struct vm_area_struct *vma, *prev_vma =3D NULL; - const char *prev_build_id; + const unsigned char *prev_build_id =3D NULL; + int i; =20 /* If the irq_work is in use, fall back to report ips. Same * fallback is used for kernel stack (!user) on a stackmap with * build_id. */ - if (!user || !current || !current->mm || irq_work_busy || - !mmap_read_trylock(current->mm)) { + if (!has_user_ctx || irq_work_busy || !mmap_read_trylock(current->mm)) { /* cannot access current->mm, fall back to ips */ - for (i =3D 0; i < trace_nr; i++) { - id_offs[i].status =3D BPF_STACK_BUILD_ID_IP; - memset(id_offs[i].build_id, 0, BUILD_ID_SIZE_MAX); - } + for (i =3D 0; i < trace_nr; i++) + stack_map_build_id_set_ip(&id_offs[i]); return; } =20 for (i =3D 0; i < trace_nr; i++) { u64 ip =3D READ_ONCE(id_offs[i].ip); + u64 offset; =20 - if (range_in_vma(prev_vma, ip, ip)) { + if (prev_build_id && range_in_vma(prev_vma, ip, ip)) { vma =3D prev_vma; - memcpy(id_offs[i].build_id, prev_build_id, BUILD_ID_SIZE_MAX); - goto build_id_valid; + offset =3D stack_map_build_id_offset(vma->vm_pgoff, vma->vm_start, ip); + stack_map_build_id_set_valid(&id_offs[i], offset, prev_build_id); + continue; } vma =3D find_vma(current->mm, ip); - if (!vma || fetch_build_id(vma, id_offs[i].build_id, may_fault)) { + if (!vma || vma_is_anonymous(vma) || + fetch_build_id(vma, id_offs[i].build_id, may_fault)) { /* per entry fall back to ips */ - id_offs[i].status =3D BPF_STACK_BUILD_ID_IP; - memset(id_offs[i].build_id, 0, BUILD_ID_SIZE_MAX); + stack_map_build_id_set_ip(&id_offs[i]); + prev_vma =3D vma; + prev_build_id =3D NULL; continue; } -build_id_valid: - id_offs[i].offset =3D (vma->vm_pgoff << PAGE_SHIFT) + ip - vma->vm_start; - id_offs[i].status =3D BPF_STACK_BUILD_ID_VALID; + offset =3D stack_map_build_id_offset(vma->vm_pgoff, vma->vm_start, ip); + stack_map_build_id_set_valid(&id_offs[i], offset, id_offs[i].build_id); prev_vma =3D vma; prev_build_id =3D id_offs[i].build_id; } --=20 2.54.0 From nobody Mon Jun 8 22:51:24 2026 Received: from out-177.mta1.migadu.com (out-177.mta1.migadu.com [95.215.58.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D088039769E for ; Mon, 25 May 2026 22:40:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779748814; cv=none; b=P7B6WZRUwkxm8UopCvTamLXv/s/lSc0xvj1mPct5UG/KF1vNEXLb4sD8jvWCKsGrKsX48rSuaulz7Qh0mPg1PhWo3+1KSA3aoJFqZlNkIbO2zWEOH6keeaB3/jz52A2zfD+FiNuuyERvBtxVyw+IWatUldS+PYuSRxecA3RfvQM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779748814; c=relaxed/simple; bh=0YxIYaIYYnT/g9UM/SJ3S5sI7yCNoyHyvzipRRE+GKc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kux0MpQz2Ia5ibneh3ya6r+L37vn3tjC6PQ3L6oyNW04baHFw0bDDO4aTK1fEA7/v+hbrnWHvlOuG25FzfHYydBZUD7XtRE4g0TcXJ7ovbfxRC8nGsg/bjuA4Fv6sz7PZQzyS9G6RQexUNSjE1qi8u4bPJPAiQPS3TsJwf49pk0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=f8szRBMV; arc=none smtp.client-ip=95.215.58.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="f8szRBMV" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1779748810; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sj231GwwXetFfO9VdtBuFvxQvVdoCH2+jkbLl3qudLo=; b=f8szRBMVLgiMt7jMsZBoZaeZu9G7V2W8islqQiazGuMFwbCQuGkpWsNthR2awrAtd3M+Qh wDaOeZhwSZuBlyqGAq2SPjpZtu8eZXOvE4ZMeaf2H6aJCIeMzPOQbZIs9sbw5Md+Xw9B6j ODWHJpm9b27xFCZsWU39DwQkHz5aI2o= From: Ihor Solodrai To: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Eduard Zingerman , Kumar Kartikeya Dwivedi Cc: Puranjay Mohan , Shakeel Butt , Mykyta Yatsenko , bpf@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-team@meta.com Subject: [PATCH bpf-next v7 2/3] bpf: Avoid faultable build ID reads under mm locks Date: Mon, 25 May 2026 15:39:47 -0700 Message-ID: <20260525223948.1920986-3-ihor.solodrai@linux.dev> In-Reply-To: <20260525223948.1920986-1-ihor.solodrai@linux.dev> References: <20260525223948.1920986-1-ihor.solodrai@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Sleepable build ID parsing can block in __kernel_read() [1], so the stackmap sleepable path must not call it while holding mmap_lock or a per-VMA read lock. The issue and the fix are conceptually similar to a recent procfs patch [2]. A similar VMA locking pattern has already been used in PROCMAP_QUERY [3]. Resolve each covered VMA with a stable read-side reference, preferring lock_vma_under_rcu() and falling back to mmap_read_trylock() only long enough to acquire the VMA read lock. Take a reference to the backing file, drop the VMA lock, and then parse the build ID through (sleepable) build_id_parse_file(). We have to use mmap_read_trylock() (and give up on failure) in this context because taking mmap_read_lock() is generally unsafe on code paths reachable from BPF programs [4], and may lead to deadlocks. [1] https://lore.kernel.org/all/20251218005818.614819-1-shakeel.butt@linux.= dev/ [2] https://lore.kernel.org/all/20260128183232.2854138-1-andrii@kernel.org/ [3] https://lore.kernel.org/all/20250808152850.2580887-1-surenb@google.com/ [4] https://lore.kernel.org/bpf/2895ecd8-df1e-4cc0-b9f9-aef893dc2360@linux.= dev/ Fixes: d4dd9775ec24 ("bpf: wire up sleepable bpf_get_stack() and bpf_get_ta= sk_stack() helpers") Suggested-by: Puranjay Mohan Signed-off-by: Ihor Solodrai --- kernel/bpf/stackmap.c | 109 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index e23be7d44503..c53cfd9a67cf 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "percpu_freelist.h" #include "mmap_unlock_work.h" =20 @@ -174,6 +175,109 @@ static inline void stack_map_build_id_set_valid(struc= t bpf_stack_build_id *id, memcpy(id->build_id, build_id, BUILD_ID_SIZE_MAX); } =20 +struct stack_map_vma_lock { + struct vm_area_struct *vma; + struct mm_struct *mm; +}; + +/* + * Acquire a stable read-side reference on the VMA covering @ip. + * + * With CONFIG_PER_VMA_LOCK=3Dy this returns a VMA with its per-VMA read + * lock held and mmap_lock dropped, so the caller may sleep. + * + * With CONFIG_PER_VMA_LOCK=3Dn it returns a VMA with mmap_lock still + * held; the caller must snapshot any fields it needs and pin vm_file + * with get_file() before stack_map_unlock_vma() drops mmap_lock, as + * the VMA may be split, merged, or freed after that. + * + * Returns NULL on failure, in which case no lock is held. + */ +static struct vm_area_struct * +stack_map_lock_vma(struct stack_map_vma_lock *lock, unsigned long ip) +{ + struct mm_struct *mm =3D lock->mm; + struct vm_area_struct *vma; + + /* noop under !CONFIG_PER_VMA_LOCK */ + vma =3D lock_vma_under_rcu(mm, ip); + if (vma) { + lock->vma =3D vma; + return vma; + } + + /* + * Taking mmap_read_lock() is unsafe here, because the caller BPF + * program might already hold it, causing a deadlock. + */ + if (!mmap_read_trylock(mm)) + return NULL; + + vma =3D vma_lookup(mm, ip); + if (!vma) { + mmap_read_unlock(mm); + return NULL; + } + +#ifdef CONFIG_PER_VMA_LOCK + if (!vma_start_read_locked(vma)) { + mmap_read_unlock(mm); + return NULL; + } + mmap_read_unlock(mm); +#endif + + lock->vma =3D vma; + return vma; +} + +static void stack_map_unlock_vma(struct stack_map_vma_lock *lock) +{ +#ifdef CONFIG_PER_VMA_LOCK + vma_end_read(lock->vma); +#else + mmap_read_unlock(lock->mm); +#endif + lock->vma =3D NULL; +} + +static void stack_map_get_build_id_offset_sleepable(struct bpf_stack_build= _id *id_offs, + u32 trace_nr) +{ + struct mm_struct *mm =3D current->mm; + struct stack_map_vma_lock lock =3D { .mm =3D mm }; + struct vm_area_struct *vma; + struct file *file; + u64 offset; + u64 ip; + + for (u32 i =3D 0; i < trace_nr; i++) { + ip =3D READ_ONCE(id_offs[i].ip); + + vma =3D stack_map_lock_vma(&lock, ip); + if (!vma) { + stack_map_build_id_set_ip(&id_offs[i]); + continue; + } + if (vma_is_anonymous(vma) || !vma->vm_file) { + stack_map_build_id_set_ip(&id_offs[i]); + stack_map_unlock_vma(&lock); + continue; + } + + file =3D get_file(vma->vm_file); + offset =3D stack_map_build_id_offset(vma->vm_pgoff, vma->vm_start, ip); + stack_map_unlock_vma(&lock); + + /* build_id_parse_file() may block on filesystem reads */ + if (build_id_parse_file(file, id_offs[i].build_id, NULL)) + stack_map_build_id_set_ip(&id_offs[i]); + else + stack_map_build_id_set_valid(&id_offs[i], offset, id_offs[i].build_id); + fput(file); + } +} + /* * Expects all id_offs[i].ip values to be set to correct initial IPs. * They will be subsequently: @@ -194,6 +298,11 @@ static void stack_map_get_build_id_offset(struct bpf_s= tack_build_id *id_offs, const unsigned char *prev_build_id =3D NULL; int i; =20 + if (may_fault && has_user_ctx) { + stack_map_get_build_id_offset_sleepable(id_offs, trace_nr); + return; + } + /* If the irq_work is in use, fall back to report ips. Same * fallback is used for kernel stack (!user) on a stackmap with * build_id. --=20 2.54.0 From nobody Mon Jun 8 22:51:24 2026 Received: from out-178.mta1.migadu.com (out-178.mta1.migadu.com [95.215.58.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34BF739E9A0 for ; Mon, 25 May 2026 22:40:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779748817; cv=none; b=IZZMbLzULOmAbAtlH73UEBrnn83CrNGZi7pKpoDwQTRalOIFn4pUNGfVrC9CFUkqUQ1cHz+73EhlmEXkJf0m+XkHWk4zC/n2Odv065Nxwd544RKGc9I7+FaoE11V5Br51G7EbgZbjDob9txqP3Ir0GK5oDegPZ/1Xpg+G0cyLUc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779748817; c=relaxed/simple; bh=2e6ts3jthodVVFufG34atIwa3tEl5LEO9/DhoXe08gY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EJqZIwxxGtMuzLG3ZxQhhVO8mutwi9B7l+pCJYGjh6rXULqL5qM0AM5Tl19/tEevOZ4iKrpsVyaFj12U9lynAw1sZqvId8gk5y0WDIPe1daF4V2sRGsvKkaXjnNkN96uVoEWQT8xeBcJVxi3zKRJjPVfNes5AKBH6lKYIsle0PY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=L+mBiCS3; arc=none smtp.client-ip=95.215.58.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="L+mBiCS3" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1779748813; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=toqCpj5veBEZ43tMu1xdjS6WjCnJ8+7ui4srFdPxUwc=; b=L+mBiCS3wI7qaiK9+50OIb0+WLfcwRmbALjd8A3Lra+rLUR1TTXtUPb1VjaZYF6aWsUmLI 0Lp0OksHCzGDktJM7rqc+BZJg5+oRreBPJAmiHoo/T9zKIoHVSOdT36ukeEUxWU/mompgh aiuGUi/2DSxfhbRrMjnb/MP1+26C2co= From: Ihor Solodrai To: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Eduard Zingerman , Kumar Kartikeya Dwivedi Cc: Puranjay Mohan , Shakeel Butt , Mykyta Yatsenko , bpf@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-team@meta.com Subject: [PATCH bpf-next v7 3/3] bpf: Cache build IDs in sleepable stackmap path Date: Mon, 25 May 2026 15:39:48 -0700 Message-ID: <20260525223948.1920986-4-ihor.solodrai@linux.dev> In-Reply-To: <20260525223948.1920986-1-ihor.solodrai@linux.dev> References: <20260525223948.1920986-1-ihor.solodrai@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Stack traces often contain adjacent IPs from the same VMA or from different VMAs backed by the same ELF file. Cache the last successfully parsed build id together with the resolved VMA range and backing file so the sleepable build id path can avoid repeated VMA locking and file parsing in common cases. Suggested-by: Mykyta Yatsenko Acked-by: Mykyta Yatsenko Acked-by: Andrii Nakryiko Signed-off-by: Ihor Solodrai --- kernel/bpf/stackmap.c | 61 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index c53cfd9a67cf..77ba03216c09 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -246,6 +246,14 @@ static void stack_map_get_build_id_offset_sleepable(st= ruct bpf_stack_build_id *i { struct mm_struct *mm =3D current->mm; struct stack_map_vma_lock lock =3D { .mm =3D mm }; + struct { + struct file *file; + const unsigned char *build_id; + unsigned long vm_start; + unsigned long vm_end; + unsigned long vm_pgoff; + } cache =3D {}; + unsigned long vm_pgoff, vm_start, vm_end; struct vm_area_struct *vma; struct file *file; u64 offset; @@ -254,6 +262,17 @@ static void stack_map_get_build_id_offset_sleepable(st= ruct bpf_stack_build_id *i for (u32 i =3D 0; i < trace_nr; i++) { ip =3D READ_ONCE(id_offs[i].ip); =20 + /* + * Range cache fast path: if ip falls within the previously + * resolved VMA range, reuse the cache build_id without + * re-acquiring the VMA lock. + */ + if (cache.build_id && ip >=3D cache.vm_start && ip < cache.vm_end) { + offset =3D stack_map_build_id_offset(cache.vm_pgoff, cache.vm_start, ip= ); + stack_map_build_id_set_valid(&id_offs[i], offset, cache.build_id); + continue; + } + vma =3D stack_map_lock_vma(&lock, ip); if (!vma) { stack_map_build_id_set_ip(&id_offs[i]); @@ -265,17 +284,47 @@ static void stack_map_get_build_id_offset_sleepable(s= truct bpf_stack_build_id *i continue; } =20 - file =3D get_file(vma->vm_file); - offset =3D stack_map_build_id_offset(vma->vm_pgoff, vma->vm_start, ip); + file =3D vma->vm_file; + vm_pgoff =3D vma->vm_pgoff; + vm_start =3D vma->vm_start; + vm_end =3D vma->vm_end; + offset =3D stack_map_build_id_offset(vm_pgoff, vm_start, ip); + + /* + * Same backing file as previous (e.g. different VMAs + * of the same ELF binary). Reuse the cache build_id. + */ + if (file =3D=3D cache.file) { + stack_map_unlock_vma(&lock); + stack_map_build_id_set_valid(&id_offs[i], offset, cache.build_id); + cache.vm_start =3D vm_start; + cache.vm_end =3D vm_end; + cache.vm_pgoff =3D vm_pgoff; + continue; + } + + file =3D get_file(file); stack_map_unlock_vma(&lock); =20 /* build_id_parse_file() may block on filesystem reads */ - if (build_id_parse_file(file, id_offs[i].build_id, NULL)) + if (build_id_parse_file(file, id_offs[i].build_id, NULL)) { stack_map_build_id_set_ip(&id_offs[i]); - else - stack_map_build_id_set_valid(&id_offs[i], offset, id_offs[i].build_id); - fput(file); + fput(file); + continue; + } + + stack_map_build_id_set_valid(&id_offs[i], offset, id_offs[i].build_id); + if (cache.file) + fput(cache.file); + cache.file =3D file; + cache.build_id =3D id_offs[i].build_id; + cache.vm_start =3D vm_start; + cache.vm_end =3D vm_end; + cache.vm_pgoff =3D vm_pgoff; } + + if (cache.file) + fput(cache.file); } =20 /* --=20 2.54.0