Skip to content

Commit 6887eff

Browse files
Donglin PengKernel Patches Daemon
authored andcommitted
libbpf: Implement lazy sorting validation for binary search optimization
This patch adds lazy validation of BTF type ordering to determine if types are sorted by name. The check is performed on first access and cached, enabling efficient binary search for sorted BTF while maintaining linear search fallback for unsorted cases. Cc: Eduard Zingerman <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Andrii Nakryiko <[email protected]> Cc: Alan Maguire <[email protected]> Cc: Song Liu <[email protected]> Cc: Xiaoqin Zhang <[email protected]> Signed-off-by: Donglin Peng <[email protected]> Signed-off-by: Donglin Peng <[email protected]>
1 parent 2f1683c commit 6887eff

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

tools/lib/bpf/btf.c

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,73 @@ int btf__resolve_type(const struct btf *btf, __u32 type_id)
911911
return type_id;
912912
}
913913

914+
/* Anonymous types (with empty names) are considered greater than named types
915+
* and are sorted after them. Two anonymous types are considered equal. Named
916+
* types are compared lexicographically.
917+
*/
918+
static int btf_compare_type_names(const void *a, const void *b, void *priv)
919+
{
920+
struct btf *btf = (struct btf *)priv;
921+
struct btf_type *ta = btf_type_by_id(btf, *(__u32 *)a);
922+
struct btf_type *tb = btf_type_by_id(btf, *(__u32 *)b);
923+
const char *na, *nb;
924+
bool anon_a, anon_b;
925+
926+
na = btf__str_by_offset(btf, ta->name_off);
927+
nb = btf__str_by_offset(btf, tb->name_off);
928+
anon_a = str_is_empty(na);
929+
anon_b = str_is_empty(nb);
930+
931+
if (anon_a && !anon_b)
932+
return 1;
933+
if (!anon_a && anon_b)
934+
return -1;
935+
if (anon_a && anon_b)
936+
return 0;
937+
938+
return strcmp(na, nb);
939+
}
940+
941+
/* Verifies that BTF types are sorted in ascending order according to their
942+
* names, with named types appearing before anonymous types. If the ordering
943+
* is correct, counts the number of named types and updates the BTF object's
944+
* nr_sorted_types field.
945+
*
946+
* Return: true if types are properly sorted, false otherwise
947+
*/
948+
static bool btf_check_sorted(struct btf *btf)
949+
{
950+
const struct btf_type *t;
951+
int i, k = 0, n, nr_sorted_types;
952+
953+
if (likely(btf->nr_sorted_types != BTF_NEED_SORT_CHECK))
954+
goto out;
955+
btf->nr_sorted_types = 0;
956+
957+
if (btf->nr_types < 2)
958+
goto out;
959+
960+
nr_sorted_types = 0;
961+
n = btf__type_cnt(btf) - 1;
962+
for (i = btf->start_id; i < n; i++) {
963+
k = i + 1;
964+
if (btf_compare_type_names(&i, &k, btf) > 0)
965+
goto out;
966+
t = btf_type_by_id(btf, i);
967+
if (!str_is_empty(btf__str_by_offset(btf, t->name_off)))
968+
nr_sorted_types++;
969+
}
970+
971+
t = btf_type_by_id(btf, k);
972+
if (!str_is_empty(btf__str_by_offset(btf, t->name_off)))
973+
nr_sorted_types++;
974+
if (nr_sorted_types)
975+
btf->nr_sorted_types = nr_sorted_types;
976+
977+
out:
978+
return btf->nr_sorted_types > 0;
979+
}
980+
914981
/* Performs binary search within specified type ID range to find the leftmost
915982
* BTF type matching the given name. The search assumes types are sorted by
916983
* name in lexicographical order within the specified range.
@@ -970,7 +1037,7 @@ static __s32 btf_find_type_by_name_kind(const struct btf *btf, int start_id,
9701037
start_id = btf->start_id;
9711038
}
9721039

973-
if (btf->nr_sorted_types != BTF_NEED_SORT_CHECK) {
1040+
if (btf_check_sorted((struct btf *)btf)) {
9741041
/* binary search */
9751042
__s32 end_id;
9761043
bool skip_first;

0 commit comments

Comments
 (0)