From patchwork Wed Jan 20 15:12:52 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: 12032645 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 BEE54C433E9 for ; Wed, 20 Jan 2021 15:23:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8E4A4233EB for ; Wed, 20 Jan 2021 15:23:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731979AbhATPXZ (ORCPT ); Wed, 20 Jan 2021 10:23:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34328 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390556AbhATPNl (ORCPT ); Wed, 20 Jan 2021 10:13:41 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F1549C061757 for ; Wed, 20 Jan 2021 07:13:00 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id d26so23432304wrb.12 for ; Wed, 20 Jan 2021 07:13:00 -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=NR8Rp1f4MT9wUwWwc3+wHHZOq9Ja7AJcb3OyBHKwQW4=; b=kOisUo6UEYbHtMYi8do2QNoV2xCPeh3gfUXcDOGGXenn66iJZoqNnJBYmh47ioMwSc NikpYOK3yt1s4g6Kg0FoNQ5LojNvvedZe0YGBHWrjSFm5LjQXlmOeVMxENBDC8Y5fGUC jwoaVJ5bYYRxr8JLdpGZOvDREP+qabm9cViFeqPtV3coxpupzo25gSn0OcFiMkMpJMS2 9GzxKXfdVbjLGV/XvD56JGvKuqRPJtSAqNzL+UjNAhsYglY4bh/u2fs+YFGtaV39r9kC 3oIzXDH1AvKeAjgmQ8/XnIBPhQ91LvPhoCcjl3AUu74eQ03ne8FJdg/venfIRVOvJy11 RNeA== 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=NR8Rp1f4MT9wUwWwc3+wHHZOq9Ja7AJcb3OyBHKwQW4=; b=SJXfXaFow9v7tT4mbOWttlgdtsjTaxmhrq3mTjqa4wuhnc5gsqF/fUvnq2ZTo4Kw0x AmZRNixzpzERsCPkEfP/FgrSvwS9M/NPw9GH3Ru05R0aS/oI/cazpdDtX9hvg/kc95WH HcugmwnYo6WMQ36udXERtd889udJedqsAs/jxlcyLHKNP8mIhAsjfW+07t53YBUXKQRK V93tQXbTEYkAEKtnQ/VgwUPWVVBpEVtW4ixJvhpSZrsTwdiYJJ73EC8TADscA2SBVifV Vsmi0qMriD4zmeFdKFVrn0XkNGPUbLEeNUw8RIsUooLluGGxlJV6Ep3fHQpDS78ak6Hc D1jA== X-Gm-Message-State: AOAM533jWdDQ7ZQxlzopasHh/98zBPtCeGpxi4AHJZBh2q2CtsfS/CqV Yy7DDK52rZL3SJDohnhAhKw= X-Google-Smtp-Source: ABdhPJy/zF9/8d1FQi60XqiOblz/BwXINC89pWJ05hCBxXsLBt4xymguj4KwGR3dqlVAUubcdOsmpA== X-Received: by 2002:a5d:62c8:: with SMTP id o8mr9995865wrv.51.1611155579682; Wed, 20 Jan 2021 07:12:59 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id c11sm4571106wmd.36.2021.01.20.07.12.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 07:12:59 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 1/5] libtracefs: New APIs for trace options Date: Wed, 20 Jan 2021 17:12:52 +0200 Message-Id: <20210120151256.43075-2-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210120151256.43075-1-tz.stoyanov@gmail.com> References: <20210120151256.43075-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_option_set(); tracefs_option_clear(); tracefs_option_is_set(); tracefs_options_get_supported(); tracefs_option_is_supported(); tracefs_options_get_enabled(); tracefs_option_is_enabled(); tracefs_option_enable(); tracefs_option_diasble(); tracefs_option_name(); Signed-off-by: Tzvetomir Stoyanov (VMware) --- include/tracefs.h | 61 +++++++++++ src/tracefs-tools.c | 244 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+) diff --git a/include/tracefs.h b/include/tracefs.h index 85a776e..2df596f 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -80,4 +80,65 @@ int tracefs_fill_local_events(const char *tracing_dir, char *tracefs_get_clock(struct tracefs_instance *instance); +enum tracefs_option_id { + TRACEFS_OPTION_INVALID = 0, + TRACEFS_OPTION_ANNOTATE, + TRACEFS_OPTION_BIN, + TRACEFS_OPTION_BLK_CGNAME, + TRACEFS_OPTION_BLK_CGROUP, + TRACEFS_OPTION_BLK_CLASSIC, + TRACEFS_OPTION_BLOCK, + TRACEFS_OPTION_CONTEXT_INFO, + TRACEFS_OPTION_DISABLE_ON_FREE, + TRACEFS_OPTION_DISPLAY_GRAPH, + TRACEFS_OPTION_EVENT_FORK, + TRACEFS_OPTION_FGRAPH_ABSTIME, + TRACEFS_OPTION_FGRAPH_CPU, + TRACEFS_OPTION_FGRAPH_DURATION, + TRACEFS_OPTION_FGRAPH_IRQS, + TRACEFS_OPTION_FGRAPH_OVERHEAD, + TRACEFS_OPTION_FGRAPH_OVERRUN, + TRACEFS_OPTION_FGRAPH_PROC, + TRACEFS_OPTION_FGRAPH_TAIL, + TRACEFS_OPTION_FUNC_STACKTRACE, + TRACEFS_OPTION_FUNCTION_FORK, + TRACEFS_OPTION_FUNCTION_TRACE, + TRACEFS_OPTION_GRAPH_TIME, + TRACEFS_OPTION_HEX, + TRACEFS_OPTION_IRQ_INFO, + TRACEFS_OPTION_LATENCY_FORMAT, + TRACEFS_OPTION_MARKERS, + TRACEFS_OPTION_OVERWRITE, + TRACEFS_OPTION_PAUSE_ON_TRACE, + TRACEFS_OPTION_PRINTK_MSG_ONLY, + TRACEFS_OPTION_PRINT_PARENT, + TRACEFS_OPTION_RAW, + TRACEFS_OPTION_RECORD_CMD, + TRACEFS_OPTION_RECORD_TGID, + TRACEFS_OPTION_SLEEP_TIME, + TRACEFS_OPTION_STACKTRACE, + TRACEFS_OPTION_SYM_ADDR, + TRACEFS_OPTION_SYM_OFFSET, + TRACEFS_OPTION_SYM_USEROBJ, + TRACEFS_OPTION_TRACE_PRINTK, + TRACEFS_OPTION_USERSTACKTRACE, + TRACEFS_OPTION_VERBOSE, +}; +#define TRACEFS_OPTION_MAX (TRACEFS_OPTION_VERBOSE + 1) + +struct tracefs_options_mask { + unsigned long long mask; +}; +void tracefs_option_set(struct tracefs_options_mask *options, enum tracefs_option_id id); +void tracefs_option_clear(struct tracefs_options_mask *options, enum tracefs_option_id id); +bool tracefs_option_is_set(struct tracefs_options_mask options, enum tracefs_option_id id); + +struct tracefs_options_mask *tracefs_options_get_supported(struct tracefs_instance *instance); +bool tracefs_option_is_supported(struct tracefs_instance *instance, enum tracefs_option_id id); +struct tracefs_options_mask *tracefs_options_get_enabled(struct tracefs_instance *instance); +bool tracefs_option_is_enabled(struct tracefs_instance *instance, enum tracefs_option_id id); +int tracefs_option_enable(struct tracefs_instance *instance, enum tracefs_option_id id); +int tracefs_option_diasble(struct tracefs_instance *instance, enum tracefs_option_id id); +const char *tracefs_option_name(enum tracefs_option_id id); + #endif /* _TRACE_FS_H */ diff --git a/src/tracefs-tools.c b/src/tracefs-tools.c index 101f389..6e7fce5 100644 --- a/src/tracefs-tools.c +++ b/src/tracefs-tools.c @@ -9,12 +9,27 @@ #include #include #include +#include +#include +#include +#include #include "tracefs.h" #include "tracefs-local.h" #define TRACE_CTRL "tracing_on" +static const char * const options_map[TRACEFS_OPTION_MAX] = { + "unknown", "annotate", "bin", "blk_cgname", "blk_cgroup", "blk_classic", + "block", "context-info", "disable_on_free", "display-graph", "event-fork", + "funcgraph-abstime", "funcgraph-cpu", "funcgraph-duration", "funcgraph-irqs", + "funcgraph-overhead", "funcgraph-overrun", "funcgraph-proc", "funcgraph-tail", + "func_stack_trace", "function-fork", "function-trace", "graph-time", "hex", + "irq-info", "latency-format", "markers", "overwrite", "pause-on-trace", + "printk-msg-only", "print-parent", "raw", "record-cmd", "record-tgid", + "sleep-time", "stacktrace", "sym-addr", "sym-offset", "sym-userobj", + "trace_printk", "userstacktrace", "verbose" }; + static int trace_on_off(int fd, bool on) { const char *val = on ? "1" : "0"; @@ -107,3 +122,232 @@ int tracefs_trace_off_fd(int fd) return -1; return trace_on_off(fd, false); } + +/** + * tracefs_option_name - Get trace option name from id + * @id: trace option id + * + * Returns string with option name, or "unknown" in case of not known option id. + * The returned string must *not* be freed. + */ +const char *tracefs_option_name(enum tracefs_option_id id) +{ + if (id < TRACEFS_OPTION_MAX) + return options_map[id]; + + return options_map[0]; +} + +/** + * 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. + */ +enum tracefs_option_id tracefs_option_id(char *name) +{ + int i; + + if (!name) + return TRACEFS_OPTION_INVALID; + + for (i = 0; i < TRACEFS_OPTION_MAX; i++) { + if (strlen(name) == strlen(options_map[i]) && + !strcmp(options_map[i], name)) + return i; + } + + return TRACEFS_OPTION_INVALID; +} + +static struct tracefs_options_mask *trace_get_options(struct tracefs_instance *instance, + bool enabled) +{ + struct tracefs_options_mask *bitmask; + enum tracefs_option_id id; + char file[PATH_MAX]; + struct dirent *dent; + char *dname = NULL; + DIR *dir = NULL; + long long val; + + bitmask = calloc(1, sizeof(struct tracefs_options_mask)); + if (!bitmask) + return NULL; + 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) + tracefs_option_set(bitmask, id); + } + closedir(dir); + tracefs_put_tracing_file(dname); + + return bitmask; + +error: + if (dir) + closedir(dir); + tracefs_put_tracing_file(dname); + free(bitmask); + return NULL; +} + +/** + * tracefs_options_get_supported - Get all supported trace options in given instance + * @instance: ftrace instance, can be NULL for the top instance + * + * Returns allocated bitmask structure with all trace options, supported in given + * instance, or NULL in case of an error. The returned structure must be freed with free() + */ +struct tracefs_options_mask *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 allocated bitmask structure with all trace options, enabled in given + * instance, or NULL in case of an error. The returned structure must be freed with free() + */ +struct tracefs_options_mask *tracefs_options_get_enabled(struct tracefs_instance *instance) +{ + return trace_get_options(instance, true); +} + +static int trace_config_option(struct tracefs_instance *instance, + enum tracefs_option_id id, bool set) +{ + char *set_str = set ? "1" : "0"; + char file[PATH_MAX]; + const char *name; + + name = tracefs_option_name(id); + if (!name) + return -1; + + snprintf(file, PATH_MAX, "options/%s", name); + if (strlen(set_str) != tracefs_instance_file_write(instance, file, set_str)) + return -1; + return 0; +} + +/** + * tracefs_option_enable - Enable trace option + * @instance: ftrace instance, can be NULL for the top instance + * @id: trace option id + * + * Returns -1 in case of an error or 0 otherwise + */ +int tracefs_option_enable(struct tracefs_instance *instance, enum tracefs_option_id id) +{ + return trace_config_option(instance, id, true); +} + +/** + * tracefs_option_diasble - Disable trace option + * @instance: ftrace instance, can be NULL for the top instance + * @id: trace option id + * + * Returns -1 in case of an error or 0 otherwise + */ +int tracefs_option_diasble(struct tracefs_instance *instance, enum tracefs_option_id id) +{ + return trace_config_option(instance, id, false); +} + +/** + * tracefs_option_is_supported - Check if an option is supported + * @instance: ftrace instance, can be NULL for the top instance + * @id: trace 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, enum tracefs_option_id id) +{ + const char *name = tracefs_option_name(id); + char file[PATH_MAX]; + + if (!name) + return false; + snprintf(file, PATH_MAX, "options/%s", name); + return tracefs_file_exists(instance, 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: trace 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, enum tracefs_option_id id) +{ + const char *name = tracefs_option_name(id); + char file[PATH_MAX]; + long long res; + + if (!name) + return false; + snprintf(file, PATH_MAX, "options/%s", name); + if (!tracefs_instance_file_read_number(instance, file, &res) && res) + return true; + + return false; +} + +/** + * tracefs_option_is_set - Check if given option is set in the bitmask + * @options: Options bitmask + * @id: trace option id + * + * Returns true if an option with given id is set in the bitmask, + * false if it is not set. + */ +bool tracefs_option_is_set(struct tracefs_options_mask options, enum tracefs_option_id id) +{ + if (id > TRACEFS_OPTION_INVALID) + return options.mask & (1ULL << (id - 1)); + return false; +} + +/** + * tracefs_option_set - Set option in options bitmask + * @options: Pointer to a bitmask with options + * @id: trace option id + */ +void tracefs_option_set(struct tracefs_options_mask *options, enum tracefs_option_id id) +{ + if (options && id > TRACEFS_OPTION_INVALID) + options->mask |= (1ULL << (id - 1)); +} + +/** + * tracefs_option_clear - Clear option from options bitmask + * @options: Pointer to a bitmask with options + * @id: trace option id + */ +void tracefs_option_clear(struct tracefs_options_mask *options, enum tracefs_option_id id) +{ + if (options && id > TRACEFS_OPTION_INVALID) + options->mask &= ~(1ULL << (id - 1)); +} From patchwork Wed Jan 20 15:12:53 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: 12032647 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 06CFBC4332B for ; Wed, 20 Jan 2021 15:23:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C0E4B23382 for ; Wed, 20 Jan 2021 15:23:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733040AbhATPX2 (ORCPT ); Wed, 20 Jan 2021 10:23:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390605AbhATPNm (ORCPT ); Wed, 20 Jan 2021 10:13:42 -0500 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F381C0613C1 for ; Wed, 20 Jan 2021 07:13:02 -0800 (PST) Received: by mail-wm1-x32c.google.com with SMTP id m2so3166194wmm.1 for ; Wed, 20 Jan 2021 07:13:01 -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=A1gyWrenc4pNhGdwD3VJR4Hq/8LXJD6FgkNTiiS2dFs=; b=Jh3yFAsKhd7j8yZFWOxLrUsTSK4XM6SvYK3hP39FFfgxHR1gbC66GyxGEbR/kI0lMX 9dEDHYnG2GuOUWy1Bhe0AoEui4mDJd6/L3/003sVtfGd2MvEaYpr+f+13m7s1IDeNw7n Fy9GwHVZE2koadSIuYxD8Cqz7ng8Npz40ozEyL+pw83mSfOZJeS7MnfkeJlEnqrPZkkU 7Ymo3J2oXfUlAlY9ZX6yNqrZiYkwfwiPTTVUjK977Jb7BVrVIbzhlqhMwAtnrvXt7XPL FjfDKaYsWD0e3pGtINvJJ5/gLeW1GcNr0Q5k81qsGcR1HUFRshTD71j83hvG9GavZgaK juow== 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=A1gyWrenc4pNhGdwD3VJR4Hq/8LXJD6FgkNTiiS2dFs=; b=mhYswPy60Jq0NPsNLeiauMzGkS3yr+S/e2sxWY1JjCoWhXrtJqumkDfJP04DD2cpog TOyUkoaoN3vZQilunxoQWGyMoe/XnAMw2+MelM8VW9GgslB2tTJ9mgYix6Zw22FSIL08 vtu+U/P6rH82YaLKkBFBnyEndKXcqBIkmD7PcMWZvgoGtF/XzPMnOXmP//WK3WUgWSYN g1zmiLib3Mw34JtxySi0/TemaTQoitrCUwW9sBvT/i24la3WupU4TIA0IKTUuwqzilIQ Ikw0v8rPwlPmqF7uToCrkPElCAL9rMWOyVoN17k1z5qtwHTPaVmTLzZdswv1RBmz1kGY 9UsA== X-Gm-Message-State: AOAM530SvLhPcKxroeLsw83GDa4EHiIRBLZdf/MhTVqR+/MVOo8GQnLn Jogfb4WcisGwmXY2wVwEljGyb+gRqujl9u3u X-Google-Smtp-Source: ABdhPJxwSTCMEmBffWBCbPuReTXBNXZu3ub9Nlkk7HPOdIjgmtiRhN74sr5/0ZvwNCreJZq1w7E51A== X-Received: by 2002:a1c:7e4e:: with SMTP id z75mr4751403wmc.40.1611155580857; Wed, 20 Jan 2021 07:13:00 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id c11sm4571106wmd.36.2021.01.20.07.12.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 07:13:00 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 2/5] libtracefs: Unit tests for tracing options APIs Date: Wed, 20 Jan 2021 17:12:53 +0200 Message-Id: <20210120151256.43075-3-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210120151256.43075-1-tz.stoyanov@gmail.com> References: <20210120151256.43075-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_option_set(); tracefs_option_clear(); tracefs_option_is_set(); tracefs_options_get_supported(); tracefs_option_is_supported(); tracefs_options_get_enabled(); tracefs_option_is_enabled(); tracefs_option_enable(); tracefs_option_diasble(); tracefs_option_name(); Signed-off-by: Tzvetomir Stoyanov (VMware) --- utest/tracefs-utest.c | 144 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c index 0520f49..1f3c042 100644 --- a/utest/tracefs-utest.c +++ b/utest/tracefs-utest.c @@ -452,6 +452,148 @@ static void test_tracing_onoff(void) close(fd); } +static bool check_option(struct tracefs_instance *instance, + enum tracefs_option_id id, bool exist, int enabled) +{ + const char *name = tracefs_option_name(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(instance, id); + CU_TEST(supported == exist); + if (supported != exist) + goto out; + snprintf(file, PATH_MAX, "options/%s", name); + path = tracefs_instance_get_file(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 >= 1); + 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 bool check_options_mask_empty(struct tracefs_options_mask *mask) +{ + int i; + + for (i = 1; i < TRACEFS_OPTION_MAX; i++) { + if (tracefs_option_is_set(*mask, i)) + return false; + } + return true; +} + +static void test_instance_tracing_options(struct tracefs_instance *instance) +{ + struct tracefs_options_mask *enabled; + struct tracefs_options_mask *all, *all_copy; + enum tracefs_option_id i = 1; + char file[PATH_MAX]; + const char *name; + + all = tracefs_options_get_supported(instance); + all_copy = tracefs_options_get_supported(instance); + enabled = tracefs_options_get_enabled(instance); + CU_TEST(all != NULL); + + /* Invalid parameters test */ + CU_TEST(!tracefs_option_is_supported(instance, TRACEFS_OPTION_INVALID)); + CU_TEST(!tracefs_option_is_enabled(instance, TRACEFS_OPTION_INVALID)); + CU_TEST(tracefs_option_enable(instance, TRACEFS_OPTION_INVALID) == -1); + CU_TEST(tracefs_option_diasble(instance, TRACEFS_OPTION_INVALID) == -1); + name = tracefs_option_name(TRACEFS_OPTION_INVALID); + CU_TEST(!strcmp(name, "unknown")); + /* Test all valid options */ + for (i = 1; i < TRACEFS_OPTION_MAX; i++) { + name = tracefs_option_name(i); + CU_TEST(name != NULL); + CU_TEST(strcmp(name, "unknown")); + snprintf(file, PATH_MAX, "options/%s", name); + + if (tracefs_option_is_set(*all, i)) { + tracefs_option_clear(all, i); + CU_TEST(!tracefs_option_is_set(*all, i)); + CU_TEST(check_option(instance, i, true, -1)); + CU_TEST(tracefs_option_is_supported(instance, i)); + } else { + CU_TEST(check_option(instance, i, false, -1)); + CU_TEST(!tracefs_option_is_supported(instance, i)); + } + + if (tracefs_option_is_set(*enabled, i)) { + tracefs_option_clear(enabled, i); + CU_TEST(!tracefs_option_is_set(*enabled, i)); + 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_option_diasble(instance, i) == 0); + CU_TEST(check_option(instance, i, true, 0)); + CU_TEST(tracefs_option_enable(instance, i) == 0); + CU_TEST(check_option(instance, i, true, 1)); + } else if (tracefs_option_is_set(*all_copy, i)) { + 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_option_enable(instance, i) == 0); + CU_TEST(check_option(instance, i, true, 1)); + CU_TEST(tracefs_option_diasble(instance, i) == 0); + CU_TEST(check_option(instance, i, true, 0)); + } + } + CU_TEST(check_options_mask_empty(all)); + CU_TEST(check_options_mask_empty(enabled)); + + free(all); + free(enabled); +} + +static void test_tracing_options(void) +{ + test_instance_tracing_options(test_instance); +} + static void exclude_string(char **strings, char *name) { int i; @@ -761,5 +903,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 Wed Jan 20 15:12:54 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: 12032649 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 220E0C4332D for ; Wed, 20 Jan 2021 15:23:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E3CA423407 for ; Wed, 20 Jan 2021 15:23:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389082AbhATPXa (ORCPT ); Wed, 20 Jan 2021 10:23:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34338 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390695AbhATPNn (ORCPT ); Wed, 20 Jan 2021 10:13:43 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1FA4FC0613CF for ; Wed, 20 Jan 2021 07:13:03 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id 6so16173844wri.3 for ; Wed, 20 Jan 2021 07:13:03 -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=ZYzwEPq/x6lTblHupVOekG9ZPbZMM5RdnFOz803vCIEYUU50nmlZ5e/iF/DkzTXb4i 4RBjGYTLz4ddrFz7ic6En5Y7H+oRSF9QX9n0Zm14T5DDDuQrEkxYOvI/8YCv9deVLQ/A CPtoEhMd+hGm0qvdRoUIJfithpljAzhV2k7E8ovb+r56ai64UNJgoAzA1QK8Di7vmdaD rKmwrvK6c07ThwSp750H7OipoYhHZ5It6omTiMErAtr1p2a2zMv7eyob+dvbn1HPkwAE HQdZdrUH87L+QGz2J2mwy/qsbhA7i/P1xFnt4bNiZynrX7CJhdGNX3Dk03uoHaP5o/We chqA== 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=E8lgqSSbGwHphEZSkhfxwREaVZNDjXwYGySzEsNx+3R33cU6V3dsrmFhaW57+i1lb3 I/xIdPCej2NFH2iXhPTEFTLywZwCc1a8kpixm3c8p5q/Omb13txe2SYS2PlAVZFRWamH E2KjMnNf1t0TJrcXp08/EfLYhPpgUI1DgojqfiyV3401flmQ04eluYoskhvKe+z47PUZ JCD9rCQti70UyGMHPhItdFdYUzz6VBdDsh40RT+NjHFwhreDcWO9LjJTKnf4oialfxaS 8g3afChnE34RiiEwJRXIyOCsEBPOLSXFAC2fpJsYWapnlewoBnztlDDh5QXIpWlRH3rR 6gEw== X-Gm-Message-State: AOAM533+bIfEngGSBYvY7/ifuhXa4SLg7FVygGFTuBdPWFA+w+UHtnb4 CxvBUN4on5ziZ+qcZdIpvP0= X-Google-Smtp-Source: ABdhPJzcnOgRD2PvPCzP43WC2m0b/5w7/YZaJResPZa4yGaXdERQIQ79psztXBPaQlhar2vMNWiAdg== X-Received: by 2002:a5d:5902:: with SMTP id v2mr7724995wrd.426.1611155581935; Wed, 20 Jan 2021 07:13:01 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id c11sm4571106wmd.36.2021.01.20.07.13.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 07:13:01 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 3/5] libtracefs: Add information about top tracing directory in instance structure Date: Wed, 20 Jan 2021 17:12:54 +0200 Message-Id: <20210120151256.43075-4-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210120151256.43075-1-tz.stoyanov@gmail.com> References: <20210120151256.43075-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 Wed Jan 20 15:12:55 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: 12032651 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 EA15BC433E0 for ; Wed, 20 Jan 2021 15:24:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B27712336D for ; Wed, 20 Jan 2021 15:24:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390567AbhATPXc (ORCPT ); Wed, 20 Jan 2021 10:23:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34348 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390847AbhATPNp (ORCPT ); Wed, 20 Jan 2021 10:13:45 -0500 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 837DAC0613D3 for ; Wed, 20 Jan 2021 07:13:04 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id e15so3164558wme.0 for ; Wed, 20 Jan 2021 07:13:04 -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=PtKzkgGu3ALXGV3VHLzz5lqTJr+GbH9+joF4w3GwVnk=; b=TmXFktN3OaHjMdzfZZot1sIFHgb5bVSJ/hnXhfTyShPhv1pZPXG06C91bmxVukMqnK xao9FUEQ8GfKQGiDhHz5UE0S2fZpcrDkWGewxk5nzO0w1ujFW27N/gayFtYfTHbLGk3S TJ7RfEVbwL5+JqxLCEagFQp1rzong1xzHgW5lIM7t7GKM1GS0RLz+WWFT2RG4v1N46WQ U3df3jfrZR7J2ChyjXZmiXFfZqlKcNFYlQaORdeCyK/7jxDWo/y81oEVVIKLs2JRkAW7 MifCI8XMKoCV/VCo31kHwTYql0n0VNdSGlJgxPISMBbiiBM6vI+CxbnY6CW7pijYVL2q /iOw== 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=PtKzkgGu3ALXGV3VHLzz5lqTJr+GbH9+joF4w3GwVnk=; b=sacRHfAVZhEi5i1d3sEzXJMJcgCtxZ61XT01E3gvDO6dabUN1nEq368mCEPJZnbnpI rJJJFYTpGnn9xIBli4k/dIB3UJiyyHCfGIpnHtcdL6NCOFDE/9FFCN2Afu8++bx9OMGk rGPV/zUhN7h6li3XAC/1ohn+wfu2/7ogvGUTDy5g6I3NjZAi5YunNgU8OM3E1FMy5bb8 EswyMwAVl2MuuxARlUru/UldD3eyULtfL2LNCCLXfN+vcwMcSdaKhMFuGvvP2YHYGo0a GZ5yY2CPDAKTGNdMB6Gk49kQZ2UocTNZkGbqh9uVfyCwEGW9bnSnYLDyWsVfvNYcB/RJ pZtA== X-Gm-Message-State: AOAM531sMaUQA9RbNE1gdiY4CV/thxB6ZvKkPPE0qgIKFcFWDMEd+KhE LbwBFqp0z/Q6Z1mXtBsNOSQ= X-Google-Smtp-Source: ABdhPJzpnLxiOHeKJL6vxW7kk6hxKhgfRfk52hC3bjBFYm89EOO2+KPClKPtjUWXVlvu5rpHnVHYFg== X-Received: by 2002:a1c:4057:: with SMTP id n84mr4733948wma.141.1611155583279; Wed, 20 Jan 2021 07:13:03 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id c11sm4571106wmd.36.2021.01.20.07.13.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 07:13:02 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 4/5] libtracefs: New APIs for getting existing trace instance Date: Wed, 20 Jan 2021 17:12:55 +0200 Message-Id: <20210120151256.43075-5-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210120151256.43075-1-tz.stoyanov@gmail.com> References: <20210120151256.43075-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_alloc(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 2df596f..3059dbb 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_alloc(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..0df4e13 100644 --- a/src/tracefs-instance.c +++ b/src/tracefs-instance.c @@ -151,6 +151,49 @@ error: return NULL; } +/** + * tracefs_instance_alloc - 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_alloc(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 Wed Jan 20 15:12:56 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: 12032629 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=-13.0 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,UNWANTED_LANGUAGE_BODY, 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 A2E46C433DB for ; Wed, 20 Jan 2021 15:17:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4C8D722CE3 for ; Wed, 20 Jan 2021 15:17:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390516AbhATPQj (ORCPT ); Wed, 20 Jan 2021 10:16:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390642AbhATPPL (ORCPT ); Wed, 20 Jan 2021 10:15:11 -0500 Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AB745C0613D6 for ; Wed, 20 Jan 2021 07:13:05 -0800 (PST) Received: by mail-wr1-x42f.google.com with SMTP id d26so23432573wrb.12 for ; Wed, 20 Jan 2021 07:13:05 -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=WbEjzL/7bdB4RrBO9mfuDo6fAwLJoUK4kwEhCZ+hvoo=; b=lOlRuvXniYgBZRQYBxukB9jV0a2fvgPvjOwYRslrEtpVBa3soGRVSgQC7gODJbOaQq 2KZ/sDhIj5SvDbYHLuiQ99BIyoux2GBa5nd3dsdKyaW1SkJgHmitzBYmfqqS+Y4UKWWo qV9BE6ocIE7ahlX1UVVmd9GjCddykuWfWuWoF5kusfmnEqddYQ//bfy8qSY9gMWLvUZX +Mi2rDOlc+bNzR9Irw0isgROPh/Vf/GVqnao/+zbiBu0/yO5cIUiqiO0Gx+lfGI+Fjtf 6WNIj2MF1qdeVAePpp6WUEBzDsKmY9AxHbB6w0j/B1WFYyOneZGuJguXWj+TA+vukYLm NQzA== 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=WbEjzL/7bdB4RrBO9mfuDo6fAwLJoUK4kwEhCZ+hvoo=; b=JkxGkQBLirHSaOtMwEVI88SmlEupl5zCy7ZONAn/U5xvQzeOEuyr2NaDNqEAvwYmgs sy6XQGEVboANqKaQFwU0UeBNnhnZ9GIGFZUnRYhokGsR85KCKd3oPZrt368xhRF4hgjM Z2X6TWsHSxD9V+04iDqDWqj9/lticZRcabfe/TcAXDaseXS3l0GgSa2WYHtI0y/Re8Cy NDPEusfYojLg08RQUnnhPnSC7WQSR8MBQcA5t67IO0ZlIIIrbCFk3qPIxM1kBkLLOaJb 5va98nCd1hOyeVXOSVmqyQuCeW/Es9zezTt3b5spfSbfF+eSv+QL49DoDMUXALzROMp4 V1PA== X-Gm-Message-State: AOAM530a1HOZMQQ2M3aAl1+eyg5d8vkVPk+Uu9tPzDVwxXN8hUGo+5Fp VrB0bOXw19SzUk4QcHbkSYJQ7sKg1W00orvZ X-Google-Smtp-Source: ABdhPJyG+gW8v7j39Y8lI2JQFU5z5Fm0Hn9oSuEx0XJTjTgbOi5DP0kQdRkOy4SOYSagZBZdOXA3JA== X-Received: by 2002:adf:9c88:: with SMTP id d8mr7934038wre.235.1611155584438; Wed, 20 Jan 2021 07:13:04 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id c11sm4571106wmd.36.2021.01.20.07.13.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 07:13:03 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 5/5] libtracefs: Unit tests for working with non default tracing dir Date: Wed, 20 Jan 2021 17:12:56 +0200 Message-Id: <20210120151256.43075-6-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210120151256.43075-1-tz.stoyanov@gmail.com> References: <20210120151256.43075-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 | 287 +++++++++++++++++++++++++++++++++--------- 1 file changed, 228 insertions(+), 59 deletions(-) diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c index 1f3c042..ed2693b 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,44 +430,56 @@ 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 void test_tracing_onoff(void) +{ + test_instance_tracing_onoff(test_instance); +} + static bool check_option(struct tracefs_instance *instance, enum tracefs_option_id id, bool exist, int enabled) { @@ -625,16 +653,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); @@ -657,7 +682,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; @@ -665,7 +699,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); @@ -686,6 +720,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; @@ -725,17 +764,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); @@ -776,6 +811,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; @@ -825,13 +869,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); @@ -842,16 +886,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_alloc(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); @@ -886,7 +1054,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", @@ -905,5 +1073,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); }