Linux-Trace-Devel Archive on lore.kernel.org
 help / color / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: "Yordan Karadzhov (VMware)" <y.karadz@gmail.com>
Cc: linux-trace-devel@vger.kernel.org
Subject: Re: [PATCH v2 13/20] kernel-shark: Complete the stream integration
Date: Wed, 14 Oct 2020 19:52:49 -0400
Message-ID: <20201014195249.16929c28@gandalf.local.home> (raw)
In-Reply-To: <20201012133523.469040-14-y.karadz@gmail.com>


> diff --git a/src/libkshark-tepdata.c b/src/libkshark-tepdata.c
> index 30c383c8..d9d57843 100644
> --- a/src/libkshark-tepdata.c
> +++ b/src/libkshark-tepdata.c
> @@ -318,6 +318,9 @@ static ssize_t get_records(struct kshark_context *kshark_ctx,
>  
>  				pid = entry->pid;
>  
> +				/* Apply Id filtering. */
> +				kshark_apply_filters(kshark_ctx, stream, entry);
> +
>  				/* Apply advanced event filtering. */
>  				if (adv_filter && adv_filter->filters &&
>  				    tep_filter_match(adv_filter, rec) != FILTER_MATCH)
> @@ -1160,6 +1163,43 @@ out:
>  	return peer_handle;
>  }
>  
> +/** A list of built in default plugins for FTRACE (trace-cmd) data. */
> +const char *tep_plugin_names[] = {
> +	"sched_events",
> +	"missed_events",
> +	"kvm_combo",
> +};
> +
> +/**
> + * Register to the data stream all default plugins for FTRACE (trace-cmd) data.
> + */
> +int kshark_tep_handle_plugins(struct kshark_context *kshark_ctx, int sd)
> +{
> +	int i, n_tep_plugins = sizeof(tep_plugin_names) / sizeof (const char *);


Note, a safer way is:

	n_tep_plugins = sizeof(tep_plugins_names) / sizeof(tep_plugin_names[0]);

Or use the ARRAY_SIZE() macro from trace-cmd.git/include/trace-cmd/trace-cmd.h:

#define ARRAY_SIZE(_a) (sizeof(_a) / sizeof((_a)[0]))

	n_tep_plugins = ARRAY_SIZE(tep_plugins_names);

  ;-)


