From patchwork Fri Jan 15 05:04:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12021429 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A0825C433E0 for ; Fri, 15 Jan 2021 05:04:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 641C423730 for ; Fri, 15 Jan 2021 05:04:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728774AbhAOFE4 (ORCPT ); Fri, 15 Jan 2021 00:04:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55730 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726361AbhAOFEz (ORCPT ); Fri, 15 Jan 2021 00:04:55 -0500 Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D8C76C0613CF for ; Thu, 14 Jan 2021 21:04:14 -0800 (PST) Received: by mail-ej1-x62d.google.com with SMTP id ga15so11575508ejb.4 for ; Thu, 14 Jan 2021 21:04:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lGkZPE9J//gBgZYdQHbGsB9y8EyXeA1zzNgqJP/2kuc=; b=MszHrI43Vc/HjVUUfaNbAxTxQzVJZ5JRpXA/yqvdQ8L2NyC0tHGLKSz3M2eKVep7bm 1Zaez4ZXAlJSBUfQ3A4eUObqFadW3gffhNsPqbmXEQ82f+VcFR/KUniig43fN6pUiSnT MBHB85Wb+u80l6aSbLIL8/Oxh6Kz0oiG5jASrDf05X/e7/6d4l9/cYgOjpimsciIWT5A dLEpocqkX53wI4+cirjoX2Dabip/T//4CEO1oZZ6aj+ZH/8rOLSxVwrC3QFBRPDgbtxE oxcYki6/+qJIncNaPje6E2r3N2MCCCmPhTCeATiTc4JlNMT21C9c2Fk34oPyAPHnI4ok S7Dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lGkZPE9J//gBgZYdQHbGsB9y8EyXeA1zzNgqJP/2kuc=; b=Rh6VZA9CWReKtpi9qobMHUe2LxJJRrdYEoETpZ7rqX4nAEL2Y0Fc5R/fTgW2rjKK5N v4T5iI/A9Hkbk6c6ryOfOwjUIT7vcPdEyjI6NksXev2WSrtTyR2vgBcqUxT/gE8GpxZt izqQoRowMQflR6Y3N6T1+aNRcohuSc+DEZbQBynsWG+55V6diPXKY2mXbmi+ob8U8Qnw Q3BWhuS9R2lnd1MzKGfH+H7ZujKKY1i+SNsXDyLdOsoIGmgp1fM6NCURRmnyDrsDcSRk DU6dJ8zjG9+5bbNeSlcLDlBgWA9mVGeShP9ma6UXPzFecDLH3b/MdNEmdhVyyc0qGbyx Gisw== X-Gm-Message-State: AOAM530FA2FLLzNUUUdcQGwXdoNb1CuLZ/J/HvGw8TH9GPF3hYEFkJSX FUQoDcBSWmWCWQ8Tzml126dxXy0HsQ/89FL5 X-Google-Smtp-Source: ABdhPJz2NEc7fo8biTz5X7ysaPIWBDI9MteLCxbWhKyCkUXPX9Bojz2LS+WyeITWy6uV5ZKdhmopDw== X-Received: by 2002:a17:906:e106:: with SMTP id gj6mr294261ejb.337.1610687053640; Thu, 14 Jan 2021 21:04:13 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id d4sm3055670edq.36.2021.01.14.21.04.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Jan 2021 21:04:12 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH 1/5] libtracefs: New APIs for trace options Date: Fri, 15 Jan 2021 07:04:06 +0200 Message-Id: <20210115050410.1194011-2-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210115050410.1194011-1-tz.stoyanov@gmail.com> References: <20210115050410.1194011-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org These new APIs can be used to check and set various trace options tracefs_options_get_supported(); tracefs_option_is_supported(); tracefs_options_get_enabled(); tracefs_option_is_enabled(); tracefs_options_set(); tracefs_options_clear(); tracefs_option_string(); Signed-off-by: Tzvetomir Stoyanov (VMware) --- include/tracefs.h | 54 ++++++++++ src/tracefs-tools.c | 251 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+) diff --git a/include/tracefs.h b/include/tracefs.h index 85a776e..1f10a00 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -80,4 +80,58 @@ int tracefs_fill_local_events(const char *tracing_dir, char *tracefs_get_clock(struct tracefs_instance *instance); +#define TRACEFS_OPTION_ANNOTATE ((unsigned long long)1 << 0) +#define TRACEFS_OPTION_BIN ((unsigned long long)1 << 1) +#define TRACEFS_OPTION_BLK_CGNAME ((unsigned long long)1 << 2) +#define TRACEFS_OPTION_BLK_CGROUP ((unsigned long long)1 << 3) +#define TRACEFS_OPTION_BLK_CLASSIC ((unsigned long long)1 << 4) +#define TRACEFS_OPTION_BLOCK ((unsigned long long)1 << 5) +#define TRACEFS_OPTION_CONTEXT_INFO ((unsigned long long)1 << 6) +#define TRACEFS_OPTION_DISABLE_ON_FREE ((unsigned long long)1 << 7) +#define TRACEFS_OPTION_DISPLAY_GRAPH ((unsigned long long)1 << 8) +#define TRACEFS_OPTION_EVENT_FORK ((unsigned long long)1 << 9) +#define TRACEFS_OPTION_FGRAPH_ABSTIME ((unsigned long long)1 << 10) +#define TRACEFS_OPTION_FGRAPH_CPU ((unsigned long long)1 << 11) +#define TRACEFS_OPTION_FGRAPH_DURATION ((unsigned long long)1 << 12) +#define TRACEFS_OPTION_FGRAPH_IRQS ((unsigned long long)1 << 13) +#define TRACEFS_OPTION_FGRAPH_OVERHEAD ((unsigned long long)1 << 14) +#define TRACEFS_OPTION_FGRAPH_OVERRUN ((unsigned long long)1 << 15) +#define TRACEFS_OPTION_FGRAPH_PROC ((unsigned long long)1 << 16) +#define TRACEFS_OPTION_FGRAPH_TAIL ((unsigned long long)1 << 17) +#define TRACEFS_OPTION_FUNC_STACKTRACE ((unsigned long long)1 << 18) +#define TRACEFS_OPTION_FUNCTION_FORK ((unsigned long long)1 << 19) +#define TRACEFS_OPTION_FUNCTION_TRACE ((unsigned long long)1 << 20) +#define TRACEFS_OPTION_GRAPH_TIME ((unsigned long long)1 << 21) +#define TRACEFS_OPTION_HEX ((unsigned long long)1 << 22) +#define TRACEFS_OPTION_IRQ_INFO ((unsigned long long)1 << 23) +#define TRACEFS_OPTION_LATENCY_FORMAT ((unsigned long long)1 << 24) +#define TRACEFS_OPTION_MARKERS ((unsigned long long)1 << 25) +#define TRACEFS_OPTION_OVERWRITE ((unsigned long long)1 << 26) +#define TRACEFS_OPTION_PAUSE_ON_TRACE ((unsigned long long)1 << 27) +#define TRACEFS_OPTION_PRINTK_MSG_ONLY ((unsigned long long)1 << 28) +#define TRACEFS_OPTION_PRINT_PARENT ((unsigned long long)1 << 29) +#define TRACEFS_OPTION_RAW ((unsigned long long)1 << 30) +#define TRACEFS_OPTION_RECORD_CMD ((unsigned long long)1 << 31) +#define TRACEFS_OPTION_RECORD_TGID ((unsigned long long)1 << 32) +#define TRACEFS_OPTION_SLEEP_TIME ((unsigned long long)1 << 33) +#define TRACEFS_OPTION_STACKTRACE ((unsigned long long)1 << 34) +#define TRACEFS_OPTION_SYM_ADDR ((unsigned long long)1 << 35) +#define TRACEFS_OPTION_SYM_OFFSET ((unsigned long long)1 << 36) +#define TRACEFS_OPTION_SYM_USEROBJ ((unsigned long long)1 << 37) +#define TRACEFS_OPTION_TEST_NOP_ACCEPT ((unsigned long long)1 << 38) +#define TRACEFS_OPTION_TEST_NOP_REFUSE ((unsigned long long)1 << 39) +#define TRACEFS_OPTION_TRACE_PRINTK ((unsigned long long)1 << 40) +#define TRACEFS_OPTION_USERSTACKTRACE ((unsigned long long)1 << 41) +#define TRACEFS_OPTION_VERBOSE ((unsigned long long)1 << 42) + +#define TRACEFS_OPTION_INVALID ((unsigned long long)1 << 43) + +unsigned long long tracefs_options_get_supported(struct tracefs_instance *instance); +bool tracefs_option_is_supported(struct tracefs_instance *instance, unsigned long long id); +unsigned long long tracefs_options_get_enabled(struct tracefs_instance *instance); +bool tracefs_option_is_enabled(struct tracefs_instance *instance, unsigned long long id); +int tracefs_options_set(struct tracefs_instance *instance, unsigned long long options); +int tracefs_options_clear(struct tracefs_instance *instance, unsigned long long options); +const char *tracefs_option_string(unsigned long long id); + #endif /* _TRACE_FS_H */ diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c index 101f389..0505552 100644 --- a/src/tracefs-tools.c +++ b/src/tracefs-tools.c @@ -9,12 +9,66 @@ #include #include #include +#include +#include +#include +#include #include "tracefs.h" #include "tracefs-local.h" #define TRACE_CTRL "tracing_on" +struct options_map { + unsigned long long id; + char *name; +} options_map[] = { + { TRACEFS_OPTION_ANNOTATE, "annotate" }, + { TRACEFS_OPTION_BIN, "bin" }, + { TRACEFS_OPTION_BLK_CGNAME, "blk_cgname" }, + { TRACEFS_OPTION_BLK_CGROUP, "blk_cgroup" }, + { TRACEFS_OPTION_BLK_CLASSIC, "blk_classic" }, + { TRACEFS_OPTION_BLOCK, "block" }, + { TRACEFS_OPTION_CONTEXT_INFO, "context-info" }, + { TRACEFS_OPTION_DISABLE_ON_FREE, "disable_on_free" }, + { TRACEFS_OPTION_DISPLAY_GRAPH, "display-graph" }, + { TRACEFS_OPTION_EVENT_FORK, "event-fork" }, + { TRACEFS_OPTION_FGRAPH_ABSTIME, "funcgraph-abstime" }, + { TRACEFS_OPTION_FGRAPH_CPU, "funcgraph-cpu" }, + { TRACEFS_OPTION_FGRAPH_DURATION, "funcgraph-duration" }, + { TRACEFS_OPTION_FGRAPH_IRQS, "funcgraph-irqs" }, + { TRACEFS_OPTION_FGRAPH_OVERHEAD, "funcgraph-overhead" }, + { TRACEFS_OPTION_FGRAPH_OVERRUN, "funcgraph-overrun" }, + { TRACEFS_OPTION_FGRAPH_PROC, "funcgraph-proc" }, + { TRACEFS_OPTION_FGRAPH_TAIL, "funcgraph-tail" }, + { TRACEFS_OPTION_FUNC_STACKTRACE, "func_stack_trace" }, + { TRACEFS_OPTION_FUNCTION_FORK, "function-fork" }, + { TRACEFS_OPTION_FUNCTION_TRACE, "function-trace" }, + { TRACEFS_OPTION_GRAPH_TIME, "graph-time" }, + { TRACEFS_OPTION_HEX, "hex" }, + { TRACEFS_OPTION_IRQ_INFO, "irq-info" }, + { TRACEFS_OPTION_LATENCY_FORMAT, "latency-format" }, + { TRACEFS_OPTION_MARKERS, "markers" }, + { TRACEFS_OPTION_OVERWRITE, "overwrite" }, + { TRACEFS_OPTION_PAUSE_ON_TRACE, "pause-on-trace" }, + { TRACEFS_OPTION_PRINTK_MSG_ONLY, "printk-msg-only" }, + { TRACEFS_OPTION_PRINT_PARENT, "print-parent" }, + { TRACEFS_OPTION_RAW, "raw" }, + { TRACEFS_OPTION_RECORD_CMD, "record-cmd" }, + { TRACEFS_OPTION_RECORD_TGID, "record-tgid" }, + { TRACEFS_OPTION_SLEEP_TIME, "sleep-time" }, + { TRACEFS_OPTION_STACKTRACE, "stacktrace" }, + { TRACEFS_OPTION_SYM_ADDR, "sym-addr" }, + { TRACEFS_OPTION_SYM_OFFSET, "sym-offset" }, + { TRACEFS_OPTION_SYM_USEROBJ, "sym-userobj" }, + { TRACEFS_OPTION_TEST_NOP_ACCEPT, "test_nop_accept" }, + { TRACEFS_OPTION_TEST_NOP_REFUSE, "test_nop_refuse" }, + { TRACEFS_OPTION_TRACE_PRINTK, "trace_printk" }, + { TRACEFS_OPTION_USERSTACKTRACE, "userstacktrace" }, + { TRACEFS_OPTION_VERBOSE, "verbose" }, + { TRACEFS_OPTION_INVALID, "unknown" }, +}; + static int trace_on_off(int fd, bool on) { const char *val = on ? "1" : "0"; @@ -107,3 +161,200 @@ int tracefs_trace_off_fd(int fd) return -1; return trace_on_off(fd, false); } + +/** + * tracefs_option_string - Get trace option name from ID + * @id: trace option ID + * + * Returns string with option name, or "unknown" in case of not known option ID + */ +const char *tracefs_option_string(unsigned long long id) +{ + int size = sizeof(options_map) / sizeof(struct options_map); + int i; + + for (i = 0; i < size; i++) { + if (options_map[i].id == id) + return options_map[i].name; + } + + return options_map[size - 1].name; +} + +/** + * tracefs_option_id - Get trace option ID from name + * @name: trace option name + * + * Returns trace option ID or TRACEFS_OPTION_INVALID in case of an error or + * unknown option name. + */ +unsigned long long tracefs_option_id(char *name) +{ + int size = sizeof(options_map) / sizeof(struct options_map); + int i; + + if (!name) + return TRACEFS_OPTION_INVALID; + + for (i = 0; i < size; i++) { + if (strlen(name) == strlen(options_map[i].name) && + !strcmp(options_map[i].name, name)) + return options_map[i].id; + } + + return TRACEFS_OPTION_INVALID; +} + +static unsigned long long trace_get_options(struct tracefs_instance *instance, + bool enabled) +{ + unsigned long long options = 0; + unsigned long long id; + char file[PATH_MAX]; + struct dirent *dent; + char *dname = NULL; + DIR *dir = NULL; + long long val; + + dname = tracefs_instance_get_file(instance, "options"); + if (!dname) + goto error; + dir = opendir(dname); + if (!dir) + goto error; + + while ((dent = readdir(dir))) { + if (*dent->d_name == '.') + continue; + if (enabled) { + snprintf(file, PATH_MAX, "options/%s", dent->d_name); + if (tracefs_instance_file_read_number(instance, file, &val) != 0 || + val != 1) + continue; + } + id = tracefs_option_id(dent->d_name); + if (id != TRACEFS_OPTION_INVALID) + options |= id; + } + closedir(dir); + tracefs_put_tracing_file(dname); + + return options; + +error: + if (dir) + closedir(dir); + tracefs_put_tracing_file(dname); + return 0; +} + +/** + * tracefs_options_get_supported - Get all supported trace options in given instance + * @instance: ftrace instance, can be NULL for the top instance + * + * Returns bitmask of all trace options, supported in given instance + */ +unsigned long long tracefs_options_get_supported(struct tracefs_instance *instance) +{ + return trace_get_options(instance, false); +} + +/** + * tracefs_options_get_enabled - Get all currently enabled trace options in given instance + * @instance: ftrace instance, can be NULL for the top instance + * + * Returns bitmask of all trace options, that are currently set in given instance + */ +unsigned long long tracefs_options_get_enabled(struct tracefs_instance *instance) +{ + return trace_get_options(instance, true); +} + +static int trace_config_options(struct tracefs_instance *instance, + unsigned long long options, bool set) +{ + int size = sizeof(options_map) / sizeof(struct options_map); + char *set_str = set ? "1" : "0"; + int str_size = strlen(set_str); + char file[PATH_MAX]; + long long i; + + for (i = 0; i < size && options; i++) { + if (!(options & options_map[i].id)) + continue; + options &= ~options_map[i].id; + snprintf(file, PATH_MAX, "options/%s", options_map[i].name); + if (str_size != tracefs_instance_file_write(instance, file, set_str)) + break; + } + + if (options) + return -1; + return 0; +} + +/** + * tracefs_options_set - Enable trace options + * @instance: ftrace instance, can be NULL for the top instance + * @options: bitmask of trace options that will be enabled + * + * Returns -1 in case of an error or 0 otherwise + */ +int tracefs_options_set(struct tracefs_instance *instance, unsigned long long options) +{ + return trace_config_options(instance, options, true); +} + +/** + * tracefs_options_clear - Disable trace options + * @instance: ftrace instance, can be NULL for the top instance + * @options: bitmask of trace options that will be disabled + * + * Returns -1 in case of an error or 0 otherwise + */ +int tracefs_options_clear(struct tracefs_instance *instance, unsigned long long options) +{ + return trace_config_options(instance, options, false); +} + +/** + * tracefs_option_is_supported - Check if an option is supported + * @instance: ftrace instance, can be NULL for the top instance + * @id: option id + * + * Returns true if an option with given id is supported by the system, false if + * it is not supported. + */ +bool tracefs_option_is_supported(struct tracefs_instance *instance, unsigned long long id) +{ + char file[PATH_MAX]; + const char *oname = tracefs_option_string(id); + + if (!oname) + return false; + snprintf(file, PATH_MAX, "options/%s", oname); + return tracefs_file_exists(instance, (char *)file); +} + +/** + * tracefs_option_is_enabled - Check if an option is enabled in given instance + * @instance: ftrace instance, can be NULL for the top instance + * @id: option id + * + * Returns true if an option with given id is enabled in the given instance, + * false if it is not enabled. + */ +bool tracefs_option_is_enabled(struct tracefs_instance *instance, unsigned long long id) +{ + const char *oname = tracefs_option_string(id); + char file[PATH_MAX]; + long long res; + + if (!oname) + return false; + snprintf(file, PATH_MAX, "options/%s", oname); + if (!tracefs_instance_file_read_number(instance, file, &res) && res) + return true; + + return false; +} From patchwork Fri Jan 15 05:04:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12021431 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 745C3C433DB for ; Fri, 15 Jan 2021 05:04:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 33B2C23A01 for ; Fri, 15 Jan 2021 05:04:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729579AbhAOFE5 (ORCPT ); Fri, 15 Jan 2021 00:04:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55736 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726361AbhAOFE4 (ORCPT ); Fri, 15 Jan 2021 00:04:56 -0500 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 17391C0613D3 for ; Thu, 14 Jan 2021 21:04:16 -0800 (PST) Received: by mail-ej1-x62b.google.com with SMTP id t16so11488062ejf.13 for ; Thu, 14 Jan 2021 21:04:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6Lgv+YxSWw/Gv/GThtlJ0i/9eYQrkKOLA9pAKrnq3MI=; b=EVdvQ3VED611fl8iDxH8m/e2OBo7pntgY/e4MWat3mmcaGXcRTjQ/d5C6qKd2kxUoM PS0GsxRgeDZI0K47KOICXAROz9j76AIvteP5eDvtoRa8/hIVXhOpLPK7ozhVMz4aNJFu QACKlQtTopYgCXJI6DM/peaB3scbd/rmtNYbJf3h1j57Gld8QtwQNKLOo4bdARQfvhw4 bZcrhUCtRj37YRY9194hWEzLBWCu1PuoKM7BNnRdXgIhq8XQlH1ufrEAp8ZMROXePxOs OL0vLRT8yLgatWogxvRzcGVMkMYrPcdWnmf5rq+J6KDfY3TLMcQdDSsUkP88WIYSkxmx +Omw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6Lgv+YxSWw/Gv/GThtlJ0i/9eYQrkKOLA9pAKrnq3MI=; b=m+Ux2RTwvxMtoVMwUaR3ml5JsH6Q/iUR2GMfUnfVz5pGI8hhWAxCGXQkuVUiqxy0PI HKu7cq1iNV2a6W3Olmkf17pEa9HB48/wq9shkGUjxwrdIaZgnSeSYYlKuMWBXf0ZggXc sIVnrObtdE05HSW9sKmlOFMRZ2EIFuEYZ0rQHsDt3Lh5UX9gk99TM9VyxFRK/dNI2+9e Xbt1hNtmyQgi7DkjF51T1cLafQ5GaR0p90q40P3PSwz1e5lNzx74wURoW/7QZ7NKA07U 1a90pYG/WwrYPglGOU6HGjYlHjn+UQwf7umECh3Vu66udS8zT5XnVP3uvgKTWOoL6XZr cJzg== X-Gm-Message-State: AOAM531x9VOsWwtBTn3bZEeljiMjJ4vTzeJx7F4tbhMKaTV1lyPz9hBP nARF96/V9M1uvSuCjZztrzpK3ekd9Qsv+15T X-Google-Smtp-Source: ABdhPJzco0ab5bcC0DzRxtzpSUTGavzDD0otFcVKUzjUiS5UyxBEtqQYu3vK0jCvhnom7RSVSUvheA== X-Received: by 2002:a17:906:b244:: with SMTP id ce4mr2303064ejb.159.1610687054797; Thu, 14 Jan 2021 21:04:14 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id d4sm3055670edq.36.2021.01.14.21.04.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Jan 2021 21:04:14 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH 2/5] libtracefs: Unit tests for tracing options APIs Date: Fri, 15 Jan 2021 07:04:07 +0200 Message-Id: <20210115050410.1194011-3-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210115050410.1194011-1-tz.stoyanov@gmail.com> References: <20210115050410.1194011-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Unit tests for these new APIs: tracefs_options_get_supported(); tracefs_option_is_supported(); tracefs_options_get_enabled(); tracefs_option_is_enabled(); tracefs_options_set(); tracefs_options_clear(); tracefs_option_string(); Signed-off-by: Tzvetomir Stoyanov (VMware) --- utest/tracefs-utest.c | 125 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c index 0520f49..1ade5dd 100644 --- a/utest/tracefs-utest.c +++ b/utest/tracefs-utest.c @@ -452,6 +452,129 @@ static void test_tracing_onoff(void) close(fd); } +static bool check_option(long long id, bool exist, int enabled) +{ + const char *name = tracefs_option_string(id); + char file[PATH_MAX]; + char *path = NULL; + bool ret = false; + bool supported; + struct stat st; + char buf[10]; + int fd; + int r; + int rstat; + + CU_TEST(name != NULL); + supported = tracefs_option_is_supported(test_instance, id); + CU_TEST(supported == exist); + if (supported != exist) + goto out; + snprintf(file, PATH_MAX, "options/%s", name); + path = tracefs_instance_get_file(test_instance, file); + CU_TEST(path != NULL); + rstat = stat(path, &st); + if (exist) { + CU_TEST(rstat == 0); + if (rstat != 0) + goto out; + } else { + CU_TEST(stat(path, &st) == -1); + if (rstat != -1) + goto out; + } + + fd = open(path, O_RDONLY); + if (exist) { + CU_TEST(fd >= 0); + if (fd < 0) + goto out; + } else { + CU_TEST(fd < 0); + if (fd >= 0) + goto out; + } + + if (exist && enabled >= 0) { + int val = enabled ? '1' : '0'; + + r = read(fd, buf, 10); + CU_TEST(r == 2); + CU_TEST(buf[0] == val); + if (buf[0] != val) + goto out; + } + + ret = true; +out: + tracefs_put_tracing_file(path); + if (fd >= 0) + close(fd); + return ret; +} + +static void test_tracing_options(void) +{ + unsigned long long options_enabled = 0; + unsigned long long options_all = 0; + unsigned long long i = 1; + char file[PATH_MAX]; + const char *name; + + options_all = tracefs_options_get_supported(test_instance); + options_enabled = tracefs_options_get_enabled(test_instance); + CU_TEST(options_all > 0); + + /* Invalid parameters test */ + CU_TEST(!tracefs_option_is_supported(test_instance, TRACEFS_OPTION_INVALID << 1)); + CU_TEST(!tracefs_option_is_enabled(test_instance, TRACEFS_OPTION_INVALID << 1)); + CU_TEST(tracefs_options_set(test_instance, TRACEFS_OPTION_INVALID << 1) == -1); + CU_TEST(tracefs_options_clear(test_instance, TRACEFS_OPTION_INVALID << 1) == -1); + name = tracefs_option_string(TRACEFS_OPTION_INVALID << 1); + CU_TEST(!strcmp(name, "unknown")); + + /* Test all valid options */ + do { + name = tracefs_option_string(i); + CU_TEST(name != NULL); + CU_TEST(strcmp(name, "unknown")); + snprintf(file, PATH_MAX, "options/%s", name); + + if (options_all & i) { + options_all &= ~i; + CU_TEST(check_option(i, true, -1)); + CU_TEST(tracefs_option_is_supported(test_instance, i)); + } else { + CU_TEST(check_option(i, false, -1)); + CU_TEST(!tracefs_option_is_supported(test_instance, i)); + } + + if (options_enabled & i) { + options_enabled &= ~i; + CU_TEST(check_option(i, true, 1)); + CU_TEST(tracefs_option_is_supported(test_instance, i)); + CU_TEST(tracefs_option_is_enabled(test_instance, i)); + CU_TEST(tracefs_options_clear(test_instance, i) == 0); + CU_TEST(check_option(i, true, 0)); + CU_TEST(tracefs_options_set(test_instance, i) == 0); + CU_TEST(check_option(i, true, 1)); + } else if (options_all & i) { + CU_TEST(check_option(i, true, 0)); + CU_TEST(tracefs_option_is_supported(test_instance, i)); + CU_TEST(!tracefs_option_is_enabled(test_instance, i)); + CU_TEST(tracefs_options_set(test_instance, i) == 0); + CU_TEST(check_option(i, true, 1)); + CU_TEST(tracefs_options_clear(test_instance, i) == 0); + CU_TEST(check_option(i, true, 0)); + } + i <<= 1; + } while (i < TRACEFS_OPTION_INVALID); + + CU_TEST(options_all == 0); + CU_TEST(options_enabled == 0); + +} + static void exclude_string(char **strings, char *name) { int i; @@ -761,5 +884,7 @@ void test_tracefs_lib(void) test_get_clock); CU_add_test(suite, "tracing on / off", test_tracing_onoff); + CU_add_test(suite, "tracing options", + test_tracing_options); } From patchwork Fri Jan 15 05:04:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12021433 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6835C433DB for ; Fri, 15 Jan 2021 05:05:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8F7B023772 for ; Fri, 15 Jan 2021 05:05:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729833AbhAOFFC (ORCPT ); Fri, 15 Jan 2021 00:05:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55756 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726361AbhAOFFB (ORCPT ); Fri, 15 Jan 2021 00:05:01 -0500 Received: from mail-ej1-x62c.google.com (mail-ej1-x62c.google.com [IPv6:2a00:1450:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4264BC0613D6 for ; Thu, 14 Jan 2021 21:04:17 -0800 (PST) Received: by mail-ej1-x62c.google.com with SMTP id by1so5156944ejc.0 for ; Thu, 14 Jan 2021 21:04:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DEipbYOY0q/m9MWeFZQuPDdlQiJOwq1nZTmlB+nMhI0=; b=b7xsEaClTUM01Sd3zuugzI4s7+tb7hIDY+pFBvfN0y9tSOu/Ved99blXdokTLkj9gK woBUMAZ3BbBVAatXv2lLpmZRMxoA3Yeie+tf7NC8PU5MjzAPodhIqFzB+uunLTEX8ryd GYQRveTvbxYwkyLBJAxsG2vR1EQdnCKQxQ/C0LQaI+EKl1BSepyjgFKtsotIm2NiL5Z/ 6tjGqVUmxJ7/nNnlwzdHcI5MTctqwcE+7GxjkNpk4TYFf+XqhKzuLdmMH7WniUv8f4Pd raR9yUBInNkqf9Pr54m3HzixnhZKm2WVsbUFWEh9QiCz2dlSrskji8WOeIjSVDqQU3YM Yl1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DEipbYOY0q/m9MWeFZQuPDdlQiJOwq1nZTmlB+nMhI0=; b=I+Th/hvYX/ZSYEfSmUdKUNR5x8IvM2ZS/Fp1oWTNAO48MFQd+foRrFFTOREx04EjFn +MFl2PXgB8bl1Ll6HYcAZ5l29KUUnpWNdVJ2EqD58a24TGJ02Xp1gd30e6Tw333jd/Kl CJL40DAidWfHBAyUjrzZc8D9fF2qjY3OyM3c5zfx9bxq1xmkYPQkidFWY46pAePUb2v0 xXo7GYSRY90WiRejz/rkV5v3rudhygCaQ4yyrcZPl8gTHm3Eo9/siX8f+mzANdTmqUch R8ASWGim6xIPPnsuvkZwypdWW01SPV5owVIt6lUpO+8SZ3mofdixH7F7bkxhoF4hRlQw RuQA== X-Gm-Message-State: AOAM530e8q0GmrYbnYjpzJdsADm+QB5fFIxH6vYNA2HEEZNvvscK8fQl aTHEyPogBgGugIWlzGNsjv4MlzHwvcqJ7MFz X-Google-Smtp-Source: ABdhPJy+mIby8xaHSwoZ8/YEXGSFV/yOSHuPVizSw6dQDKiM5F12sPoi3mZppqAI6zUdZZJeBNv65w== X-Received: by 2002:a17:907:d25:: with SMTP id gn37mr7373790ejc.381.1610687056047; Thu, 14 Jan 2021 21:04:16 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id d4sm3055670edq.36.2021.01.14.21.04.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Jan 2021 21:04:15 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH 3/5] libtracefs: Add information about top tracing directory in instance structure Date: Fri, 15 Jan 2021 07:04:08 +0200 Message-Id: <20210115050410.1194011-4-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210115050410.1194011-1-tz.stoyanov@gmail.com> References: <20210115050410.1194011-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org There are use cases, where the library could be used with non default system trace directory - for example a partial copy of a system trace directory from another machine. More flexibility is added to the tracefs library, to handle these use cases. The full path to the system trace directory is added in the instance structure and is used to get trace files from that instance. Signed-off-by: Tzvetomir Stoyanov (VMware) --- src/tracefs-instance.c | 80 ++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c index b5f8298..468da1b 100644 --- a/src/tracefs-instance.c +++ b/src/tracefs-instance.c @@ -20,30 +20,43 @@ #define FLAG_INSTANCE_NEWLY_CREATED (1 << 0) struct tracefs_instance { + char *trace_dir; char *name; int flags; }; /** * instance_alloc - allocate a new ftrace instance + * @trace_dir - Full path to the tracing directory, where the instance is * @name: The name of the instance (instance will point to this) * * Returns a newly allocated instance, or NULL in case of an error. */ -static struct tracefs_instance *instance_alloc(const char *name) +static struct tracefs_instance *instance_alloc(const char *trace_dir, const char *name) { struct tracefs_instance *instance; instance = calloc(1, sizeof(*instance)); - if (instance && name) { + if (!instance) + goto error; + instance->trace_dir = strdup(trace_dir); + if (!instance->trace_dir) + goto error; + if (name) { instance->name = strdup(name); - if (!instance->name) { - free(instance); - instance = NULL; - } + if (!instance->name) + goto error; } return instance; + +error: + if (instance) { + free(instance->name); + free(instance->trace_dir); + free(instance); + } + return NULL; } /** @@ -56,6 +69,7 @@ void tracefs_instance_free(struct tracefs_instance *instance) { if (!instance) return; + free(instance->trace_dir); free(instance->name); free(instance); } @@ -105,12 +119,16 @@ bool tracefs_instance_is_new(struct tracefs_instance *instance) struct tracefs_instance *tracefs_instance_create(const char *name) { struct tracefs_instance *inst = NULL; + char *path = NULL; + const char *tdir; struct stat st; mode_t mode; - char *path; int ret; - inst = instance_alloc(name); + tdir = tracefs_tracing_dir(); + if (!tdir) + return NULL; + inst = instance_alloc(tdir, name); if (!inst) return NULL; @@ -170,18 +188,18 @@ int tracefs_instance_destroy(struct tracefs_instance *instance) char * tracefs_instance_get_file(struct tracefs_instance *instance, const char *file) { - char *path; - char *buf; + char *path = NULL; int ret; - if (instance && instance->name) { - ret = asprintf(&buf, "instances/%s/%s", instance->name, file); - if (ret < 0) - return NULL; - path = tracefs_get_tracing_file(buf); - free(buf); - } else - path = tracefs_get_tracing_file(file); + if (!instance) + return tracefs_get_tracing_file(file); + if (!instance->name) + ret = asprintf(&path, "%s/%s", instance->trace_dir, file); + else + ret = asprintf(&path, "%s/instances/%s/%s", + instance->trace_dir, instance->name, file); + if (ret < 0) + return NULL; return path; } @@ -196,21 +214,21 @@ tracefs_instance_get_file(struct tracefs_instance *instance, const char *file) */ char *tracefs_instance_get_dir(struct tracefs_instance *instance) { - char *buf; - char *path; + char *path = NULL; int ret; - if (instance && instance->name) { - ret = asprintf(&buf, "instances/%s", instance->name); - if (ret < 0) { - warning("Failed to allocate path for instance %s", - instance->name); - return NULL; - } - path = tracefs_get_tracing_file(buf); - free(buf); - } else - path = trace_find_tracing_dir(); + if (!instance) /* Top instance of default system trace directory */ + return trace_find_tracing_dir(); + + if (!instance->name) + return strdup(instance->trace_dir); + + ret = asprintf(&path, "%s/instances/%s", instance->trace_dir, instance->name); + if (ret < 0) { + warning("Failed to allocate path for instance %s", + instance->name); + return NULL; + } return path; } From patchwork Fri Jan 15 05:04:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12021435 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 41E95C433E0 for ; Fri, 15 Jan 2021 05:05:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E28023772 for ; Fri, 15 Jan 2021 05:05:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731575AbhAOFFO (ORCPT ); Fri, 15 Jan 2021 00:05:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55806 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726361AbhAOFFO (ORCPT ); Fri, 15 Jan 2021 00:05:14 -0500 Received: from mail-ej1-x62e.google.com (mail-ej1-x62e.google.com [IPv6:2a00:1450:4864:20::62e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A3B5C061786 for ; Thu, 14 Jan 2021 21:04:18 -0800 (PST) Received: by mail-ej1-x62e.google.com with SMTP id w1so11507226ejf.11 for ; Thu, 14 Jan 2021 21:04:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ptMlY7gFRD7MomV3w62QcfI2MNa6nf68S716lDFDzZ0=; b=eCcJPO2G9aL5FXM+PbcyNGm7qXb3J8VvP2E4NUZ/WcobXO+NE/RKsbqZUpPqkIVKjf jsXf9ioFm3XTZwjdUm4d+2FVd5/otOz9Hf0ObEfjpwX7GNlqcPdsim4REaq2U0Qrahdn J1PDpb7ZR37S+8YEY33ckORTockYc0nvc3JkMXNOYWmgcQWQWjFGQluQSW6r/bPR1qUc EgKYaagfR1s1mF+hEbMTgCwCZ9LI9jE3x1VEvD/SDzjGcx651BBhfz3rPQMUsZ5yJdkk PIUZ41XVkiMjDGsyEftW7KLw7lox1Z+yIGw8E8qm5t88EgCZLzdrG0OLdJQ55P5DSJaY XMjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ptMlY7gFRD7MomV3w62QcfI2MNa6nf68S716lDFDzZ0=; b=JMxplaJrPf4JEIEgUbOmY472pJDWOuQU3/Z2pNonculm1G30GLfK14uDKNAdbFYgFy 0YZHXhvDDxfbB/5iuxL7q2Zp7sSygzHzrwXeJ5HS94r/v/vS6cfZQJXtC64nmPrVIvm6 ffdcVPk7jedIjfLpe2srfdJgwNCExySQPmrQn9opABYBSMRp/wU0xL7LZ+ykpLB8OhCi Q9btTJyUJXFSpTuxqHEF8sV8fXzluJqCIGK+vwRw2mTgylEazXmlGilMjA/smfwUSF1J wzOe+a8PG4wqiWaLXKRSoMsktO7Plrjnc0lS3yTArEN+D060p05aTc7hd8aUU4K9qtZv uebw== X-Gm-Message-State: AOAM532Vf7vq0auzw0UbhLZMyM98B7/n4wNtsi2Agf/QnsRZjvZqSq51 BA0fE+0lT6xdPwzh/IoOO8I= X-Google-Smtp-Source: ABdhPJyEUGt5hhFaR29l5znvPXsh4dREstHEWHjmgNPyyxVuXzi9Vt8cRTkCu5cy0pI33DEqeXKpVg== X-Received: by 2002:a17:906:ae42:: with SMTP id lf2mr7304045ejb.487.1610687057070; Thu, 14 Jan 2021 21:04:17 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id d4sm3055670edq.36.2021.01.14.21.04.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Jan 2021 21:04:16 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH 4/5] libtracefs: New APIs for getting existing trace instance Date: Fri, 15 Jan 2021 07:04:09 +0200 Message-Id: <20210115050410.1194011-5-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210115050410.1194011-1-tz.stoyanov@gmail.com> References: <20210115050410.1194011-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org The new API allocates an instance structure for existing trace instance. It has an optional tracing_dir parameter, which allows to get instances from non default trace directory. If the instance with the given name does not exist, the API fails. If no name is given, the structure for the top instance in the given trace directory is allocated and returned. struct tracefs_instance *tracefs_instance_get(const char *tracing_dir, const char *name); This helper API is added also, to get the tracing directory where the instance is configured. In most cases this should be the default system trace directroy mount point. const char *tracefs_instance_get_trace_dir(struct tracefs_instance *instance); Signed-off-by: Tzvetomir Stoyanov (VMware) --- include/tracefs.h | 3 +++ src/tracefs-instance.c | 57 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/tracefs.h b/include/tracefs.h index 1f10a00..20aa995 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -20,9 +20,12 @@ struct tracefs_instance; void tracefs_instance_free(struct tracefs_instance *instance); struct tracefs_instance *tracefs_instance_create(const char *name); +struct tracefs_instance *tracefs_instance_get(const char *tracing_dir, + const char *name); int tracefs_instance_destroy(struct tracefs_instance *instance); bool tracefs_instance_is_new(struct tracefs_instance *instance); const char *tracefs_instance_get_name(struct tracefs_instance *instance); +const char *tracefs_instance_get_trace_dir(struct tracefs_instance *instance); char * tracefs_instance_get_file(struct tracefs_instance *instance, const char *file); char *tracefs_instance_get_dir(struct tracefs_instance *instance); diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c index 468da1b..112e237 100644 --- a/src/tracefs-instance.c +++ b/src/tracefs-instance.c @@ -151,6 +151,49 @@ error: return NULL; } +/** + * tracefs_instance_get - Allocate an instance structure for existing trace instance + * @tracing_dir: full path to the system trace directory, where the new instance is + * if NULL, the default top tracing directory is used. + * @name: Name of the instance. + * + * Allocates and initializes a new instance structure. If the instance does not + * exist, do not create it and exit with error. + * Returns a pointer to a newly allocated instance, or NULL in case of an error + * or the requested instance does not exists. + * The returned instance must be freed by tracefs_instance_free(). + */ +struct tracefs_instance *tracefs_instance_get(const char *tracing_dir, + const char *name) +{ + struct tracefs_instance *inst = NULL; + char file[PATH_MAX]; + const char *tdir; + struct stat st; + int ret; + + if (tracing_dir) { + ret = stat(tracing_dir, &st); + if (ret < 0 || !S_ISDIR(st.st_mode)) + return NULL; + tdir = tracing_dir; + + } else + tdir = tracefs_tracing_dir(); + if (!tdir) + return NULL; + + if (name) { + sprintf(file, "%s/instances/%s", tdir, name); + ret = stat(file, &st); + if (ret < 0 || !S_ISDIR(st.st_mode)) + return NULL; + } + inst = instance_alloc(tdir, name); + + return inst; +} + /** * tracefs_instance_destroy - Remove a ftrace instance * @instance: Pointer to the instance to be removed @@ -247,6 +290,20 @@ const char *tracefs_instance_get_name(struct tracefs_instance *instance) return NULL; } +/** + * tracefs_instance_get_trace_dir - return the top trace directory, where the instance is confuigred + * @instance: ftrace instance + * + * Returns the top trace directory where the given @instance is configured. + * The returned string must *not* be freed. + */ +const char *tracefs_instance_get_trace_dir(struct tracefs_instance *instance) +{ + if (instance) + return instance->trace_dir; + return NULL; +} + static int write_file(const char *file, const char *str) { int ret; From patchwork Fri Jan 15 05:04:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12021437 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 989B7C433DB for ; Fri, 15 Jan 2021 05:05:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5937F23772 for ; Fri, 15 Jan 2021 05:05:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726361AbhAOFFP (ORCPT ); Fri, 15 Jan 2021 00:05:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55808 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731570AbhAOFFO (ORCPT ); Fri, 15 Jan 2021 00:05:14 -0500 Received: from mail-ej1-x631.google.com (mail-ej1-x631.google.com [IPv6:2a00:1450:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC9CEC061793 for ; Thu, 14 Jan 2021 21:04:19 -0800 (PST) Received: by mail-ej1-x631.google.com with SMTP id t16so11488189ejf.13 for ; Thu, 14 Jan 2021 21:04:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=H1IH3ZQcz64kG7pDGKbHg5uc5lFAK3+6W/LDm17hCYw=; b=L8fm2lMl+4rh9UmpHg8OTM5L0/k0U5kwdAgzJeDAJiiBVDjBK8TRvXDQ6shR2n/poy roJhX90hesYCj9ABZEfN4k2CZ7/w5CvEunVjiBTH+q2XtfEzi1+6n+ur0EVwwwM9n6kL 0zCXryeCkjIIz+8eqBp7Meu+CYDhnp5MdL/YZ/1gQkHDXx0xrFz7Ow2OMr7PIv7qgRXV 1Ov5uT2TsI57MM2Vd10D4mZKOeVbivXxPEXkRHhEI4WdYOvB7p+0XPaR/RsQfyV/HiV3 0IiKd3o8IEq2qG5InKCfq8VC3d7sUuA5aZLVC8nB0luPH7oujx8C3PDt6zr5ou6PcgNh 5FHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=H1IH3ZQcz64kG7pDGKbHg5uc5lFAK3+6W/LDm17hCYw=; b=WgcjZud1GiAPfl3vr4RmbE4c9svNwzqkzpNXlRU1v8KJVOAat+ITTBYTi8hSwwZ2Zg WGJf54kLv8glZwDe8oelfdLLMXx8pGBxLR/pPKgpw67lINluQeuhgNTlb6uzNvuyEQRY KD/BpVRUvFxz9FlXV1X1YvPLGcDhraJhRnjHlnFWm+946HVKp5caBvo5kUEeQOpHI6YY UAALEO4jnJDPRLVFisQ9k9FBo6HJO+Ja/vuSDKJ6+0F0i1JHFQySn32bCaa0m/dQsp0e pfj/9QgLM/FUthvVtWzF0s1ip+rrtx5sqjHZ7YJ5v8fNuVAItTm2zOo2atEj2bgD0K15 IWWw== X-Gm-Message-State: AOAM5330jp/CryGyd8aaL7dcdscGSeh6nG4ZRcpKwGlpw5ssQdoLUsZO EjCWbUUxY9rjEKmSXaJTYJQ= X-Google-Smtp-Source: ABdhPJx1JxUtUPPFQzOdtKHaexh5MU3J2Onj/2Fx7D0ATZArCOihfN7/8xX/49YLGkgGYifNqHRMRA== X-Received: by 2002:a17:906:4e53:: with SMTP id g19mr7441274ejw.454.1610687058450; Thu, 14 Jan 2021 21:04:18 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id d4sm3055670edq.36.2021.01.14.21.04.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Jan 2021 21:04:17 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH 5/5] libtracefs: Unit tests for working with non default tracing dir Date: Fri, 15 Jan 2021 07:04:10 +0200 Message-Id: <20210115050410.1194011-6-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210115050410.1194011-1-tz.stoyanov@gmail.com> References: <20210115050410.1194011-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org All unit tests are modified to work with custom defined trace directory, instead of default system one. A new tests are added which duplicate part of the system trace directory and test various library APIs on that copy. Signed-off-by: Tzvetomir Stoyanov (VMware) --- utest/tracefs-utest.c | 349 +++++++++++++++++++++++++++++++----------- 1 file changed, 261 insertions(+), 88 deletions(-) diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c index 1ade5dd..a45a19a 100644 --- a/utest/tracefs-utest.c +++ b/utest/tracefs-utest.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -18,8 +19,15 @@ #define TRACEFS_SUITE "trasefs library" #define TEST_INSTANCE_NAME "cunit_test_iter" +#define TEST_TRACE_DIR "/tmp/trace_utest.XXXXXX" #define TEST_ARRAY_SIZE 500 +#define ALL_TRACERS "available_tracers" +#define CUR_TRACER "current_tracer" +#define PER_CPU "per_cpu" +#define TRACE_ON "tracing_on" +#define TRACE_CLOCK "trace_clock" + static struct tracefs_instance *test_instance; static struct tep_handle *test_tep; struct test_sample { @@ -55,7 +63,7 @@ static int test_callback(struct tep_event *event, struct tep_record *record, return 0; } -static void test_iter_write(void) +static void test_iter_write(struct tracefs_instance *instance) { int cpus = sysconf(_SC_NPROCESSORS_CONF); cpu_set_t *cpuset, *cpusave; @@ -70,7 +78,7 @@ static void test_iter_write(void) sched_getaffinity(0, cpu_size, cpusave); - path = tracefs_instance_get_file(test_instance, "trace_marker"); + path = tracefs_instance_get_file(instance, "trace_marker"); CU_TEST(path != NULL); fd = open(path, O_WRONLY); tracefs_put_tracing_file(path); @@ -94,15 +102,15 @@ static void test_iter_write(void) } -static void iter_raw_events_on_cpu(int cpu) +static void iter_raw_events_on_cpu(struct tracefs_instance *instance, int cpu) { int check = 0; int ret; int i; test_found = 0; - test_iter_write(); - ret = tracefs_iterate_raw_events(test_tep, test_instance, NULL, 0, + test_iter_write(instance); + ret = tracefs_iterate_raw_events(test_tep, instance, NULL, 0, test_callback, &cpu); CU_TEST(ret == 0); if (cpu < 0) { @@ -120,22 +128,27 @@ static void iter_raw_events_on_cpu(int cpu) } } -static void test_iter_raw_events(void) +static void test_instance_iter_raw_events(struct tracefs_instance *instance) { int cpus = sysconf(_SC_NPROCESSORS_CONF); int ret; int i; - ret = tracefs_iterate_raw_events(NULL, test_instance, NULL, 0, test_callback, NULL); + ret = tracefs_iterate_raw_events(NULL, instance, NULL, 0, test_callback, NULL); CU_TEST(ret < 0); ret = tracefs_iterate_raw_events(test_tep, NULL, NULL, 0, test_callback, NULL); CU_TEST(ret == 0); - ret = tracefs_iterate_raw_events(test_tep, test_instance, NULL, 0, NULL, NULL); + ret = tracefs_iterate_raw_events(test_tep, instance, NULL, 0, NULL, NULL); CU_TEST(ret < 0); - iter_raw_events_on_cpu(-1); + iter_raw_events_on_cpu(instance, -1); for (i = 0; i < cpus; i++) - iter_raw_events_on_cpu(i); + iter_raw_events_on_cpu(instance, i); +} + +static void test_iter_raw_events(void) +{ + test_instance_iter_raw_events(test_instance); } #define RAND_STR_SIZE 20 @@ -215,10 +228,6 @@ static void test_instance_file_read(struct tracefs_instance *inst, const char *f free(file); } -#define ALL_TRACERS "available_tracers" -#define CUR_TRACER "current_tracer" -#define PER_CPU "per_cpu" -#define TRACE_ON "tracing_on" static void test_instance_file(void) { struct tracefs_instance *instance = NULL; @@ -323,7 +332,7 @@ static void test_instance_file(void) free(inst_dir); } -static bool check_fd_name(int fd, char *name) +static bool check_fd_name(int fd, const char *dir, const char *name) { char link[PATH_MAX + 1]; char path[PATH_MAX + 1]; @@ -344,6 +353,10 @@ static bool check_fd_name(int fd, char *name) if (ret > PATH_MAX || ret < 0) return false; path[ret] = 0; + ret = strncmp(dir, path, strlen(dir)); + CU_TEST(ret == 0); + if (ret) + return false; file = basename(path); CU_TEST(file != NULL); if (!file) @@ -389,23 +402,26 @@ static bool check_fd_mode(int fd, int mode) return true; } -static void test_instance_file_fd(void) +static void test_instance_file_fd(struct tracefs_instance *instance) { const char *name = get_rand_str(); + const char *tdir = tracefs_instance_get_trace_dir(instance); long long res = -1; char rd[2]; int fd; - fd = tracefs_instance_file_open(test_instance, name, -1); + CU_TEST(tdir != NULL); + fd = tracefs_instance_file_open(instance, name, -1); CU_TEST(fd == -1); - fd = tracefs_instance_file_open(test_instance, TRACE_ON, O_RDONLY); + fd = tracefs_instance_file_open(instance, TRACE_ON, O_RDONLY); CU_TEST(fd >= 0); - CU_TEST(check_fd_name(fd, TRACE_ON)); + + CU_TEST(check_fd_name(fd, tdir, TRACE_ON)); CU_TEST(check_fd_mode(fd, O_RDONLY)); - CU_TEST(tracefs_instance_file_read_number(test_instance, "available_tracer", &res) != 0); - CU_TEST(tracefs_instance_file_read_number(test_instance, name, &res) != 0); - CU_TEST(tracefs_instance_file_read_number(test_instance, TRACE_ON, &res) == 0); + CU_TEST(tracefs_instance_file_read_number(instance, ALL_TRACERS, &res) != 0); + CU_TEST(tracefs_instance_file_read_number(instance, name, &res) != 0); + CU_TEST(tracefs_instance_file_read_number(instance, TRACE_ON, &res) == 0); CU_TEST((res == 0 || res == 1)); CU_TEST(read(fd, &rd, 1) == 1); rd[1] = 0; @@ -414,45 +430,57 @@ static void test_instance_file_fd(void) close(fd); } -static void test_tracing_onoff(void) +static void test_file_fd(void) { + test_instance_file_fd(test_instance); +} + +static void test_instance_tracing_onoff(struct tracefs_instance *instance) +{ + const char *tdir = tracefs_instance_get_trace_dir(instance); long long res = -1; int fd; - fd = tracefs_trace_on_get_fd(test_instance); + CU_TEST(tdir != NULL); + fd = tracefs_trace_on_get_fd(instance); CU_TEST(fd >= 0); - CU_TEST(check_fd_name(fd, TRACE_ON)); + CU_TEST(check_fd_name(fd, tdir, TRACE_ON)); CU_TEST(check_fd_mode(fd, O_RDWR)); - CU_TEST(tracefs_instance_file_read_number(test_instance, TRACE_ON, &res) == 0); + CU_TEST(tracefs_instance_file_read_number(instance, TRACE_ON, &res) == 0); if (res == 1) { - CU_TEST(tracefs_trace_is_on(test_instance) == 1); - CU_TEST(tracefs_trace_off(test_instance) == 0); - CU_TEST(tracefs_trace_is_on(test_instance) == 0); - CU_TEST(tracefs_trace_on(test_instance) == 0); - CU_TEST(tracefs_trace_is_on(test_instance) == 1); + CU_TEST(tracefs_trace_is_on(instance) == 1); + CU_TEST(tracefs_trace_off(instance) == 0); + CU_TEST(tracefs_trace_is_on(instance) == 0); + CU_TEST(tracefs_trace_on(instance) == 0); + CU_TEST(tracefs_trace_is_on(instance) == 1); CU_TEST(tracefs_trace_off_fd(fd) == 0); - CU_TEST(tracefs_trace_is_on(test_instance) == 0); + CU_TEST(tracefs_trace_is_on(instance) == 0); CU_TEST(tracefs_trace_on_fd(fd) == 0); - CU_TEST(tracefs_trace_is_on(test_instance) == 1); + CU_TEST(tracefs_trace_is_on(instance) == 1); } else { - CU_TEST(tracefs_trace_is_on(test_instance) == 0); - CU_TEST(tracefs_trace_on(test_instance) == 0); - CU_TEST(tracefs_trace_is_on(test_instance) == 1); - CU_TEST(tracefs_trace_off(test_instance) == 0); - CU_TEST(tracefs_trace_is_on(test_instance) == 0); + CU_TEST(tracefs_trace_is_on(instance) == 0); + CU_TEST(tracefs_trace_on(instance) == 0); + CU_TEST(tracefs_trace_is_on(instance) == 1); + CU_TEST(tracefs_trace_off(instance) == 0); + CU_TEST(tracefs_trace_is_on(instance) == 0); CU_TEST(tracefs_trace_on_fd(fd) == 0); - CU_TEST(tracefs_trace_is_on(test_instance) == 1); + CU_TEST(tracefs_trace_is_on(instance) == 1); CU_TEST(tracefs_trace_off_fd(fd) == 0); - CU_TEST(tracefs_trace_is_on(test_instance) == 0); + CU_TEST(tracefs_trace_is_on(instance) == 0); } if (fd >= 0) close(fd); } -static bool check_option(long long id, bool exist, int enabled) +static void test_tracing_onoff(void) +{ + test_instance_tracing_onoff(test_instance); +} + +static bool check_option(struct tracefs_instance *instance, long long id, bool exist, int enabled) { const char *name = tracefs_option_string(id); char file[PATH_MAX]; @@ -466,12 +494,12 @@ static bool check_option(long long id, bool exist, int enabled) int rstat; CU_TEST(name != NULL); - supported = tracefs_option_is_supported(test_instance, id); + supported = tracefs_option_is_supported(instance, id); CU_TEST(supported == exist); if (supported != exist) goto out; snprintf(file, PATH_MAX, "options/%s", name); - path = tracefs_instance_get_file(test_instance, file); + path = tracefs_instance_get_file(instance, file); CU_TEST(path != NULL); rstat = stat(path, &st); if (exist) { @@ -499,7 +527,7 @@ static bool check_option(long long id, bool exist, int enabled) int val = enabled ? '1' : '0'; r = read(fd, buf, 10); - CU_TEST(r == 2); + CU_TEST(r >= 1); CU_TEST(buf[0] == val); if (buf[0] != val) goto out; @@ -513,7 +541,7 @@ out: return ret; } -static void test_tracing_options(void) +static void test_instance_tracing_options(struct tracefs_instance *instance) { unsigned long long options_enabled = 0; unsigned long long options_all = 0; @@ -521,15 +549,15 @@ static void test_tracing_options(void) char file[PATH_MAX]; const char *name; - options_all = tracefs_options_get_supported(test_instance); - options_enabled = tracefs_options_get_enabled(test_instance); + options_all = tracefs_options_get_supported(instance); + options_enabled = tracefs_options_get_enabled(instance); CU_TEST(options_all > 0); /* Invalid parameters test */ - CU_TEST(!tracefs_option_is_supported(test_instance, TRACEFS_OPTION_INVALID << 1)); - CU_TEST(!tracefs_option_is_enabled(test_instance, TRACEFS_OPTION_INVALID << 1)); - CU_TEST(tracefs_options_set(test_instance, TRACEFS_OPTION_INVALID << 1) == -1); - CU_TEST(tracefs_options_clear(test_instance, TRACEFS_OPTION_INVALID << 1) == -1); + CU_TEST(!tracefs_option_is_supported(instance, TRACEFS_OPTION_INVALID << 1)); + CU_TEST(!tracefs_option_is_enabled(instance, TRACEFS_OPTION_INVALID << 1)); + CU_TEST(tracefs_options_set(instance, TRACEFS_OPTION_INVALID << 1) == -1); + CU_TEST(tracefs_options_clear(instance, TRACEFS_OPTION_INVALID << 1) == -1); name = tracefs_option_string(TRACEFS_OPTION_INVALID << 1); CU_TEST(!strcmp(name, "unknown")); @@ -542,37 +570,41 @@ static void test_tracing_options(void) if (options_all & i) { options_all &= ~i; - CU_TEST(check_option(i, true, -1)); - CU_TEST(tracefs_option_is_supported(test_instance, i)); + CU_TEST(check_option(instance, i, true, -1)); + CU_TEST(tracefs_option_is_supported(instance, i)); } else { - CU_TEST(check_option(i, false, -1)); - CU_TEST(!tracefs_option_is_supported(test_instance, i)); + CU_TEST(check_option(instance, i, false, -1)); + CU_TEST(!tracefs_option_is_supported(instance, i)); } if (options_enabled & i) { options_enabled &= ~i; - CU_TEST(check_option(i, true, 1)); - CU_TEST(tracefs_option_is_supported(test_instance, i)); - CU_TEST(tracefs_option_is_enabled(test_instance, i)); - CU_TEST(tracefs_options_clear(test_instance, i) == 0); - CU_TEST(check_option(i, true, 0)); - CU_TEST(tracefs_options_set(test_instance, i) == 0); - CU_TEST(check_option(i, true, 1)); + CU_TEST(check_option(instance, i, true, 1)); + CU_TEST(tracefs_option_is_supported(instance, i)); + CU_TEST(tracefs_option_is_enabled(instance, i)); + CU_TEST(tracefs_options_clear(instance, i) == 0); + CU_TEST(check_option(instance, i, true, 0)); + CU_TEST(tracefs_options_set(instance, i) == 0); + CU_TEST(check_option(instance, i, true, 1)); } else if (options_all & i) { - CU_TEST(check_option(i, true, 0)); - CU_TEST(tracefs_option_is_supported(test_instance, i)); - CU_TEST(!tracefs_option_is_enabled(test_instance, i)); - CU_TEST(tracefs_options_set(test_instance, i) == 0); - CU_TEST(check_option(i, true, 1)); - CU_TEST(tracefs_options_clear(test_instance, i) == 0); - CU_TEST(check_option(i, true, 0)); + CU_TEST(check_option(instance, i, true, 0)); + CU_TEST(tracefs_option_is_supported(instance, i)); + CU_TEST(!tracefs_option_is_enabled(instance, i)); + CU_TEST(tracefs_options_set(instance, i) == 0); + CU_TEST(check_option(instance, i, true, 1)); + CU_TEST(tracefs_options_clear(instance, i) == 0); + CU_TEST(check_option(instance, i, true, 0)); } i <<= 1; } while (i < TRACEFS_OPTION_INVALID); CU_TEST(options_all == 0); CU_TEST(options_enabled == 0); +} +static void test_tracing_options(void) +{ + test_instance_tracing_options(test_instance); } static void exclude_string(char **strings, char *name) @@ -606,16 +638,13 @@ static void test_check_files(const char *fdir, char **files) CU_TEST(files[i][0] == '/'); } -static void test_system_event(void) +static void system_event(const char *tdir) { - const char *tdir; + char **systems; char **events; char *sdir = NULL; - tdir = tracefs_tracing_dir(); - CU_TEST(tdir != NULL); - systems = tracefs_event_systems(tdir); CU_TEST(systems != NULL); @@ -638,7 +667,16 @@ static void test_system_event(void) free(sdir); } -static void test_tracers(void) +static void test_system_event(void) +{ + const char *tdir; + + tdir = tracefs_tracing_dir(); + CU_TEST(tdir != NULL); + system_event(tdir); +} + +static void test_instance_tracers(struct tracefs_instance *instance) { const char *tdir; char **tracers; @@ -646,7 +684,7 @@ static void test_tracers(void) char *tracer; int i; - tdir = tracefs_tracing_dir(); + tdir = tracefs_instance_get_trace_dir(instance); CU_TEST(tdir != NULL); tracers = tracefs_tracers(tdir); @@ -667,6 +705,11 @@ static void test_tracers(void) free(tfile); } +static void test_tracers(void) +{ + test_instance_tracers(test_instance); +} + static void test_check_events(struct tep_handle *tep, char *system, bool exist) { struct dirent *dent; @@ -706,17 +749,13 @@ static void test_check_events(struct tep_handle *tep, char *system, bool exist) } -static void test_local_events(void) +static void local_events(const char *tdir) { struct tep_handle *tep; - const char *tdir; char **systems; char *lsystems[3]; int i; - tdir = tracefs_tracing_dir(); - CU_TEST(tdir != NULL); - tep = tracefs_local_events(tdir); CU_TEST(tep != NULL); @@ -757,6 +796,15 @@ static void test_local_events(void) tracefs_list_free(systems); } +static void test_local_events(void) +{ + const char *tdir; + + tdir = tracefs_tracing_dir(); + CU_TEST(tdir != NULL); + local_events(tdir); +} + struct test_walk_instance { struct tracefs_instance *instance; bool found; @@ -806,13 +854,13 @@ static void test_instances_walk(void) } } -static void current_clock_check(const char *clock) +static void current_clock_check(struct tracefs_instance *instance, const char *clock) { int size = 0; char *clocks; char *str; - clocks = tracefs_instance_file_read(test_instance, "trace_clock", &size); + clocks = tracefs_instance_file_read(instance, TRACE_CLOCK, &size); CU_TEST(clocks != NULL); CU_TEST(size > strlen(clock)); str = strstr(clocks, clock); @@ -823,16 +871,140 @@ static void current_clock_check(const char *clock) free(clocks); } -static void test_get_clock(void) +static void test_instance_get_clock(struct tracefs_instance *instance) { const char *clock; - clock = tracefs_get_clock(test_instance); + clock = tracefs_get_clock(instance); CU_TEST(clock != NULL); - current_clock_check(clock); + current_clock_check(instance, clock); free((char *)clock); } +static void test_get_clock(void) +{ + test_instance_get_clock(test_instance); +} + +static void copy_trace_file(const char *from, char *to) +{ + int fd_from = -1; + int fd_to = -1; + char buf[512]; + int ret; + + fd_from = open(from, O_RDONLY); + if (fd_from < 0) + goto out; + fd_to = open(to, O_WRONLY | O_TRUNC | O_CREAT); + if (fd_to < 0) + goto out; + + while ((ret = read(fd_from, buf, 512)) > 0) { + if (write(fd_to, buf, ret) == -1) + break; + } + +out: + if (fd_to >= 0) + close(fd_to); + if (fd_from >= 0) + close(fd_from); +} + +static int trace_dir_base; +static char *trace_tmp_dir; +static int copy_trace_walk(const char *fpath, const struct stat *sb, + int typeflag, struct FTW *ftwbuf) +{ + char path[PATH_MAX]; + + sprintf(path, "%s%s", trace_tmp_dir, fpath + trace_dir_base); + + switch (typeflag) { + case FTW_D: + mkdir(path, 0750); + break; + case FTW_F: + copy_trace_file(fpath, path); + break; + default: + break; + } + return 0; +} + +static void dup_trace_dir(char *to, char *dir) +{ + const char *trace_dir = tracefs_tracing_dir(); + char file_from[PATH_MAX]; + char file_to[PATH_MAX]; + + sprintf(file_from, "%s/%s", trace_dir, dir); + sprintf(file_to, "%s/%s", to, dir); + trace_tmp_dir = file_to; + trace_dir_base = strlen(file_from); + nftw(file_from, copy_trace_walk, 20, 0); +} + +static void dup_trace_file(char *to, char *file) +{ + const char *trace_dir = tracefs_tracing_dir(); + char file_from[PATH_MAX]; + char file_to[PATH_MAX]; + + sprintf(file_from, "%s/%s", trace_dir, file); + sprintf(file_to, "%s/%s", to, file); + copy_trace_file(file_from, file_to); +} + +static char *copy_trace_dir(void) +{ + char template[] = TEST_TRACE_DIR; + char *dname = mkdtemp(template); + + dup_trace_dir(dname, "events"); + dup_trace_dir(dname, "options"); + dup_trace_file(dname, TRACE_ON); + dup_trace_file(dname, CUR_TRACER); + dup_trace_file(dname, TRACE_CLOCK); + dup_trace_file(dname, ALL_TRACERS); + + return strdup(dname); +} + +static int del_trace_walk(const char *fpath, const struct stat *sb, + int typeflag, struct FTW *ftwbuf) +{ + remove(fpath); + return 0; +} + +void del_trace_dir(char *dir) +{ + nftw(dir, del_trace_walk, 20, FTW_DEPTH); +} + +static void test_custom_trace_dir(void) +{ + struct tracefs_instance *instance; + char *dname = copy_trace_dir(); + + instance = tracefs_instance_get(dname, NULL); + CU_TEST(instance != NULL); + + system_event(dname); + local_events(dname); + test_instance_tracing_options(instance); + test_instance_get_clock(instance); + test_instance_file_fd(instance); + test_instance_tracers(instance); + + tracefs_instance_free(instance); + del_trace_dir(dname); + free(dname); +} + static int test_suite_destroy(void) { tracefs_instance_destroy(test_instance); @@ -867,7 +1039,7 @@ void test_tracefs_lib(void) CU_add_test(suite, "tracing file / directory APIs", test_trace_file); CU_add_test(suite, "instance file / directory APIs", - test_instance_file_fd); + test_file_fd); CU_add_test(suite, "instance file descriptor", test_instance_file); CU_add_test(suite, "systems and events APIs", @@ -886,5 +1058,6 @@ void test_tracefs_lib(void) test_tracing_onoff); CU_add_test(suite, "tracing options", test_tracing_options); - + CU_add_test(suite, "custom system directory", + test_custom_trace_dir); }