From: Alan Maguire <alan.maguire@oracle.com>
To: Potnuri Bharat Teja <bharat@chelsio.com>
Cc: Bart Van Assche <bvanassche@acm.org>,
"bpf@vger.kernel.org" <bpf@vger.kernel.org>,
Martin KaFai Lau <martin.lau@linux.dev>,
Nilay Shroff <nilay@linux.ibm.com>
Subject: Re: Kernel build fails if both CONFIG_DEBUG_INFO_BTF and CONFIG_CHELSIO_T4=y (was CONFIG_KCSAN)
Date: Thu, 20 Nov 2025 22:18:27 +0000 [thread overview]
Message-ID: <bc54daab-3b01-4a25-8032-52a123fa823f@oracle.com> (raw)
In-Reply-To: <aR9YasvOhnSI564i@chelsio.com>
On 20/11/2025 18:05, Potnuri Bharat Teja wrote:
> On Thursday, November 11/20/25, 2025 at 23:23:39 +0530, Alan Maguire wrote:
>> On 20/11/2025 14:20, Alan Maguire wrote:
>>> On 18/11/2025 16:47, Bart Van Assche wrote:
>>>> On 11/18/25 4:07 AM, Alan Maguire wrote:
>>>>> hi Bart, thanks for the report! Not a know issue to me at least; I tried
>>>>> to reproduce it with pahole v1.31 + gcc 12 and no luck. Would you mind
>>>>> sharing a few additional details:
>>>>>
>>>>> - compiler version
>>>>> - pahole version
>>>>> - full .config
>>>>
>>>> Hi Alan,
>>>>
>>>> My answers to your questions are as follows:
>>>> * Compiler version: gcc version 14.2.0 (Debian 14.2.0-19+build5)
>>>> * pahole version: v1.30
>>>> * Kernel config: has been attached to this email.
>>>>
>>>
>>> thanks Bart! I've reproduced this now with gcc-14.2.1 + pahole 1.30 and
>>> it is also observed with latest pahole 1.31. Investigating now, but if
>>> you want to work around it in the short term, disabling CONFIG_WERROR
>>> should allow resolve_btfids to proceed even where duplicate types are
>>> present. Hopefully we will have a root cause/fix shortly though. Thanks
>>> again for the report!
>>>
>>
>> [adding cxgb4 maintainer, for reasons that will become clearer below.
>> Context here is that Bart is seeing kernel builds fail at the
>> resolve_btfids stage; resolve_btfids is finding the BPF Type Format
>> representation of core kernel data structures has duplicate entries for
>> key kernel data structures like task_struct]
>
>>
>> After adding some debug-only messaging to btf__dedup() in libbpf (which
>> I will send as a patch as it makes debugging these situations much
>> easier) I saw:
>>
>> libbpf: struct 'task_struct' (size 2560 vlen 194) appears equivalent but
>> differs for 23-indexed cand/canon member 'sched_class'/'sched_class': 0
>>
>> Examining sched_class we see:
>>
>> [107] STRUCT 'task_struct' size=2560 vlen=194
>> ...
>> 'sched_class' type_id=480 bits_offset=5440
>> ...
>>
>> [479] CONST '(anon)' type_id=8624
>> [480] PTR '(anon)' type_id=479
>>
>> [8624] STRUCT 'sched_class' size=216 vlen=27
>> 'enqueue_task' type_id=8844 bits_offset=0
>> 'dequeue_task' type_id=8846 bits_offset=64
>> 'yield_task' type_id=8823 bits_offset=128
>> 'yield_to_task' type_id=8848 bits_offset=192
>> 'wakeup_preempt' type_id=8844 bits_offset=256
>> 'balance' type_id=8851 bits_offset=320
>> 'pick_task' type_id=8853 bits_offset=384
>> 'pick_next_task' type_id=8855 bits_offset=448
>> 'put_prev_task' type_id=8857 bits_offset=512
>> 'set_next_task' type_id=8859 bits_offset=576
>> 'select_task_rq' type_id=8861 bits_offset=640
>> 'migrate_task_rq' type_id=8863 bits_offset=704
>> 'task_woken' type_id=8865 bits_offset=768
>> 'set_cpus_allowed' type_id=8868 bits_offset=832
>> 'rq_online' type_id=8823 bits_offset=896
>> 'rq_offline' type_id=8823 bits_offset=960
>> 'find_lock_rq' type_id=8870 bits_offset=1024
>> 'task_tick' type_id=8844 bits_offset=1088
>> 'task_fork' type_id=236 bits_offset=1152
>> 'task_dead' type_id=236 bits_offset=1216
>> 'switching_to' type_id=8865 bits_offset=1280
>> 'switched_from' type_id=8865 bits_offset=1344
>> 'switched_to' type_id=8865 bits_offset=1408
>> 'reweight_task' type_id=8873 bits_offset=1472
>> 'prio_changed' type_id=8844 bits_offset=1536
>> 'get_rr_interval' type_id=8875 bits_offset=1600
>> 'update_curr' type_id=8823 bits_offset=1664
>>
>>
>> Now looking at the first duplicate:
>>
>> [36354] STRUCT 'task_struct' size=2560 vlen=194
>> ...
>> 'sched_class' type_id=36389 bits_offset=5440
>> ...
>>
>>
>> [36387] STRUCT 'sched_class' size=64 vlen=6
>> 'state' type_id=28 bits_offset=0
>> 'idx' type_id=28 bits_offset=8
>> 'info' type_id=38195 bits_offset=32
>> 'bind_type' type_id=38228 bits_offset=256
>> 'entry_list' type_id=90 bits_offset=320
>> 'refcnt' type_id=84 bits_offset=448
>> [36388] CONST '(anon)' type_id=36387
>> [36389] PTR '(anon)' type_id=36388
>>
>>
>> sched_class looks totally different! The reason is cxgb4 declares its
>> own sched_class while also #include'ing task_struct-related headers.
>> Bart's config exposed this because he had CONFIG_CHELSIO_T4=y (I had 'm'
>> in my config).
>>
>> If we look at drivers/net/ethernet/chelsio/cxgb4/sched.h we indeed see:
>>
>> struct sched_class {
>> u8 state;
>> u8 idx;
>> struct ch_sched_params info;
>> enum sched_bind_type bind_type;
>> struct list_head entry_list;
>> atomic_t refcnt;
>> };
>>
>> ..and cxgb4_main.c has #include <linux/sched.h> and #include <sched.h>
>> with the clashing sched_class. Using pahole we can establish that the
>> BTF encoding is simply reflecting the DWARF representation ("pahole
>> cxgb4.ko" shows this), so BTF is effectively correctly reflecting the
>> underlying DWARF representation. This will make life confusing for
>> debuggers too.
>>
>> So although it is a bit of a pain, I would suggest the simplest approach
>> is to perhaps look at renaming sched_class to be a bit more
>> domain-specific - ch_sched_class perhaps? That way it will not clash
>> with task_struct's sched_class.
>>
>> I can send a patch but it would be great to get cxgb4 maintainers' take
>> here first.
> Thanks for adding me and the detailed debug, Alan and Bart.
> I will try this and let you know.
FYI I verified that changing sched_class to ch_sched_class like the
following resolves the build issue:
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 392723ef14e5..ac0c7fe5743b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3485,7 +3485,7 @@ static int cxgb_set_tx_maxrate(struct net_device
*dev, int index, u32 rate)
struct adapter *adap = pi->adapter;
struct ch_sched_queue qe = { 0 };
struct ch_sched_params p = { 0 };
- struct sched_class *e;
+ struct ch_sched_class *e;
u32 req_rate;
int err = 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c
b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c
index 1672d3afe5be..f8dcf0b4abcd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c
@@ -56,7 +56,7 @@ static int cxgb4_matchall_egress_validate(struct
net_device *dev,
struct port_info *pi = netdev2pinfo(dev);
struct flow_action_entry *entry;
struct ch_sched_queue qe;
- struct sched_class *e;
+ struct ch_sched_class *e;
u64 max_link_rate;
u32 i, speed;
int ret;
@@ -180,7 +180,7 @@ static int cxgb4_matchall_alloc_tc(struct net_device
*dev,
struct port_info *pi = netdev2pinfo(dev);
struct adapter *adap = netdev2adap(dev);
struct flow_action_entry *entry;
- struct sched_class *e;
+ struct ch_sched_class *e;
int ret;
u32 i;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c
b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c
index 338b04f339b3..a2dcd2e24263 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c
@@ -330,7 +330,7 @@ static int cxgb4_mqprio_alloc_tc(struct net_device *dev,
struct cxgb4_tc_port_mqprio *tc_port_mqprio;
struct port_info *pi = netdev2pinfo(dev);
struct adapter *adap = netdev2adap(dev);
- struct sched_class *e;
+ struct ch_sched_class *e;
int ret;
u8 i;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sched.c
b/drivers/net/ethernet/chelsio/cxgb4/sched.c
index a1b14468d1ff..e15554b347c0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sched.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sched.c
@@ -44,7 +44,7 @@ static int t4_sched_class_fw_cmd(struct port_info *pi,
{
struct adapter *adap = pi->adapter;
struct sched_table *s = pi->sched_tbl;
- struct sched_class *e;
+ struct ch_sched_class *e;
int err = 0;
e = &s->tab[p->u.params.class];
@@ -122,7 +122,7 @@ static void *t4_sched_entry_lookup(struct port_info *pi,
const u32 val)
{
struct sched_table *s = pi->sched_tbl;
- struct sched_class *e, *end;
+ struct ch_sched_class *e, *end;
void *found = NULL;
/* Look for an entry with matching @val */
@@ -166,7 +166,7 @@ static void *t4_sched_entry_lookup(struct port_info *pi,
return found;
}
-struct sched_class *cxgb4_sched_queue_lookup(struct net_device *dev,
+struct ch_sched_class *cxgb4_sched_queue_lookup(struct net_device *dev,
struct ch_sched_queue *p)
{
struct port_info *pi = netdev2pinfo(dev);
@@ -187,7 +187,7 @@ static int t4_sched_queue_unbind(struct port_info
*pi, struct ch_sched_queue *p)
struct sched_queue_entry *qe = NULL;
struct adapter *adap = pi->adapter;
struct sge_eth_txq *txq;
- struct sched_class *e;
+ struct ch_sched_class *e;
int err = 0;
if (p->queue < 0 || p->queue >= pi->nqsets)
@@ -218,7 +218,7 @@ static int t4_sched_queue_bind(struct port_info *pi,
struct ch_sched_queue *p)
struct sched_queue_entry *qe = NULL;
struct adapter *adap = pi->adapter;
struct sge_eth_txq *txq;
- struct sched_class *e;
+ struct ch_sched_class *e;
unsigned int qid;
int err = 0;
@@ -260,7 +260,7 @@ static int t4_sched_flowc_unbind(struct port_info
*pi, struct ch_sched_flowc *p)
{
struct sched_flowc_entry *fe = NULL;
struct adapter *adap = pi->adapter;
- struct sched_class *e;
+ struct ch_sched_class *e;
int err = 0;
if (p->tid < 0 || p->tid >= adap->tids.neotids)
@@ -288,7 +288,7 @@ static int t4_sched_flowc_bind(struct port_info *pi,
struct ch_sched_flowc *p)
struct sched_table *s = pi->sched_tbl;
struct sched_flowc_entry *fe = NULL;
struct adapter *adap = pi->adapter;
- struct sched_class *e;
+ struct ch_sched_class *e;
int err = 0;
if (p->tid < 0 || p->tid >= adap->tids.neotids)
@@ -322,7 +322,7 @@ static int t4_sched_flowc_bind(struct port_info *pi,
struct ch_sched_flowc *p)
}
static void t4_sched_class_unbind_all(struct port_info *pi,
- struct sched_class *e,
+ struct ch_sched_class *e,
enum sched_bind_type type)
{
if (!e)
@@ -476,12 +476,12 @@ int cxgb4_sched_class_unbind(struct net_device
*dev, void *arg,
}
/* If @p is NULL, fetch any available unused class */
-static struct sched_class *t4_sched_class_lookup(struct port_info *pi,
+static struct ch_sched_class *t4_sched_class_lookup(struct port_info *pi,
const struct
ch_sched_params *p)
{
struct sched_table *s = pi->sched_tbl;
- struct sched_class *found = NULL;
- struct sched_class *e, *end;
+ struct ch_sched_class *found = NULL;
+ struct ch_sched_class *e, *end;
if (!p) {
/* Get any available unused class */
@@ -522,10 +522,10 @@ static struct sched_class
*t4_sched_class_lookup(struct port_info *pi,
return found;
}
-static struct sched_class *t4_sched_class_alloc(struct port_info *pi,
+static struct ch_sched_class *t4_sched_class_alloc(struct port_info *pi,
struct ch_sched_params *p)
{
- struct sched_class *e = NULL;
+ struct ch_sched_class *e = NULL;
u8 class_id;
int err;
@@ -579,8 +579,8 @@ static struct sched_class
*t4_sched_class_alloc(struct port_info *pi,
* scheduling class with matching @p is found, then the matching class is
* returned.
*/
-struct sched_class *cxgb4_sched_class_alloc(struct net_device *dev,
- struct ch_sched_params *p)
+struct ch_sched_class *cxgb4_sched_class_alloc(struct net_device *dev,
+ struct ch_sched_params *p)
{
struct port_info *pi = netdev2pinfo(dev);
u8 class_id;
@@ -607,7 +607,7 @@ void cxgb4_sched_class_free(struct net_device *dev,
u8 classid)
struct port_info *pi = netdev2pinfo(dev);
struct sched_table *s = pi->sched_tbl;
struct ch_sched_params p;
- struct sched_class *e;
+ struct ch_sched_class *e;
u32 speed;
int ret;
@@ -640,7 +640,7 @@ void cxgb4_sched_class_free(struct net_device *dev,
u8 classid)
}
}
-static void t4_sched_class_free(struct net_device *dev, struct
sched_class *e)
+static void t4_sched_class_free(struct net_device *dev, struct
ch_sched_class *e)
{
struct port_info *pi = netdev2pinfo(dev);
@@ -660,7 +660,7 @@ struct sched_table *t4_init_sched(unsigned int
sched_size)
s->sched_size = sched_size;
for (i = 0; i < s->sched_size; i++) {
- memset(&s->tab[i], 0, sizeof(struct sched_class));
+ memset(&s->tab[i], 0, sizeof(struct ch_sched_class));
s->tab[i].idx = i;
s->tab[i].state = SCHED_STATE_UNUSED;
INIT_LIST_HEAD(&s->tab[i].entry_list);
@@ -682,7 +682,7 @@ void t4_cleanup_sched(struct adapter *adap)
continue;
for (i = 0; i < s->sched_size; i++) {
- struct sched_class *e;
+ struct ch_sched_class *e;
e = &s->tab[i];
if (e->state == SCHED_STATE_ACTIVE)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sched.h
b/drivers/net/ethernet/chelsio/cxgb4/sched.h
index 6b3c778815f0..94d45de793ef 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sched.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/sched.h
@@ -71,7 +71,7 @@ struct sched_flowc_entry {
struct ch_sched_flowc param;
};
-struct sched_class {
+struct ch_sched_class {
u8 state;
u8 idx;
struct ch_sched_params info;
@@ -82,7 +82,7 @@ struct sched_class {
struct sched_table { /* per port scheduling table */
u8 sched_size;
- struct sched_class tab[] __counted_by(sched_size);
+ struct ch_sched_class tab[] __counted_by(sched_size);
};
static inline bool can_sched(struct net_device *dev)
@@ -103,14 +103,14 @@ static inline bool valid_class_id(struct
net_device *dev, u8 class_id)
return true;
}
-struct sched_class *cxgb4_sched_queue_lookup(struct net_device *dev,
+struct ch_sched_class *cxgb4_sched_queue_lookup(struct net_device *dev,
struct ch_sched_queue *p);
int cxgb4_sched_class_bind(struct net_device *dev, void *arg,
enum sched_bind_type type);
int cxgb4_sched_class_unbind(struct net_device *dev, void *arg,
enum sched_bind_type type);
-struct sched_class *cxgb4_sched_class_alloc(struct net_device *dev,
+struct ch_sched_class *cxgb4_sched_class_alloc(struct net_device *dev,
struct ch_sched_params *p);
void cxgb4_sched_class_free(struct net_device *dev, u8 classid);
next prev parent reply other threads:[~2025-11-20 22:19 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-17 20:40 Kernel build fails if both CONFIG_DEBUG_INFO_BTF and CONFIG_KCSAN are enabled Bart Van Assche
2025-11-18 12:07 ` Alan Maguire
2025-11-18 16:47 ` Bart Van Assche
2025-11-20 14:20 ` Alan Maguire
2025-11-20 17:53 ` Kernel build fails if both CONFIG_DEBUG_INFO_BTF and CONFIG_CHELSIO_T4=y (was CONFIG_KCSAN) Alan Maguire
2025-11-20 18:05 ` Potnuri Bharat Teja
2025-11-20 22:18 ` Alan Maguire [this message]
2025-11-21 17:22 ` Bart Van Assche
2025-11-21 18:15 ` Alan Maguire
2025-11-24 11:48 ` Potnuri Bharat Teja
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bc54daab-3b01-4a25-8032-52a123fa823f@oracle.com \
--to=alan.maguire@oracle.com \
--cc=bharat@chelsio.com \
--cc=bpf@vger.kernel.org \
--cc=bvanassche@acm.org \
--cc=martin.lau@linux.dev \
--cc=nilay@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox