On 4/11/24 15:13, Eduard Zingerman wrote:
On Tue, 2024-04-09 at 17:41 -0700, Kui-Feng Lee wrote:
[...]
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index f397ccdc6d4b..ee53dcd14bd4 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -390,6 +390,9 @@ static inline u32 btf_field_type_align(enum btf_field_type type)
static inline void bpf_obj_init_field(const struct btf_field *field, void *addr)
{
+ u32 elem_size;
+ int i;
+
memset(addr, 0, field->size);
switch (field->type) {
@@ -400,6 +403,10 @@ static inline void bpf_obj_init_field(const struct btf_field *field, void *addr)
RB_CLEAR_NODE((struct rb_node *)addr);
break;
case BPF_LIST_HEAD:
+ elem_size = field->size / field->nelems;
+ for (i = 0; i < field->nelems; i++, addr += elem_size)
+ INIT_LIST_HEAD((struct list_head *)addr);
+ break;
In btf_find_datasec_var() nelem > 1 is allowed for the following types:
- BPF_LIST_{NODE,HEAD}
- BPF_KPTR_{REF,UNREF,PERCPU}:
- BPF_RB_{NODE,ROOT}
Of these types bpf_obj_init_field() handles in a special way
BPF_RB_NODE, BPF_LIST_HEAD and BPF_LIST_NODE.
However, only BPF_LIST_HEAD handling is adjusted in this patch.
Is there a reason to omit BPF_RB_NODE and BPF_LIST_NODE?
Declaring arrays of list nodes or rbtree nodes seems to be not useful
since they don't contain any useful information. Let me explain below.
We usually declare node fields in other struct types. I guess declaring
arrays of struct types containing node fields is what we actually want.
For example,
struct foo {
struct bpf_list_node node;
...
};
struct foo all_nodes[64];
However, the verifier doesn't look into fields of a outer struct type
except array fields handling by this patchset. In this case, a data
section, it doesn't look into foo even we declare a global variable of
struct foo. For example,
struct foo gFoo;
gFoo would not work since the verifier doesn't follow gFoo and look into
struct foo.
So, I decided not to support rbtree nodes and list nodes.
However, there are a discussion about looking into fields of struct
types in an outer struct type. So, we will have another patchset to
implement it. Once we have it, we can support the case of gFoo and
all_nodes described earlier.
case BPF_LIST_NODE:
INIT_LIST_HEAD((struct list_head *)addr);
break;
[...]