BPF List
 help / color / mirror / Atom feed
From: Yonghong Song <yonghong.song@linux.dev>
To: Jiri Olsa <jolsa@kernel.org>, Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org, Martin KaFai Lau <kafai@fb.com>,
	Song Liu <songliubraving@fb.com>, Yonghong Song <yhs@fb.com>,
	John Fastabend <john.fastabend@gmail.com>,
	KP Singh <kpsingh@chromium.org>,
	Stanislav Fomichev <sdf@google.com>, Hao Luo <haoluo@google.com>
Subject: Re: [PATCHv2 bpf-next] selftests/bpf: Add read_trace_pipe_iter function
Date: Wed, 10 Apr 2024 17:09:18 -0700	[thread overview]
Message-ID: <64fa1c03-26dc-4ec3-a54c-205900950862@linux.dev> (raw)
In-Reply-To: <20240410140952.292261-1-jolsa@kernel.org>


On 4/10/24 7:09 AM, Jiri Olsa wrote:
> We have two printk tests reading trace_pipe in non blocking way,
> with the very same code. Moving that in new read_trace_pipe_iter
> function.
>
> Current read_trace_pipe is used from sampless/bpf and needs to
> do blocking read and printf of the trace_pipe data, using new
> read_trace_pipe_iter to implement that.
>
> Both printk tests do early checks for the number of found messages
> and can bail earlier, but I did not find any speed difference w/o
> that condition, so I did not complicate the change more for that.
>
> Some of the samples/bpf programs use read_trace_pipe function,
> so I kept that interface untouched. I did not see any issues with
> affected samples/bpf programs other than there's slight change in
> read_trace_pipe output. The current code uses puts that adds new
> line after the printed string, so we would occasionally see extra
> new line. With this patch we read output per lines, so there's no
> need to use puts and we can use just printf instead without extra
> new line.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>

Ack with a nit below.

Acked-by: Yonghong Song <yonghong.song@linux.dev>

> ---
>   v2 changes:
>     - call read_trace_pipe_iter callback only in case there's new data
>       read from getline
>
>   .../selftests/bpf/prog_tests/trace_printk.c   | 36 +++--------
>   .../selftests/bpf/prog_tests/trace_vprintk.c  | 36 +++--------
>   tools/testing/selftests/bpf/trace_helpers.c   | 63 ++++++++++++-------
>   tools/testing/selftests/bpf/trace_helpers.h   |  2 +
>   4 files changed, 60 insertions(+), 77 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/trace_printk.c b/tools/testing/selftests/bpf/prog_tests/trace_printk.c
> index 7b9124d506a5..e56e88596d64 100644
> --- a/tools/testing/selftests/bpf/prog_tests/trace_printk.c
> +++ b/tools/testing/selftests/bpf/prog_tests/trace_printk.c
> @@ -5,18 +5,19 @@
>   
>   #include "trace_printk.lskel.h"
>   
> -#define TRACEFS_PIPE	"/sys/kernel/tracing/trace_pipe"
> -#define DEBUGFS_PIPE	"/sys/kernel/debug/tracing/trace_pipe"
>   #define SEARCHMSG	"testing,testing"
>   
> +static void trace_pipe_cb(const char *str, void *data)
> +{
> +	if (strstr(str, SEARCHMSG) != NULL)
> +		(*(int *)data)++;
> +}
> +
>   void serial_test_trace_printk(void)
>   {
>   	struct trace_printk_lskel__bss *bss;
> -	int err = 0, iter = 0, found = 0;
>   	struct trace_printk_lskel *skel;
> -	char *buf = NULL;
> -	FILE *fp = NULL;
> -	size_t buflen;
> +	int err = 0, found = 0;
>   
>   	skel = trace_printk_lskel__open();
>   	if (!ASSERT_OK_PTR(skel, "trace_printk__open"))
> @@ -35,16 +36,6 @@ void serial_test_trace_printk(void)
>   	if (!ASSERT_OK(err, "trace_printk__attach"))
>   		goto cleanup;
>   
> -	if (access(TRACEFS_PIPE, F_OK) == 0)
> -		fp = fopen(TRACEFS_PIPE, "r");
> -	else
> -		fp = fopen(DEBUGFS_PIPE, "r");
> -	if (!ASSERT_OK_PTR(fp, "fopen(TRACE_PIPE)"))
> -		goto cleanup;
> -
> -	/* We do not want to wait forever if this test fails... */
> -	fcntl(fileno(fp), F_SETFL, O_NONBLOCK);
> -
>   	/* wait for tracepoint to trigger */
>   	usleep(1);
>   	trace_printk_lskel__detach(skel);
> @@ -56,21 +47,12 @@ void serial_test_trace_printk(void)
>   		goto cleanup;
>   
>   	/* verify our search string is in the trace buffer */
> -	while (getline(&buf, &buflen, fp) >= 0 || errno == EAGAIN) {
> -		if (strstr(buf, SEARCHMSG) != NULL)
> -			found++;
> -		if (found == bss->trace_printk_ran)
> -			break;

The above condition is not covered, but I think it is okay since the test
will run in serial mode.

> -		if (++iter > 1000)
> -			break;
> -	}
> +	ASSERT_OK(read_trace_pipe_iter(trace_pipe_cb, &found, 1000),
> +		 "read_trace_pipe_iter");
>   
>   	if (!ASSERT_EQ(found, bss->trace_printk_ran, "found"))
>   		goto cleanup;
>   
>   cleanup:
>   	trace_printk_lskel__destroy(skel);
> -	free(buf);
> -	if (fp)
> -		fclose(fp);
>   }
> diff --git a/tools/testing/selftests/bpf/prog_tests/trace_vprintk.c b/tools/testing/selftests/bpf/prog_tests/trace_vprintk.c
> index 44ea2fd88f4c..2af6a6f2096a 100644
> --- a/tools/testing/selftests/bpf/prog_tests/trace_vprintk.c
> +++ b/tools/testing/selftests/bpf/prog_tests/trace_vprintk.c
> @@ -5,18 +5,19 @@
>   
>   #include "trace_vprintk.lskel.h"
>   
> -#define TRACEFS_PIPE	"/sys/kernel/tracing/trace_pipe"
> -#define DEBUGFS_PIPE	"/sys/kernel/debug/tracing/trace_pipe"
>   #define SEARCHMSG	"1,2,3,4,5,6,7,8,9,10"
>   
> +static void trace_pipe_cb(const char *str, void *data)
> +{
> +	if (strstr(str, SEARCHMSG) != NULL)
> +		(*(int *)data)++;
> +}
> +
>   void serial_test_trace_vprintk(void)
>   {
>   	struct trace_vprintk_lskel__bss *bss;
> -	int err = 0, iter = 0, found = 0;
>   	struct trace_vprintk_lskel *skel;
> -	char *buf = NULL;
> -	FILE *fp = NULL;
> -	size_t buflen;
> +	int err = 0, found = 0;
>   
>   	skel = trace_vprintk_lskel__open_and_load();
>   	if (!ASSERT_OK_PTR(skel, "trace_vprintk__open_and_load"))
> @@ -28,16 +29,6 @@ void serial_test_trace_vprintk(void)
>   	if (!ASSERT_OK(err, "trace_vprintk__attach"))
>   		goto cleanup;
>   
> -	if (access(TRACEFS_PIPE, F_OK) == 0)
> -		fp = fopen(TRACEFS_PIPE, "r");
> -	else
> -		fp = fopen(DEBUGFS_PIPE, "r");
> -	if (!ASSERT_OK_PTR(fp, "fopen(TRACE_PIPE)"))
> -		goto cleanup;
> -
> -	/* We do not want to wait forever if this test fails... */
> -	fcntl(fileno(fp), F_SETFL, O_NONBLOCK);
> -
>   	/* wait for tracepoint to trigger */
>   	usleep(1);
>   	trace_vprintk_lskel__detach(skel);
> @@ -49,14 +40,8 @@ void serial_test_trace_vprintk(void)
>   		goto cleanup;
>   
>   	/* verify our search string is in the trace buffer */
> -	while (getline(&buf, &buflen, fp) >= 0 || errno == EAGAIN) {
> -		if (strstr(buf, SEARCHMSG) != NULL)
> -			found++;
> -		if (found == bss->trace_vprintk_ran)
> -			break;
> -		if (++iter > 1000)
> -			break;
> -	}
> +	ASSERT_OK(read_trace_pipe_iter(trace_pipe_cb, &found, 1000),
> +		 "read_trace_pipe_iter");
>   
>   	if (!ASSERT_EQ(found, bss->trace_vprintk_ran, "found"))
>   		goto cleanup;
> @@ -66,7 +51,4 @@ void serial_test_trace_vprintk(void)
>   
>   cleanup:
>   	trace_vprintk_lskel__destroy(skel);
> -	free(buf);
> -	if (fp)
> -		fclose(fp);
>   }

