Skip to content

Commit 23ff945

Browse files
Donglin PengKernel Patches Daemon
authored andcommitted
btf: Add lazy sorting validation for binary search
Implement lazy validation of BTF type ordering to enable 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 4bd5e23 commit 23ff945

File tree

1 file changed

+65
-1
lines changed

1 file changed

+65
-1
lines changed

kernel/bpf/btf.c

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,70 @@ u32 btf_nr_types(const struct btf *btf)
552552
return total;
553553
}
554554

555+
/* Anonymous types (with empty names) are considered greater than named types
556+
* and are sorted after them. Two anonymous types are considered equal. Named
557+
* types are compared lexicographically.
558+
*/
559+
static int btf_compare_type_names(const void *a, const void *b, void *priv)
560+
{
561+
struct btf *btf = (struct btf *)priv;
562+
const struct btf_type *ta = btf_type_by_id(btf, *(__u32 *)a);
563+
const struct btf_type *tb = btf_type_by_id(btf, *(__u32 *)b);
564+
const char *na, *nb;
565+
566+
if (!ta->name_off && tb->name_off)
567+
return 1;
568+
if (ta->name_off && !tb->name_off)
569+
return -1;
570+
if (!ta->name_off && !tb->name_off)
571+
return 0;
572+
573+
na = btf_name_by_offset(btf, ta->name_off);
574+
nb = btf_name_by_offset(btf, tb->name_off);
575+
return strcmp(na, nb);
576+
}
577+
578+
/* Verifies that BTF types are sorted in ascending order according to their
579+
* names, with named types appearing before anonymous types. If the ordering
580+
* is correct, counts the number of named types and updates the BTF object's
581+
* nr_sorted_types field.
582+
*
583+
* Return: true if types are properly sorted, false otherwise
584+
*/
585+
static bool btf_check_sorted(struct btf *btf)
586+
{
587+
const struct btf_type *t;
588+
int i, n, k = 0, nr_sorted_types;
589+
590+
if (likely(btf->nr_sorted_types != BTF_NEED_SORT_CHECK))
591+
goto out;
592+
btf->nr_sorted_types = 0;
593+
594+
if (btf->nr_types < 2)
595+
goto out;
596+
597+
nr_sorted_types = 0;
598+
n = btf_nr_types(btf) - 1;
599+
for (i = btf_start_id(btf); i < n; i++) {
600+
k = i + 1;
601+
if (btf_compare_type_names(&i, &k, btf) > 0)
602+
goto out;
603+
604+
t = btf_type_by_id(btf, i);
605+
if (t->name_off)
606+
nr_sorted_types++;
607+
}
608+
609+
t = btf_type_by_id(btf, k);
610+
if (t->name_off)
611+
nr_sorted_types++;
612+
if (nr_sorted_types)
613+
btf->nr_sorted_types = nr_sorted_types;
614+
615+
out:
616+
return btf->nr_sorted_types > 0;
617+
}
618+
555619
/* Performs binary search within specified type ID range to find the leftmost
556620
* BTF type matching the given name. The search assumes types are sorted by
557621
* name in lexicographical order within the specified range.
@@ -610,7 +674,7 @@ s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind)
610674
goto out;
611675
}
612676

613-
if (btf->nr_sorted_types != BTF_NEED_SORT_CHECK) {
677+
if (btf_check_sorted((struct btf *)btf)) {
614678
/* binary search */
615679
bool skip_first;
616680
s32 start_id, end_id;;

0 commit comments

Comments
 (0)