public inbox for dtrace@lists.linux.dev
 help / color / mirror / Atom feed
From: Kris Van Hees <kris.van.hees@oracle.com>
To: eugene.loh@oracle.com
Cc: dtrace@lists.linux.dev, dtrace-devel@oss.oracle.com
Subject: Re: [PATCH 31/38] Fix dt_pebs_init() call
Date: Mon, 26 Aug 2024 10:30:06 -0400	[thread overview]
Message-ID: <ZsyRbgnYtFelMhM8@oracle.com> (raw)
In-Reply-To: <20240627053904.21996-12-eugene.loh@oracle.com>

This patch goes against the intent of the code, as far as I can see.  The
point of performing the size check prior to increasing the buffer size was
to enforce the limit on the size that was explicit set by the user.  Then,
if that size was sufficient, then DTrace is at liberty to increase that
size to a whole multiple of the page size.

But if I were to insist that a buffer can only be 24 bytes, and 24 bytes are
not enough to store a single trace record, DTrace should report an error
rather than increasing my bufsize setting on its own.

On Thu, Jun 27, 2024 at 01:38:57AM -0400, eugene.loh@oracle.com wrote:
> From: Eugene Loh <eugene.loh@oracle.com>
> 
> The function had a few issues, mainly with its comments,
> ranging from typos to incorrect descriptions of behavior.
> 
> The function has only one caller.  The enforcement of a
> size minimum was problematic in a number of respects:
> - it was missing 4 bytes
> - it was enforcing the minimum before the size was
>     increased by the caller
> - it was checking dt_pebs_init()==-1,
>     missing errors with other negative return values
> 
> So change the function to accept a minimum and change its
> return values.
> 
> Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
> ---
>  libdtrace/dt_peb.c                          | 27 ++++++++++-----------
>  libdtrace/dt_peb.h                          |  2 +-
>  libdtrace/dt_work.c                         | 15 +++++++-----
>  test/unittest/options/err.b-too-low.d       | 22 +++++++++--------
>  test/unittest/options/err.bufsize-too-low.d | 22 +++++++++--------
>  test/unittest/options/tst.b.d               | 22 +++++++++--------
>  test/unittest/options/tst.bufsize.d         | 22 +++++++++--------
>  7 files changed, 71 insertions(+), 61 deletions(-)
> 
> diff --git a/libdtrace/dt_peb.c b/libdtrace/dt_peb.c
> index 5268f089..4983ba91 100644
> --- a/libdtrace/dt_peb.c
> +++ b/libdtrace/dt_peb.c
> @@ -136,18 +136,14 @@ dt_pebs_exit(dtrace_hdl_t *dtp)
>  }
>  
>  /*
> - * Initialize the perf event buffers (one per online CPU).  Each buffer will
> - * the given number of pages (i.e. the total size of each buffer will be
> - * num_pages * getpagesize()).  The  allocated memory for each buffer is mmap'd
> - * so the kernel can write to it, and its representative file descriptor is
> - * recorded in the 'buffers' BPF map so that BPF code knows where to write
> - * trace data for a specific CPU.
> + * Initialize the perf event buffers, one per online CPU.  Each buffer will
> + * have num_pages * getpagesize()).  The dt_peb_open() call mmaps the allocated
> + * memory so the kernel can write to it.  The file descriptor is recorded in
> + * the 'buffers' BPF map and added to the event polling file descriptor.
>   *
> - * An event polling file descriptor is created as well, and it is configured to
> - * monitor all perf event buffers at once.  This file descriptor is returned
> - * upon success..  Failure is indicated with a -1 return value.
> + * The return value indicates success (0) or failure (-1).
>   */
> -int dt_pebs_init(dtrace_hdl_t *dtp, size_t bufsize)
> +int dt_pebs_init(dtrace_hdl_t *dtp, size_t bufsize, size_t bufsizemin)
>  {
>  	int		i;
>  	int		mapfd;
> @@ -166,12 +162,15 @@ int dt_pebs_init(dtrace_hdl_t *dtp, size_t bufsize)
>  		fprintf(stderr, "bufsize increased to %lu\n",
>  			num_pages * getpagesize());
>  
> +	if (num_pages * getpagesize() < bufsizemin)
> +		return dt_set_errno(dtp, EDT_BUFTOOSMALL);
> +
>  	/*
>  	 * Determine the fd for the 'buffers' BPF map.
>  	 */
>  	idp = dt_dlib_get_map(dtp, "buffers");
>  	if (idp == NULL || idp->di_id == DT_IDENT_UNDEF)
> -		return -ENOENT;
> +		return dt_set_errno(dtp, EDT_NOMEM);    // FIXME we used to do something more akin to ENOENT
>  
>  	mapfd = idp->di_id;
>  
> @@ -180,7 +179,7 @@ int dt_pebs_init(dtrace_hdl_t *dtp, size_t bufsize)
>  	 */
>  	dtp->dt_pebset = dt_zalloc(dtp, sizeof(dt_pebset_t));
>  	if (dtp->dt_pebset == NULL)
> -		return -ENOMEM;
> +		return dt_set_errno(dtp, EDT_NOMEM);
>  
>  	/*
>  	 * Allocate the per-CPU perf event buffers.
> @@ -189,7 +188,7 @@ int dt_pebs_init(dtrace_hdl_t *dtp, size_t bufsize)
>  			 sizeof(struct dt_peb));
>  	if (pebs == NULL) {
>  		dt_free(dtp, dtp->dt_pebset);
> -		return -ENOMEM;
> +		return dt_set_errno(dtp, EDT_NOMEM);
>  	}
>  
>  	dtp->dt_pebset->pebs = pebs;
> @@ -241,5 +240,5 @@ int dt_pebs_init(dtrace_hdl_t *dtp, size_t bufsize)
>  fail:
>  	dt_pebs_exit(dtp);
>  
> -	return -1;
> +	return dt_set_errno(dtp, EDT_NOMEM);  // FIXME need something better
>  }
> diff --git a/libdtrace/dt_peb.h b/libdtrace/dt_peb.h
> index e0f408f2..9ad23252 100644
> --- a/libdtrace/dt_peb.h
> +++ b/libdtrace/dt_peb.h
> @@ -43,7 +43,7 @@ typedef struct dt_pebset {
>  } dt_pebset_t;
>  
>  extern void dt_pebs_exit(dtrace_hdl_t *);
> -extern int dt_pebs_init(dtrace_hdl_t *, size_t);
> +extern int dt_pebs_init(dtrace_hdl_t *, size_t, size_t);
>  
>  #ifdef	__cplusplus
>  }
> diff --git a/libdtrace/dt_work.c b/libdtrace/dt_work.c
> index 69a86358..7a0eb1da 100644
> --- a/libdtrace/dt_work.c
> +++ b/libdtrace/dt_work.c
> @@ -267,18 +267,21 @@ dtrace_go(dtrace_hdl_t *dtp, uint_t cflags)
>  		return dt_set_errno(dtp, errno);
>  
>  	/*
> -	 * We need enough space for the pref_event_header, a 32-bit size, a
> +	 * We need enough space for the perf_event_header, a 32-bit size, a
>  	 * 4-byte gap, and the largest trace data record we may be writing to
>  	 * the buffer.  In other words, the buffer needs to be large enough to
>  	 * hold at least one perf-encapsulated trace data record.
> +	 *
> +	 * While dt_pebs_init() rounds the requested size up, size==0 is a
> +	 * special case.
>  	 */
>  	dtrace_getopt(dtp, "bufsize", &size);
> -	if (size == 0 ||
> -	    size < sizeof(struct perf_event_header) + sizeof(uint32_t) +
> -		   dtp->dt_maxreclen)
> +	if (size == 0)
>  		return dt_set_errno(dtp, EDT_BUFTOOSMALL);
> -	if (dt_pebs_init(dtp, size) == -1)
> -		return dt_set_errno(dtp, EDT_NOMEM);
> +	if (dt_pebs_init(dtp, size,
> +			 sizeof(struct perf_event_header) + sizeof(uint32_t)
> +			 + 4 + dtp->dt_maxreclen) == -1)
> +		return -1;
>  
>  	/*
>  	 * We must initialize the aggregation consumer handling before we
> diff --git a/test/unittest/options/err.b-too-low.d b/test/unittest/options/err.b-too-low.d
> index bb77e37c..f62155dd 100644
> --- a/test/unittest/options/err.b-too-low.d
> +++ b/test/unittest/options/err.b-too-low.d
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> @@ -12,19 +12,21 @@
>   */
>  
>  /*
> - * We use a buffer size of 59 because that should be just too small to hold the
> - * trace records generated in this script:
> - *	- perf_event_header (40 bytes)
> - *	- size (4 bytes)
> - *	- gap (4 bytes)
> - *	- EPID (4 bytes)
> - *	- tag (4 bytes)
> - *	- exit value (4 bytes)
> + * We need over 4k bytes for the 4 string trace records generated in this script
> + * plus some meta data.
> + * A bufsize of 1 to 4096 bytes is rounded up to 4096 and is insufficient.
> + * A bufsize of 4097 to 8192 bytes is rounded up to 8192 and is sufficient.
>   */
> -/* @@runtest-opts: -b59 */
> +/* @@runtest-opts: -b4096 */
> +
> +#pragma D option strsize=1024
>  
>  BEGIN
>  {
> +	trace("abc");
> +	trace("def");
> +	trace("ghi");
> +	trace("jkl");
>  	exit(0);
>  }
>  
> diff --git a/test/unittest/options/err.bufsize-too-low.d b/test/unittest/options/err.bufsize-too-low.d
> index bbbdb5c5..25efdf72 100644
> --- a/test/unittest/options/err.bufsize-too-low.d
> +++ b/test/unittest/options/err.bufsize-too-low.d
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> @@ -12,19 +12,21 @@
>   */
>  
>  /*
> - * We use a buffer size of 59 because that should be just too small to hold the
> - * trace records generated in this script:
> - *	- perf_event_header (40 bytes)
> - *	- size (4 bytes)
> - *	- gap (4 bytes)
> - *	- EPID (4 bytes)
> - *	- tag (4 bytes)
> - *	- exit value (4 bytes)
> + * We need over 4k bytes for the 4 string trace records generated in this script
> + * plus some meta data.
> + * A bufsize of 1 to 4096 bytes is rounded up to 4096 and is insufficient.
> + * A bufsize of 4097 to 8192 bytes is rounded up to 8192 and is sufficient.
>   */
> -/* @@runtest-opts: -xbufsize=59 */
> +/* @@runtest-opts: -xbufsize=4096 */
> +
> +#pragma D option strsize=1024
>  
>  BEGIN
>  {
> +	trace("abc");
> +	trace("def");
> +	trace("ghi");
> +	trace("jkl");
>  	exit(0);
>  }
>  
> diff --git a/test/unittest/options/tst.b.d b/test/unittest/options/tst.b.d
> index 57fa030d..3bf08edc 100644
> --- a/test/unittest/options/tst.b.d
> +++ b/test/unittest/options/tst.b.d
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> @@ -12,19 +12,21 @@
>   */
>  
>  /*
> - * We use a buffer size of 60 because that should be the exact size necessary
> - * to hold the trace records generated in this script:
> - *	- perf_event_header (40 bytes)
> - *	- size (4 bytes)
> - *	- gap (4 bytes)
> - *	- EPID (4 bytes)
> - *	- tag (4 bytes)
> - *	- exit value (4 bytes)
> + * We need over 4k bytes for the 4 string trace records generated in this script
> + * plus some meta data.
> + * A bufsize of 1 to 4096 bytes is rounded up to 4096 and is insufficient.
> + * A bufsize of 4097 to 8192 bytes is rounded up to 8192 and is sufficient.
>   */
> -/* @@runtest-opts: -b60 */
> +/* @@runtest-opts: -b4097 */
> +
> +#pragma D option strsize=1024
>  
>  BEGIN
>  {
> +	trace("abc");
> +	trace("def");
> +	trace("ghi");
> +	trace("jkl");
>  	exit(0);
>  }
>  
> diff --git a/test/unittest/options/tst.bufsize.d b/test/unittest/options/tst.bufsize.d
> index 96b0f1b8..23af81aa 100644
> --- a/test/unittest/options/tst.bufsize.d
> +++ b/test/unittest/options/tst.bufsize.d
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> @@ -12,19 +12,21 @@
>   */
>  
>  /*
> - * We use a buffer size of 60 because that should be the exact size necessary
> - * to hold the trace records generated in this script:
> - *	- perf_event_header (40 bytes)
> - *	- size (4 bytes)
> - *	- gap (4 bytes)
> - *	- EPID (4 bytes)
> - *	- tag (4 bytes)
> - *	- exit value (4 bytes)
> + * We need over 4k bytes for the 4 string trace records generated in this script
> + * plus some meta data.
> + * A bufsize of 1 to 4096 bytes is rounded up to 4096 and is insufficient.
> + * A bufsize of 4097 to 8192 bytes is rounded up to 8192 and is sufficient.
>   */
> -/* @@runtest-opts: -xbufsize=60 */
> +/* @@runtest-opts: -xbufsize=4097 */
> +
> +#pragma D option strsize=1024
>  
>  BEGIN
>  {
> +	trace("abc");
> +	trace("def");
> +	trace("ghi");
> +	trace("jkl");
>  	exit(0);
>  }
>  
> -- 
> 2.18.4
> 

  reply	other threads:[~2024-08-26 14:30 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-27  5:38 [PATCH 20/38] Add a hook for a provider-specific "update" function eugene.loh
2024-06-27  5:38 ` [PATCH 21/38] Add some comments eugene.loh
2024-07-19 20:39   ` Kris Van Hees
2024-06-27  5:38 ` [PATCH 22/38] Fix aggs comment in dt_cg_tramp_prologue_act() eugene.loh
2024-07-19 20:44   ` Kris Van Hees
2024-07-19 23:15     ` Eugene Loh
2024-06-27  5:38 ` [PATCH 23/38] test: Clean up the specsize tests eugene.loh
2024-06-27  5:38 ` [PATCH 24/38] test: Make test independent of specific PC eugene.loh
2024-07-19 21:02   ` Kris Van Hees
2024-07-22  0:05     ` Eugene Loh
2024-06-27  5:38 ` [PATCH 25/38] test: Clean up tests still expecting obsolete "at DIF offset NN" eugene.loh
2024-07-19 21:08   ` Kris Van Hees
2024-06-27  5:38 ` [PATCH 26/38] test: Annotate xfail (chill not implemented yet) eugene.loh
2024-07-19 21:12   ` Kris Van Hees
2024-07-19 23:38     ` Eugene Loh
2024-10-29 15:05       ` Kris Van Hees
2024-10-29 21:13         ` Eugene Loh
2024-06-27  5:38 ` [PATCH 27/38] test: Fix the speculative tests that checked bufsize eugene.loh
2024-06-27  5:38 ` [PATCH 28/38] Remove unused "next" arg from dt_flowindent() eugene.loh
2024-08-28 19:41   ` Kris Van Hees
2024-06-27  5:38 ` [PATCH 29/38] Allow relocation of the ERROR PRID eugene.loh
2024-07-19 21:41   ` [DTrace-devel] " Kris Van Hees
2024-07-19 23:49     ` Eugene Loh
2024-06-27  5:38 ` [PATCH 30/38] Allow relocation on BPF_OR instructions eugene.loh
2024-07-19 21:34   ` Kris Van Hees
2024-09-30 21:19     ` Kris Van Hees
2024-09-30 22:00       ` Eugene Loh
2024-06-27  5:38 ` [PATCH 31/38] Fix dt_pebs_init() call eugene.loh
2024-08-26 14:30   ` Kris Van Hees [this message]
2024-08-26 15:42     ` Eugene Loh
2024-08-26 16:20       ` Kris Van Hees
2024-08-28 20:57         ` Eugene Loh
2024-08-28 21:16           ` Kris Van Hees
2024-08-30  0:54             ` Eugene Loh
2024-08-30  2:26               ` [DTrace-devel] " Kris Van Hees
2024-08-30  5:42                 ` Eugene Loh
2024-08-30 16:53                   ` Kris Van Hees
2024-08-30 19:06                     ` Eugene Loh
2024-08-30 20:07                       ` Kris Van Hees
2024-06-27  5:38 ` [PATCH 32/38] Widen the EPID to include the PRID eugene.loh
2024-06-27  5:38 ` [PATCH 33/38] Eliminate dt_pdesc eugene.loh
2024-06-27  5:39 ` [PATCH 34/38] Create the BPF uprobes map eugene.loh
2024-06-27  5:39 ` [PATCH 35/38] Use uprobes map to call clauses conditionally eugene.loh
2024-06-27  5:39 ` [PATCH 36/38] Inline copyout_val() eugene.loh
2024-06-27  5:39 ` [PATCH 37/38] Fix some dctx->mst->specsize comments eugene.loh
2024-07-18 20:41   ` Kris Van Hees
2024-06-27  5:39 ` [PATCH 38/38] Systemwide USDT WIP eugene.loh
2024-07-19 20:31 ` [PATCH 20/38] Add a hook for a provider-specific "update" function Kris Van Hees
2024-07-20  0:08   ` Eugene Loh

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=ZsyRbgnYtFelMhM8@oracle.com \
    --to=kris.van.hees@oracle.com \
    --cc=dtrace-devel@oss.oracle.com \
    --cc=dtrace@lists.linux.dev \
    --cc=eugene.loh@oracle.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