> +	struct kshark_plugin_list *plugin;
> +	struct kshark_data_stream *stream;
> +
> +	stream = kshark_get_data_stream(kshark_ctx, sd);
> +	if (!stream)
> +		return -EEXIST;
> +
> +	for (i = 0; i < n_tep_plugins; ++i) {
> +		plugin = kshark_find_plugin_by_name(kshark_ctx->plugins,
> +						    tep_plugin_names[i]);
> +
> +		if (plugin && plugin->process_interface) {
> +			kshark_register_plugin_to_stream(stream,
> +							 plugin->process_interface,
> +							 true);
> +		} else {
> +			fprintf(stderr, "Plugin \"%s\" not found.\n",
> +				tep_plugin_names[i]);
> +		}
> +	}
> +
> +	return kshark_handle_all_dpis(stream, KSHARK_PLUGIN_INIT);
> +}
> +
>  /** The Process Id of the Idle tasks is zero. */
>  #define LINUX_IDLE_TASK_PID	0
>  
> @@ -1210,6 +1250,172 @@ static int kshark_tep_stream_init(struct kshark_data_stream *stream,
>  	return -EFAULT;
>  }
>  
> +static struct tracecmd_input *get_top_input(struct kshark_context *kshark_ctx,
> +					    int sd)
> +{
> +	struct kshark_data_stream *top_stream;
> +
> +	top_stream = kshark_get_data_stream(kshark_ctx, sd);
> +	if (!top_stream)
> +		return NULL;
> +
> +	return kshark_get_tep_input(top_stream);
> +}
> +
> +/**
> + * @brief Get an array containing the names of all buffers in FTRACE data
> + *	  file.
> + *
> + * @param kshark_ctx: Input location for context pointer.
> + * @param sd: Data stream identifier of the top buffers in the FTRACE data
> + *	  file.
> + * @param n_buffers: Output location for the size of the outputted array,
> + *	    or a negative error code on failure.
> + *
> + * @returns Array of strings on success, or NULL on failure. The user is
> + *	    responsible for freeing the elements of the outputted array.
> + */
> +char **kshark_tep_get_buffer_names(struct kshark_context *kshark_ctx, int sd,
> +				   int *n_buffers)
> +{
> +	struct tracecmd_input *top_input;
> +	char **buffer_names;
> +	int i, n;
> +
> +	top_input = get_top_input(kshark_ctx, sd);
> +	if (!top_input) {
> +		*n_buffers = -EFAULT;
> +		return NULL;
> +	}
> +
> +	n = tracecmd_buffer_instances(top_input);
> +	buffer_names = malloc(n * sizeof(char *));

Need to check buffer_names.

> +
> +	for (i = 0; i < n; ++i)
> +		buffer_names[i] =
> +			strdup(tracecmd_buffer_instance_name(top_input, i));
> +

And each buffer_names[i].

> +	*n_buffers = n;
> +	return buffer_names;
> +}
> +
> +static void set_stream_fields(struct tracecmd_input *top_input, int i,
> +			      const char *file,
> +			      const char *name,
> +			      struct kshark_data_stream *buffer_stream,
> +			      struct tracecmd_input **buffer_input)
> +{
> +	*buffer_input = tracecmd_buffer_instance_handle(top_input, i);
> +
> +	buffer_stream->name = strdup(name);
> +	buffer_stream->file = strdup(file);

And the ->name and ->file.

> +	buffer_stream->format = KS_TEP_DATA;
> +}
> +
> +/**
> + * @brief Open a given buffers in FTRACE (trace-cmd) data file.
> + *
> + * @param kshark_ctx: Input location for context pointer.
> + * @param sd: Data stream identifier of the top buffers in the FTRACE data
> + *	  file.
> + * @param buffer_name: The name of the buffer to open.
> + *
> + * @returns Data stream identifier of the buffer on success. Otherwise a
> + *	    negative error code.
> + */
> +int kshark_tep_open_buffer(struct kshark_context *kshark_ctx, int sd,
> +			   const char *buffer_name)
> +{
> +	struct kshark_data_stream *top_stream, *buffer_stream;
> +	struct tracecmd_input *top_input, *buffer_input;
> +	int i, sd_buffer, n_buffers, ret = -ENODATA;
> +	char **names;
> +
> +	top_stream = kshark_get_data_stream(kshark_ctx, sd);
> +	if (!top_stream)
> +		return -EFAULT;
> +
> +	top_input = kshark_get_tep_input(top_stream);
> +	if (!top_input)
> +		return -EFAULT;
> +
> +	names = kshark_tep_get_buffer_names(kshark_ctx, sd, &n_buffers);
> +
> +	sd_buffer = kshark_add_stream(kshark_ctx);
> +	buffer_stream = kshark_get_data_stream(kshark_ctx, sd_buffer);
> +	if (!buffer_stream)
> +		return -EFAULT;
> +
> +	for (i = 0; i < n_buffers; ++i) {
> +		if (strcmp(buffer_name, names[i]) == 0) {
> +			set_stream_fields(top_input, i,
> +					  top_stream->file,
> +					  buffer_name,
> +					  buffer_stream,
> +					  &buffer_input);
> +
> +			ret = kshark_tep_stream_init(buffer_stream,
> +						     buffer_input);
> +			break;
> +		}
> +	}
> +
> +	for (i = 0; i < n_buffers; ++i)
> +		free(names[i]);
> +	free(names);
> +
> +	return (ret < 0)? ret : buffer_stream->stream_id;
> +}
> +
> +/**
> + * @brief Initialize data streams for all buffers in a FTRACE (trace-cmd) data
> + *	  file.
> + *
> + * @param kshark_ctx: Input location for context pointer.
> + * @param sd: Data stream identifier of the top buffers in the FTRACE data
> + *	  file.
> + *
> + * @returns The total number of data streams initialized on success. Otherwise
> + *	    a negative error code.
> + */
> +int kshark_tep_init_all_buffers(struct kshark_context *kshark_ctx,
> +				int sd)
> +{
> +	struct kshark_data_stream *top_stream, *buffer_stream;
> +	struct tracecmd_input *buffer_input;
> +	struct tracecmd_input *top_input;
> +	int i, n_buffers, sd_buffer, ret;
> +
> +	top_stream = kshark_get_data_stream(kshark_ctx, sd);
> +	if (!top_stream)
> +		return -EFAULT;
> +
> +	top_input = kshark_get_tep_input(top_stream);
> +	if (!top_input)
> +		return -EFAULT;
> +
> +	n_buffers = tracecmd_buffer_instances(top_input);
> +	for (i = 0; i < n_buffers; ++i) {
> +		sd_buffer = kshark_add_stream(kshark_ctx);
> +		if (sd_buffer < 0)
> +			return -EFAULT;
> +
> +		buffer_stream = kshark_ctx->stream[sd_buffer];
> +
> +		set_stream_fields(top_input, i,
> +				  top_stream->file,
> +				  tracecmd_buffer_instance_name(top_input, i),
> +				  buffer_stream,
> +				  &buffer_input);
> +
> +		ret = kshark_tep_stream_init(buffer_stream, buffer_input);
> +		if (ret != 0)
> +			return -EFAULT;
> +	}
> +
> +	return n_buffers;
> +}
> +
>  /** Initialize the FTRACE data input (from file). */
>  int kshark_tep_init_input(struct kshark_data_stream *stream,
>  			  const char *file)
> @@ -1389,3 +1595,149 @@ char **kshark_tracecmd_local_plugins()
>  {
>  	return tracefs_tracers(tracefs_get_tracing_dir());
>  }
> +
> +/**
> + * @brief Free an array, allocated by kshark_tracecmd_get_hostguest_mapping() API
> + *
> + *
> + * @param map: Array, allocated by kshark_tracecmd_get_hostguest_mapping() API
> + * @param count: Number of entries in the array
> + *
> + */
> +void kshark_tracecmd_free_hostguest_map(struct kshark_host_guest_map *map, int count)
> +{
> +	int i;
> +
> +	if (!map)
> +		return;
> +	for (i = 0; i < count; i++) {
> +		free(map[i].guest_name);
> +		free(map[i].cpu_pid);
> +		memset(&map[i], 0, sizeof(*map));
> +	}
> +	free(map);
> +}
> +
> +/**
> + * @brief Get mapping of guest VCPU to host task, running that VCPU.
> + *	  Array of mappings for each guest is allocated and returned
> + *	  in map input parameter.
> + *
> + *
> + * @param map: Returns allocated array of kshark_host_guest_map structures, each
> + *	       one describing VCPUs mapping of one guest.
> + *
> + * @return The number of entries in the *map array, or a negative error code on
> + *	   failure.
> + */
> +int kshark_tracecmd_get_hostguest_mapping(struct kshark_host_guest_map **map)
> +{
> +	struct kshark_host_guest_map *gmap = NULL;
> +	struct tracecmd_input *peer_handle = NULL;
> +	struct kshark_data_stream *peer_stream;
> +	struct tracecmd_input *guest_handle = NULL;
> +	struct kshark_data_stream *guest_stream;
> +	struct kshark_context *kshark_ctx = NULL;
> +	unsigned long long trace_id;
> +	const char *name;
> +	int vcpu_count;
> +	const int *cpu_pid;
> +	int *stream_ids;
> +	int i, j, k;
> +	int count = 0;
> +	int ret;
> +
> +	if (!map || !kshark_instance(&kshark_ctx))
> +		return -EFAULT;
> +	if (*map)
> +		return -EEXIST;
> +
> +	stream_ids = kshark_all_streams(kshark_ctx);
> +	for (i = 0; i < kshark_ctx->n_streams; i++) {
> +		guest_stream = kshark_get_data_stream(kshark_ctx, stream_ids[i]);
> +		if (!guest_stream || guest_stream->format != KS_TEP_DATA)
> +			continue;
> +		guest_handle = kshark_get_tep_input(guest_stream);
> +		if (!guest_handle)
> +			continue;
> +		trace_id = tracecmd_get_traceid(guest_handle);
> +		if (!trace_id)
> +			continue;
> +		for (j = 0; j < kshark_ctx->n_streams; j++) {
> +			if (stream_ids[i] == stream_ids[j])
> +				continue;
> +			peer_stream = kshark_get_data_stream(kshark_ctx, stream_ids[j]);
> +			if (!peer_stream || peer_stream->format != KS_TEP_DATA)
> +				continue;
> +			peer_handle = kshark_get_tep_input(peer_stream);
> +			if (!peer_handle)
> +				continue;
> +			ret = tracecmd_get_guest_cpumap(peer_handle, trace_id,
> +							&name, &vcpu_count, &cpu_pid);
> +			if (!ret && vcpu_count) {
> +				gmap = realloc(*map,
> +					       (count + 1) * sizeof(struct kshark_host_guest_map));
> +				if (!gmap)
> +					goto mem_error;
> +				*map = gmap;
> +				memset(&gmap[count], 0, sizeof(struct kshark_host_guest_map));
> +				count++;
> +				gmap[count - 1].guest_id = stream_ids[i];
> +				gmap[count - 1].host_id = stream_ids[j];
> +				gmap[count - 1].guest_name = strdup(name);
> +				if (!gmap[count - 1].guest_name)
> +					goto mem_error;
> +				gmap[count - 1].vcpu_count = vcpu_count;
> +				gmap[count - 1].cpu_pid = malloc(sizeof(int) * vcpu_count);
> +				if (!gmap[count - 1].cpu_pid)
> +					goto mem_error;
> +				for (k = 0; k < vcpu_count; k++)
> +					gmap[count - 1].cpu_pid[k] = cpu_pid[k];
> +				break;
> +			}
> +		}
> +	}
> +
> +	free(stream_ids);
> +	return count;
> +
> +mem_error:
> +	free(stream_ids);
> +	if (*map) {
> +		kshark_tracecmd_free_hostguest_map(*map, count);
> +		*map = NULL;
> +	}
> +
> +	return -ENOMEM;
> +}
> +
> +/**
> + * @brief Find the data stream corresponding the top buffer of a FTRACE
> + *	  (trace-cmd) data file.
> + *
> + * @param kshark_ctx: Input location for context pointer.
> + * @param file: The name of the file.
> + *
> + * @returns Data stream identifier of the top buffers in the FTRACE data
> + *	    fileon success. Otherwise a negative error code.
> + */
> +int kshark_tep_find_top_stream(struct kshark_context *kshark_ctx,
> +			       const char *file)
> +{
> +	struct kshark_data_stream *top_stream = NULL, *stream;
> +	int i, *stream_ids = kshark_all_streams(kshark_ctx);
> +
> +	for (i = 0; i < kshark_ctx->n_streams; ++i) {
> +		stream = kshark_ctx->stream[stream_ids[i]];
> +		if (strcmp(stream->file, file) == 0 &&
> +		    strcmp(stream->name, "top") == 0)

I noticed that you hardcode the top_stream name as "top". A couple of
comments. One, good software practice is not to have any open constants.
That is, always use a macro, as it makes it easier to go global changes
later on. Also, don't call it "top". What happens if I make an instance
called "top". Will it confuse this?

Maybe make it a non printable character:

const char top_name[] = { 0x1b, 0x00 }; // Non printable character
#define TOP_NAME	(char *)&top_name

Or something like this.


> +			top_stream = stream;
> +	}
> +
> +	free(stream_ids);
> +
> +	if (!top_stream)
> +		return -EEXIST;
> +
> +	return top_stream->stream_id;
> +}
> diff --git a/src/libkshark-tepdata.h b/src/libkshark-tepdata.h
> index a2bd211e..b6c9439e 100644
> --- a/src/libkshark-tepdata.h
> +++ b/src/libkshark-tepdata.h
> @@ -41,9 +41,58 @@ void kshark_tep_filter_reset(struct kshark_data_stream *stream);
>  
>  char **kshark_tracecmd_local_plugins();
>  
> +struct tep_handle;
> +
> +struct tep_handle *kshark_get_tep(struct kshark_data_stream *stream);
> +
> +struct tracecmd_input;
> +
> +struct tracecmd_input *kshark_get_tep_input(struct kshark_data_stream *stream);
> +
> +struct tep_record;
> +
>  ssize_t kshark_load_tep_records(struct kshark_context *kshark_ctx, int sd,
>  				struct tep_record ***data_rows);
>  
> +/**
> + * Structure representing the mapping between the virtual CPUs and their
> + * corresponding processes in the host.
> + */
> +struct kshark_host_guest_map {
> +	/** ID of guest stream */
> +	int guest_id;
> +
> +	/** ID of host stream */
> +	int host_id;
> +
> +	/** Guest name */
> +	char *guest_name;
> +
> +	/** Number of guest's CPUs in *cpu_pid array */
> +	int vcpu_count;
> +
> +	/** Array of host task PIDs, index is the VCPU id */
> +	int *cpu_pid;
> +};
> +
> +void kshark_tracecmd_free_hostguest_map(struct kshark_host_guest_map *map,
> +					int count);
> +
> +int kshark_tracecmd_get_hostguest_mapping(struct kshark_host_guest_map **map);
> +
> +char **kshark_tep_get_buffer_names(struct kshark_context *kshark_ctx, int sd,
> +				   int *n_buffers);
> +
> +int kshark_tep_open_buffer(struct kshark_context *kshark_ctx, int sd,
> +			   const char *buffer_name);
> +
> +int kshark_tep_init_all_buffers(struct kshark_context *kshark_ctx, int sd);
> +
> +int kshark_tep_handle_plugins(struct kshark_context *kshark_ctx, int sd);
> +
> +int kshark_tep_find_top_stream(struct kshark_context *kshark_ctx,
> +			       const char *file);
> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/src/libkshark.c b/src/libkshark.c
> index bd2e4cc0..6ce7b6ba 100644
> --- a/src/libkshark.c
> +++ b/src/libkshark.c
> @@ -1,7 +1,7 @@
>  // SPDX-License-Identifier: LGPL-2.1
>  
>  /*
> - * Copyright (C) 2017 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
> + * Copyright (C) 2017 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
>   */
>  
>   /**
> @@ -9,8 +9,10 @@
>   *  @brief   API for processing of tracing data.
>   */
>  
> +#ifndef _GNU_SOURCE
>  /** Use GNU C Library. */
> -#define _GNU_SOURCE 1
> +#define _GNU_SOURCE
> +#endif // _GNU_SOURCE
>  
>  // C
>  #include <stdlib.h>
> @@ -36,16 +38,6 @@ static bool kshark_default_context(struct kshark_context **context)
>  				    sizeof(*kshark_ctx->stream));
>  
>  	kshark_ctx->collections = NULL;
> -	kshark_ctx->plugins = NULL;
> -
> -	kshark_ctx->show_task_filter = tracecmd_filter_id_hash_alloc();
> -	kshark_ctx->hide_task_filter = tracecmd_filter_id_hash_alloc();
> -
> -	kshark_ctx->show_event_filter = tracecmd_filter_id_hash_alloc();
> -	kshark_ctx->hide_event_filter = tracecmd_filter_id_hash_alloc();
> -
> -	kshark_ctx->show_cpu_filter = tracecmd_filter_id_hash_alloc();
> -	kshark_ctx->hide_cpu_filter = tracecmd_filter_id_hash_alloc();
>  
>  	kshark_ctx->filter_mask = 0x0;
>  
> @@ -386,6 +378,12 @@ void kshark_close(struct kshark_context *kshark_ctx, int sd)
>  	if (!stream)
>  		return;
>  
> +	/*
> +	 * All data collections are file specific. Make sure that collections
> +	 * from this file are not going to be used with another file.
> +	 */
> +	kshark_unregister_stream_collections(&kshark_ctx->collections, sd);
> +
>  	/* Close all active plugins for this stream. */
>  	if (stream->plugins) {
>  		kshark_handle_all_dpis(stream, KSHARK_PLUGIN_CLOSE);
> @@ -530,103 +528,134 @@ ssize_t kshark_get_task_pids(struct kshark_context *kshark_ctx, int sd,
>  	return stream->tasks->count;
>  }
>  
> -static bool filter_find(struct tracecmd_filter_id *filter, int pid,
> +static bool filter_find(struct kshark_hash_id *filter, int pid,
>  			bool test)
>  {
>  	return !filter || !filter->count ||
> -		!!(unsigned long)tracecmd_filter_id_find(filter, pid) == test;
> +	       kshark_hash_id_find(filter, pid) == test;
>  }
>  
> -static bool kshark_show_task(struct kshark_context *kshark_ctx, int pid)
> +static bool kshark_show_task(struct kshark_data_stream *stream, int pid)
>  {
> -	return filter_find(kshark_ctx->show_task_filter, pid, true) &&
> -	       filter_find(kshark_ctx->hide_task_filter, pid, false);
> +	return filter_find(stream->show_task_filter, pid, true) &&
> +	       filter_find(stream->hide_task_filter, pid, false);
>  }
>  
> -static bool kshark_show_event(struct kshark_context *kshark_ctx, int pid)
> +static bool kshark_show_event(struct kshark_data_stream *stream, int pid)
>  {
> -	return filter_find(kshark_ctx->show_event_filter, pid, true) &&
> -	       filter_find(kshark_ctx->hide_event_filter, pid, false);
> +	return filter_find(stream->show_event_filter, pid, true) &&
> +	       filter_find(stream->hide_event_filter, pid, false);
>  }
>  
> -static bool kshark_show_cpu(struct kshark_context *kshark_ctx, int cpu)
> +static bool kshark_show_cpu(struct kshark_data_stream *stream, int cpu)
>  {
> -	return filter_find(kshark_ctx->show_cpu_filter, cpu, true) &&
> -	       filter_find(kshark_ctx->hide_cpu_filter, cpu, false);
> +	return filter_find(stream->show_cpu_filter, cpu, true) &&
> +	       filter_find(stream->hide_cpu_filter, cpu, false);
> +}
> +
> +static struct kshark_hash_id *get_filter(struct kshark_context *kshark_ctx,
> +					 int sd,
> +					 enum kshark_filter_type filter_id)
> +{
> +	struct kshark_data_stream *stream;
> +
> +	stream = kshark_get_data_stream(kshark_ctx, sd);
> +	if (!stream)
> +		return NULL;
> +
> +	return kshark_get_filter(stream, filter_id);
>  }
>  
>  /**
> - * @brief Add an Id value to the filster specified by "filter_id".
> + * @brief Get an Id Filter.
> + *
> + * @param stream: Input location for a Trace data stream pointer.
> + * @param filter_id: Identifier of the filter.
> + */
> +struct kshark_hash_id *
> +kshark_get_filter(struct kshark_data_stream *stream,
> +		  enum kshark_filter_type filter_id)
> +{
> +	switch (filter_id) {
> +	case KS_SHOW_CPU_FILTER:
> +		return stream->show_cpu_filter;
> +	case KS_HIDE_CPU_FILTER:
> +		return stream->hide_cpu_filter;
> +	case KS_SHOW_EVENT_FILTER:
> +		return stream->show_event_filter;
> +	case KS_HIDE_EVENT_FILTER:
> +		return stream->hide_event_filter;
> +	case KS_SHOW_TASK_FILTER:
> +		return stream->show_task_filter;
> +	case KS_HIDE_TASK_FILTER:
> +		return stream->hide_task_filter;
> +	default:
> +		return NULL;
> +	}
> +}
> +
> +/**
> + * @brief Add an Id value to the filter specified by "filter_id".
>   *
>   * @param kshark_ctx: Input location for the session context pointer.
> + * @param sd: Data stream identifier.
>   * @param filter_id: Identifier of the filter.
>   * @param id: Id value to be added to the filter.
>   */
> -void kshark_filter_add_id(struct kshark_context *kshark_ctx,
> +void kshark_filter_add_id(struct kshark_context *kshark_ctx, int sd,
>  			  int filter_id, int id)
>  {
> -	struct tracecmd_filter_id *filter;
> +	struct kshark_hash_id *filter;
>  
> -	switch (filter_id) {
> -		case KS_SHOW_CPU_FILTER:
> -			filter = kshark_ctx->show_cpu_filter;
> -			break;
> -		case KS_HIDE_CPU_FILTER:
> -			filter = kshark_ctx->hide_cpu_filter;
> -			break;
> -		case KS_SHOW_EVENT_FILTER:
> -			filter = kshark_ctx->show_event_filter;
> -			break;
> -		case KS_HIDE_EVENT_FILTER:
> -			filter = kshark_ctx->hide_event_filter;
> -			break;
> -		case KS_SHOW_TASK_FILTER:
> -			filter = kshark_ctx->show_task_filter;
> -			break;
> -		case KS_HIDE_TASK_FILTER:
> -			filter = kshark_ctx->hide_task_filter;
> -			break;
> -		default:
> -			return;
> +	filter = get_filter(kshark_ctx, sd, filter_id);
> +	if (filter)
> +		kshark_hash_id_add(filter, id);
> +}
> +
> +/**
> + * @brief Get an array containing all Ids associated with a given Id Filter.
> + *
> + * @param kshark_ctx: Input location for context pointer.
> + * @param sd: Data stream identifier.
> + * @param filter_id: Identifier of the filter.
> + * @param n: Output location for the size of the returned array.
> + *
> + * @return The user is responsible for freeing the array.
> + */
> +int *kshark_get_filter_ids(struct kshark_context *kshark_ctx, int sd,
> +			   int filter_id, int *n)
> +{
> +	struct kshark_hash_id *filter;
> +
> +	filter = get_filter(kshark_ctx, sd, filter_id);
> +	if (filter) {
> +		if (n)
> +			*n = filter->count;
> +
> +		return kshark_hash_ids(filter);
>  	}
>  
> -	tracecmd_filter_id_add(filter, id);
> +	if (n)
> +		*n = 0;
> +
> +	return NULL;
>  }
>  
>  /**
> - * @brief Clear (reset) the filster specified by "filter_id".
> + * @brief Clear (reset) the filter specified by "filter_id".
>   *
>   * @param kshark_ctx: Input location for the session context pointer.
> + * @param sd: Data stream identifier.
>   * @param filter_id: Identifier of the filter.
>   */
> -void kshark_filter_clear(struct kshark_context *kshark_ctx, int filter_id)
> +void kshark_filter_clear(struct kshark_context *kshark_ctx, int sd,
> +			 int filter_id)
>  {
> -	struct tracecmd_filter_id *filter;
> -
> -	switch (filter_id) {
> -		case KS_SHOW_CPU_FILTER:
> -			filter = kshark_ctx->show_cpu_filter;
> -			break;
> -		case KS_HIDE_CPU_FILTER:
> -			filter = kshark_ctx->hide_cpu_filter;
> -			break;
> -		case KS_SHOW_EVENT_FILTER:
> -			filter = kshark_ctx->show_event_filter;
> -			break;
> -		case KS_HIDE_EVENT_FILTER:
> -			filter = kshark_ctx->hide_event_filter;
> -			break;
> -		case KS_SHOW_TASK_FILTER:
> -			filter = kshark_ctx->show_task_filter;
> -			break;
> -		case KS_HIDE_TASK_FILTER:
> -			filter = kshark_ctx->hide_task_filter;
> -			break;
> -		default:
> -			return;
> -	}
> +	struct kshark_hash_id *filter;
>  
> -	tracecmd_filter_id_clear(filter);
> +	filter = get_filter(kshark_ctx, sd, filter_id);
> +	if (filter)
> +		kshark_hash_id_clear(filter);
>  }
>  
>  /**
> @@ -636,7 +665,7 @@ void kshark_filter_clear(struct kshark_context *kshark_ctx, int filter_id)
>   *
>   * @returns True if the Id filter is set, otherwise False.
>   */
> -bool kshark_this_filter_is_set(struct tracecmd_filter_id *filter)
> +bool kshark_this_filter_is_set(struct kshark_hash_id *filter)
>  {
>  	return filter && filter->count;
>  }
> @@ -645,17 +674,49 @@ bool kshark_this_filter_is_set(struct tracecmd_filter_id *filter)
>   * @brief Check if an Id filter is set.
>   *
>   * @param kshark_ctx: Input location for the session context pointer.
> + * @param sd: Data stream identifier.
>   *
> - * @returns True if at least one Id filter is set, otherwise False.
> + * @returns True if at least one Id filter of the stream is set, otherwise
> + *	    False.
>   */
> -bool kshark_filter_is_set(struct kshark_context *kshark_ctx)
> +bool kshark_filter_is_set(struct kshark_context *kshark_ctx, int sd)
>  {
> -	return kshark_this_filter_is_set(kshark_ctx->show_task_filter) ||
> --              kshark_this_filter_is_set(kshark_ctx->hide_task_filter) ||
> --              kshark_this_filter_is_set(kshark_ctx->show_cpu_filter) ||
> --              kshark_this_filter_is_set(kshark_ctx->hide_cpu_filter) ||
> --              kshark_this_filter_is_set(kshark_ctx->show_event_filter) ||
> --              kshark_this_filter_is_set(kshark_ctx->hide_event_filter);
> +	struct kshark_data_stream *stream;
> +
> +	stream = kshark_get_data_stream(kshark_ctx, sd);
> +	if (!stream)
> +		return false;
> +
> +	return kshark_this_filter_is_set(stream->show_task_filter) ||
> +	       kshark_this_filter_is_set(stream->hide_task_filter)  ||
> +	       kshark_this_filter_is_set(stream->show_cpu_filter)   ||
> +	       kshark_this_filter_is_set(stream->hide_cpu_filter)   ||
> +	       kshark_this_filter_is_set(stream->show_event_filter) ||
> +	       kshark_this_filter_is_set(stream->hide_event_filter);
> +}
> +
> +/**
> + * @brief Apply filters to a given entry.
> + *
> + * @param kshark_ctx: Input location for the session context pointer.
> + * @param stream: Input location for a Trace data stream pointer.
> + * @param entry: Input location for entry.
> + */
> +void kshark_apply_filters(struct kshark_context *kshark_ctx,
> +			  struct kshark_data_stream *stream,
> +			  struct kshark_entry *entry)
> +{
> +	/* Apply event filtering. */
> +	if (!kshark_show_event(stream, entry->event_id))
> +		unset_event_filter_flag(kshark_ctx, entry);
> +
> +	/* Apply CPU filtering. */
> +	if (!kshark_show_cpu(stream, entry->cpu))
> +		entry->visible &= ~kshark_ctx->filter_mask;
> +
> +	/* Apply task filtering. */
> +	if (!kshark_show_task(stream, entry->pid))
> +		entry->visible &= ~kshark_ctx->filter_mask;
>  }
>  
>  static void set_all_visible(uint8_t *v) {
> @@ -663,56 +724,100 @@ static void set_all_visible(uint8_t *v) {
>  	*v |= 0xFF & ~KS_PLUGIN_UNTOUCHED_MASK;
>  }
>  
> +static void filter_entries(struct kshark_context *kshark_ctx, int sd,
> +			   struct kshark_entry **data, size_t n_entries)
> +{
> +	struct kshark_data_stream *stream = NULL;
> +	size_t i;
> +
> +	/* Sanity checks before starting. */
> +	if (sd >= 0) {
> +		/* We will filter particular Data stream. */
> +		stream = kshark_get_data_stream(kshark_ctx, sd);
> +		if (!stream)
> +			return;
> +
> +		if (stream->format == KS_TEP_DATA &&
> +		    kshark_tep_filter_is_set(stream)) {
> +			/* The advanced filter is set. */
> +			fprintf(stderr,
> +				"Failed to filter (sd = %i)!\n", sd);
> +			fprintf(stderr,
> +				"Reset the Advanced filter or reload the data.\n");
> +
> +			return;
> +		}
> +
> +		if (!kshark_filter_is_set(kshark_ctx, sd))
> +			return;
> +	}
> +
> +	/* Apply only the Id filters. */
> +	for (i = 0; i < n_entries; ++i) {
> +		if (sd >= 0) {
> +			/*
> +			 * We only filter particular stream. Chack is the entry
> +			 * belongs to this stream.
> +			 */
> +			if (data[i]->stream_id != sd)
> +				continue;
> +		} else {
> +			/* We filter all streams. */
> +			stream = kshark_ctx->stream[data[i]->stream_id];

Like we have discussed, we should be able to get a stream from the
kshark_ctx and the content of data[i], if we make data[i] point to a
pointer to an entry.

-- Steve


> +		}
> +
> +		/* Start with and entry which is visible everywhere. */
> +		set_all_visible(&data[i]->visible);
> +
> +		/* Apply Id filtering. */
> +		kshark_apply_filters(kshark_ctx, stream, data[i]);
> +	}
> +}
> +

  reply index

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-12 13:35 [PATCH v2 00/20] Start KernelShark v2 transformation Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 01/20] kernel-shark: Start introducing KernelShark 2.0 Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 02/20] kernel-shark: Use only signed types in kshark_entry Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 03/20] kernel-shark: Introduce libkshark-hash Yordan Karadzhov (VMware)
2020-10-12 14:05   ` Steven Rostedt
2020-10-12 14:05     ` Steven Rostedt
2020-10-12 14:18       ` Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 04/20] kernel-shark: Introduce Data streams Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 05/20] kernel-shark: Add stream_id to kshark_entry Yordan Karadzhov (VMware)
2020-10-13  0:05   ` Steven Rostedt
2020-10-29 10:08     ` Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 06/20] kernel-shark: Rename static methods in libkshark Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 07/20] kernel-shark: Add basic methods for Data streams Yordan Karadzhov (VMware)
2020-10-13  0:18   ` Steven Rostedt
2020-10-29 10:10     ` Yordan Karadzhov (VMware)
2020-10-29 14:04       ` Steven Rostedt
2020-10-29 14:49         ` Yordan Karadzhov (VMware)
2020-10-30  1:57           ` Steven Rostedt
2020-11-03 13:38             ` Yordan Karadzhov (VMware)
2020-11-04 15:41               ` Steven Rostedt
2020-11-05 14:35                 ` Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 08/20] kernel-shark: Housekeeping before implementing stream interface Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 09/20] kernel-shark: Add stream interface for trace-cmd data Yordan Karadzhov (VMware)
2020-10-13  0:44   ` Steven Rostedt
2020-10-29 11:16     ` Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 10/20] kernel-shark: Start using data streams Yordan Karadzhov (VMware)
2020-10-14 18:56   ` Steven Rostedt
2020-11-05 14:58     ` Yordan Karadzhov (VMware)
2020-11-05 18:17       ` Steven Rostedt
2020-11-06 14:31         ` Yordan Karadzhov (VMware)
2020-11-06 15:18           ` Steven Rostedt
2020-11-09 14:49             ` Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 11/20] kernel-shark: Remove dead code Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 12/20] kernel-shark: Redesign the plugin interface Yordan Karadzhov (VMware)
2020-10-14 21:09   ` Steven Rostedt
2020-10-12 13:35 ` [PATCH v2 13/20] kernel-shark: Complete the stream integration Yordan Karadzhov (VMware)
2020-10-14 23:52   ` Steven Rostedt [this message]
2020-10-12 13:35 ` [PATCH v2 14/20] kernel-shark: Provide merging of multiple data streams Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 15/20] kernel-shark: Integrate the stream definitions with data model Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 16/20] kernel-shark: Use only signed types for model defs Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 17/20] kernel-shark: Add ksmodel_get_bin() Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 18/20] kernel-shark: Protect ksmodel_set_in_range_bining() Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 19/20] kernel-shark: Add methods for time calibration Yordan Karadzhov (VMware)
2020-10-12 13:35 ` [PATCH v2 20/20] kernel-shark: Integrate streams with libkshark-configio Yordan Karadzhov (VMware)
2020-11-05 19:22   ` Steven Rostedt
2020-11-09 14:55     ` Yordan Karadzhov (VMware)
2020-11-09 15:28       ` Steven Rostedt

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=20201014195249.16929c28@gandalf.local.home \
    --to=rostedt@goodmis.org \
    --cc=linux-trace-devel@vger.kernel.org \
    --cc=y.karadz@gmail.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

Linux-Trace-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-trace-devel/0 linux-trace-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-trace-devel linux-trace-devel/ https://lore.kernel.org/linux-trace-devel \
		linux-trace-devel@vger.kernel.org
	public-inbox-index linux-trace-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-trace-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git