[DTrace-devel] [PATCH 53/61] Add support for aggregation keys

Kris Van Hees kris.van.hees at oracle.com
Wed Sep 14 18:14:18 UTC 2022


Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>

... albeit in modified form due to other chagnes I introduced that change the
    storage layout for indexed aggregations.

... on dev

On Fri, Jul 08, 2022 at 10:45:37AM -0400, eugene.loh--- via DTrace-devel wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
> 
> In the DTrace port to BPF, the initial support for aggregations
> had the kernel maintaining aggregations in a per-CPU BPF map that
> was statically allocated and managed.  Each aggregation had its
> own region of per-CPU memory.  That is, run-time aggregation keys
> were not supported.
> 
> To support aggregation keys, switch to a per-CPU BPF hash map.
> The hash map key comprises:
> 
> *)  the aggregation variable ID
> 
> *)  the aggregation keys (if any)
> 
> *)  a 64-bit zero (to conform to dynamic variable "tuples")
> 
> On the producer (dt_cg.c) side:
> 
> *)  Use the existing dt_cg_arglist() to process the
>     aggregation keys and produce the BPF hash map key.
> 
> *)  Call the new dt_get_agg() to get a pointer to the
>     aggregation data in the BPF hash map.  The function call
>     will create the element if needed, increment the data
>     counter, and advance the pointer to the actual data.
> 
> *)  Push this pointer to the stack.
> 
> *)  Call the aggregation function: compute the value
>     to be aggregated and pop the stack for the pointer
>     to where the aggregation data is.
> 
> *)  Record the aggregation description (e.g., sizes of
>     keys and data) if not already done.  This step is
>     performed during code generation, though it does not
>     generate code per se.
> 
> On the consumer (dt_aggregate.c) side, to snapshot aggregation data:
> 
> *)  Use dt_bpf_map_next_key() to walk the keys of the
>     BPF hash map.
> 
> *)  For each hash map key, read the aggregation data on all CPUs.
> 
> *)  For each CPU with a nonzero data counter value, check
>     dt_aggregate's user-space hash table for this key-specific
>     aggregation.  Initialize or aggregate the user-space data
>     accordingly.
> 
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
> ---
>  bpf/Build                                     |   1 +
>  bpf/get_agg.c                                 |  42 +++
>  include/dtrace/faults_defines.h               |   1 +
>  libdtrace/dt_aggregate.c                      | 256 ++++++++----------
>  libdtrace/dt_bpf.c                            |  34 ++-
>  libdtrace/dt_cg.c                             | 129 +++++----
>  libdtrace/dt_dctx.h                           |   1 -
>  libdtrace/dt_error.c                          |   1 +
>  libdtrace/dt_impl.h                           |   2 +-
>  test/demo/intro/countdown-multiple.d          |   3 +-
>  test/demo/intro/countdown-quant.d             |   3 +-
>  test/demo/out/printa.d                        |   3 +-
>  test/demo/script/syscall.d                    |   3 +-
>  test/demo/user/libc.d                         |   3 +-
>  test/stress/buffering/err.resize2.d           |   1 -
>  .../actions/printa/err.D_PRINTA_AGGKEY.d      |   3 +-
>  .../actions/printa/err.D_PRINTA_AGGPROTO.d    |   3 +-
>  test/unittest/aggs/tst.count2.d               |   3 +-
>  test/unittest/aggs/tst.count3.d               |   3 +-
>  test/unittest/aggs/tst.denormalizeonly.d      |   3 +-
>  test/unittest/aggs/tst.fmtnormalize.d         |   3 +-
>  test/unittest/aggs/tst.forms.d                |   3 +-
>  test/unittest/aggs/tst.keysort.d              |   3 +-
>  test/unittest/aggs/tst.lquantize.d            |   3 +-
>  test/unittest/aggs/tst.lquantrange.d          |   3 +-
>  test/unittest/aggs/tst.lquantzero.d           |   4 +-
>  test/unittest/aggs/tst.multiaggs1.d           |   3 +-
>  test/unittest/aggs/tst.multinormalize.d       |   3 +-
>  test/unittest/aggs/tst.neglquant.d            |   1 -
>  test/unittest/aggs/tst.negorder.d             |   3 +-
>  test/unittest/aggs/tst.negquant.d             |   1 -
>  test/unittest/aggs/tst.order.d                |   3 +-
>  test/unittest/aggs/tst.quantize.d             |   3 +-
>  test/unittest/aggs/tst.quantmany.d            |   3 +-
>  test/unittest/aggs/tst.quantzero.d            |   4 +-
>  test/unittest/aggs/tst.signedkeyspos.d        |   3 +-
>  test/unittest/aggs/tst.valsortkeypos.d        |   3 +-
>  test/unittest/funcs/substr/tst.substrminate.d |   1 -
>  test/unittest/grammar/tst.stmts.d             |   3 +-
>  test/unittest/misc/tst.haslam.d               |   3 +-
>  test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d |   4 +-
>  .../multiaggs/err.D_PRINTA_AGGPROTO.d         |   4 +-
>  test/unittest/multiaggs/tst.many.d            |   3 +-
>  test/unittest/multiaggs/tst.sort.d            |   3 +-
>  test/unittest/multiaggs/tst.sortpos.d         |   3 +-
>  test/unittest/multiaggs/tst.zero.d            |   3 +-
>  test/unittest/multiaggs/tst.zero2.d           |   3 +-
>  test/unittest/multiaggs/tst.zero3.d           |   3 +-
>  test/unittest/printa/tst.dynwidth.d           |   3 +-
>  test/unittest/printa/tst.tuple.d              |   3 +-
>  50 files changed, 294 insertions(+), 292 deletions(-)
>  create mode 100644 bpf/get_agg.c
> 
> diff --git a/bpf/Build b/bpf/Build
> index b29f4b91..41de1bb8 100644
> --- a/bpf/Build
> +++ b/bpf/Build
> @@ -25,6 +25,7 @@ bpf_dlib_SOURCES = \
>  	agg_lqbin.c agg_qbin.c \
>  	basename.S \
>  	dirname.S \
> +	get_agg.c \
>  	get_bvar.c \
>  	get_dvar.c \
>  	index.S \
> diff --git a/bpf/get_agg.c b/bpf/get_agg.c
> new file mode 100644
> index 00000000..dc3f8443
> --- /dev/null
> +++ b/bpf/get_agg.c
> @@ -0,0 +1,42 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + */
> +#include <linux/bpf.h>
> +#include <stdint.h>
> +#include <bpf-helpers.h>
> +
> +#ifndef noinline
> +# define noinline	__attribute__((noinline))
> +#endif
> +
> +extern struct bpf_map_def aggs;
> +
> +noinline uint64_t *dt_get_agg(const char *key, const uint64_t *zer, uint64_t val)
> +{
> +	uint64_t	*valp;
> +
> +	/* try to look up the key */
> +	valp = bpf_map_lookup_elem(&aggs, key);
> +
> +	/* if not found, create it */
> +	if (valp == 0) {
> +		/* start with all zeroes */
> +		if (bpf_map_update_elem(&aggs, key, zer, BPF_ANY) < 0)
> +			return 0;
> +		valp = bpf_map_lookup_elem(&aggs, key);
> +		if (valp == 0)
> +			return 0;
> +
> +		/* val is nonzero only for min() and max() */
> +		valp[1] = val;
> +	}
> +
> +	/* increment the data counter */
> +	valp[0] += 1;
> +
> +	/* advance past the data counter */
> +	valp += 1;
> +
> +	return valp;
> +}
> diff --git a/include/dtrace/faults_defines.h b/include/dtrace/faults_defines.h
> index 3cefb0ee..f671f341 100644
> --- a/include/dtrace/faults_defines.h
> +++ b/include/dtrace/faults_defines.h
> @@ -33,6 +33,7 @@
>  #define DTRACEFLT_TUPOFLOW		8	/* Tuple stack overflow */
>  #define DTRACEFLT_BADSTACK		9	/* Bad stack */
>  #define DTRACEFLT_BADSIZE		10	/* Bad size */
> +#define DTRACEFLT_NOAGGS		11	/* Out of aggregations space */
>  
>  #define DTRACEFLT_LIBRARY		1000	/* Library-level fault */
>  
> diff --git a/libdtrace/dt_aggregate.c b/libdtrace/dt_aggregate.c
> index 10df98da..bfb32b02 100644
> --- a/libdtrace/dt_aggregate.c
> +++ b/libdtrace/dt_aggregate.c
> @@ -409,13 +409,6 @@ dt_aggregate_aggid(dt_ahashent_t *ent)
>  typedef void (*agg_cpu_f)(dt_ident_t *aid,
>      int64_t *dst, int64_t *src, uint_t realsz);
>  
> -typedef struct dt_snapstate {
> -	dtrace_hdl_t	*dtp;
> -	processorid_t	cpu;
> -	char		*buf;
> -	dt_aggregate_t	*agp;
> -} dt_snapstate_t;
> -
>  static void
>  dt_agg_one_agg(uint_t act, int64_t *dst, int64_t *src, uint_t realsz)
>  {
> @@ -440,29 +433,27 @@ dt_agg_one_agg(uint_t act, int64_t *dst, int64_t *src, uint_t realsz)
>  }
>  
>  static int
> -dt_aggregate_snap_one(dt_idhash_t *dhp, dt_ident_t *aid, dt_snapstate_t *st)
> +dt_aggregate_snap_one(dtrace_hdl_t *dtp, dt_ident_t *aid, char *key, int64_t *src, int cpu)
>  {
> -	dt_ahash_t		*agh = &st->agp->dtat_hash;
> +	dt_ahash_t		*agh = &dtp->dt_aggregate.dtat_hash;
>  	dt_ahashent_t		*h;
>  	dtrace_aggdesc_t	*agg;
>  	dtrace_aggdata_t	*agd;
>  	dtrace_recdesc_t	*rec;
> -	uint64_t		hval = aid->di_id;
> +	uint64_t		hval = aid->di_id;  /* FIXME: need better hash value */
>  	size_t			ndx = hval % agh->dtah_size;
>  	int			rval;
>  	uint_t			i, datasz;
> -	int64_t			*src;
> -	int			nrecs;
> +	int			irec, nrecs;
> +	caddr_t			data;
> +	size_t			roffs;
>  
> -	rval = dt_aggid_lookup(st->dtp, aid->di_id, &agg);
> +	rval = dt_aggid_lookup(dtp, aid->di_id, &agg);
>  	if (rval != 0)
>  		return rval;
>  
>  	nrecs = agg->dtagd_nrecs;
>  
> -	/* point to the data counter */
> -	src = (int64_t *)(st->buf + aid->di_offset);
> -
>  	/* skip it if data counter is 0 */
>  	if (*src == 0)
>  		return 0;
> @@ -478,76 +469,95 @@ dt_aggregate_snap_one(dt_idhash_t *dhp, dt_ident_t *aid, dt_snapstate_t *st)
>  
>  		if (h->dtahe_hval != hval || h->dtahe_size != agg->dtagd_size)
>  			continue;
> +		agd = &h->dtahe_data;
> +		data = agd->dtada_data;
> +
> +		/* compare the non-data records */
> +		for (irec = 0; irec < nrecs - 1; irec++) {
> +			rec = &agg->dtagd_recs[irec];
> +			roffs = rec->dtrd_offset;
> +
> +			if (memcmp(&key[roffs], &data[roffs], rec->dtrd_size))
> +				goto hashnext;
> +		}
>  
>  		/* Entry found - process the data. */
> -		agd = &h->dtahe_data;
>  		act = ((dt_ident_t *)aid->di_iarg)->di_id;
> -
>  		rec = &agg->dtagd_recs[nrecs - 1];
> -		dt_agg_one_agg(act, (int64_t *)(agd->dtada_data + rec->dtrd_offset),
> -			       src, datasz);
> +		roffs = rec->dtrd_offset;
> +		dt_agg_one_agg(act, (int64_t *)&data[roffs], src, datasz);
>  
>  		/* If we keep per-CPU data - process that as well. */
>  		if (agd->dtada_percpu != NULL)
> -			dt_agg_one_agg(act, (int64_t *)agd->dtada_percpu[st->cpu],
> +			dt_agg_one_agg(act, (int64_t *)agd->dtada_percpu[cpu],
>  			    src, datasz);
>  
>  		return 0;
> +
> +hashnext:
> +		continue;
>  	}
>  
>  	/* add it to the hash table */
> -	h = dt_zalloc(st->dtp, sizeof(dt_ahashent_t));
> +	h = dt_zalloc(dtp, sizeof(dt_ahashent_t));
>  	if (h == NULL)
> -		return dt_set_errno(st->dtp, EDT_NOMEM);
> +		return dt_set_errno(dtp, EDT_NOMEM);
>  
>  	agd = &h->dtahe_data;
> -	agd->dtada_data = dt_alloc(st->dtp, agg->dtagd_size);
> -	if (agd->dtada_data == NULL) {
> -		dt_free(st->dtp, h);
> -		return dt_set_errno(st->dtp, EDT_NOMEM);
> +	data = dt_alloc(dtp, agg->dtagd_size);
> +	if (data == NULL) {
> +		dt_free(dtp, h);
> +		return dt_set_errno(dtp, EDT_NOMEM);
>  	}
> +	agd->dtada_data = data;
>  
>  	/* initialize the variable ID */
> -	*((long *)agd->dtada_data) = agg->dtagd_varid;
> +	*((long *)data) = agg->dtagd_varid;
>  
> -	/* FIXME: initialize the keys */
> +	/* initialize the non-data records */
> +	for (irec = 0; irec < nrecs - 1; irec++) {
> +		rec = &agg->dtagd_recs[irec];
> +		roffs = rec->dtrd_offset;
> +		memcpy(&data[roffs], &key[roffs], rec->dtrd_size);
> +	}
>  
>  	/* copy the data */
>  	rec = &agg->dtagd_recs[nrecs - 1];
> -	memcpy(agd->dtada_data + rec->dtrd_offset, src, datasz);
> +	roffs = rec->dtrd_offset;
> +	memcpy(&data[roffs], src, datasz);
>  
>  	agd->dtada_size = agg->dtagd_size;
>  	agd->dtada_desc = agg;
> -	agd->dtada_hdl = st->dtp;
> +	agd->dtada_hdl = dtp;
>  
>  	h->dtahe_hval = hval;
>  	h->dtahe_size = agg->dtagd_size;
>  
> -	if (st->agp->dtat_flags & DTRACE_A_PERCPU) {
> -		char	**percpu = dt_calloc(st->dtp,
> -					     st->dtp->dt_conf.max_cpuid + 1,
> +	if (dtp->dt_aggregate.dtat_flags & DTRACE_A_PERCPU) {
> +		char	**percpu = dt_calloc(dtp,
> +					     dtp->dt_conf.max_cpuid + 1,
>  					     sizeof(char *));
>  
>  		if (percpu == NULL) {
> -			dt_free(st->dtp, agd->dtada_data);
> -			dt_free(st->dtp, h);
> +			dt_free(dtp, data);
> +			dt_free(dtp, h);
>  
> -			dt_set_errno(st->dtp, EDT_NOMEM);
> +			dt_set_errno(dtp, EDT_NOMEM);
>  		}
>  
> -		for (i = 0; i <= st->dtp->dt_conf.max_cpuid; i++) {
> -			percpu[i] = dt_zalloc(st->dtp, datasz);
> +		for (i = 0; i <= dtp->dt_conf.max_cpuid; i++) {
> +			percpu[i] = dt_zalloc(dtp, datasz);
>  			if (percpu[i] == NULL) {
>  				while (--i >= 0)
> -					dt_free(st->dtp, percpu[i]);
> -				dt_free(st->dtp, agd->dtada_data);
> -				dt_free(st->dtp, h);
> +					dt_free(dtp, percpu[i]);
> +				dt_free(dtp, data);
> +				dt_free(dtp, h);
>  
> -				dt_set_errno(st->dtp, EDT_NOMEM);
> +				dt_set_errno(dtp, EDT_NOMEM);
>  			}
>  		}
>  
> -		memcpy(percpu[st->cpu], src, datasz);
> +		memcpy(percpu[cpu], src, datasz);
>  		agd->dtada_percpu = percpu;
>  	}
>  
> @@ -567,22 +577,6 @@ dt_aggregate_snap_one(dt_idhash_t *dhp, dt_ident_t *aid, dt_snapstate_t *st)
>  	return 0;
>  }
>  
> -static int
> -dt_aggregate_snap_cpu(dtrace_hdl_t *dtp, processorid_t cpu)
> -{
> -	dt_aggregate_t	*agp = &dtp->dt_aggregate;
> -	char		*buf = agp->dtat_cpu_buf[cpu];
> -	dt_snapstate_t	st;
> -
> -	st.dtp = dtp;
> -	st.cpu = cpu;
> -	st.buf = buf;
> -	st.agp = agp;
> -
> -	return dt_idhash_iter(dtp->dt_aggs,
> -			      (dt_idhash_f *)dt_aggregate_snap_one, &st);
> -}
> -
>  /*
>   * Retrieve all aggregation data for the enabled CPUs and aggregate it.
>   */
> @@ -590,28 +584,62 @@ int
>  dtrace_aggregate_snap(dtrace_hdl_t *dtp)
>  {
>  	dt_aggregate_t	*agp = &dtp->dt_aggregate;
> -	uint32_t	key = 0;
> -	int		i, rval;
> +	int		i, fd = dtp->dt_aggmap_fd;
> +	uint_t		keysiz = dtp->dt_maxtuplesize;
> +	uint_t		valsiz = dtp->dt_aggsiz;
> +	char		*buf = agp->dtat_buf;
> +	char		*key = buf;
> +	char		*nxt = agp->dtat_nextkey;
> +	int64_t		*val = (int64_t *)(buf + keysiz);
> +	uint32_t	*varID_ptr = (uint32_t *)key;
> +
> +	if (buf == NULL)
> +		return 0;
> +
> +	dtrace_aggregate_clear(dtp);
>  
>  	/*
> -	 * If we do not have a buffer initialized, we will not be processing
> -	 * aggregations, so there is nothing to be done here.
> +	 * To start the iteration over BPF hash map keys,
> +	 * we need a key that will not be recognized.
> +	 * Just set its varID to an unrecognized value.
>  	 */
> -	if (agp->dtat_cpu_buf == NULL)
> -		return 0;
> +	*varID_ptr = DTRACE_AGGIDNONE;
> +
> +	/* now iterate over BPF hash map keys */
> +	while (dt_bpf_map_next_key(fd, key, nxt) == 0) {
> +		uint32_t varID;
> +		dt_ident_t *aid;
> +
> +		/* get next value */
> +		memcpy(key, nxt, keysiz);
> +		if (dt_bpf_map_lookup(fd, key, val) == -1) {
> +			printf("FAIL to look up\n");
> +			return 1;
> +		}
>  
> -	dtrace_aggregate_clear(dtp);
> +		/* read the key's var ID */
> +		varID = *varID_ptr;
>  
> -	rval = dt_bpf_map_lookup(dtp->dt_aggmap_fd, &key, agp->dtat_buf);
> -	if (rval != 0)
> -		return dt_set_errno(dtp, -rval);
> +		/* get the aid */
> +		aid = dt_idhash_lookup(dtp->dt_aggs, dtp->dt_adesc[varID]->dtagd_name);
>  
> -	for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
> -		rval = dt_aggregate_snap_cpu(dtp, dtp->dt_conf.cpus[i].cpu_id);
> -		if (rval != 0)
> -			return rval;
> +		/* look for on-line CPUs */
> +		for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
> +			int cpu = dtp->dt_conf.cpus[i].cpu_id;
> +			int64_t *data = (int64_t*) (((char *)val) + cpu * valsiz);
> +
> +			/* look for non-zero data counters */
> +			if (*data == 0)
> +				continue;
> +
> +			/* process it */
> +			dt_aggregate_snap_one(dtp, aid, key, data, cpu);
> +		}
>  	}
>  
> +	/* check for normal end of iteration */
> +	assert(errno == ENOENT);
> +
>  	return 0;
>  }
>  
> @@ -974,49 +1002,14 @@ dt_aggregate_bundlecmp(const void *lhs, const void *rhs)
>  	}
>  }
>  
> -/*
> - * Callback for initializing the min() and max() aggregation functions.
> - * The minimum 64 bit value is set for max() and the maximum 64 bit value is
> - * set for min(), so that any other value fed to the functions will register
> - * properly.
> - *
> - * The data counter of the first aggregation is used as a flag to
> - * indicate whether an initial value was stored for any aggregation.
> - */
> -static int
> -init_minmax(dt_idhash_t *dhp, dt_ident_t *aid, char *buf)
> -{
> -	dt_ident_t *fid = aid->di_iarg;
> -	int64_t *ptr;
> -	int64_t value;
> -
> -	assert(aid->di_kind == DT_IDENT_AGG);
> -	assert(fid);
> -
> -	if (fid->di_id == DT_AGG_MIN)
> -		value = INT64_MAX;
> -	else if (fid->di_id == DT_AGG_MAX)
> -		value = INT64_MIN;
> -	else
> -		return 0;
> -
> -	/* Indicate that we are setting initial values. */
> -	*(int64_t *)buf = 1;
> -
> -	/* skip ptr[0], it is the data counter */
> -	ptr = (int64_t *)(buf + aid->di_offset);
> -	ptr[1] = value;
> -
> -	return 0;
> -}
> -
>  int
>  dt_aggregate_go(dtrace_hdl_t *dtp)
>  {
>  	dt_aggregate_t	*agp = &dtp->dt_aggregate;
>  	dt_ahash_t	*agh = &agp->dtat_hash;
> -	int		aggsz, i;
> -	uint32_t	key = 0;
> +	int		aggsz;
> +	uint_t		keysiz = dtp->dt_maxtuplesize;
> +	uint_t		valsiz = dtp->dt_aggsiz;
>  
>  	/* If there are no aggregations there is nothing to do. */
>  	aggsz = dt_idhash_datasize(dtp->dt_aggs);
> @@ -1025,53 +1018,27 @@ dt_aggregate_go(dtrace_hdl_t *dtp)
>  
>  	/*
>  	 * Allocate a buffer to hold the aggregation data for all possible
> -	 * CPUs, and initialize the per-CPU data pointers for CPUs that are
> -	 * currently enabled.
> +	 * CPUs.  Allocate a buffer to hold the next key in the BPF map.
>  	 */
> -	agp->dtat_buf = dt_zalloc(dtp, dtp->dt_conf.num_possible_cpus * aggsz);
> +	agp->dtat_buf = dt_zalloc(dtp, keysiz + dtp->dt_conf.num_possible_cpus * valsiz);
>  	if (agp->dtat_buf == NULL)
>  		return dt_set_errno(dtp, EDT_NOMEM);
> -
> -	agp->dtat_cpu_buf = dt_calloc(dtp, dtp->dt_conf.max_cpuid + 1,
> -				      sizeof(char *));
> -	if (agp->dtat_cpu_buf == NULL) {
> +	agp->dtat_nextkey = dt_zalloc(dtp, keysiz);
> +	if (agp->dtat_nextkey == NULL) {
>  		dt_free(dtp, agp->dtat_buf);
>  		return dt_set_errno(dtp, EDT_NOMEM);
>  	}
>  
> -	for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
> -		int	cpu = dtp->dt_conf.cpus[i].cpu_id;
> -
> -		agp->dtat_cpu_buf[cpu] = agp->dtat_buf + cpu * aggsz;
> -	}
> -
>  	/* Create the aggregation hash. */
>  	agh->dtah_size = DTRACE_AHASHSIZE;
>  	agh->dtah_hash = dt_zalloc(dtp,
>  				   agh->dtah_size * sizeof(dt_ahashent_t *));
>  	if (agh->dtah_hash == NULL) {
> -		dt_free(dtp, agp->dtat_cpu_buf);
> +		dt_free(dtp, agp->dtat_nextkey);
>  		dt_free(dtp, agp->dtat_buf);
>  		return dt_set_errno(dtp, EDT_NOMEM);
>  	}
>  
> -	/* Initialize the starting values for min() and max() aggregations.  */
> -	dt_idhash_iter(dtp->dt_aggs, (dt_idhash_f *) init_minmax,
> -		       agp->dtat_buf);
> -	if (*(int64_t *)agp->dtat_buf == 0)
> -		return 0;
> -	*(int64_t *)agp->dtat_buf = 0;  /* clear the flag */
> -	for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
> -		int	cpu = dtp->dt_conf.cpus[i].cpu_id;
> -
> -		/* Data for CPU 0 was populated, so skip it. */
> -		if (cpu == 0)
> -			continue;
> -
> -		memcpy(agp->dtat_cpu_buf[cpu], agp->dtat_buf, aggsz);
> -	}
> -	dt_bpf_map_update(dtp->dt_aggmap_fd, &key, agp->dtat_buf);
> -
>  	return 0;
>  }
>  
> @@ -1845,7 +1812,6 @@ dt_aggregate_destroy(dtrace_hdl_t *dtp)
>  		hash->dtah_all = NULL;
>  		hash->dtah_size = 0;
>  	}
> -
> -	dt_free(dtp, agp->dtat_cpu_buf);
> +	dt_free(dtp, agp->dtat_nextkey);
>  	dt_free(dtp, agp->dtat_buf);
>  }
> diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
> index 8d7f38f2..107b65a6 100644
> --- a/libdtrace/dt_bpf.c
> +++ b/libdtrace/dt_bpf.c
> @@ -194,9 +194,7 @@ populate_probes_map(dtrace_hdl_t *dtp, int fd)
>   * - state:	DTrace session state, used to communicate state between BPF
>   *		programs and userspace.  The content of the map is defined in
>   *		dt_state.h.
> - * - aggs:	Aggregation data buffer map, associated with each CPU.  The
> - *		map is implemented as a global per-CPU map with a singleton
> - *		element (key 0).
> + * - aggs:	Aggregation data buffer map, a per-CPU hash.
>   * - specs:	Map associating speculation IDs with a dt_bpf_specs_t struct
>   *		giving the number of buffers speculated into for this
>   *		speculation, and the number drained by userspace.
> @@ -271,11 +269,18 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
>  	/*
>  	 * Check if there is aggregation data to be collected.
>  	 */
> -	sz = dt_idhash_datasize(dtp->dt_aggs);
> -	if (sz > 0) {
> +	if (dtp->dt_aggsiz > 0) {
> +		/* FIXME: need a better model for BPF map size */
> +		size_t nelems = dtp->dt_options[DTRACEOPT_AGGSIZE]
> +				/ (dtp->dt_conf.max_cpuid + 1)
> +				/ (dtp->dt_maxtuplesize + dtp->dt_aggsiz);
> +
> +		/* create the map */
>  		dtp->dt_aggmap_fd = create_gmap(dtp, "aggs",
> -						BPF_MAP_TYPE_PERCPU_ARRAY,
> -						sizeof(uint32_t), sz, 1);
> +						BPF_MAP_TYPE_PERCPU_HASH,
> +						dtp->dt_maxtuplesize,
> +						dtp->dt_aggsiz,
> +						nelems);
>  		if (dtp->dt_aggmap_fd == -1)
>  			return -1;	/* dt_errno is set for us */
>  	}
> @@ -367,6 +372,8 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
>  	/* figure out how big the region of zeroes should be */
>  	if (dtp->dt_zerosize < dtp->dt_maxtuplesize)
>  		dtp->dt_zerosize = dtp->dt_maxtuplesize;
> +	if (dtp->dt_zerosize < dtp->dt_aggsiz)
> +		dtp->dt_zerosize = dtp->dt_aggsiz;
>  
>  	/* global variables, including a region of zeroes */
>  	dtp->dt_zerooffset = P2ROUNDUP(dt_idhash_datasize(dtp->dt_globals), 8);
> @@ -403,7 +410,18 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
>  		dt_bpf_map_update(fd, &key, &dflt);
>  	}
>  
> -	if (dtp->dt_maxtuplesize > 0 &&
> +	/*
> +	 * Note:
> +	 *
> +	 * - dt_maxtuplesize>0 can mean we are using the tuples map
> +	 *   *OR* that we are using aggregations
> +	 *
> +	 * - dvarc!=0 can mean we are using the tuples map
> +	 *   *OR* that we are using keyless dvars (e.g., "self->x")
> +	 *
> +	 * So check both conditions before creating a "tuples" map.
> +	 */
> +	if (dtp->dt_maxtuplesize > 0 && dvarc != 0 &&
>  	    create_gmap(dtp, "tuples", BPF_MAP_TYPE_HASH,
>  			dtp->dt_maxtuplesize, sizeof(uint64_t), dvarc) == -1)
>  		return -1;		/* dt_errno is set for us */
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index 5a74f5ad..257af074 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -206,8 +206,6 @@ dt_cg_tramp_prologue_act(dt_pcb_t *pcb, dt_activity_t act)
>  	DT_CG_STORE_MAP_PTR("strtab", DCTX_STRTAB);
>  	if (dtp->dt_options[DTRACEOPT_SCRATCHSIZE] > 0)
>  		DT_CG_STORE_MAP_PTR("scratchmem", DCTX_SCRATCHMEM);
> -	if (dt_idhash_datasize(dtp->dt_aggs) > 0)
> -		DT_CG_STORE_MAP_PTR("aggs", DCTX_AGG);
>  	if (dt_idhash_datasize(dtp->dt_globals) > 0 || dtp->dt_zerosize > 0)
>  		DT_CG_STORE_MAP_PTR("gvars", DCTX_GVARS);
>  	if (dtp->dt_maxlvaralloc > 0)
> @@ -2623,9 +2621,31 @@ dt_cg_push_stack(dt_irlist_t *dlp, dt_regset_t *drp, int reg)
>  	dt_regset_free(drp, tmp);
>  }
>  
> +static int
> +dt_cg_pop_stack(dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	int reg;
> +	int tmp;
> +
> +	if ((reg = dt_regset_alloc(drp)) == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +	if ((tmp = dt_regset_alloc(drp)) == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +
> +	emit(dlp, BPF_LOAD(BPF_DW, tmp, BPF_REG_FP, DT_STK_SP));
> +	emit(dlp, BPF_ALU64_IMM(BPF_ADD, tmp, DT_STK_SLOT_SZ));
> +	emit(dlp, BPF_LOAD(BPF_DW, reg, tmp, 0));
> +	emit(dlp, BPF_STORE(BPF_DW, BPF_REG_FP, DT_STK_SP, tmp));
> +	dt_regset_free(drp, tmp);
> +
> +	return reg;
> +}
> +
>  /*
>   * Generate code to push the specified argument list on to the tuple stack.
> - * We use this routine for handling the index tuple for associative arrays.
> + * We use this routine for handling the index tuple for associative arrays
> + * as well as keys for aggregations.
> + *
>   * We must first generate code for all subexpressions because any subexpression
>   * could itself require the use of the tuple assembly area and we only provide
>   * one.
> @@ -5449,60 +5469,13 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  					     sizeof(uint64_t) + (sz)); \
>  	} while (0)
>  
> -/*
> - * Return a register that holds a pointer to the aggregation data to be
> - * updated.
> - *
> - * We update the data counter (first value in the aggregation) to
> - * signal that the aggregation has data.  The location of data for the
> - * given aggregation is stored in the register returned from this function.
> - */
> -static int
> -dt_cg_agg_buf_prepare(dt_ident_t *aid, int size, dt_irlist_t *dlp,
> -		      dt_regset_t *drp)
> -{
> -	int		rptr;
> -
> -	TRACE_REGSET("            Prep: Begin");
> -
> -	dt_regset_xalloc(drp, BPF_REG_0);
> -	rptr = dt_regset_alloc(drp);
> -	assert(rptr != -1);
> -
> -	/*
> -	 *	ptr = dctx->agg;	// lddw %rptr, [%fp + DT_STK_DCTX]
> -	 *				// lddw %rptr, [%rptr + DCTX_AGG]
> -	 */
> -	emit(dlp, BPF_LOAD(BPF_DW, rptr, BPF_REG_FP, DT_STK_DCTX));
> -	emit(dlp, BPF_LOAD(BPF_DW, rptr, rptr, DCTX_AGG));
> -
> -	/*
> -	 *	*((uint64_t *)(ptr + aid->di_offset))++;
> -	 *				// mov %r0, 1
> -	 *				// xadd [%rptr + aid->di_offset], %r0
> -	 *      ptr += aid->di_offset + sizeof(uint64_t);
> -	 *				// add %rptr, aid->di_offset +
> -	 *				//	      sizeof(uint64_t)
> -	 */
> -	emit(dlp, BPF_MOV_IMM(BPF_REG_0, 1));
> -	emit(dlp, BPF_XADD_REG(BPF_DW, rptr, aid->di_offset, BPF_REG_0));
> -	emit(dlp, BPF_ALU64_IMM(BPF_ADD, rptr, aid->di_offset + sizeof(uint64_t)));
> -
> -	dt_regset_free(drp, BPF_REG_0);
> -
> -	TRACE_REGSET("            Prep: End  ");
> -
> -	return rptr;
> -}
> -
>  #define DT_CG_AGG_IMPL(aid, sz, dlp, drp, f, ...) \
>  	do {								\
>  		int	dreg;						\
>  									\
>  		TRACE_REGSET("        Upd: Begin ");			\
>  									\
> -		dreg = dt_cg_agg_buf_prepare((aid), (sz), (dlp), (drp));\
> -									\
> +		dreg = dt_cg_pop_stack((dlp), (drp));			\
>  		(f)((dlp), (drp), dreg, ## __VA_ARGS__);		\
>  		dt_regset_free((drp), dreg);				\
>  									\
> @@ -6524,8 +6497,11 @@ dt_cg_agg(dt_pcb_t *pcb, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  	dtrace_hdl_t	*dtp = pcb->pcb_hdl;
>  	dt_ident_t	*aid, *fid;
>  	dt_cg_aggfunc_f	*aggfp;
> -	int		nrecs, off;
> +	int		nrecs, off, tup;
>  	dt_node_t	*d;
> +	dt_ident_t	*zero_off = dt_dlib_get_var(dtp, "ZERO_OFF");
> +	dt_ident_t	*idp;
> +	uint_t		Lgot_agg;
>  
>  	/*
>  	 * If the aggregation has no aggregating function applied to it, then
> @@ -6543,17 +6519,56 @@ dt_cg_agg(dt_pcb_t *pcb, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  		dnerror(dnp->dn_aggfun, D_AGG_SCALAR, "%s( ) argument #1 must "
>  			"be of scalar type\n", fid->di_name);
>  
> -	/* FIXME */
> -	if (dnp->dn_aggtup != NULL)
> -		dnerror(dnp->dn_aggtup, D_ARR_BADREF, "indexing is not "
> -			"supported yet: @%s\n", dnp->dn_ident->di_name);
> -
>  	assert(fid->di_id >= DT_AGG_BASE && fid->di_id < DT_AGG_HIGHEST);
>  
>  	dt_cg_clsflags(pcb, DTRACEACT_AGGREGATION, dnp);
>  	aggfp = _dt_cg_agg[DT_AGG_IDX(fid->di_id)];
>  	assert(aggfp != NULL);
>  
> +	/* generate BPF code for keys (if any) */
> +	tup = dt_cg_arglist(aid, dnp->dn_aggtup, dlp, drp);
> +
> +	/* insert the aggregation var ID in the lead, 4-byte slot */
> +	emit(dlp,  BPF_STORE_IMM(BPF_W, tup, 0, aid->di_id));
> +
> +	/* call dt_get_agg() to get the agg data pointer */
> +
> +	if (dt_regset_xalloc_args(drp) == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +	emit(dlp,  BPF_MOV_REG(BPF_REG_1, tup));
> +	dt_regset_free(drp, tup);
> +	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_2, BPF_REG_FP, DT_STK_DCTX));
> +	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_2, BPF_REG_2, DCTX_GVARS));
> +	emite(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -1), zero_off);
> +
> +	switch (fid->di_id) {
> +	case DT_AGG_MAX:
> +		dt_cg_setx(dlp, BPF_REG_3, INT64_MIN);
> +		break;
> +	case DT_AGG_MIN:
> +		dt_cg_setx(dlp, BPF_REG_3, INT64_MAX);
> +		break;
> +	default:
> +		emit(dlp, BPF_MOV_IMM(BPF_REG_3, 0));
> +		break;
> +	}
> +
> +	dt_regset_xalloc(drp, BPF_REG_0);
> +	idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_agg");
> +	assert(idp != NULL);
> +	emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
> +	dt_regset_free_args(drp);
> +	Lgot_agg = dt_irlist_label(dlp);
> +	emit(dlp,  BPF_BRANCH_IMM(BPF_JNE, BPF_REG_0, 0, Lgot_agg));
> +	dt_cg_probe_error(yypcb, DTRACEFLT_NOAGGS, DT_ISIMM, 0);
> +	emitl(dlp, Lgot_agg,
> +		   BPF_NOP());
> +
> +	/* push agg data pointer onto the stack */
> +
> +	dt_cg_push_stack(dlp, drp, BPF_REG_0);
> +
> +	/* evaluate aggregation */
>  	(*aggfp)(pcb, aid, dnp, dlp, drp);
>  
>  	/* add this agg id if we are seeing it for the first time */
> diff --git a/libdtrace/dt_dctx.h b/libdtrace/dt_dctx.h
> index c93fff2b..fe084d2e 100644
> --- a/libdtrace/dt_dctx.h
> +++ b/libdtrace/dt_dctx.h
> @@ -66,7 +66,6 @@ typedef struct dt_dctx {
>  #define DCTX_MEM	offsetof(dt_dctx_t, mem)
>  #define DCTX_SCRATCHMEM	offsetof(dt_dctx_t, scratchmem)
>  #define DCTX_STRTAB	offsetof(dt_dctx_t, strtab)
> -#define DCTX_AGG	offsetof(dt_dctx_t, agg)
>  #define DCTX_GVARS	offsetof(dt_dctx_t, gvars)
>  #define DCTX_LVARS	offsetof(dt_dctx_t, lvars)
>  
> diff --git a/libdtrace/dt_error.c b/libdtrace/dt_error.c
> index 576b1199..b9e19014 100644
> --- a/libdtrace/dt_error.c
> +++ b/libdtrace/dt_error.c
> @@ -207,6 +207,7 @@ dtrace_faultstr(dtrace_hdl_t *dtp, int fault)
>  		{ DTRACEFLT_TUPOFLOW,	"tuple stack overflow" },
>  		{ DTRACEFLT_BADSTACK,	"bad stack" },
>  		{ DTRACEFLT_BADSIZE,	"invalid size" },
> +		{ DTRACEFLT_NOAGGS,	"out of aggregations space" },
>  		{ DTRACEFLT_LIBRARY,	"library-level fault" },
>  		{ 0,			NULL }
>  	};
> diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
> index be2b0121..85e2b878 100644
> --- a/libdtrace/dt_impl.h
> +++ b/libdtrace/dt_impl.h
> @@ -206,7 +206,7 @@ typedef struct dt_tstring {
>  } dt_tstring_t;
>  
>  typedef struct dt_aggregate {
> -	char **dtat_cpu_buf;		/* per-CPU agg snapshot buffers */
> +	char *dtat_nextkey;		/* buffer for next key */
>  	char *dtat_buf;			/* aggregation snapshot buffer */
>  	int dtat_flags;			/* aggregate flags */
>  	dt_ahash_t dtat_hash;		/* aggregate hash table */
> diff --git a/test/demo/intro/countdown-multiple.d b/test/demo/intro/countdown-multiple.d
> index 03db541e..e98f41ee 100644
> --- a/test/demo/intro/countdown-multiple.d
> +++ b/test/demo/intro/countdown-multiple.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2011, 2022, 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.
>   */
>  
> -/* @@xfail: dtv2 */
>  /* @@trigger: none */
>  
>  /* @@tags: unstable */
> diff --git a/test/demo/intro/countdown-quant.d b/test/demo/intro/countdown-quant.d
> index 2ab29b78..6a4b92a6 100644
> --- a/test/demo/intro/countdown-quant.d
> +++ b/test/demo/intro/countdown-quant.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2011, 2022, 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.
>   */
>  
> -/* @@xfail: dtv2 */
>  /* @@trigger: none */
>  
>  dtrace:::BEGIN
> diff --git a/test/demo/out/printa.d b/test/demo/out/printa.d
> index 28ba2175..ae63cfc6 100644
> --- a/test/demo/out/printa.d
> +++ b/test/demo/out/printa.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2005, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  profile:::tick-997
>  {
> diff --git a/test/demo/script/syscall.d b/test/demo/script/syscall.d
> index 69091aa5..0b73d45b 100644
> --- a/test/demo/script/syscall.d
> +++ b/test/demo/script/syscall.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2005, 2022, 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.
>   */
>  
> -/* @@xfail: dtv2 */
>  /* @@runtest-opts: -c /bin/true */
>  /* @@trigger: none */
>  
> diff --git a/test/demo/user/libc.d b/test/demo/user/libc.d
> index 99e7a51c..dad274b8 100644
> --- a/test/demo/user/libc.d
> +++ b/test/demo/user/libc.d
> @@ -1,11 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2005, 2022, 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.
>   */
>  
> -/* @@xfail: dtv2 */
>  /* @@runtest-opts: -c /usr/bin/date */
>  
>  pid$target:libc.so::entry
> diff --git a/test/stress/buffering/err.resize2.d b/test/stress/buffering/err.resize2.d
> index 277ec6cc..9b408958 100644
> --- a/test/stress/buffering/err.resize2.d
> +++ b/test/stress/buffering/err.resize2.d
> @@ -5,7 +5,6 @@
>   * http://oss.oracle.com/licenses/upl.
>   */
>  /* @@timeout: 500 */
> -/* @@xfail: need support for aggregation keys */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/actions/printa/err.D_PRINTA_AGGKEY.d b/test/unittest/actions/printa/err.D_PRINTA_AGGKEY.d
> index c6014316..23859ebe 100644
> --- a/test/unittest/actions/printa/err.D_PRINTA_AGGKEY.d
> +++ b/test/unittest/actions/printa/err.D_PRINTA_AGGKEY.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2020, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  /*
>   * ASSERTION: printa() requires aggregation arguments to have matching key
>   *	signatures
> diff --git a/test/unittest/actions/printa/err.D_PRINTA_AGGPROTO.d b/test/unittest/actions/printa/err.D_PRINTA_AGGPROTO.d
> index d327a9c5..4be6fb45 100644
> --- a/test/unittest/actions/printa/err.D_PRINTA_AGGPROTO.d
> +++ b/test/unittest/actions/printa/err.D_PRINTA_AGGPROTO.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2020, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  /*
>   * ASSERTION: printa() requires aggregation arguments to have matching key
>   *	signatures (matching key component types)
> diff --git a/test/unittest/aggs/tst.count2.d b/test/unittest/aggs/tst.count2.d
> index b03c5cc2..b59a16b5 100644
> --- a/test/unittest/aggs/tst.count2.d
> +++ b/test/unittest/aggs/tst.count2.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.count3.d b/test/unittest/aggs/tst.count3.d
> index 4595fc74..a1884bac 100644
> --- a/test/unittest/aggs/tst.count3.d
> +++ b/test/unittest/aggs/tst.count3.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.denormalizeonly.d b/test/unittest/aggs/tst.denormalizeonly.d
> index c4e15141..d232f95e 100644
> --- a/test/unittest/aggs/tst.denormalizeonly.d
> +++ b/test/unittest/aggs/tst.denormalizeonly.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.fmtnormalize.d b/test/unittest/aggs/tst.fmtnormalize.d
> index 5b5b4154..a08f7368 100644
> --- a/test/unittest/aggs/tst.fmtnormalize.d
> +++ b/test/unittest/aggs/tst.fmtnormalize.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.forms.d b/test/unittest/aggs/tst.forms.d
> index ef129556..06e3996e 100644
> --- a/test/unittest/aggs/tst.forms.d
> +++ b/test/unittest/aggs/tst.forms.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.keysort.d b/test/unittest/aggs/tst.keysort.d
> index 9c157c3d..a8213bf2 100644
> --- a/test/unittest/aggs/tst.keysort.d
> +++ b/test/unittest/aggs/tst.keysort.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/aggs/tst.lquantize.d b/test/unittest/aggs/tst.lquantize.d
> index e09214a9..e1764238 100644
> --- a/test/unittest/aggs/tst.lquantize.d
> +++ b/test/unittest/aggs/tst.lquantize.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.lquantrange.d b/test/unittest/aggs/tst.lquantrange.d
> index 4b42d566..cd0a3fab 100644
> --- a/test/unittest/aggs/tst.lquantrange.d
> +++ b/test/unittest/aggs/tst.lquantrange.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/aggs/tst.lquantzero.d b/test/unittest/aggs/tst.lquantzero.d
> index 1b869ebb..8f69d9a9 100644
> --- a/test/unittest/aggs/tst.lquantzero.d
> +++ b/test/unittest/aggs/tst.lquantzero.d
> @@ -1,14 +1,12 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> -
>  BEGIN
>  {
>  	a = 7;
> diff --git a/test/unittest/aggs/tst.multiaggs1.d b/test/unittest/aggs/tst.multiaggs1.d
> index 371aa720..c9afd225 100644
> --- a/test/unittest/aggs/tst.multiaggs1.d
> +++ b/test/unittest/aggs/tst.multiaggs1.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.multinormalize.d b/test/unittest/aggs/tst.multinormalize.d
> index 90b8a32d..6abf76c2 100644
> --- a/test/unittest/aggs/tst.multinormalize.d
> +++ b/test/unittest/aggs/tst.multinormalize.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.neglquant.d b/test/unittest/aggs/tst.neglquant.d
> index 6629438b..63e3796b 100644
> --- a/test/unittest/aggs/tst.neglquant.d
> +++ b/test/unittest/aggs/tst.neglquant.d
> @@ -4,7 +4,6 @@
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/aggs/tst.negorder.d b/test/unittest/aggs/tst.negorder.d
> index c6b2bba1..4d5e6386 100644
> --- a/test/unittest/aggs/tst.negorder.d
> +++ b/test/unittest/aggs/tst.negorder.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/aggs/tst.negquant.d b/test/unittest/aggs/tst.negquant.d
> index 78fa96ba..b9dff159 100644
> --- a/test/unittest/aggs/tst.negquant.d
> +++ b/test/unittest/aggs/tst.negquant.d
> @@ -4,7 +4,6 @@
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/aggs/tst.order.d b/test/unittest/aggs/tst.order.d
> index e8a8b469..9777cab6 100644
> --- a/test/unittest/aggs/tst.order.d
> +++ b/test/unittest/aggs/tst.order.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/aggs/tst.quantize.d b/test/unittest/aggs/tst.quantize.d
> index db7b4190..3ae31449 100644
> --- a/test/unittest/aggs/tst.quantize.d
> +++ b/test/unittest/aggs/tst.quantize.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.quantmany.d b/test/unittest/aggs/tst.quantmany.d
> index b58f5326..de7d5635 100644
> --- a/test/unittest/aggs/tst.quantmany.d
> +++ b/test/unittest/aggs/tst.quantmany.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/aggs/tst.quantzero.d b/test/unittest/aggs/tst.quantzero.d
> index 8fc80b41..0b7d9fdf 100644
> --- a/test/unittest/aggs/tst.quantzero.d
> +++ b/test/unittest/aggs/tst.quantzero.d
> @@ -1,14 +1,12 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> -
>  BEGIN
>  {
>  	a = 7;
> diff --git a/test/unittest/aggs/tst.signedkeyspos.d b/test/unittest/aggs/tst.signedkeyspos.d
> index 93803a7e..9530ab5c 100644
> --- a/test/unittest/aggs/tst.signedkeyspos.d
> +++ b/test/unittest/aggs/tst.signedkeyspos.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/aggs/tst.valsortkeypos.d b/test/unittest/aggs/tst.valsortkeypos.d
> index 9f8fe0dd..d1de72b4 100644
> --- a/test/unittest/aggs/tst.valsortkeypos.d
> +++ b/test/unittest/aggs/tst.valsortkeypos.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> diff --git a/test/unittest/funcs/substr/tst.substrminate.d b/test/unittest/funcs/substr/tst.substrminate.d
> index 84aa60c7..573a2076 100644
> --- a/test/unittest/funcs/substr/tst.substrminate.d
> +++ b/test/unittest/funcs/substr/tst.substrminate.d
> @@ -4,7 +4,6 @@
>   * Licensed under the Universal Permissive License v 1.0 as shown at
>   * http://oss.oracle.com/licenses/upl.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  #pragma D option aggsortkey
> diff --git a/test/unittest/grammar/tst.stmts.d b/test/unittest/grammar/tst.stmts.d
> index 18ed60b2..919c3166 100644
> --- a/test/unittest/grammar/tst.stmts.d
> +++ b/test/unittest/grammar/tst.stmts.d
> @@ -1,6 +1,6 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> @@ -13,7 +13,6 @@
>   *
>   */
>  
> -/* @@xfail: dtv2 */
>  /* @@timeout: 25 */
>  
>  BEGIN
> diff --git a/test/unittest/misc/tst.haslam.d b/test/unittest/misc/tst.haslam.d
> index 997d22df..406a9ead 100644
> --- a/test/unittest/misc/tst.haslam.d
> +++ b/test/unittest/misc/tst.haslam.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION: test for off-by-one error in the format lookup code
> diff --git a/test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d b/test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d
> index a5b5c522..a9ea789b 100644
> --- a/test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d
> +++ b/test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d
> @@ -1,10 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
> +
>  #pragma D option quiet
>  
>  BEGIN
> diff --git a/test/unittest/multiaggs/err.D_PRINTA_AGGPROTO.d b/test/unittest/multiaggs/err.D_PRINTA_AGGPROTO.d
> index 238421f4..b8887e81 100644
> --- a/test/unittest/multiaggs/err.D_PRINTA_AGGPROTO.d
> +++ b/test/unittest/multiaggs/err.D_PRINTA_AGGPROTO.d
> @@ -1,10 +1,10 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
> +
>  #pragma D option quiet
>  
>  BEGIN
> diff --git a/test/unittest/multiaggs/tst.many.d b/test/unittest/multiaggs/tst.many.d
> index 5c94d2da..168cca13 100644
> --- a/test/unittest/multiaggs/tst.many.d
> +++ b/test/unittest/multiaggs/tst.many.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option destructive
>  #pragma D option quiet
> diff --git a/test/unittest/multiaggs/tst.sort.d b/test/unittest/multiaggs/tst.sort.d
> index c61e2c1a..f9be92df 100644
> --- a/test/unittest/multiaggs/tst.sort.d
> +++ b/test/unittest/multiaggs/tst.sort.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/multiaggs/tst.sortpos.d b/test/unittest/multiaggs/tst.sortpos.d
> index f6adb378..36763186 100644
> --- a/test/unittest/multiaggs/tst.sortpos.d
> +++ b/test/unittest/multiaggs/tst.sortpos.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/multiaggs/tst.zero.d b/test/unittest/multiaggs/tst.zero.d
> index acfb99e1..197949cd 100644
> --- a/test/unittest/multiaggs/tst.zero.d
> +++ b/test/unittest/multiaggs/tst.zero.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/multiaggs/tst.zero2.d b/test/unittest/multiaggs/tst.zero2.d
> index 28cd4cbf..cba509bc 100644
> --- a/test/unittest/multiaggs/tst.zero2.d
> +++ b/test/unittest/multiaggs/tst.zero2.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/multiaggs/tst.zero3.d b/test/unittest/multiaggs/tst.zero3.d
> index 31b41acc..6dd3763f 100644
> --- a/test/unittest/multiaggs/tst.zero3.d
> +++ b/test/unittest/multiaggs/tst.zero3.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/printa/tst.dynwidth.d b/test/unittest/printa/tst.dynwidth.d
> index 06051ae1..d6039ca3 100644
> --- a/test/unittest/printa/tst.dynwidth.d
> +++ b/test/unittest/printa/tst.dynwidth.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> diff --git a/test/unittest/printa/tst.tuple.d b/test/unittest/printa/tst.tuple.d
> index 4fc05e6a..2996edaa 100644
> --- a/test/unittest/printa/tst.tuple.d
> +++ b/test/unittest/printa/tst.tuple.d
> @@ -1,10 +1,9 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2006, 2022, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  /*
>   * ASSERTION:
> -- 
> 2.18.4
> 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list