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