On 2020-03-18 20:02, jer...@marvell.com wrote:
> From: Jerin Jacob <jer...@marvell.com>
>
> Define eal_trace_init() and eal_trace_fini() EAL interface
> functions that rte_eal_init() and rte_eal_cleanup() function can be
> use to initialize and finalize the trace subsystem.
> eal_trace_init() function will add the following
> functionality if trace is enabled through EAL command line param.
>
> - Test for trace registration failure.
> - Test for duplicate trace name registration
> - Generate UUID ver 4.
> - Create a trace directory
>
> Signed-off-by: Jerin Jacob <jer...@marvell.com>
> Signed-off-by: Sunil Kumar Kori <sk...@marvell.com>
> ---
>   lib/librte_eal/common/eal_common_trace.c      |  54 ++++++
>   .../common/eal_common_trace_utils.c           | 173 ++++++++++++++++++
>   lib/librte_eal/common/eal_trace.h             |  21 +++
>   lib/librte_eal/common/meson.build             |   1 +
>   lib/librte_eal/freebsd/eal/Makefile           |   1 +
>   lib/librte_eal/linux/eal/Makefile             |   1 +
>   6 files changed, 251 insertions(+)
>   create mode 100644 lib/librte_eal/common/eal_common_trace_utils.c
>
> diff --git a/lib/librte_eal/common/eal_common_trace.c 
> b/lib/librte_eal/common/eal_common_trace.c
> index f8855e09b..abb221cf3 100644
> --- a/lib/librte_eal/common/eal_common_trace.c
> +++ b/lib/librte_eal/common/eal_common_trace.c
> @@ -22,6 +22,60 @@ RTE_DEFINE_PER_LCORE(int, ctf_count);
>   static struct trace_point_head tp_list = STAILQ_HEAD_INITIALIZER(tp_list);
>   static struct trace trace;
>   
> +struct trace*
> +trace_obj_get(void)
> +{
> +     return &trace;
> +}
> +
> +struct trace_point_head *
> +trace_list_head_get(void)
> +{
> +     return &tp_list;
> +}
> +
> +int
> +eal_trace_init(void)
> +{
> +     /* One of the Trace registration failed */
> +     if (trace.register_errno) {
> +             rte_errno = trace.register_errno;
> +             goto fail;
> +     }
> +
> +     if (rte_trace_global_is_disabled())
> +             return 0;
> +
> +     rte_spinlock_init(&trace.lock);
> +
> +     /* Is duplicate trace name registered */
> +     if (trace_has_duplicate_entry())
> +             goto fail;
> +
> +     /* Generate UUID ver 4 with total size of events and number of events */
> +     trace_uuid_generate();
> +
> +     /* Create trace directory */
> +     if (trace_mkdir())
> +             goto fail;
> +
> +
> +     rte_trace_global_mode_set(trace.mode);
> +
> +     return 0;
> +
> +fail:
> +     trace_err("failed to initialize trace [%s]", rte_strerror(rte_errno));
> +     return -rte_errno;
> +}
> +
> +void
> +eal_trace_fini(void)
> +{
> +     if (rte_trace_global_is_disabled())
> +             return;
> +}
> +
>   bool
>   rte_trace_global_is_enabled(void)
>   {
> diff --git a/lib/librte_eal/common/eal_common_trace_utils.c 
> b/lib/librte_eal/common/eal_common_trace_utils.c
> new file mode 100644
> index 000000000..f7d59774c
> --- /dev/null
> +++ b/lib/librte_eal/common/eal_common_trace_utils.c
> @@ -0,0 +1,173 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2020 Marvell International Ltd.
> + */
> +
> +#include <fnmatch.h>
> +#include <pwd.h>
> +#include <sys/stat.h>
> +#include <time.h>
> +
> +#include <rte_common.h>
> +#include <rte_errno.h>
> +#include <rte_string_fns.h>
> +
> +#include "eal_filesystem.h"
> +#include "eal_trace.h"
> +
> +static bool
> +trace_entry_compare(const char *name)
> +{
> +     struct trace_point_head *tp_list = trace_list_head_get();
> +     struct trace_point *tp;
> +     int count = 0;
> +
> +     STAILQ_FOREACH(tp, tp_list, next) {
> +             if (strncmp(tp->name, name, TRACE_POINT_NAME_SIZE) == 0)
> +                     count++;
> +             if (count > 1) {
> +                     trace_err("found duplicate entry %s", name);
> +                     rte_errno = EEXIST;
> +                     return 1;

Maybe an assertion would be better here, especially since the caller 
doesn't seem to care about the fact the list is inconsistent.

Change 1 -> true.

> +             }
> +     }
> +     return 0;
return false;
> +}
> +
> +bool
> +trace_has_duplicate_entry(void)
> +{
> +     struct trace_point_head *tp_list = trace_list_head_get();
> +     struct trace_point *tp;
> +
> +     /* Is duplicate trace name registered */
> +     STAILQ_FOREACH(tp, tp_list, next)
> +             if (trace_entry_compare(tp->name))
> +                     return true;
> +
> +     return false;
> +}
> +
> +void
> +trace_uuid_generate(void)
> +{
> +     struct trace_point_head *tp_list = trace_list_head_get();
> +     struct trace *trace = trace_obj_get();
> +     struct trace_point *tp;
> +     uint64_t sz_total = 0;
> +
> +     /* Go over the registered trace points to get total size of events */
> +     STAILQ_FOREACH(tp, tp_list, next) {
> +             const uint16_t sz = *tp->handle & __RTE_TRACE_FIELD_SIZE_MASK;
> +             sz_total += sz;
> +     }
> +
> +     rte_uuid_t uuid = RTE_UUID_INIT(sz_total, trace->nb_trace_points,
> +             0x4370, 0x8f50, 0x222ddd514176ULL);
> +     rte_uuid_copy(trace->uuid, uuid);
> +}
> +
> +static int
> +trace_session_name_generate(char *trace_dir)
> +{
> +     struct tm *tm_result;
> +     time_t tm;
> +     int rc;
> +
> +     tm = time(NULL);
> +     if ((int)tm == -1)
> +             goto fail;
> +
> +     tm_result = localtime(&tm);
> +     if (tm_result == NULL)
> +             goto fail;
> +
> +     rc = rte_strscpy(trace_dir,
> +                      eal_get_hugefile_prefix(), TRACE_PREFIX_LEN);
> +     if (rc == -E2BIG)
> +             rc = TRACE_PREFIX_LEN;
> +     trace_dir[rc++] = '-';
> +
> +     rc = strftime(trace_dir + rc, TRACE_DIR_STR_LEN - rc,
> +                     "%Y-%m-%d-%p-%I-%M-%S", tm_result);
> +     if (rc == 0)
> +             goto fail;
> +
> +     return rc;
> +fail:
> +     rte_errno = errno;
> +     return -rte_errno;
> +}
> +
> +static int
> +trace_dir_default_path_get(char *dir_path)
> +{
> +     struct trace *trace = trace_obj_get();
> +     uint32_t size = sizeof(trace->dir);
> +     struct passwd *pwd;
> +     char *home_dir;
> +
> +     /* First check for shell environment variable */
> +     home_dir = getenv("HOME");
In case of the application being started with 'sudo', $HOME will not be 
"/root", but rather the original user. This sounds like a bug to me.
> +     if (home_dir == NULL) {
> +             /* Fallback to password file entry */
> +             pwd = getpwuid(getuid());
> +             if (pwd == NULL)
> +                     return -EINVAL;
> +
> +             home_dir = pwd->pw_dir;
> +     }
> +
> +     /* Append dpdk-traces to directory */
> +     if (snprintf(dir_path, size, "%s/dpdk-traces/", home_dir) < 0)
> +             return -ENAMETOOLONG;
> +
> +     return 0;
> +}
> +
> +int
> +trace_mkdir(void)
> +{
> +     struct trace *trace = trace_obj_get();
> +     char session[TRACE_DIR_STR_LEN];
> +     char *dir_path;
> +     int rc;
> +
> +     if (!trace->dir_offset) {
> +             dir_path = (char *)calloc(1, sizeof(trace->dir));
calloc() returns a void pointer, so no need to cast it.
> +             if (dir_path == NULL) {
> +                     trace_err("fail to allocate memory\n");
> +                     return -ENOMEM;
> +             }
> +
> +             rc = trace_dir_default_path_get(dir_path);
> +             if (rc < 0) {
> +                     trace_err("fail to get default path\n");
> +                     free(dir_path);
> +                     return rc;
> +             }
> +
> +     }
> +
> +     /* Create the path if it t exist, no "mkdir -p" available here */
> +     rc = mkdir(trace->dir, 0700);
> +     if (rc < 0 && errno != EEXIST) {
> +             trace_err("mkdir %s failed [%s]", trace->dir, strerror(errno));
> +             rte_errno = errno;
> +             return -rte_errno;
> +     }
> +
> +     rc = trace_session_name_generate(session);
> +     if (rc < 0)
> +             return rc;
> +
> +     rc = mkdir(trace->dir, 0700);
> +     if (rc < 0) {
> +             trace_err("mkdir %s failed [%s]", trace->dir, strerror(errno));
> +             rte_errno = errno;
> +             return -rte_errno;
> +     }
> +
> +     RTE_LOG(INFO, EAL, "Trace dir: %s\n", trace->dir);
> +     return 0;

Is dir_path leaked? I can't find a free(), except in one of the error cases.

> +}
> +
> diff --git a/lib/librte_eal/common/eal_trace.h 
> b/lib/librte_eal/common/eal_trace.h
> index 9f90a5d17..10c2f03ac 100644
> --- a/lib/librte_eal/common/eal_trace.h
> +++ b/lib/librte_eal/common/eal_trace.h
> @@ -5,7 +5,9 @@
>   #ifndef __EAL_TRACE_H
>   #define __EAL_TRACE_H
>   
> +#include <rte_spinlock.h>
>   #include <rte_trace.h>
> +#include <rte_uuid.h>
>   
>   #define trace_err(fmt, args...)\
>       RTE_LOG(ERR, EAL, "%s():%u " fmt "\n",\
> @@ -15,6 +17,8 @@
>       RTE_LOG(CRIT, EAL, "%s():%u " fmt "\n",\
>               __func__, __LINE__, ## args)
>   
> +#define TRACE_PREFIX_LEN 12
> +#define TRACE_DIR_STR_LEN (sizeof("YYYY-mm-dd-AM-HH-MM-SS") + 
> TRACE_PREFIX_LEN)
>   #define TRACE_CTF_FIELD_SIZE 384
>   #define TRACE_POINT_NAME_SIZE 64
>   
> @@ -26,11 +30,15 @@ struct trace_point {
>   };
>   
>   struct trace {
> +     char dir[PATH_MAX];
> +     int dir_offset;
>       int register_errno;
>       bool global_status;
>       enum rte_trace_mode_e mode;
> +     rte_uuid_t uuid;
>       uint32_t level;
>       uint32_t nb_trace_points;
> +     rte_spinlock_t lock;
>   };
>   
>   /* Helper functions */
> @@ -41,7 +49,20 @@ trace_id_get(rte_trace_t trace)
>               __RTE_TRACE_FIELD_ID_SHIFT;
>   }
>   
> +/* Trace object functions */
> +struct trace *trace_obj_get(void);
> +
>   /* Trace point list functions */
>   STAILQ_HEAD(trace_point_head, trace_point);
> +struct trace_point_head *trace_list_head_get(void);
> +
> +/* Util functions */
> +bool trace_has_duplicate_entry(void);
> +void trace_uuid_generate(void);
> +int trace_mkdir(void);
> +
> +/* EAL interface */
> +int eal_trace_init(void);
> +void eal_trace_fini(void);
>   
>   #endif /* __EAL_TRACE_H */
> diff --git a/lib/librte_eal/common/meson.build 
> b/lib/librte_eal/common/meson.build
> index 88c14ebe5..716a255d2 100644
> --- a/lib/librte_eal/common/meson.build
> +++ b/lib/librte_eal/common/meson.build
> @@ -29,6 +29,7 @@ common_sources = files(
>       'eal_common_thread.c',
>       'eal_common_timer.c',
>       'eal_common_trace.c',
> +     'eal_common_trace_utils.c',
>       'eal_common_uuid.c',
>       'hotplug_mp.c',
>       'malloc_elem.c',
> diff --git a/lib/librte_eal/freebsd/eal/Makefile 
> b/lib/librte_eal/freebsd/eal/Makefile
> index b2fcc4212..8c444da02 100644
> --- a/lib/librte_eal/freebsd/eal/Makefile
> +++ b/lib/librte_eal/freebsd/eal/Makefile
> @@ -61,6 +61,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_proc.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_fbarray.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_uuid.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_trace.c
> +SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += eal_common_trace_utils.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += rte_malloc.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += hotplug_mp.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_FREEBSD) += malloc_elem.c
> diff --git a/lib/librte_eal/linux/eal/Makefile 
> b/lib/librte_eal/linux/eal/Makefile
> index 95470d3bb..bd9993e58 100644
> --- a/lib/librte_eal/linux/eal/Makefile
> +++ b/lib/librte_eal/linux/eal/Makefile
> @@ -69,6 +69,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_proc.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_fbarray.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_uuid.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_trace.c
> +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += eal_common_trace_utils.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += rte_malloc.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += hotplug_mp.c
>   SRCS-$(CONFIG_RTE_EXEC_ENV_LINUX) += malloc_elem.c


Reply via email to