xref: /dpdk/lib/eal/common/eal_common_trace_utils.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(C) 2020 Marvell International Ltd.
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <fnmatch.h>
699a2dd95SBruce Richardson #include <pwd.h>
799a2dd95SBruce Richardson #include <sys/stat.h>
899a2dd95SBruce Richardson #include <time.h>
999a2dd95SBruce Richardson 
1099a2dd95SBruce Richardson #include <rte_common.h>
1199a2dd95SBruce Richardson #include <rte_errno.h>
1299a2dd95SBruce Richardson #include <rte_string_fns.h>
1399a2dd95SBruce Richardson 
1499a2dd95SBruce Richardson #include "eal_filesystem.h"
15*ae67895bSDavid Marchand #include "eal_private.h"
1699a2dd95SBruce Richardson #include "eal_trace.h"
1799a2dd95SBruce Richardson 
1899a2dd95SBruce Richardson const char *
trace_mode_to_string(enum rte_trace_mode mode)1999a2dd95SBruce Richardson trace_mode_to_string(enum rte_trace_mode mode)
2099a2dd95SBruce Richardson {
2199a2dd95SBruce Richardson 	switch (mode) {
2299a2dd95SBruce Richardson 	case RTE_TRACE_MODE_OVERWRITE: return "overwrite";
2399a2dd95SBruce Richardson 	case RTE_TRACE_MODE_DISCARD: return "discard";
2499a2dd95SBruce Richardson 	default: return "unknown";
2599a2dd95SBruce Richardson 	}
2699a2dd95SBruce Richardson }
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson const char *
trace_area_to_string(enum trace_area_e area)2999a2dd95SBruce Richardson trace_area_to_string(enum trace_area_e area)
3099a2dd95SBruce Richardson {
3199a2dd95SBruce Richardson 	switch (area) {
3299a2dd95SBruce Richardson 	case TRACE_AREA_HEAP: return "heap";
3399a2dd95SBruce Richardson 	case TRACE_AREA_HUGEPAGE: return "hugepage";
3499a2dd95SBruce Richardson 	default: return "unknown";
3599a2dd95SBruce Richardson 	}
3699a2dd95SBruce Richardson }
3799a2dd95SBruce Richardson 
3899a2dd95SBruce Richardson static bool
trace_entry_compare(const char * name)3999a2dd95SBruce Richardson trace_entry_compare(const char *name)
4099a2dd95SBruce Richardson {
4199a2dd95SBruce Richardson 	struct trace_point_head *tp_list = trace_list_head_get();
4299a2dd95SBruce Richardson 	struct trace_point *tp;
4399a2dd95SBruce Richardson 	int count = 0;
4499a2dd95SBruce Richardson 
4599a2dd95SBruce Richardson 	STAILQ_FOREACH(tp, tp_list, next) {
46477cc313SDavid Marchand 		if (strcmp(tp->name, name) == 0)
4799a2dd95SBruce Richardson 			count++;
4899a2dd95SBruce Richardson 		if (count > 1) {
4999a2dd95SBruce Richardson 			trace_err("found duplicate entry %s", name);
5099a2dd95SBruce Richardson 			rte_errno = EEXIST;
5199a2dd95SBruce Richardson 			return true;
5299a2dd95SBruce Richardson 		}
5399a2dd95SBruce Richardson 	}
5499a2dd95SBruce Richardson 	return false;
5599a2dd95SBruce Richardson }
5699a2dd95SBruce Richardson 
5799a2dd95SBruce Richardson bool
trace_has_duplicate_entry(void)5899a2dd95SBruce Richardson trace_has_duplicate_entry(void)
5999a2dd95SBruce Richardson {
6099a2dd95SBruce Richardson 	struct trace_point_head *tp_list = trace_list_head_get();
6199a2dd95SBruce Richardson 	struct trace_point *tp;
6299a2dd95SBruce Richardson 
6399a2dd95SBruce Richardson 	/* Is duplicate trace name registered */
6499a2dd95SBruce Richardson 	STAILQ_FOREACH(tp, tp_list, next)
6599a2dd95SBruce Richardson 		if (trace_entry_compare(tp->name))
6699a2dd95SBruce Richardson 			return true;
6799a2dd95SBruce Richardson 
6899a2dd95SBruce Richardson 	return false;
6999a2dd95SBruce Richardson }
7099a2dd95SBruce Richardson 
7199a2dd95SBruce Richardson void
trace_uuid_generate(void)7299a2dd95SBruce Richardson trace_uuid_generate(void)
7399a2dd95SBruce Richardson {
7499a2dd95SBruce Richardson 	struct trace_point_head *tp_list = trace_list_head_get();
7599a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
7699a2dd95SBruce Richardson 	struct trace_point *tp;
7799a2dd95SBruce Richardson 	uint64_t sz_total = 0;
7899a2dd95SBruce Richardson 
7999a2dd95SBruce Richardson 	/* Go over the registered trace points to get total size of events */
8099a2dd95SBruce Richardson 	STAILQ_FOREACH(tp, tp_list, next) {
8199a2dd95SBruce Richardson 		const uint16_t sz = *tp->handle & __RTE_TRACE_FIELD_SIZE_MASK;
8299a2dd95SBruce Richardson 		sz_total += sz;
8399a2dd95SBruce Richardson 	}
8499a2dd95SBruce Richardson 
8599a2dd95SBruce Richardson 	rte_uuid_t uuid = RTE_UUID_INIT(sz_total, trace->nb_trace_points,
8699a2dd95SBruce Richardson 		0x4370, 0x8f50, 0x222ddd514176ULL);
8799a2dd95SBruce Richardson 	rte_uuid_copy(trace->uuid, uuid);
8899a2dd95SBruce Richardson }
8999a2dd95SBruce Richardson 
9099a2dd95SBruce Richardson static int
trace_session_name_generate(char ** trace_dir)91eb870201SDavid Marchand trace_session_name_generate(char **trace_dir)
9299a2dd95SBruce Richardson {
93eb870201SDavid Marchand 	char date[sizeof("YYYY-mm-dd-AM-HH-MM-SS")];
9499a2dd95SBruce Richardson 	struct tm *tm_result;
9599a2dd95SBruce Richardson 	time_t tm;
9699a2dd95SBruce Richardson 
9799a2dd95SBruce Richardson 	tm = time(NULL);
9899a2dd95SBruce Richardson 	if ((int)tm == -1)
9999a2dd95SBruce Richardson 		goto fail;
10099a2dd95SBruce Richardson 
10199a2dd95SBruce Richardson 	tm_result = localtime(&tm);
10299a2dd95SBruce Richardson 	if (tm_result == NULL)
10399a2dd95SBruce Richardson 		goto fail;
10499a2dd95SBruce Richardson 
105eb870201SDavid Marchand 	if (strftime(date, sizeof(date), "%Y-%m-%d-%p-%I-%M-%S", tm_result) == 0) {
106d59a9406SChengwen Feng 		errno = ENOSPC;
10799a2dd95SBruce Richardson 		goto fail;
108d59a9406SChengwen Feng 	}
10999a2dd95SBruce Richardson 
110eb870201SDavid Marchand 	if (asprintf(trace_dir, "%s-%s", eal_get_hugefile_prefix(), date) == -1)
111eb870201SDavid Marchand 		goto fail;
112eb870201SDavid Marchand 
113eb870201SDavid Marchand 	return 0;
11499a2dd95SBruce Richardson fail:
11599a2dd95SBruce Richardson 	rte_errno = errno;
116eb870201SDavid Marchand 	return -1;
11799a2dd95SBruce Richardson }
11899a2dd95SBruce Richardson 
11999a2dd95SBruce Richardson static int
trace_dir_update(const char * str)12099a2dd95SBruce Richardson trace_dir_update(const char *str)
12199a2dd95SBruce Richardson {
12299a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
123eb870201SDavid Marchand 	char *dir;
124eb870201SDavid Marchand 	int rc;
12599a2dd95SBruce Richardson 
126eb870201SDavid Marchand 	rc = asprintf(&dir, "%s%s", trace->dir != NULL ? trace->dir : "", str);
127eb870201SDavid Marchand 	if (rc != -1) {
128eb870201SDavid Marchand 		free(trace->dir);
129eb870201SDavid Marchand 		trace->dir = dir;
130eb870201SDavid Marchand 	}
13199a2dd95SBruce Richardson 	return rc;
13299a2dd95SBruce Richardson }
13399a2dd95SBruce Richardson 
13499a2dd95SBruce Richardson int
eal_trace_args_save(const char * val)13599a2dd95SBruce Richardson eal_trace_args_save(const char *val)
13699a2dd95SBruce Richardson {
13799a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
13899a2dd95SBruce Richardson 	struct trace_arg *arg = malloc(sizeof(*arg));
13999a2dd95SBruce Richardson 
14099a2dd95SBruce Richardson 	if (arg == NULL) {
14199a2dd95SBruce Richardson 		trace_err("failed to allocate memory for %s", val);
14299a2dd95SBruce Richardson 		return -ENOMEM;
14399a2dd95SBruce Richardson 	}
14499a2dd95SBruce Richardson 
14599a2dd95SBruce Richardson 	arg->val = strdup(val);
14699a2dd95SBruce Richardson 	if (arg->val == NULL) {
14799a2dd95SBruce Richardson 		trace_err("failed to allocate memory for %s", val);
14899a2dd95SBruce Richardson 		free(arg);
14999a2dd95SBruce Richardson 		return -ENOMEM;
15099a2dd95SBruce Richardson 	}
15199a2dd95SBruce Richardson 
15299a2dd95SBruce Richardson 	STAILQ_INSERT_TAIL(&trace->args, arg, next);
15399a2dd95SBruce Richardson 	return 0;
15499a2dd95SBruce Richardson }
15599a2dd95SBruce Richardson 
15699a2dd95SBruce Richardson void
eal_trace_args_free(void)15799a2dd95SBruce Richardson eal_trace_args_free(void)
15899a2dd95SBruce Richardson {
15999a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
16099a2dd95SBruce Richardson 	struct trace_arg *arg;
16199a2dd95SBruce Richardson 
16299a2dd95SBruce Richardson 	while (!STAILQ_EMPTY(&trace->args)) {
16399a2dd95SBruce Richardson 		arg = STAILQ_FIRST(&trace->args);
16499a2dd95SBruce Richardson 		STAILQ_REMOVE_HEAD(&trace->args, next);
16599a2dd95SBruce Richardson 		free(arg->val);
16699a2dd95SBruce Richardson 		free(arg);
16799a2dd95SBruce Richardson 	}
16899a2dd95SBruce Richardson }
16999a2dd95SBruce Richardson 
17099a2dd95SBruce Richardson int
trace_args_apply(const char * arg)17199a2dd95SBruce Richardson trace_args_apply(const char *arg)
17299a2dd95SBruce Richardson {
17399a2dd95SBruce Richardson 	if (rte_trace_regexp(arg, true) < 0) {
17499a2dd95SBruce Richardson 		trace_err("cannot enable trace for %s", arg);
17599a2dd95SBruce Richardson 		return -1;
17699a2dd95SBruce Richardson 	}
17799a2dd95SBruce Richardson 
17899a2dd95SBruce Richardson 	return 0;
17999a2dd95SBruce Richardson }
18099a2dd95SBruce Richardson 
18199a2dd95SBruce Richardson int
eal_trace_bufsz_args_save(char const * val)18299a2dd95SBruce Richardson eal_trace_bufsz_args_save(char const *val)
18399a2dd95SBruce Richardson {
18499a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
18599a2dd95SBruce Richardson 	uint64_t bufsz;
18699a2dd95SBruce Richardson 
18799a2dd95SBruce Richardson 	bufsz = rte_str_to_size(val);
18899a2dd95SBruce Richardson 	if (bufsz == 0) {
18999a2dd95SBruce Richardson 		trace_err("buffer size cannot be zero");
19099a2dd95SBruce Richardson 		return -EINVAL;
19199a2dd95SBruce Richardson 	}
19299a2dd95SBruce Richardson 
19399a2dd95SBruce Richardson 	trace->buff_len = bufsz;
19499a2dd95SBruce Richardson 	return 0;
19599a2dd95SBruce Richardson }
19699a2dd95SBruce Richardson 
19799a2dd95SBruce Richardson void
trace_bufsz_args_apply(void)19899a2dd95SBruce Richardson trace_bufsz_args_apply(void)
19999a2dd95SBruce Richardson {
20099a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
20199a2dd95SBruce Richardson 
20299a2dd95SBruce Richardson 	if (trace->buff_len == 0)
20399a2dd95SBruce Richardson 		trace->buff_len = 1024 * 1024; /* 1MB */
20499a2dd95SBruce Richardson }
20599a2dd95SBruce Richardson 
20699a2dd95SBruce Richardson int
eal_trace_mode_args_save(const char * val)20799a2dd95SBruce Richardson eal_trace_mode_args_save(const char *val)
20899a2dd95SBruce Richardson {
20999a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
21099a2dd95SBruce Richardson 	size_t len = strlen(val);
21199a2dd95SBruce Richardson 	unsigned long tmp;
21299a2dd95SBruce Richardson 	char *pattern;
21399a2dd95SBruce Richardson 
21499a2dd95SBruce Richardson 	if (len == 0) {
21599a2dd95SBruce Richardson 		trace_err("value is not provided with option");
21699a2dd95SBruce Richardson 		return -EINVAL;
21799a2dd95SBruce Richardson 	}
21899a2dd95SBruce Richardson 
21999a2dd95SBruce Richardson 	pattern = (char *)calloc(1, len + 2);
22099a2dd95SBruce Richardson 	if (pattern == NULL) {
22199a2dd95SBruce Richardson 		trace_err("fail to allocate memory");
22299a2dd95SBruce Richardson 		return -ENOMEM;
22399a2dd95SBruce Richardson 	}
22499a2dd95SBruce Richardson 
22599a2dd95SBruce Richardson 	sprintf(pattern, "%s*", val);
22699a2dd95SBruce Richardson 
22799a2dd95SBruce Richardson 	if (fnmatch(pattern, "overwrite", 0) == 0)
22899a2dd95SBruce Richardson 		tmp = RTE_TRACE_MODE_OVERWRITE;
22999a2dd95SBruce Richardson 	else if (fnmatch(pattern, "discard", 0) == 0)
23099a2dd95SBruce Richardson 		tmp = RTE_TRACE_MODE_DISCARD;
23199a2dd95SBruce Richardson 	else {
23299a2dd95SBruce Richardson 		free(pattern);
23399a2dd95SBruce Richardson 		return -EINVAL;
23499a2dd95SBruce Richardson 	}
23599a2dd95SBruce Richardson 
23699a2dd95SBruce Richardson 	trace->mode = tmp;
23799a2dd95SBruce Richardson 	free(pattern);
23899a2dd95SBruce Richardson 	return 0;
23999a2dd95SBruce Richardson }
24099a2dd95SBruce Richardson 
24199a2dd95SBruce Richardson int
eal_trace_dir_args_save(char const * val)24299a2dd95SBruce Richardson eal_trace_dir_args_save(char const *val)
24399a2dd95SBruce Richardson {
24499a2dd95SBruce Richardson 	char *dir_path;
24599a2dd95SBruce Richardson 	int rc;
24699a2dd95SBruce Richardson 
24799a2dd95SBruce Richardson 	if (asprintf(&dir_path, "%s/", val) == -1) {
24899a2dd95SBruce Richardson 		trace_err("failed to copy directory: %s", strerror(errno));
24999a2dd95SBruce Richardson 		return -ENOMEM;
25099a2dd95SBruce Richardson 	}
25199a2dd95SBruce Richardson 
25299a2dd95SBruce Richardson 	rc = trace_dir_update(dir_path);
25399a2dd95SBruce Richardson 	free(dir_path);
25499a2dd95SBruce Richardson 	return rc;
25599a2dd95SBruce Richardson }
25699a2dd95SBruce Richardson 
25799a2dd95SBruce Richardson int
trace_epoch_time_save(void)25899a2dd95SBruce Richardson trace_epoch_time_save(void)
25999a2dd95SBruce Richardson {
26099a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
26199a2dd95SBruce Richardson 	struct timespec epoch = { 0, 0 };
26299a2dd95SBruce Richardson 	uint64_t avg, start, end;
26399a2dd95SBruce Richardson 
26499a2dd95SBruce Richardson 	start = rte_get_tsc_cycles();
26599a2dd95SBruce Richardson 	if (clock_gettime(CLOCK_REALTIME, &epoch) < 0) {
26699a2dd95SBruce Richardson 		trace_err("failed to get the epoch time");
26799a2dd95SBruce Richardson 		return -1;
26899a2dd95SBruce Richardson 	}
26999a2dd95SBruce Richardson 	end = rte_get_tsc_cycles();
27099a2dd95SBruce Richardson 	avg = (start + end) >> 1;
27199a2dd95SBruce Richardson 
27299a2dd95SBruce Richardson 	trace->epoch_sec = (uint64_t) epoch.tv_sec;
27399a2dd95SBruce Richardson 	trace->epoch_nsec = (uint64_t) epoch.tv_nsec;
27499a2dd95SBruce Richardson 	trace->uptime_ticks = avg;
27599a2dd95SBruce Richardson 
27699a2dd95SBruce Richardson 	return 0;
27799a2dd95SBruce Richardson }
27899a2dd95SBruce Richardson 
27999a2dd95SBruce Richardson static int
trace_dir_default_path_get(char ** dir_path)280eb870201SDavid Marchand trace_dir_default_path_get(char **dir_path)
28199a2dd95SBruce Richardson {
28299a2dd95SBruce Richardson 	struct passwd *pwd;
28399a2dd95SBruce Richardson 	char *home_dir;
28499a2dd95SBruce Richardson 
28599a2dd95SBruce Richardson 	/* First check for shell environment variable */
28699a2dd95SBruce Richardson 	home_dir = getenv("HOME");
28799a2dd95SBruce Richardson 	if (home_dir == NULL) {
28899a2dd95SBruce Richardson 		/* Fallback to password file entry */
28999a2dd95SBruce Richardson 		pwd = getpwuid(getuid());
29099a2dd95SBruce Richardson 		if (pwd == NULL)
29199a2dd95SBruce Richardson 			return -EINVAL;
29299a2dd95SBruce Richardson 
29399a2dd95SBruce Richardson 		home_dir = pwd->pw_dir;
29499a2dd95SBruce Richardson 	}
29599a2dd95SBruce Richardson 
29699a2dd95SBruce Richardson 	/* Append dpdk-traces to directory */
297eb870201SDavid Marchand 	if (asprintf(dir_path, "%s/dpdk-traces/", home_dir) == -1)
298eb870201SDavid Marchand 		return -ENOMEM;
29999a2dd95SBruce Richardson 
30099a2dd95SBruce Richardson 	return 0;
30199a2dd95SBruce Richardson }
30299a2dd95SBruce Richardson 
303d6fd5a01SDavid Marchand static int
trace_mkdir(void)30499a2dd95SBruce Richardson trace_mkdir(void)
30599a2dd95SBruce Richardson {
30699a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
307d6fd5a01SDavid Marchand 	static bool already_done;
308eb870201SDavid Marchand 	char *session;
30999a2dd95SBruce Richardson 	int rc;
31099a2dd95SBruce Richardson 
311d6fd5a01SDavid Marchand 	if (already_done)
312d6fd5a01SDavid Marchand 		return 0;
313d6fd5a01SDavid Marchand 
314eb870201SDavid Marchand 	if (trace->dir == NULL) {
315eb870201SDavid Marchand 		char *dir_path;
31699a2dd95SBruce Richardson 
317eb870201SDavid Marchand 		rc = trace_dir_default_path_get(&dir_path);
31899a2dd95SBruce Richardson 		if (rc < 0) {
31999a2dd95SBruce Richardson 			trace_err("fail to get default path");
32099a2dd95SBruce Richardson 			return rc;
32199a2dd95SBruce Richardson 		}
32299a2dd95SBruce Richardson 
32399a2dd95SBruce Richardson 		rc = trace_dir_update(dir_path);
32499a2dd95SBruce Richardson 		free(dir_path);
32599a2dd95SBruce Richardson 		if (rc < 0)
32699a2dd95SBruce Richardson 			return rc;
32799a2dd95SBruce Richardson 	}
32899a2dd95SBruce Richardson 
32999a2dd95SBruce Richardson 	/* Create the path if it t exist, no "mkdir -p" available here */
33099a2dd95SBruce Richardson 	rc = mkdir(trace->dir, 0700);
33199a2dd95SBruce Richardson 	if (rc < 0 && errno != EEXIST) {
33299a2dd95SBruce Richardson 		trace_err("mkdir %s failed [%s]", trace->dir, strerror(errno));
33399a2dd95SBruce Richardson 		rte_errno = errno;
33499a2dd95SBruce Richardson 		return -rte_errno;
33599a2dd95SBruce Richardson 	}
33699a2dd95SBruce Richardson 
337eb870201SDavid Marchand 	rc = trace_session_name_generate(&session);
33899a2dd95SBruce Richardson 	if (rc < 0)
33999a2dd95SBruce Richardson 		return rc;
34099a2dd95SBruce Richardson 	rc = trace_dir_update(session);
341eb870201SDavid Marchand 	free(session);
34299a2dd95SBruce Richardson 	if (rc < 0)
34399a2dd95SBruce Richardson 		return rc;
34499a2dd95SBruce Richardson 
34599a2dd95SBruce Richardson 	rc = mkdir(trace->dir, 0700);
34699a2dd95SBruce Richardson 	if (rc < 0) {
34799a2dd95SBruce Richardson 		trace_err("mkdir %s failed [%s]", trace->dir, strerror(errno));
34899a2dd95SBruce Richardson 		rte_errno = errno;
34999a2dd95SBruce Richardson 		return -rte_errno;
35099a2dd95SBruce Richardson 	}
35199a2dd95SBruce Richardson 
352*ae67895bSDavid Marchand 	EAL_LOG(INFO, "Trace dir: %s", trace->dir);
353d6fd5a01SDavid Marchand 	already_done = true;
35499a2dd95SBruce Richardson 	return 0;
35599a2dd95SBruce Richardson }
35699a2dd95SBruce Richardson 
35799a2dd95SBruce Richardson static int
trace_meta_save(struct trace * trace)35899a2dd95SBruce Richardson trace_meta_save(struct trace *trace)
35999a2dd95SBruce Richardson {
36099a2dd95SBruce Richardson 	char file_name[PATH_MAX];
36199a2dd95SBruce Richardson 	FILE *f;
36299a2dd95SBruce Richardson 	int rc;
36399a2dd95SBruce Richardson 
36499a2dd95SBruce Richardson 	rc = snprintf(file_name, PATH_MAX, "%s/metadata", trace->dir);
36599a2dd95SBruce Richardson 	if (rc < 0)
36699a2dd95SBruce Richardson 		return rc;
36799a2dd95SBruce Richardson 
36899a2dd95SBruce Richardson 	f = fopen(file_name, "w");
36999a2dd95SBruce Richardson 	if (f == NULL)
37099a2dd95SBruce Richardson 		return -errno;
37199a2dd95SBruce Richardson 
37299a2dd95SBruce Richardson 	rc = rte_trace_metadata_dump(f);
37399a2dd95SBruce Richardson 
37499a2dd95SBruce Richardson 	if (fclose(f))
37599a2dd95SBruce Richardson 		rc = -errno;
37699a2dd95SBruce Richardson 
37799a2dd95SBruce Richardson 	return rc;
37899a2dd95SBruce Richardson }
37999a2dd95SBruce Richardson 
38099a2dd95SBruce Richardson 
38199a2dd95SBruce Richardson static inline int
trace_file_sz(struct __rte_trace_header * hdr)38299a2dd95SBruce Richardson trace_file_sz(struct __rte_trace_header *hdr)
38399a2dd95SBruce Richardson {
38499a2dd95SBruce Richardson 	return sizeof(struct __rte_trace_stream_header) + hdr->offset;
38599a2dd95SBruce Richardson }
38699a2dd95SBruce Richardson 
38799a2dd95SBruce Richardson static int
trace_mem_save(struct trace * trace,struct __rte_trace_header * hdr,uint32_t cnt)38899a2dd95SBruce Richardson trace_mem_save(struct trace *trace, struct __rte_trace_header *hdr,
38999a2dd95SBruce Richardson 		uint32_t cnt)
39099a2dd95SBruce Richardson {
39199a2dd95SBruce Richardson 	char file_name[PATH_MAX];
39299a2dd95SBruce Richardson 	FILE *f;
39399a2dd95SBruce Richardson 	int rc;
39499a2dd95SBruce Richardson 
39599a2dd95SBruce Richardson 	rc = snprintf(file_name, PATH_MAX, "%s/channel0_%d", trace->dir, cnt);
39699a2dd95SBruce Richardson 	if (rc < 0)
39799a2dd95SBruce Richardson 		return rc;
39899a2dd95SBruce Richardson 
39999a2dd95SBruce Richardson 	f = fopen(file_name, "w");
40099a2dd95SBruce Richardson 	if (f == NULL)
40199a2dd95SBruce Richardson 		return -errno;
40299a2dd95SBruce Richardson 
40399a2dd95SBruce Richardson 	rc = fwrite(&hdr->stream_header, trace_file_sz(hdr), 1, f);
40499a2dd95SBruce Richardson 	rc = (rc == 1) ?  0 : -EACCES;
40599a2dd95SBruce Richardson 
40699a2dd95SBruce Richardson 	if (fclose(f))
40799a2dd95SBruce Richardson 		rc = -errno;
40899a2dd95SBruce Richardson 
40999a2dd95SBruce Richardson 	return rc;
41099a2dd95SBruce Richardson }
41199a2dd95SBruce Richardson 
41299a2dd95SBruce Richardson int
rte_trace_save(void)41399a2dd95SBruce Richardson rte_trace_save(void)
41499a2dd95SBruce Richardson {
41599a2dd95SBruce Richardson 	struct trace *trace = trace_obj_get();
41699a2dd95SBruce Richardson 	struct __rte_trace_header *header;
41799a2dd95SBruce Richardson 	uint32_t count;
41899a2dd95SBruce Richardson 	int rc = 0;
41999a2dd95SBruce Richardson 
42099a2dd95SBruce Richardson 	if (trace->nb_trace_mem_list == 0)
42199a2dd95SBruce Richardson 		return rc;
42299a2dd95SBruce Richardson 
423d6fd5a01SDavid Marchand 	rc = trace_mkdir();
424d6fd5a01SDavid Marchand 	if (rc < 0)
425d6fd5a01SDavid Marchand 		return rc;
426d6fd5a01SDavid Marchand 
42799a2dd95SBruce Richardson 	rc = trace_meta_save(trace);
42899a2dd95SBruce Richardson 	if (rc)
42999a2dd95SBruce Richardson 		return rc;
43099a2dd95SBruce Richardson 
43199a2dd95SBruce Richardson 	rte_spinlock_lock(&trace->lock);
43299a2dd95SBruce Richardson 	for (count = 0; count < trace->nb_trace_mem_list; count++) {
43399a2dd95SBruce Richardson 		header = trace->lcore_meta[count].mem;
43499a2dd95SBruce Richardson 		rc =  trace_mem_save(trace, header, count);
43599a2dd95SBruce Richardson 		if (rc)
43699a2dd95SBruce Richardson 			break;
43799a2dd95SBruce Richardson 	}
43899a2dd95SBruce Richardson 	rte_spinlock_unlock(&trace->lock);
43999a2dd95SBruce Richardson 	return rc;
44099a2dd95SBruce Richardson }
441