From: Alan Maguire <alan.maguire@oracle.com>
To: ast@kernel.org, daniel@iogearbox.net, andriin@fb.com, yhs@fb.com
Cc: linux@rasmusvillemoes.dk, andriy.shevchenko@linux.intel.com,
pmladek@suse.com, kafai@fb.com, songliubraving@fb.com,
john.fastabend@gmail.com, kpsingh@chromium.org, shuah@kernel.org,
rdna@fb.com, scott.branden@broadcom.com, quentin@isovalent.com,
cneirabustos@gmail.com, jakub@cloudflare.com, mingo@redhat.com,
rostedt@goodmis.org, bpf@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
acme@kernel.org, Alan Maguire <alan.maguire@oracle.com>
Subject: [PATCH v5 bpf-next 5/6] bpf: add bpf_seq_btf_write helper
Date: Fri, 18 Sep 2020 14:34:34 +0100 [thread overview]
Message-ID: <1600436075-2961-6-git-send-email-alan.maguire@oracle.com> (raw)
In-Reply-To: <1600436075-2961-1-git-send-email-alan.maguire@oracle.com>
A helper is added to allow seq file writing of kernel data
structures using vmlinux BTF. Its signature is
long bpf_seq_btf_write(struct seq_file *m, struct btf_ptr *ptr,
u32 btf_ptr_size, u64 flags);
Flags and struct btf_ptr definitions/use are identical to the
bpf_btf_snprintf helper, and the helper returns 0 on success
or a negative error value.
Suggested-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
include/linux/btf.h | 3 ++
include/uapi/linux/bpf.h | 10 ++++++
kernel/bpf/btf.c | 17 +++++++---
kernel/trace/bpf_trace.c | 75 +++++++++++++++++++++++++++++++++---------
tools/include/uapi/linux/bpf.h | 10 ++++++
5 files changed, 96 insertions(+), 19 deletions(-)
diff --git a/include/linux/btf.h b/include/linux/btf.h
index 3e5cdc2..eed23a4 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -69,6 +69,9 @@ const struct btf_type *btf_type_id_size(const struct btf *btf,
void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj,
struct seq_file *m);
+int btf_type_seq_show_flags(const struct btf *btf, u32 type_id, void *obj,
+ struct seq_file *m, u64 flags);
+
/*
* Copy len bytes of string representation of obj of BTF type_id into buf.
*
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 9b89b67..c0815f1 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3614,6 +3614,15 @@ struct bpf_stack_build_id {
* The number of bytes that were written (or would have been
* written if output had to be truncated due to string size),
* or a negative error in cases of failure.
+ *
+ * long bpf_seq_btf_write(struct seq_file *m, struct btf_ptr *ptr, u32 ptr_size, u64 flags)
+ * Description
+ * Use BTF to write to seq_write a string representation of
+ * *ptr*->ptr, using *ptr*->type name or *ptr*->type_id as per
+ * bpf_btf_snprintf() above. *flags* are identical to those
+ * used for bpf_btf_snprintf.
+ * Return
+ * 0 on success or a negative error in case of failure.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -3766,6 +3775,7 @@ struct bpf_stack_build_id {
FN(d_path), \
FN(copy_from_user), \
FN(btf_snprintf), \
+ FN(seq_btf_write), \
/* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 70f5b88..0902464 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5328,17 +5328,26 @@ static void btf_seq_show(struct btf_show *show, const char *fmt, ...)
va_end(args);
}
-void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj,
- struct seq_file *m)
+int btf_type_seq_show_flags(const struct btf *btf, u32 type_id, void *obj,
+ struct seq_file *m, u64 flags)
{
struct btf_show sseq;
sseq.target = m;
sseq.showfn = btf_seq_show;
- sseq.flags = BTF_SHOW_NONAME | BTF_SHOW_COMPACT | BTF_SHOW_ZERO |
- BTF_SHOW_UNSAFE;
+ sseq.flags = flags;
btf_type_show(btf, type_id, obj, &sseq);
+
+ return sseq.state.status;
+}
+
+void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj,
+ struct seq_file *m)
+{
+ (void) btf_type_seq_show_flags(btf, type_id, obj, m,
+ BTF_SHOW_NONAME | BTF_SHOW_COMPACT |
+ BTF_SHOW_ZERO | BTF_SHOW_UNSAFE);
}
struct btf_show_snprintf {
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index f171e03..eee36a8 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -71,6 +71,10 @@ static struct bpf_raw_event_map *bpf_get_raw_tracepoint_module(const char *name)
u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
u64 bpf_get_stack(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
+static int bpf_btf_printf_prepare(struct btf_ptr *ptr, u32 btf_ptr_size,
+ u64 flags, const struct btf **btf,
+ s32 *btf_id);
+
/**
* trace_call_bpf - invoke BPF program
* @call: tracepoint event
@@ -780,6 +784,30 @@ struct bpf_seq_printf_buf {
.btf_id = bpf_seq_write_btf_ids,
};
+BPF_CALL_4(bpf_seq_btf_write, struct seq_file *, m, struct btf_ptr *, ptr,
+ u32, btf_ptr_size, u64, flags)
+{
+ const struct btf *btf;
+ s32 btf_id;
+ int ret;
+
+ ret = bpf_btf_printf_prepare(ptr, btf_ptr_size, flags, &btf, &btf_id);
+ if (ret)
+ return ret;
+
+ return btf_type_seq_show_flags(btf, btf_id, ptr->ptr, m, flags);
+}
+
+static const struct bpf_func_proto bpf_seq_btf_write_proto = {
+ .func = bpf_seq_btf_write,
+ .gpl_only = true,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_BTF_ID,
+ .arg2_type = ARG_PTR_TO_MEM,
+ .arg3_type = ARG_CONST_SIZE_OR_ZERO,
+ .btf_id = bpf_seq_write_btf_ids,
+};
+
static __always_inline int
get_map_perf_counter(struct bpf_map *map, u64 flags,
u64 *value, u64 *enabled, u64 *running)
@@ -1151,15 +1179,14 @@ static bool bpf_d_path_allowed(const struct bpf_prog *prog)
#define BTF_F_ALL (BTF_F_COMPACT | BTF_F_NONAME | \
BTF_F_PTR_RAW | BTF_F_ZERO)
-BPF_CALL_5(bpf_btf_snprintf, char *, str, u32, str_size, struct btf_ptr *, ptr,
- u32, btf_ptr_size, u64, flags)
+static int bpf_btf_printf_prepare(struct btf_ptr *ptr, u32 btf_ptr_size,
+ u64 flags, const struct btf **btf,
+ s32 *btf_id)
{
u8 btf_kind = BTF_KIND_TYPEDEF;
char type_name[KSYM_NAME_LEN];
const struct btf_type *t;
- const struct btf *btf;
const char *btf_type;
- s32 btf_id;
int ret;
if (unlikely(flags & ~(BTF_F_ALL)))
@@ -1168,10 +1195,10 @@ static bool bpf_d_path_allowed(const struct bpf_prog *prog)
if (btf_ptr_size != sizeof(struct btf_ptr))
return -EINVAL;
- btf = bpf_get_btf_vmlinux();
+ *btf = bpf_get_btf_vmlinux();
- if (IS_ERR_OR_NULL(btf))
- return PTR_ERR(btf);
+ if (IS_ERR_OR_NULL(*btf))
+ return PTR_ERR(*btf);
if (ptr->type != NULL) {
ret = copy_from_kernel_nofault(type_name, ptr->type,
@@ -1201,20 +1228,34 @@ static bool bpf_d_path_allowed(const struct bpf_prog *prog)
*
* Fall back to BTF_KIND_INT if this fails.
*/
- btf_id = btf_find_by_name_kind(btf, btf_type, btf_kind);
- if (btf_id < 0)
- btf_id = btf_find_by_name_kind(btf, btf_type,
- BTF_KIND_INT);
+ *btf_id = btf_find_by_name_kind(*btf, btf_type, btf_kind);
+ if (*btf_id < 0)
+ *btf_id = btf_find_by_name_kind(*btf, btf_type,
+ BTF_KIND_INT);
} else if (ptr->type_id > 0)
- btf_id = ptr->type_id;
+ *btf_id = ptr->type_id;
else
return -EINVAL;
- if (btf_id > 0)
- t = btf_type_by_id(btf, btf_id);
- if (btf_id <= 0 || !t)
+ if (*btf_id > 0)
+ t = btf_type_by_id(*btf, *btf_id);
+ if (*btf_id <= 0 || !t)
return -ENOENT;
+ return 0;
+}
+
+BPF_CALL_5(bpf_btf_snprintf, char *, str, u32, str_size, struct btf_ptr *, ptr,
+ u32, btf_ptr_size, u64, flags)
+{
+ const struct btf *btf;
+ s32 btf_id;
+ int ret;
+
+ ret = bpf_btf_printf_prepare(ptr, btf_ptr_size, flags, &btf, &btf_id);
+ if (ret)
+ return ret;
+
return btf_type_snprintf_show(btf, btf_id, ptr->ptr, str, str_size,
flags);
}
@@ -1715,6 +1756,10 @@ static void put_bpf_raw_tp_regs(void)
return prog->expected_attach_type == BPF_TRACE_ITER ?
&bpf_seq_write_proto :
NULL;
+ case BPF_FUNC_seq_btf_write:
+ return prog->expected_attach_type == BPF_TRACE_ITER ?
+ &bpf_seq_btf_write_proto :
+ NULL;
case BPF_FUNC_d_path:
return &bpf_d_path_proto;
default:
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 9b89b67..c0815f1 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3614,6 +3614,15 @@ struct bpf_stack_build_id {
* The number of bytes that were written (or would have been
* written if output had to be truncated due to string size),
* or a negative error in cases of failure.
+ *
+ * long bpf_seq_btf_write(struct seq_file *m, struct btf_ptr *ptr, u32 ptr_size, u64 flags)
+ * Description
+ * Use BTF to write to seq_write a string representation of
+ * *ptr*->ptr, using *ptr*->type name or *ptr*->type_id as per
+ * bpf_btf_snprintf() above. *flags* are identical to those
+ * used for bpf_btf_snprintf.
+ * Return
+ * 0 on success or a negative error in case of failure.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -3766,6 +3775,7 @@ struct bpf_stack_build_id {
FN(d_path), \
FN(copy_from_user), \
FN(btf_snprintf), \
+ FN(seq_btf_write), \
/* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
--
1.8.3.1
next prev parent reply other threads:[~2020-09-18 13:37 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-18 13:34 [PATCH v5 bpf-next 0/6] bpf: add helpers to support BTF-based kernel data display Alan Maguire
2020-09-18 13:34 ` [PATCH v5 bpf-next 1/6] bpf: provide function to get vmlinux BTF information Alan Maguire
2020-09-18 13:34 ` [PATCH v5 bpf-next 2/6] bpf: move to generic BTF show support, apply it to seq files/strings Alan Maguire
2020-09-18 13:34 ` [PATCH v5 bpf-next 3/6] bpf: add bpf_btf_snprintf helper Alan Maguire
2020-09-18 13:34 ` [PATCH v5 bpf-next 4/6] selftests/bpf: add bpf_btf_snprintf helper tests Alan Maguire
2020-09-18 13:34 ` Alan Maguire [this message]
2020-09-22 1:10 ` [PATCH v5 bpf-next 5/6] bpf: add bpf_seq_btf_write helper Alexei Starovoitov
2020-09-18 13:34 ` [PATCH v5 bpf-next 6/6] selftests/bpf: add test for " Alan Maguire
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=1600436075-2961-6-git-send-email-alan.maguire@oracle.com \
--to=alan.maguire@oracle.com \
--cc=acme@kernel.org \
--cc=andriin@fb.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=cneirabustos@gmail.com \
--cc=daniel@iogearbox.net \
--cc=jakub@cloudflare.com \
--cc=john.fastabend@gmail.com \
--cc=kafai@fb.com \
--cc=kpsingh@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux@rasmusvillemoes.dk \
--cc=mingo@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=pmladek@suse.com \
--cc=quentin@isovalent.com \
--cc=rdna@fb.com \
--cc=rostedt@goodmis.org \
--cc=scott.branden@broadcom.com \
--cc=shuah@kernel.org \
--cc=songliubraving@fb.com \
--cc=yhs@fb.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;
as well as URLs for NNTP newsgroup(s).