tools/perf/builtin-inject.c

Source file repositories/reference/linux-study-clean/tools/perf/builtin-inject.c

File Facts

System
Linux kernel
Corpus path
tools/perf/builtin-inject.c
Extension
.c
Size
76394 bytes
Lines
2801
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

gs->tool.context_switch	= guest_session__repipe;
	gs->tool.ksymbol	= guest_session__ksymbol_event;
	gs->tool.text_poke	= guest_session__repipe;
	/*
	 * Processing a build ID creates a struct dso with that build ID. Later,
	 * all guest dsos are iterated and the build IDs processed into the host
	 * session where they will be output to the Build ID feature section
	 * when the perf.data file header is written.
	 */
	gs->tool.build_id	= perf_event__process_build_id;
	/* Process the id index to know what VCPU an ID belongs to */
	gs->tool.id_index	= perf_event__process_id_index;

	gs->tool.ordered_events	= true;
	gs->tool.ordering_requires_timestamps = true;

	gs->data.path	= name;
	gs->data.force	= force;
	gs->data.mode	= PERF_DATA_MODE_READ;

	session = perf_session__new(&gs->data, &gs->tool);
	if (IS_ERR(session))
		return PTR_ERR(session);
	gs->session = session;

	/*
	 * Initial events have zero'd ID samples. Get default ID sample size
	 * used for removing them.
	 */
	gs->dflt_id_hdr_size = session->machines.host.id_hdr_size;
	/* And default ID for adding back a host-compatible ID sample */
	gs->dflt_id = evlist__first_id(session->evlist);
	if (!gs->dflt_id) {
		pr_err("Guest data has no sample IDs");
		return -EINVAL;
	}

	/* Temporary file for guest events */
	gs->tmp_file_name = strdup(tmp_file_name);
	if (!gs->tmp_file_name)
		return -ENOMEM;
	gs->tmp_fd = mkstemp(gs->tmp_file_name);
	if (gs->tmp_fd < 0)
		return -errno;

	if (zstd_init(&gs->session->zstd_data, 0) < 0)
		pr_warning("Guest session decompression initialization failed.\n");

	/*
	 * perf does not support processing 2 sessions simultaneously, so output
	 * guest events to a temporary file.
	 */
	ret = perf_session__process_events(gs->session);
	if (ret)
		return ret;

	if (lseek(gs->tmp_fd, 0, SEEK_SET))
		return -errno;

	return 0;
}

/* Free hlist nodes assuming hlist_node is the first member of hlist entries */
static void free_hlist(struct hlist_head *heads, size_t hlist_sz)
{
	struct hlist_node *pos, *n;
	size_t i;

	for (i = 0; i < hlist_sz; ++i) {
		hlist_for_each_safe(pos, n, &heads[i]) {
			hlist_del(pos);
			free(pos);
		}
	}
}

static void guest_session__exit(struct guest_session *gs)
{
	if (gs->session) {
		perf_session__delete(gs->session);
		free_hlist(gs->heads, PERF_EVLIST__HLIST_SIZE);
		free_hlist(gs->tids, PERF_EVLIST__HLIST_SIZE);
	}
	if (gs->tmp_file_name) {
		if (gs->tmp_fd >= 0)
			close(gs->tmp_fd);
		unlink(gs->tmp_file_name);
		zfree(&gs->tmp_file_name);
	}
	zfree(&gs->vcpu);

Annotation

Implementation Notes