diff mbox series

[RFC,2/2] libbpf: Add btf__field_exists

Message ID 20220404083816.1560501-3-nborisov@suse.com (mailing list archive)
State RFC
Delegated to: BPF
Headers show
Series Add btf__field_exists | expand

Checks

Context Check Description
bpf/vmtest-bpf-PR fail merge-conflict
netdev/tree_selection success Not a local patch

Commit Message

Nikolay Borisov April 4, 2022, 8:38 a.m. UTC
There isn't currently a convenience function to check if a particular
kernel version is running similar to bpf_core_field_exists. There can be
cases where based on the actual kernel being run different kprobes has
to be used when tracing the kernel. One example is the change introduced
in 4c5b47997521 ("vfs: add fileattr ops"). Before this commit if one
wants to trace fileattr changes this has to be done by a distinct kprobe
on every filesystem as there was no common code where fileattr changes
when through. Post this commit this can be performed by a single kprobe
on the common vfs_fileattr_set function.

To accommodate such use cases simply add a libbpf api btf__field_exists
which can be used to check for the running kernel version and act
appropriately.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 tools/lib/bpf/btf.c      | 28 ++++++++++++++++++++++++++++
 tools/lib/bpf/btf.h      |  2 ++
 tools/lib/bpf/libbpf.map |  1 +
 3 files changed, 31 insertions(+)
diff mbox series

Patch

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 9aa19c89f758..890a2071bd00 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -697,6 +697,34 @@  int btf__resolve_type(const struct btf *btf, __u32 type_id)
 	return type_id;
 }
 
+bool btf__field_exists(const struct btf *btf, const char *struct_name,
+		       const char *field_name)
+{
+	const struct btf_type *t;
+	struct btf_member *m;
+	int i;
+	__s32 type_id = btf__find_by_name(btf, struct_name);
+
+	if (type_id < 0)
+		return false;
+
+	t = btf__type_by_id(btf, type_id);
+	if (!t)
+		return false;
+
+	if (!btf_is_composite(t))
+		return false;
+
+	for_each_member(i, t, m) {
+		const char *n = btf__name_by_offset(btf, m->name_off);
+
+		if (strcmp(n, field_name) == 0)
+			return true;
+	}
+
+	return false;
+}
+
 __s32 btf__find_by_name(const struct btf *btf, const char *type_name)
 {
 	__u32 i, nr_types = btf__type_cnt(btf);
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index 74039f8afc63..1eb8d840b46b 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -144,6 +144,8 @@  LIBBPF_API enum btf_endianness btf__endianness(const struct btf *btf);
 LIBBPF_API int btf__set_endianness(struct btf *btf, enum btf_endianness endian);
 LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
 LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
+LIBBPF_API bool btf__field_exists(const struct btf *btf, const char *struct_name,
+				 const char *field_name);
 LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id);
 LIBBPF_API int btf__fd(const struct btf *btf);
 LIBBPF_API void btf__set_fd(struct btf *btf, int fd);
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 529783967793..9a0d50604cca 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -427,6 +427,7 @@  LIBBPF_0.7.0 {
 		bpf_program__log_level;
 		bpf_program__set_log_buf;
 		bpf_program__set_log_level;
+		btf__field_exists;
 		libbpf_probe_bpf_helper;
 		libbpf_probe_bpf_map_type;
 		libbpf_probe_bpf_prog_type;