[...]

>   ssize_t get_uprobe_offset(const void *addr)
>   {
>   	size_t start, end, base;
> @@ -413,3 +390,43 @@ int read_build_id(const char *path, char *build_id, size_t size)
>   	close(fd);
>   	return err;
>   }
> +
> +int read_trace_pipe_iter(void (*cb)(const char *str, void *data), void *data, int iter)
> +{
> +	size_t buflen, n;
> +	char *buf = NULL;
> +	FILE *fp = NULL;
> +
> +	if (access(TRACEFS_PIPE, F_OK) == 0)
> +		fp = fopen(TRACEFS_PIPE, "r");
> +	else
> +		fp = fopen(DEBUGFS_PIPE, "r");
> +	if (!fp)
> +		return -1;
> +
> +	 /* We do not want to wait forever when iter is specified. */
> +	if (iter)
> +		fcntl(fileno(fp), F_SETFL, O_NONBLOCK);
> +
> +	while ((n = getline(&buf, &buflen, fp) >= 0) || errno == EAGAIN) {
> +		if (n > 0)
> +			cb(buf, data);
> +		if (iter && !(--iter))

"if (iter-- == 1)" should also work. But your code works too.

> +			break;
> +	}
> +
> +	free(buf);
> +	if (fp)
> +		fclose(fp);
> +	return 0;
> +}
> +
[...]

  reply	other threads:[~2024-04-11  0:09 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-10 14:09 [PATCHv2 bpf-next] selftests/bpf: Add read_trace_pipe_iter function Jiri Olsa
2024-04-11  0:09 ` Yonghong Song [this message]
2024-04-12  9:44   ` Jiri Olsa
2024-04-12 16:30 ` patchwork-bot+netdevbpf

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=64fa1c03-26dc-4ec3-a54c-205900950862@linux.dev \
    --to=yonghong.song@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=haoluo@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kafai@fb.com \
    --cc=kpsingh@chromium.org \
    --cc=sdf@google.com \
    --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