All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.