From patchwork Thu Aug 19 13:08:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 12447179 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 7E38AC4320A for ; Thu, 19 Aug 2021 13:08:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 67B7D61101 for ; Thu, 19 Aug 2021 13:08:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238357AbhHSNJT (ORCPT ); Thu, 19 Aug 2021 09:09:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52654 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229670AbhHSNJS (ORCPT ); Thu, 19 Aug 2021 09:09:18 -0400 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 49C2AC061575 for ; Thu, 19 Aug 2021 06:08:42 -0700 (PDT) Received: by mail-wm1-x329.google.com with SMTP id k5-20020a05600c1c85b02902e699a4d20cso4008683wms.2 for ; Thu, 19 Aug 2021 06:08:42 -0700 (PDT) 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=dvQOYcdkaA9RAlrwEppLpq09VEggm5oXxIPlxlY+fqE=; b=U5QLsVnBhRYo592EhNG1wc2Jw5fzQ9ejIN1eZmcQ9CyOlRPG+vx1/uL9glgqFEyqsb OmcZvd2U9MHIqpjDjzJgd7MveLSdjWhxUb3NIe4MoM0pror2m7W43zTX76fewzvkuyOF Mn1ExSyWa5FZ3IoP1V/ZsmGLqe47qqsSLOtTMpb2cHAGOtbraiQf1NU9Nw1x7lHAP8l5 xC/cMafoavoOzUE9yTCGgPlOXQrb25EkhCoQqfdDfUdUOfuY0nO6ii/sF0aLx25Ul2L9 vkVwzwmO/NTZsvdR154OzFEaPczl5NYZKIm/D00O8Nshks9/Cc0IuqfxVsBlhtne54wh Fv4w== 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=dvQOYcdkaA9RAlrwEppLpq09VEggm5oXxIPlxlY+fqE=; b=L+V0Let+dJLiUbS0Omsnj1O0MphGuZ/CXYobMcW8Gey9oicxLvRqu2z88/ot+/dYnA vQTPpLjIVjvuO3CNqgw4sQsGTxuUHImLY00ai7jIdENSjCQmKolXVPwH1vnbeShhzFlF ++D05vmIBZuD5jccvKbMDAogMgIrFaJT3DUD3QPijxLSYmUGi5ohD4cOms17Tv7bSv9m 19ICxYEZmnC0BCE61OQWYM9STs6nmcZe9sUGHGA1jhltUK9TXWvJXikcjSremQpxNe+S x4FVf90sUGnoR2GDn3pTrT93ZyFLKUeqFgjQpWM1Wc8g7AaP4JP2O/N6tX74NGngtjLY 8p2g== X-Gm-Message-State: AOAM530op9B0U8j0EqjHiPDY2OLMuf/1l4TAe19YdgMKgGzfXeM7dMHT EaHQF7N1L6qmY2hye7wRJ8MvgcRnGW0= X-Google-Smtp-Source: ABdhPJx65V8vP/l3GbbMXsS2GkffI4auU46ncoJZrGYzb2f8nLCk92jJlPbZx8S3gOGXPr3jMhNatA== X-Received: by 2002:a1c:5404:: with SMTP id i4mr13770000wmb.80.1629378520618; Thu, 19 Aug 2021 06:08:40 -0700 (PDT) Received: from crow.eng.vmware.com ([146.247.46.133]) by smtp.gmail.com with ESMTPSA id f17sm2889978wrt.49.2021.08.19.06.08.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 06:08:40 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: linux-trace-devel@vger.kernel.org Cc: "Yordan Karadzhov (VMware)" Subject: [PATCH v2 1/7] trace-cruncher: Use proper naming in common.h Date: Thu, 19 Aug 2021 16:08:21 +0300 Message-Id: <20210819130827.12327-2-y.karadz@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210819130827.12327-1-y.karadz@gmail.com> References: <20210819130827.12327-1-y.karadz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org PyTepEvent was the first Python type defined in the C extension module. A legacy from this first implementation can be found in the naming of some variables used by the type definition macros. Signed-off-by: Yordan Karadzhov (VMware) --- src/common.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common.h b/src/common.h index 9985328..6046c0f 100644 --- a/src/common.h +++ b/src/common.h @@ -54,27 +54,27 @@ static inline void no_free() #define STR(x) #x -#define MAKE_TYPE_STR(x) STR(traceevent.x) +#define MAKE_TYPE_STR(x) STR(trace.x) -#define MAKE_DIC_STR(x) STR(libtraceevent x object) +#define MAKE_DIC_STR(x) STR(libtrace x object) #define C_OBJECT_WRAPPER_DECLARE(c_type, py_type) \ typedef struct { \ PyObject_HEAD \ struct c_type *ptrObj; \ } py_type; \ -PyObject *py_type##_New(struct c_type *evt_ptr); \ +PyObject *py_type##_New(struct c_type *c_ptr); \ bool py_type##TypeInit(); \ #define C_OBJECT_WRAPPER(c_type, py_type, ptr_free) \ static PyTypeObject py_type##Type = { \ PyVarObject_HEAD_INIT(NULL, 0) MAKE_TYPE_STR(c_type) \ }; \ -PyObject *py_type##_New(struct c_type *evt_ptr) \ +PyObject *py_type##_New(struct c_type *c_ptr) \ { \ py_type *newObject; \ newObject = PyObject_New(py_type, &py_type##Type); \ - newObject->ptrObj = evt_ptr; \ + newObject->ptrObj = c_ptr; \ return (PyObject *) newObject; \ } \ static int py_type##_init(py_type *self, PyObject *args, PyObject *kwargs) \ From patchwork Thu Aug 19 13:08:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 12447181 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 EAB8DC432BE for ; Thu, 19 Aug 2021 13:08:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CBA5061153 for ; Thu, 19 Aug 2021 13:08:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238379AbhHSNJT (ORCPT ); Thu, 19 Aug 2021 09:09:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52656 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229670AbhHSNJT (ORCPT ); Thu, 19 Aug 2021 09:09:19 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EBA3BC061575 for ; Thu, 19 Aug 2021 06:08:42 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id r7so9134955wrs.0 for ; Thu, 19 Aug 2021 06:08:42 -0700 (PDT) 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=fTA18C1juGWZITUqmZQxJSRUfIcz4vFTw5d47852z3k=; b=TgIRnYiDJ022o6IIsnJdGiinc0S7cC9bOUwwvr6vWmo3JQXcOsLIIfPwYwz0XRX7nk zkSshO+LuoZ/RcJ1ofmUlfyjCVp9uvLJF2BuLs1Bhrhin2c23DAtnv1DPigJqThz/S0v vLr6eotkfUIGpO97PGul3Wj+pQRkAO9M/6jCt/7vlTxv9okRlGjQPRj8CfWhUUyGa1r5 opNENxbqaj9nxqS0RU9QYZzvSAoTzrEjowso2puG2z0XzO9SOBG6r0RDg1twZKllw6Wp D18ZINvdKzJQ92dgm4zHns2xpZ6/x4QkRrclW3vDme4j472vG/ALpyPOv+dsOliH5MDL FspQ== 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=fTA18C1juGWZITUqmZQxJSRUfIcz4vFTw5d47852z3k=; b=HFyXYX+3E6a95LCt93ZXUaO2jmY3KJqlwi7GPs1yuRHbG2Hjx2aVbRdsg0nIQhaabP xHHPkXS1l5/jBTYYgBOXR0/bi8ho9VrMCpDSkhXjPM+W+59f2BFVg7EwM5kXU7Rozz0v EpnXBecYPLuJU1RvNvkn8yOClWtKu0KmsfRdnwF/2PYDHr7Psb6HIaTjdfZ3F7Zs9kVT Sgqh+8NFVaePzWLekWgYLrGY4MdU0CBP5hG+MtVeb2P38xqT4CH0P1Y9+ydFGQCyiq8G 4Vf4CkpbbsgLe3vBUUDXOq0kXcj75nBEHfzBRpLEev7N4B8FbK1kzwIVB4EjfzObzpH3 yQug== X-Gm-Message-State: AOAM533EpP3KQa54yZ0YmvyhWAYvOAErjq9SfaQLy7k3GeC8MAT2h6Lu rMEvc06CW8F+rH8VKuao0LVu1DuYWj4= X-Google-Smtp-Source: ABdhPJxsty+mS8e3UVWZOWg9i2i3bDEuotcU1AG9NaD/Ru4KkRwWonZJt5rq7hG50ppnxeJKNyk9dw== X-Received: by 2002:adf:eacb:: with SMTP id o11mr3804503wrn.418.1629378521388; Thu, 19 Aug 2021 06:08:41 -0700 (PDT) Received: from crow.eng.vmware.com ([146.247.46.133]) by smtp.gmail.com with ESMTPSA id f17sm2889978wrt.49.2021.08.19.06.08.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 06:08:41 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: linux-trace-devel@vger.kernel.org Cc: "Yordan Karadzhov (VMware)" Subject: [PATCH v2 2/7] trace-cruncher: Add type checking for the custom Python types Date: Thu, 19 Aug 2021 16:08:22 +0300 Message-Id: <20210819130827.12327-3-y.karadz@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210819130827.12327-1-y.karadz@gmail.com> References: <20210819130827.12327-1-y.karadz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org The new method checks if an object has a Python type that matches the type defined in the C extension module. Signed-off-by: Yordan Karadzhov (VMware) --- src/common.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common.h b/src/common.h index 6046c0f..fa64696 100644 --- a/src/common.h +++ b/src/common.h @@ -65,6 +65,7 @@ static inline void no_free() } py_type; \ PyObject *py_type##_New(struct c_type *c_ptr); \ bool py_type##TypeInit(); \ +bool py_type##_Check(PyObject *obj); \ #define C_OBJECT_WRAPPER(c_type, py_type, ptr_free) \ static PyTypeObject py_type##Type = { \ @@ -101,5 +102,9 @@ bool py_type##TypeInit() \ Py_INCREF(&py_type##Type); \ return true; \ } \ +bool py_type##_Check(PyObject *obj) \ +{ \ + return (obj->ob_type == &py_type##Type) ? true : false; \ +} \ #endif From patchwork Thu Aug 19 13:08:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 12447183 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 5D01BC4338F for ; Thu, 19 Aug 2021 13:08:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 459C261152 for ; Thu, 19 Aug 2021 13:08:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238460AbhHSNJU (ORCPT ); Thu, 19 Aug 2021 09:09:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52660 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229670AbhHSNJT (ORCPT ); Thu, 19 Aug 2021 09:09:19 -0400 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A436AC061575 for ; Thu, 19 Aug 2021 06:08:43 -0700 (PDT) Received: by mail-wm1-x32d.google.com with SMTP id l24-20020a05600c089800b002e71a10130eso768784wmp.5 for ; Thu, 19 Aug 2021 06:08:43 -0700 (PDT) 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=w6Bx292jRooy4aRoWEgGqgTm8rpQYiL/U8yEpITgcY8=; b=rZmwOX4js8gzDTbvtA8tPaV0w3MCbB3xyZn/F1j07GxPvblsGA2gJs/GNORvBwBUCk 9jkjsujhrInpjV0FnqArtWZ85/54BFjM15BZbRy6+sFR1ES/TTAtCvFZ+75ij7vvN3x2 IokCU70+C7g9zhRTFsB/V/14A66kefFw/ad2uHtxAEGZkqQ/mXxhATq71ut8V+kIoyYT 3RAaoxB4rF709pcTrSuDRM5d5vr/YVpHMJbl3h5rC0Ib6sENzByRRQ6YYDwrizr9k/lx 2imq6AkZrvJ4puBE64IpsvYvF0k4wNZqAQY6tDG6wswNRWteZ8gs/DG0JcEalPNPY4zK GmQA== 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=w6Bx292jRooy4aRoWEgGqgTm8rpQYiL/U8yEpITgcY8=; b=AJUbNlyoxt68ftPgoDH/gtaosliEbImKTYtizANcPVOKcVjpvWQMSbEwoeZVsU4o2O 2eigeQh3NBpA7TCrHR8ynrtHsdBNeG14+hBCthnyUBVaqOEeBIhz1Zshf/SWBXpA4/g1 Ua7gNFltClfn7JLWtFd+R4C2FSQBRWnZLt1RfD2Reu5lIQ4qq2hivKAsADQqw28nysUS 3qo9oOgfsgIAPk1CUDcV1HsPl+TXH4B/eljU2exl/vuVH+AKPdHS9v5Go6Ad0HMylULZ bieQXo3IvXOl7wtuiOp2djRUAJm6CohjM/OnIJekfpk0STsSqRfiyf5xxdAalVSTRrMi ub4A== X-Gm-Message-State: AOAM5312ioRRLCsiWg3jtUQ1e0caMbqFzoiqog1dFkyTyCnMOScInXnG xm+AWbvm3NRL/kVgXAYQgB4gJkt3pHw= X-Google-Smtp-Source: ABdhPJz1uorkd+7iyptq+SVmZqKS8GvsOFQSHwAz7orRxUEKhjeeDyRrVFmP3IOQwsAXcOJr3zdPnw== X-Received: by 2002:a05:600c:4a29:: with SMTP id c41mr13493410wmp.86.1629378522080; Thu, 19 Aug 2021 06:08:42 -0700 (PDT) Received: from crow.eng.vmware.com ([146.247.46.133]) by smtp.gmail.com with ESMTPSA id f17sm2889978wrt.49.2021.08.19.06.08.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 06:08:41 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: linux-trace-devel@vger.kernel.org Cc: "Yordan Karadzhov (VMware)" Subject: [PATCH v2 3/7] trace-cruncher: Allow for detachable custom objects Date: Thu, 19 Aug 2021 16:08:23 +0300 Message-Id: <20210819130827.12327-4-y.karadz@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210819130827.12327-1-y.karadz@gmail.com> References: <20210819130827.12327-1-y.karadz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org libtracefs distinguishes between freeing the resources managed by an object and the freeing of object itself. One can take tracefs_instance_destroy() and tracefs_instance_free() as example. The user can call tracefs_instance_free() without calling tracefs_instance_destroy(). In this case no memory will leak, but the instance will continue to exist after the program exits (will be 'detached'). Here we add mechanisms that will make possible to detach object from the ftracepy module. Signed-off-by: Yordan Karadzhov (VMware) --- src/common.h | 19 +++++++++++++++++-- src/ftracepy-utils.c | 20 ++++++++++++++++++++ src/ftracepy-utils.h | 2 ++ src/ftracepy.c | 11 ++++++++--- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/common.h b/src/common.h index fa64696..b7f6a87 100644 --- a/src/common.h +++ b/src/common.h @@ -46,28 +46,40 @@ static inline bool is_set(const char *arg) return !(is_all(arg) || is_no_arg(arg)); } -static inline void no_free() +static inline void no_free(void *ptr) { } #define NO_FREE no_free +static inline void no_destroy(void *ptr) +{ +} + +#define NO_DESTROY no_destroy + #define STR(x) #x #define MAKE_TYPE_STR(x) STR(trace.x) #define MAKE_DIC_STR(x) STR(libtrace x object) +typedef struct { + PyObject_HEAD + bool destroy; +} PyFtrace_Object_HEAD; + #define C_OBJECT_WRAPPER_DECLARE(c_type, py_type) \ typedef struct { \ PyObject_HEAD \ + bool destroy; \ struct c_type *ptrObj; \ } py_type; \ PyObject *py_type##_New(struct c_type *c_ptr); \ bool py_type##TypeInit(); \ bool py_type##_Check(PyObject *obj); \ -#define C_OBJECT_WRAPPER(c_type, py_type, ptr_free) \ +#define C_OBJECT_WRAPPER(c_type, py_type, obj_destroy, ptr_free) \ static PyTypeObject py_type##Type = { \ PyVarObject_HEAD_INIT(NULL, 0) MAKE_TYPE_STR(c_type) \ }; \ @@ -76,6 +88,7 @@ PyObject *py_type##_New(struct c_type *c_ptr) \ py_type *newObject; \ newObject = PyObject_New(py_type, &py_type##Type); \ newObject->ptrObj = c_ptr; \ + newObject->destroy = true; \ return (PyObject *) newObject; \ } \ static int py_type##_init(py_type *self, PyObject *args, PyObject *kwargs) \ @@ -85,6 +98,8 @@ static int py_type##_init(py_type *self, PyObject *args, PyObject *kwargs) \ } \ static void py_type##_dealloc(py_type *self) \ { \ + if (self->destroy) \ + obj_destroy(self->ptrObj); \ ptr_free(self->ptrObj); \ Py_TYPE(self)->tp_free(self); \ } \ diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c index 6739db7..197804b 100644 --- a/src/ftracepy-utils.c +++ b/src/ftracepy-utils.c @@ -536,6 +536,26 @@ PyObject *PyFtrace_dir(PyObject *self) return PyUnicode_FromString(tracefs_tracing_dir()); } +PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"object", NULL}; + PyFtrace_Object_HEAD *obj_head; + PyObject *py_obj = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, + kwargs, + "O", + kwlist, + &py_obj)) { + return false; + } + + obj_head = (PyFtrace_Object_HEAD *)py_obj; + obj_head->destroy = false; + + Py_RETURN_NONE; +} + static char aname_pool[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h index 5d7c19c..514c79b 100644 --- a/src/ftracepy-utils.h +++ b/src/ftracepy-utils.h @@ -46,6 +46,8 @@ PyObject *PyTep_get_event(PyTep *self, PyObject *args, PyObject *PyFtrace_dir(PyObject *self); +PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs); + PyObject *PyFtrace_create_instance(PyObject *self, PyObject *args, PyObject *kwargs); diff --git a/src/ftracepy.c b/src/ftracepy.c index e3fec7b..2296ec9 100644 --- a/src/ftracepy.c +++ b/src/ftracepy.c @@ -25,7 +25,7 @@ static PyMethodDef PyTepRecord_methods[] = { {NULL} }; -C_OBJECT_WRAPPER(tep_record, PyTepRecord, NO_FREE) +C_OBJECT_WRAPPER(tep_record, PyTepRecord, NO_DESTROY, NO_FREE) static PyMethodDef PyTepEvent_methods[] = { {"name", @@ -55,7 +55,7 @@ static PyMethodDef PyTepEvent_methods[] = { {NULL} }; -C_OBJECT_WRAPPER(tep_event, PyTepEvent, NO_FREE) +C_OBJECT_WRAPPER(tep_event, PyTepEvent, NO_DESTROY, NO_FREE) static PyMethodDef PyTep_methods[] = { {"init_local", @@ -71,7 +71,7 @@ static PyMethodDef PyTep_methods[] = { {NULL} }; -C_OBJECT_WRAPPER(tep_handle, PyTep, tep_free) +C_OBJECT_WRAPPER(tep_handle, PyTep, NO_DESTROY, tep_free) static PyMethodDef ftracepy_methods[] = { {"dir", @@ -79,6 +79,11 @@ static PyMethodDef ftracepy_methods[] = { METH_NOARGS, "Get the absolute path to the tracefs directory." }, + {"detach", + (PyCFunction) PyFtrace_detach, + METH_VARARGS | METH_KEYWORDS, + "Detach object from the \'ftracepy\' module." + }, {"create_instance", (PyCFunction) PyFtrace_create_instance, METH_VARARGS | METH_KEYWORDS, From patchwork Thu Aug 19 13:08:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 12447185 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 38BE9C432BE for ; Thu, 19 Aug 2021 13:08:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 235636108D for ; Thu, 19 Aug 2021 13:08:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238877AbhHSNJV (ORCPT ); Thu, 19 Aug 2021 09:09:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52666 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229670AbhHSNJV (ORCPT ); Thu, 19 Aug 2021 09:09:21 -0400 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68996C061575 for ; Thu, 19 Aug 2021 06:08:44 -0700 (PDT) Received: by mail-wm1-x329.google.com with SMTP id g138so3806881wmg.4 for ; Thu, 19 Aug 2021 06:08:44 -0700 (PDT) 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=zFRs/M9wMW+DUuDFVNtiPHd3qiwsxhy6U/N1IU6w4kk=; b=V062v8Zd4RrZeujxSSr/XjHcraOXeQ607MnefS92iXiu8QBwOM/XrWXlaYyyebJea2 SNDtAQ4iWu0NEiANaEpPnGv2+ykBl2tDuBLjdu0Hs+/iczE4hV2nECGU6wxtO1BBWO7U Ge549AU6NUioke8rEeIFZADMsXj8IUZe31xV58cxXmddR5ptb8Ha+UOecYeqvR8ns/aQ 1bQFFMQjhx+r49ctkbb0fVcxKaz1Vf3GJnu+MkZ/VxHGPT34L3ftldQkDGnwS7EdYa+u 9uMjhJuWaYquVY9b5t1Y8zLsjvjaQsLBzJJAbUjdXckotnqsorsGAFCz/PfRGr+bC8G4 bdGQ== 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=zFRs/M9wMW+DUuDFVNtiPHd3qiwsxhy6U/N1IU6w4kk=; b=XenO45UZiAHRPU9DrjxPxul+BgjQN0owZB/WPe8lydWvq+WYAhP9ICJq2kSe7w6GUa MSk5UX5pASvO+PgGlL1lplO+aHIjdhsD9VMk9WQy4aLgohuo0mnGaYD4kRcgQHAeVciY IVg06mReTaXQdRO6Xoxt6MV4NhZDkdEJSSOBcNNZPESfNnhrBBNRAzyhPdpDDTdoK2Oh uA16V3ZKJqBOQ9390KlYFHVZX0x6Vty9VkxpeFqO63HQoV905xPNgkq7MyRj153Ib4GX wj6Mp5oeYNJN8N85DtbCK1ZtYIfiZzOf6tU0o8FMGCEqnLwc6lK1hyH6gmllospnnshL r1GQ== X-Gm-Message-State: AOAM532eAB0z3l99Vv0rHEVvQ6lSLM7tSpj7N5kbCCDQ4qrCZKbYfL9X QaEFP2akKppV0CMMUWwitDBnn0mI8I4= X-Google-Smtp-Source: ABdhPJwAqCq+22ZcGH1j2pzELlg5DpFbeD4/5KJtonEWviSUyZDs2NMviWCH2ldfqb9I/u00+4HNUA== X-Received: by 2002:a1c:730a:: with SMTP id d10mr13713675wmb.59.1629378522814; Thu, 19 Aug 2021 06:08:42 -0700 (PDT) Received: from crow.eng.vmware.com ([146.247.46.133]) by smtp.gmail.com with ESMTPSA id f17sm2889978wrt.49.2021.08.19.06.08.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 06:08:42 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: linux-trace-devel@vger.kernel.org Cc: "Yordan Karadzhov (VMware)" Subject: [PATCH v2 4/7] trace-cruncher: Define Python type for instances Date: Thu, 19 Aug 2021 16:08:24 +0300 Message-Id: <20210819130827.12327-5-y.karadz@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210819130827.12327-1-y.karadz@gmail.com> References: <20210819130827.12327-1-y.karadz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org We add a custom Python type that wraps the 'tracefs_instance' object, defined in libtracefs. This is a preparation for a general refactorung of the way libtracefs instances are handled by trace-cruncher. Signed-off-by: Yordan Karadzhov (VMware) --- src/ftracepy-utils.c | 5 +++++ src/ftracepy-utils.h | 4 ++++ src/ftracepy.c | 17 +++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c index 197804b..a75f19b 100644 --- a/src/ftracepy-utils.c +++ b/src/ftracepy-utils.c @@ -531,6 +531,11 @@ bool get_instance_from_arg(PyObject *args, PyObject *kwargs, return true; } +PyObject *PyTfsInstance_dir(PyTfsInstance *self) +{ + return PyUnicode_FromString(tracefs_instance_get_dir(self->ptrObj)); +} + PyObject *PyFtrace_dir(PyObject *self) { return PyUnicode_FromString(tracefs_tracing_dir()); diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h index 514c79b..c674804 100644 --- a/src/ftracepy-utils.h +++ b/src/ftracepy-utils.h @@ -22,6 +22,8 @@ C_OBJECT_WRAPPER_DECLARE(tep_event, PyTepEvent) C_OBJECT_WRAPPER_DECLARE(tep_handle, PyTep) +C_OBJECT_WRAPPER_DECLARE(tracefs_instance, PyTfsInstance) + PyObject *PyTepRecord_time(PyTepRecord* self); PyObject *PyTepRecord_cpu(PyTepRecord* self); @@ -44,6 +46,8 @@ PyObject *PyTep_init_local(PyTep *self, PyObject *args, PyObject *PyTep_get_event(PyTep *self, PyObject *args, PyObject *kwargs); +PyObject *PyTfsInstance_dir(PyTfsInstance *self); + PyObject *PyFtrace_dir(PyObject *self); PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs); diff --git a/src/ftracepy.c b/src/ftracepy.c index 2296ec9..97b410f 100644 --- a/src/ftracepy.c +++ b/src/ftracepy.c @@ -73,6 +73,19 @@ static PyMethodDef PyTep_methods[] = { C_OBJECT_WRAPPER(tep_handle, PyTep, NO_DESTROY, tep_free) +static PyMethodDef PyTfsInstance_methods[] = { + {"dir", + (PyCFunction) PyTfsInstance_dir, + METH_NOARGS, + "Get the absolute path to the instance directory." + }, + {NULL, NULL, 0, NULL} +}; + +C_OBJECT_WRAPPER(tracefs_instance, PyTfsInstance, + tracefs_instance_destroy, + tracefs_instance_free) + static PyMethodDef ftracepy_methods[] = { {"dir", (PyCFunction) PyFtrace_dir, @@ -326,6 +339,9 @@ PyMODINIT_FUNC PyInit_ftracepy(void) if (!PyTepRecordTypeInit()) return NULL; + if (!PyTfsInstanceTypeInit()) + return NULL; + TFS_ERROR = PyErr_NewException("tracecruncher.ftracepy.tfs_error", NULL, NULL); @@ -340,6 +356,7 @@ PyMODINIT_FUNC PyInit_ftracepy(void) PyModule_AddObject(module, "tep_handle", (PyObject *) &PyTepType); PyModule_AddObject(module, "tep_event", (PyObject *) &PyTepEventType); PyModule_AddObject(module, "tep_record", (PyObject *) &PyTepRecordType); + PyModule_AddObject(module, "tracefs_instance", (PyObject *) &PyTfsInstanceType); PyModule_AddObject(module, "tfs_error", TFS_ERROR); PyModule_AddObject(module, "tep_error", TEP_ERROR); From patchwork Thu Aug 19 13:08:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 12447189 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 C736AC4320A for ; Thu, 19 Aug 2021 13:08:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ADDD061152 for ; Thu, 19 Aug 2021 13:08:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239151AbhHSNJX (ORCPT ); Thu, 19 Aug 2021 09:09:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52678 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239334AbhHSNJW (ORCPT ); Thu, 19 Aug 2021 09:09:22 -0400 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A27D7C061757 for ; Thu, 19 Aug 2021 06:08:45 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id x12so9000160wrr.11 for ; Thu, 19 Aug 2021 06:08:45 -0700 (PDT) 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=cciFYLyq7aMFAOob86mDspLiwDNUue0Eur+CQfHphBU=; b=fJxwa8WNldtTzbUvzLa8mZIW4YaSrRLciSAsEXVEtq1qhbVYKC6A8i0XOCHpB/ZGkw hVKMkIPunrKFUCB072qka8TsgPHUpkdynXz6pfjwBsF8uTmdpjFqGRydJjPK1bCAnRZ9 CI772Qfo4Mpib0KBK4PbHAhWRNvzXKloWAI6ddZx57K6IfpvoYhDMDCU3wcb6kWqAF05 OAdMVJPO5zTBx1C/KqF2AN4G+b3qZHq7Rn9IGN4+HvKwBRGMQ6rYA2GPqTYdUgKlZlxd GGHbDW56VrGPmvaUoJjdro9Qlmr3/e/kn+E/53ohEmiXxF06dlo5hKab1NbrU168igUP 8q6Q== 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=cciFYLyq7aMFAOob86mDspLiwDNUue0Eur+CQfHphBU=; b=L/QCaAc+vnEb0y5MxyK4AFoq7BFtVlVJ1zoB8Fb3S4tFCEXj7ELDaaM6NIL6rgbfoW qJlHiSl/QjFpctsloQqFfP8ZQaErdDj45idglqc+rrH69r1oF/jeGKXbQM2puGV5RRID H6tGIH1ycBZPt+1SG+I4sbSk7Ms7Ke0Wero5j4TgmhWOqYkgh/CJNezfSKpJ5YAp8IUJ HDLwF1rwUkmt3gO5MrXzAvVk2em7ltBI6ozqUI3O+ceZChL13y+RP1r4q5Z3qj/QOdDu EOYmvRC04sPtF9nvwb5RdExKdhIzz6okYS3fzRC7Thpglm3C2MEE60PKII71eBYiGtLO jipw== X-Gm-Message-State: AOAM530vfWk+Wchun47TqyMn54NxgNxJh8NuwSsulj0bZZOTFJ9D0vot +tAZJryGEmsMDjLIzkCjKpG08bIPii4= X-Google-Smtp-Source: ABdhPJyQUtErlV9+diRnT6cREz3Ugbw0PEqcSVhRMmPVy6fgGF0ZkjLoz9pSz2LHuxRGKqEiKfvbrg== X-Received: by 2002:a5d:4583:: with SMTP id p3mr3732308wrq.398.1629378523711; Thu, 19 Aug 2021 06:08:43 -0700 (PDT) Received: from crow.eng.vmware.com ([146.247.46.133]) by smtp.gmail.com with ESMTPSA id f17sm2889978wrt.49.2021.08.19.06.08.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 06:08:43 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: linux-trace-devel@vger.kernel.org Cc: "Yordan Karadzhov (VMware)" Subject: [PATCH v2 5/7] trace-cruncher: Refactor the way libtracefs instances are handled Date: Thu, 19 Aug 2021 16:08:25 +0300 Message-Id: <20210819130827.12327-6-y.karadz@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210819130827.12327-1-y.karadz@gmail.com> References: <20210819130827.12327-1-y.karadz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Currently all libtracefs instances created by trace-cruncher are wrapped by a dedicated C structure and stored in a binary search tree. The ordering in the tree is based on a string comparison. The tree is used for accessing the created instances and for cleanup when the module exits (garbage collection). In this refactoring we eliminate the need of the tree by switching to using the custom Python type for libtracefs instances. The new type is defined in the C extension of the module. Signed-off-by: Yordan Karadzhov (VMware) --- src/ftracepy-utils.c | 412 +++++------------- src/ftracepy-utils.h | 10 - src/ftracepy.c | 20 - tests/1_unit/test_01_ftracepy_unit.py | 245 +++++------ .../test_01_ftracepy_integration.py | 56 +-- 5 files changed, 242 insertions(+), 501 deletions(-) diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c index a75f19b..5d7d9af 100644 --- a/src/ftracepy-utils.c +++ b/src/ftracepy-utils.c @@ -19,7 +19,6 @@ // trace-cruncher #include "ftracepy-utils.h" -static void *instance_root; PyObject *TFS_ERROR; PyObject *TEP_ERROR; PyObject *TRACECRUNCHER_ERROR; @@ -419,118 +418,6 @@ static PyObject *tfs_list2py_list(char **list) return py_list; } -struct instance_wrapper { - struct tracefs_instance *ptr; - const char *name; -}; - -const char *instance_wrapper_get_name(const struct instance_wrapper *iw) -{ - if (!iw->ptr) - return iw->name; - - return tracefs_instance_get_name(iw->ptr); -} - -static int instance_compare(const void *a, const void *b) -{ - const struct instance_wrapper *iwa, *iwb; - - iwa = (const struct instance_wrapper *) a; - iwb = (const struct instance_wrapper *) b; - - return strcmp(instance_wrapper_get_name(iwa), - instance_wrapper_get_name(iwb)); -} - -void instance_wrapper_free(void *ptr) -{ - struct instance_wrapper *iw; - if (!ptr) - return; - - iw = ptr; - if (iw->ptr) { - if (tracefs_instance_destroy(iw->ptr) < 0) - fprintf(stderr, - "\ntfs_error: Failed to destroy instance '%s'.\n", - get_instance_name(iw->ptr)); - - free(iw->ptr); - } - - free(ptr); -} - -static void destroy_all_instances(void) -{ - tdestroy(instance_root, instance_wrapper_free); - instance_root = NULL; -} - -static struct tracefs_instance *find_instance(const char *name) -{ - struct instance_wrapper iw, **iw_ptr; - if (!is_set(name)) - return NULL; - - if (!tracefs_instance_exists(name)) { - PyErr_Format(TFS_ERROR, "Trace instance \'%s\' does not exist.", - name); - return NULL; - } - - iw.ptr = NULL; - iw.name = name; - iw_ptr = tfind(&iw, &instance_root, instance_compare); - if (!iw_ptr || !(*iw_ptr) || !(*iw_ptr)->ptr || - strcmp(tracefs_instance_get_name((*iw_ptr)->ptr), name) != 0) { - PyErr_Format(TFS_ERROR, "Unable to find trace instances \'%s\'.", - name); - return NULL; - } - - return (*iw_ptr)->ptr; -} - -bool get_optional_instance(const char *instance_name, - struct tracefs_instance **instance) -{ - *instance = NULL; - if (is_set(instance_name)) { - *instance = find_instance(instance_name); - if (!instance) { - PyErr_Format(TFS_ERROR, - "Failed to find instance \'%s\'.", - instance_name); - return false; - } - } - - return true; -} - -bool get_instance_from_arg(PyObject *args, PyObject *kwargs, - struct tracefs_instance **instance) -{ - const char *instance_name; - - static char *kwlist[] = {"instance", NULL}; - instance_name = NO_ARG; - if (!PyArg_ParseTupleAndKeywords(args, - kwargs, - "|s", - kwlist, - &instance_name)) { - return false; - } - - if (!get_optional_instance(instance_name, instance)) - return false; - - return true; -} - PyObject *PyTfsInstance_dir(PyTfsInstance *self) { return PyUnicode_FromString(tracefs_instance_get_dir(self->ptrObj)); @@ -590,7 +477,6 @@ static bool tracing_OFF(struct tracefs_instance *instance); PyObject *PyFtrace_create_instance(PyObject *self, PyObject *args, PyObject *kwargs) { - struct instance_wrapper *iw, **iw_ptr; struct tracefs_instance *instance; const char *name = NO_ARG; int tracing_on = true; @@ -618,115 +504,53 @@ PyObject *PyFtrace_create_instance(PyObject *self, PyObject *args, return NULL; } - iw = calloc(1, sizeof(*iw)); - if (!iw) { - MEM_ERROR - return NULL; - } - - iw->ptr = instance; - iw_ptr = tsearch(iw, &instance_root, instance_compare); - if (!iw_ptr || !(*iw_ptr) || !(*iw_ptr)->ptr || - strcmp(tracefs_instance_get_name((*iw_ptr)->ptr), name) != 0) { - PyErr_Format(TFS_ERROR, - "Failed to store new trace instance \'%s\'.", - name); - tracefs_instance_destroy(instance); - tracefs_instance_free(instance); - free(iw); - - return NULL; - } - if (!tracing_on) tracing_OFF(instance); - return PyUnicode_FromString(name); + return PyTfsInstance_New(instance); } -PyObject *PyFtrace_destroy_instance(PyObject *self, PyObject *args, - PyObject *kwargs) +static bool get_optional_instance(PyObject *py_obj, + struct tracefs_instance **instance) { - struct tracefs_instance *instance; - struct instance_wrapper iw; - char *name; + PyTfsInstance *py_inst; - static char *kwlist[] = {"name", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, - kwargs, - "s", - kwlist, - &name)) { - return NULL; - } - - if (is_all(name)) { - destroy_all_instances(); - Py_RETURN_NONE; + if (!py_obj) { + *instance = NULL; + return true; } - instance = find_instance(name); - if (!instance) { - PyErr_Format(TFS_ERROR, - "Unable to destroy trace instances \'%s\'.", - name); - return NULL; + if (!PyTfsInstance_Check(py_obj)) { + PyErr_SetString(TRACECRUNCHER_ERROR, + "Passing argument \'instance\' with incompatible type."); + return false; } - iw.ptr = NULL; - iw.name = name; - tdelete(&iw, &instance_root, instance_compare); - - tracefs_instance_destroy(instance); - tracefs_instance_free(instance); + py_inst = (PyTfsInstance *)py_obj; + *instance = py_inst->ptrObj; - Py_RETURN_NONE; + return true; } -PyObject *instance_list; - -static void instance_action(const void *nodep, VISIT which, int depth) +bool get_instance_from_arg(PyObject *args, PyObject *kwargs, + struct tracefs_instance **instance) { - struct instance_wrapper *iw = *( struct instance_wrapper **) nodep; - const char *name; - - switch(which) { - case preorder: - case endorder: - break; + static char *kwlist[] = {"instance", NULL}; + PyObject *py_inst = NULL; + *instance = NULL; - case postorder: - case leaf: - name = tracefs_instance_get_name(iw->ptr); - PyList_Append(instance_list, PyUnicode_FromString(name)); - break; + if (!PyArg_ParseTupleAndKeywords(args, + kwargs, + "|O", + kwlist, + &py_inst)) { + return false; } -} - -PyObject *PyFtrace_get_all_instances(PyObject *self) -{ - instance_list = PyList_New(0); - twalk(instance_root, instance_action); - - return instance_list; -} - -PyObject *PyFtrace_destroy_all_instances(PyObject *self) -{ - destroy_all_instances(); - - Py_RETURN_NONE; -} - -PyObject *PyFtrace_instance_dir(PyObject *self, PyObject *args, - PyObject *kwargs) -{ - struct tracefs_instance *instance; - if (!get_instance_from_arg(args, kwargs, &instance)) + if (!get_optional_instance(py_inst, instance)) return NULL; - return PyUnicode_FromString(tracefs_instance_get_dir(instance)); + return true; } PyObject *PyFtrace_available_tracers(PyObject *self, PyObject *args, @@ -748,21 +572,22 @@ PyObject *PyFtrace_available_tracers(PyObject *self, PyObject *args, PyObject *PyFtrace_set_current_tracer(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *file = "current_tracer", *tracer, *instance_name; + static char *kwlist[] = {"tracer", "instance", NULL}; + const char *file = "current_tracer", *tracer; struct tracefs_instance *instance; + PyObject *py_inst = NULL; - static char *kwlist[] = {"tracer", "instance", NULL}; - tracer = instance_name = NO_ARG; + tracer = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|ss", + "|sO", kwlist, &tracer, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; if (is_set(tracer) && @@ -836,20 +661,21 @@ PyObject *PyFtrace_available_system_events(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"system", "instance", NULL}; - const char *instance_name = NO_ARG, *system; struct tracefs_instance *instance; + PyObject *py_inst = NULL; + const char *system; char **list; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|s", + "s|O", kwlist, &system, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; list = tracefs_system_events(tracefs_instance_get_dir(instance), @@ -947,21 +773,22 @@ static bool set_enable_event(PyObject *self, bool enable) { static char *kwlist[] = {"instance", "system", "event", NULL}; - const char *instance_name, *system, *event; struct tracefs_instance *instance; + PyObject *py_inst = NULL; + const char *system, *event; - instance_name = system = event = NO_ARG; + system = event = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|sss", + "|Oss", kwlist, - &instance_name, + &py_inst, &system, &event)) { return false; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return false; return event_enable_disable(instance, system, event, enable); @@ -995,22 +822,21 @@ static bool set_enable_events(PyObject *self, PyObject *args, PyObject *kwargs, PyObject *system_list = NULL, *event_list = NULL, *system_event_list; const char **systems = NULL, **events = NULL; struct tracefs_instance *instance; - const char *instance_name; + PyObject *py_inst = NULL; char *file = NULL; int ret, s, e; - instance_name = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|sOO", + "|OOO", kwlist, - &instance_name, + &py_inst, &system_list, &event_list)) { return false; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return false; if (!system_list && !event_list) @@ -1122,21 +948,22 @@ PyObject *PyFtrace_event_is_enabled(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"instance", "system", "event", NULL}; - const char *instance_name, *system, *event; struct tracefs_instance *instance; + PyObject *py_inst = NULL; + const char *system, *event; - instance_name = system = event = NO_ARG; + system = event = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|sss", + "|Oss", kwlist, - &instance_name, + &py_inst, &system, &event)) { return false; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return false; return event_is_enabled(instance, system, event); @@ -1145,23 +972,24 @@ PyObject *PyFtrace_event_is_enabled(PyObject *self, PyObject *args, PyObject *PyFtrace_set_event_filter(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *instance_name = NO_ARG, *system, *event, *filter; + const char *system, *event, *filter; struct tracefs_instance *instance; + PyObject *py_inst = NULL; char path[PATH_MAX]; static char *kwlist[] = {"system", "event", "filter", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "sss|s", + "ssO|)", kwlist, &system, &event, &filter, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; sprintf(path, "events/%s/%s/filter", system, event); @@ -1176,22 +1004,23 @@ PyObject *PyFtrace_set_event_filter(PyObject *self, PyObject *args, PyObject *PyFtrace_clear_event_filter(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *instance_name = NO_ARG, *system, *event; struct tracefs_instance *instance; + PyObject *py_inst = NULL; + const char *system, *event; char path[PATH_MAX]; static char *kwlist[] = {"system", "event", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ss|s", + "ss|O", kwlist, &system, &event, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; sprintf(path, "events/%s/%s/filter", system, event); @@ -1350,21 +1179,21 @@ static bool set_pid(struct tracefs_instance *instance, PyObject *PyFtrace_set_event_pid(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *instance_name = NO_ARG; struct tracefs_instance *instance; + PyObject *py_inst = NULL; PyObject *pid_val; static char *kwlist[] = {"pid", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|s", + "O|O", kwlist, &pid_val, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; if (!set_pid(instance, "set_event_pid", pid_val)) @@ -1376,21 +1205,21 @@ PyObject *PyFtrace_set_event_pid(PyObject *self, PyObject *args, PyObject *PyFtrace_set_ftrace_pid(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *instance_name = NO_ARG; struct tracefs_instance *instance; + PyObject *py_inst = NULL; PyObject *pid_val; static char *kwlist[] = {"pid", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|s", + "O|O", kwlist, &pid_val, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; if (!set_pid(instance, "set_ftrace_pid", pid_val)) @@ -1416,20 +1245,21 @@ static bool set_opt(struct tracefs_instance *instance, static PyObject *set_option_py_args(PyObject *args, PyObject *kwargs, const char *val) { - const char *instance_name = NO_ARG, *opt; struct tracefs_instance *instance; + PyObject *py_inst = NULL; + const char *opt; static char *kwlist[] = {"option", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|s", + "s|O", kwlist, &opt, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; if (!set_opt(instance, opt, val)) @@ -1453,21 +1283,22 @@ PyObject *PyFtrace_disable_option(PyObject *self, PyObject *args, PyObject *PyFtrace_option_is_set(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *instance_name = NO_ARG, *opt; struct tracefs_instance *instance; + PyObject *py_inst = NULL; enum tracefs_option_id opt_id; + const char *opt; static char *kwlist[] = {"option", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|s", + "s|O", kwlist, &opt, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; opt_id = tracefs_option_id(opt); @@ -1706,22 +1537,23 @@ PyObject *PyFtrace_registered_kprobes(PyObject *self) PyObject *PyFtrace_set_kprobe_filter(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *instance_name = NO_ARG, *event, *filter; struct tracefs_instance *instance; + PyObject *py_inst = NULL; + const char *event, *filter; char path[PATH_MAX]; static char *kwlist[] = {"event", "filter", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ss|s", + "ss|O", kwlist, &event, &filter, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; sprintf(path, "events/%s/%s/filter", TC_SYS, event); @@ -1736,21 +1568,22 @@ PyObject *PyFtrace_set_kprobe_filter(PyObject *self, PyObject *args, PyObject *PyFtrace_clear_kprobe_filter(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *instance_name = NO_ARG, *event; struct tracefs_instance *instance; + PyObject *py_inst = NULL; char path[PATH_MAX]; + const char *event; static char *kwlist[] = {"event", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|s", + "s|O", kwlist, &event, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; sprintf(path, "events/%s/%s/filter", TC_SYS, event); @@ -1767,19 +1600,19 @@ static bool enable_kprobe(PyObject *self, PyObject *args, PyObject *kwargs, { static char *kwlist[] = {"event", "instance", NULL}; struct tracefs_instance *instance; - const char *instance_name, *event; + PyObject *py_inst = NULL; + const char *event = NO_ARG; - instance_name = event = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|s", + "s|O", kwlist, &event, - &instance_name)) { + &py_inst)) { return false; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return false; return event_enable_disable(instance, TC_SYS, event, enable); @@ -1808,19 +1641,19 @@ PyObject *PyFtrace_kprobe_is_enabled(PyObject *self, PyObject *args, { static char *kwlist[] = {"event", "instance", NULL}; struct tracefs_instance *instance; - const char *instance_name, *event; + PyObject *py_inst = NULL; + const char *event = NO_ARG; - instance_name = event = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|s", + "s|O", kwlist, &event, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; return event_is_enabled(instance, TC_SYS, event); @@ -2023,27 +1856,27 @@ static bool init_callback_tep(struct tracefs_instance *instance, PyObject *PyFtrace_trace_shell_process(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *plugin = "__main__", *py_callback = "callback", *instance_name; + const char *plugin = "__main__", *py_callback = "callback"; static char *kwlist[] = {"process", "plugin", "callback", "instance", NULL}; struct tracefs_instance *instance; + PyObject *py_inst = NULL; struct tep_handle *tep; PyObject *py_func; char *process; pid_t pid; - instance_name = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|sss", + "s|ssO", kwlist, &process, &plugin, &py_callback, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; if (!init_callback_tep(instance, plugin, py_callback, &tep, &py_func)) @@ -2070,27 +1903,27 @@ PyObject *PyFtrace_trace_shell_process(PyObject *self, PyObject *args, PyObject *PyFtrace_trace_process(PyObject *self, PyObject *args, PyObject *kwargs) { - const char *plugin = "__main__", *py_callback = "callback", *instance_name; + const char *plugin = "__main__", *py_callback = "callback"; static char *kwlist[] = {"argv", "plugin", "callback", "instance", NULL}; struct tracefs_instance *instance; + PyObject *py_inst = NULL; struct tep_handle *tep; PyObject *py_func, *py_argv, *py_arg; pid_t pid; int i, argc; - instance_name = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|sss", + "O|ssO", kwlist, &py_argv, &plugin, &py_callback, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; if (!init_callback_tep(instance, plugin, py_callback, &tep, &py_func)) @@ -2173,8 +2006,7 @@ PyObject *PyFtrace_iterate_trace(PyObject *self, PyObject *args, const char *plugin = "__main__", *py_callback = "callback"; bool *callback_status = &callback_ctx.status; bool *keep_going = &iterate_keep_going; - - const char *instance_name; + PyObject *py_inst = NULL; struct tep_handle *tep; PyObject *py_func; int ret; @@ -2182,20 +2014,19 @@ PyObject *PyFtrace_iterate_trace(PyObject *self, PyObject *args, (*(volatile bool *)keep_going) = true; signal(SIGINT, iterate_stop); - instance_name = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|sss", + "|ssO", kwlist, &plugin, &py_callback, - &instance_name)) { + &py_inst)) { return NULL; } py_func = get_callback_func(plugin, py_callback); if (!py_func || - !get_optional_instance(instance_name, &itr_instance) || + !get_optional_instance(py_inst, &itr_instance) || !notrace_this_pid(itr_instance)) return NULL; @@ -2219,22 +2050,22 @@ PyObject *PyFtrace_iterate_trace(PyObject *self, PyObject *args, PyObject *PyFtrace_hook2pid(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"pid", "fork", "instance", NULL}; - const char *instance_name = NO_ARG; struct tracefs_instance *instance; + PyObject *py_inst = NULL; PyObject *pid_val; int fork = -1; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|ps", + "O|pO", kwlist, &pid_val, &fork, - &instance_name)) { + &py_inst)) { return NULL; } - if (!get_optional_instance(instance_name, &instance)) + if (!get_optional_instance(py_inst, &instance)) return NULL; if (!hook2pid(instance, pid_val, fork)) @@ -2246,5 +2077,4 @@ PyObject *PyFtrace_hook2pid(PyObject *self, PyObject *args, PyObject *kwargs) void PyFtrace_at_exit(void) { destroy_all_kprobes(); - destroy_all_instances(); } diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h index c674804..04de1f3 100644 --- a/src/ftracepy-utils.h +++ b/src/ftracepy-utils.h @@ -55,16 +55,6 @@ PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs); PyObject *PyFtrace_create_instance(PyObject *self, PyObject *args, PyObject *kwargs); -PyObject *PyFtrace_destroy_instance(PyObject *self, PyObject *args, - PyObject *kwargs); - -PyObject *PyFtrace_get_all_instances(PyObject *self); - -PyObject *PyFtrace_destroy_all_instances(PyObject *self); - -PyObject *PyFtrace_instance_dir(PyObject *self, PyObject *args, - PyObject *kwargs); - PyObject *PyFtrace_available_tracers(PyObject *self, PyObject *args, PyObject *kwargs); diff --git a/src/ftracepy.c b/src/ftracepy.c index 97b410f..3c55e50 100644 --- a/src/ftracepy.c +++ b/src/ftracepy.c @@ -102,26 +102,6 @@ static PyMethodDef ftracepy_methods[] = { METH_VARARGS | METH_KEYWORDS, "Create new tracefs instance." }, - {"get_all_instances", - (PyCFunction) PyFtrace_get_all_instances, - METH_NOARGS, - "Get all existing tracefs instances." - }, - {"destroy_instance", - (PyCFunction) PyFtrace_destroy_instance, - METH_VARARGS | METH_KEYWORDS, - "Destroy existing tracefs instance." - }, - {"destroy_all_instances", - (PyCFunction) PyFtrace_destroy_all_instances, - METH_NOARGS, - "Destroy all existing tracefs instances." - }, - {"instance_dir", - (PyCFunction) PyFtrace_instance_dir, - METH_VARARGS | METH_KEYWORDS, - "Get the absolute path to the instance directory." - }, {"available_tracers", (PyCFunction) PyFtrace_available_tracers, METH_VARARGS | METH_KEYWORDS, diff --git a/tests/1_unit/test_01_ftracepy_unit.py b/tests/1_unit/test_01_ftracepy_unit.py index 0d62da2..57db0ad 100644 --- a/tests/1_unit/test_01_ftracepy_unit.py +++ b/tests/1_unit/test_01_ftracepy_unit.py @@ -22,48 +22,20 @@ class InstanceTestCase(unittest.TestCase): self.assertTrue(os.path.isdir(instances_dir)) def test_create_instance(self): - ft.create_instance(instance_name) - self.assertTrue(ft.is_tracing_ON(instance_name)) + inst = ft.create_instance(instance_name) + self.assertTrue(ft.is_tracing_ON(inst)) instances_dir = ft.dir() + '/instances/' self.assertTrue(os.path.isdir(instances_dir + instance_name)) auto_inst = ft.create_instance(tracing_on=False) self.assertFalse(ft.is_tracing_ON(auto_inst)) - ft.destroy_instance(auto_inst) - - def test_destroy_instance(self): - ft.destroy_instance(instance_name) - instances_dir = ft.dir() + '/instances/' - self.assertFalse(os.path.isdir(instances_dir + instance_name)) - - err = 'Unable to destroy trace instances' - with self.assertRaises(Exception) as context: - ft.destroy_instance(instance_name) - self.assertTrue(err in str(context.exception)) - - ft.create_instance(instance_name) - ft.create_instance(another_instance_name) - ft.destroy_all_instances() - self.assertFalse(os.path.isdir(instances_dir + instance_name)) - - ft.create_instance(instance_name) - ft.create_instance(another_instance_name) - ft.destroy_instance('all') - self.assertFalse(os.path.isdir(instances_dir + instance_name)) - - def test_get_all(self): - ft.create_instance(instance_name) - ft.create_instance(another_instance_name) - self.assertEqual(ft.get_all_instances(), - [instance_name, another_instance_name]) - ft.destroy_all_instances() def test_instance_dir(self): - ft.create_instance(instance_name) + inst = ft.create_instance(instance_name) tracefs_dir = ft.dir(); instance_dir = tracefs_dir + '/instances/' + instance_name - self.assertEqual(instance_dir, ft.instance_dir(instance_name)) - ft.destroy_all_instances() + self.assertEqual(instance_dir, inst.dir()) + class PyTepTestCase(unittest.TestCase): def test_init_local(self): @@ -73,8 +45,8 @@ class PyTepTestCase(unittest.TestCase): tep.init_local(dir=tracefs_dir, systems=['sched', 'irq']); - ft.create_instance(instance_name) - tracefs_dir = ft.instance_dir(instance_name) + inst = ft.create_instance(instance_name) + tracefs_dir = inst.dir() tep.init_local(dir=tracefs_dir, systems=['sched', 'irq']); err='function missing required argument \'dir\'' @@ -86,7 +58,6 @@ class PyTepTestCase(unittest.TestCase): with self.assertRaises(Exception) as context: tep.init_local(dir='no_dir', systems=['sched', 'irq']); self.assertTrue(err in str(context.exception)) - ft.destroy_all_instances() def test_get_event(self): tracefs_dir = ft.dir() @@ -144,302 +115,284 @@ class EventsTestCase(unittest.TestCase): self.assertTrue(len(systems) > 1) self.assertTrue('sched' in systems) - ft.create_instance(instance_name) - systems = ft.available_event_systems(instance_name) + inst = ft.create_instance(instance_name) + systems = ft.available_event_systems(inst) self.assertTrue(len(systems) > 1) self.assertTrue('sched' in systems) - ft.destroy_all_instances() - def test_available_system_events(self): events = ft.available_system_events(system='sched') self.assertTrue(len(events) > 1) self.assertTrue('sched_switch' in events) - ft.create_instance(instance_name) - events = ft.available_system_events(instance=instance_name, - system='sched') + inst = ft.create_instance(instance_name) + events = ft.available_system_events(instance=inst, + system='sched') self.assertTrue(len(events) > 1) self.assertTrue('sched_switch' in events) err = 'function missing required argument' with self.assertRaises(Exception) as context: - ft.available_system_events(instance=instance_name) + ft.available_system_events(instance=inst) self.assertTrue(err in str(context.exception)) - ft.destroy_all_instances() - def test_enable_event(self): - ft.create_instance(instance_name) - - ret = ft.event_is_enabled(instance=instance_name, system='all') + inst = ft.create_instance(instance_name) + ret = ft.event_is_enabled(instance=inst, system='all') self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, system='all') - ret = ft.event_is_enabled(instance=instance_name, system='all') + ft.enable_event(instance=inst, system='all') + ret = ft.event_is_enabled(instance=inst, system='all') self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, system='all') - ret = ft.event_is_enabled(instance=instance_name, system='all') + ft.disable_event(instance=inst, system='all') + ret = ft.event_is_enabled(instance=inst, system='all') self.assertEqual(ret, '0') - ret = ft.event_is_enabled(instance=instance_name, event='all') + ret = ft.event_is_enabled(instance=inst, event='all') self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, event='all') - ret = ft.event_is_enabled(instance=instance_name, event='all') + ft.enable_event(instance=inst, event='all') + ret = ft.event_is_enabled(instance=inst, event='all') self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, event='all') - ret = ft.event_is_enabled(instance=instance_name, event='all') + ft.disable_event(instance=inst, event='all') + ret = ft.event_is_enabled(instance=inst, event='all') self.assertEqual(ret, '0') - ret = ft.event_is_enabled(instance=instance_name, system='sched') + ret = ft.event_is_enabled(instance=inst, system='sched') self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, system='sched') - ret = ft.event_is_enabled(instance=instance_name, system='sched') + ft.enable_event(instance=inst, system='sched') + ret = ft.event_is_enabled(instance=inst, system='sched') self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, system='sched') - ret = ft.event_is_enabled(instance=instance_name, system='sched') + ft.disable_event(instance=inst, system='sched') + ret = ft.event_is_enabled(instance=inst, system='sched') self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, + ft.enable_event(instance=inst, system='sched', event='sched_switch') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_switch') self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, + ft.disable_event(instance=inst, system='sched', event='sched_switch') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_switch') self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, + ft.enable_event(instance=inst, system='sched', event='all') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='all') self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, + ft.disable_event(instance=inst, system='sched', event='all') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='all') self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, + ft.enable_event(instance=inst, event='sched_switch') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_switch') self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, + ft.disable_event(instance=inst, event='sched_switch') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_switch') self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, + ft.enable_event(instance=inst, system='all', event='sched_switch') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_switch') self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, + ft.disable_event(instance=inst, system='all', event='sched_switch') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_switch') self.assertEqual(ret, '0') - ft.destroy_all_instances() - def test_enable_event_err(self): - ft.create_instance(instance_name) + inst = ft.create_instance(instance_name) err = 'Failed to enable/disable event' with self.assertRaises(Exception) as context: - ft.enable_event(instance=instance_name, + ft.enable_event(instance=inst, system='zero') self.assertTrue(err in str(context.exception)) with self.assertRaises(Exception) as context: - ft.enable_event(instance=instance_name, + ft.enable_event(instance=inst, system='sched', event='zero') self.assertTrue(err in str(context.exception)) - ft.destroy_all_instances() - def test_enable_events(self): - ft.create_instance(instance_name) - ft.enable_events(instance=instance_name, + inst = ft.create_instance(instance_name) + ft.enable_events(instance=inst, events='all') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, event='all') self.assertEqual(ret, '1') - ft.disable_events(instance=instance_name, + ft.disable_events(instance=inst, events='all') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, event='all') self.assertEqual(ret, '0') - ft.enable_events(instance=instance_name, + ft.enable_events(instance=inst, systems=['sched', 'irq']) - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='all') self.assertEqual(ret, '1') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='irq', event='all') self.assertEqual(ret, '1') - ft.disable_events(instance=instance_name, + ft.disable_events(instance=inst, systems=['sched', 'irq']) - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='all') self.assertEqual(ret, '0') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='irq', event='all') self.assertEqual(ret, '0') - ft.enable_events(instance=instance_name, + ft.enable_events(instance=inst, systems=['sched', 'irq'], events=[['sched_switch', 'sched_waking'], ['all']]) - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_switch') self.assertEqual(ret, '1') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_waking') self.assertEqual(ret, '1') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_wakeup') self.assertEqual(ret, '0') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='irq', event='all') self.assertEqual(ret, '1') - ft.disable_events(instance=instance_name, + ft.disable_events(instance=inst, systems=['sched', 'irq'], events=[['sched_switch', 'sched_waking'], ['all']]) - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_switch') self.assertEqual(ret, '0') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='sched', event='sched_waking') self.assertEqual(ret, '0') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system='irq', event='all') self.assertEqual(ret, '0') - ft.destroy_all_instances() - def test_enable_events_err(self): - ft.create_instance(instance_name) + inst = ft.create_instance(instance_name) err = 'Inconsistent \"events\" argument' with self.assertRaises(Exception) as context: - ft.enable_events(instance=instance_name, + ft.enable_events(instance=inst, systems=['sched'], events=['all']) self.assertTrue(err in str(context.exception)) err = 'Failed to enable events for unspecified system' with self.assertRaises(Exception) as context: - ft.enable_events(instance=instance_name, + ft.enable_events(instance=inst, events=['sched_switch', 'sched_wakeup']) self.assertTrue(err in str(context.exception)) err = 'Failed to enable/disable event' with self.assertRaises(Exception) as context: - ft.enable_events(instance=instance_name, + ft.enable_events(instance=inst, systems=['sched'], events=[['no_event']]) self.assertTrue(err in str(context.exception)) - ft.destroy_all_instances() - class OptionsTestCase(unittest.TestCase): def test_enable_option(self): - ft.create_instance(instance_name) + inst = ft.create_instance(instance_name) opt = 'event-fork' - ret = ft.option_is_set(instance=instance_name, - option=opt) + ret = ft.option_is_set(instance=inst, + option=opt) self.assertFalse(ret) - ft.enable_option(instance=instance_name, + ft.enable_option(instance=inst, option=opt) - ret = ft.option_is_set(instance=instance_name, + ret = ft.option_is_set(instance=inst, option=opt) self.assertTrue(ret) - ft.disable_option(instance=instance_name, + ft.disable_option(instance=inst, option=opt) - ret = ft.option_is_set(instance=instance_name, + ret = ft.option_is_set(instance=inst, option=opt) self.assertFalse(ret) opt = 'no-opt' err = 'Failed to set option \"no-opt\"' with self.assertRaises(Exception) as context: - ft.enable_option(instance=instance_name, + ft.enable_option(instance=inst, option=opt) self.assertTrue(err in str(context.exception)) - ft.destroy_all_instances() - def test_supported_options(self): - ft.create_instance(instance_name) - opts = ft.supported_options(instance_name) + inst = ft.create_instance(instance_name) + opts = ft.supported_options(inst) self.assertTrue(len(opts) > 20) self.assertTrue('event-fork' in opts) - ft.destroy_all_instances() - def test_enabled_options(self): - ft.create_instance(instance_name) - opts = ft.enabled_options(instance_name) + inst = ft.create_instance(instance_name) + opts = ft.enabled_options(inst) n = len(opts) - ft.enable_option(instance=instance_name, option='function-fork') - ft.enable_option(instance=instance_name, option='event-fork') - opts = ft.enabled_options(instance_name) + ft.enable_option(instance=inst, option='function-fork') + ft.enable_option(instance=inst, option='event-fork') + opts = ft.enabled_options(inst) self.assertEqual(len(opts), n + 2) self.assertTrue('event-fork' in opts) self.assertTrue('function-fork' in opts) - ft.destroy_all_instances() class KprobeTestCase(unittest.TestCase): def test_register_kprobe(self): @@ -487,17 +440,17 @@ class KprobeTestCase(unittest.TestCase): ft.register_kprobe(event=evt1, function=evt1_func, probe=evt1_prove) - ft.create_instance(instance_name) - ft.enable_kprobe(instance=instance_name, event=evt1) - ret = ft.kprobe_is_enabled(instance=instance_name, event=evt1) + inst = ft.create_instance(instance_name) + ft.enable_kprobe(instance=inst, event=evt1) + ret = ft.kprobe_is_enabled(instance=inst, event=evt1) self.assertEqual(ret, '1') - ft.disable_kprobe(instance=instance_name, event=evt1) - ret = ft.kprobe_is_enabled(instance=instance_name, event=evt1) + ft.disable_kprobe(instance=inst, event=evt1) + ret = ft.kprobe_is_enabled(instance=inst, event=evt1) self.assertEqual(ret, '0') ft.unregister_kprobe(event='ALL') - ft.destroy_all_instances() + class TracingOnTestCase(unittest.TestCase): def test_ON_OF(self): @@ -505,16 +458,14 @@ class TracingOnTestCase(unittest.TestCase): self.assertTrue(ft.is_tracing_ON()) ft.tracing_OFF() - ft.create_instance(instance_name) - ft.tracing_ON(instance=instance_name) - self.assertTrue(ft.is_tracing_ON(instance=instance_name)) + inst = ft.create_instance(instance_name) + ft.tracing_ON(instance=inst) + self.assertTrue(ft.is_tracing_ON(instance=inst)) self.assertFalse(ft.is_tracing_ON()) - ft.tracing_OFF(instance=instance_name) - - ft.destroy_all_instances() + ft.tracing_OFF(instance=inst) def test_err(self): - err = 'returned a result with an error set' + err = 'incompatible type' with self.assertRaises(Exception) as context: ft.tracing_ON('zero') self.assertTrue(err in str(context.exception)) diff --git a/tests/2_integration/test_01_ftracepy_integration.py b/tests/2_integration/test_01_ftracepy_integration.py index d3b2c6b..824decd 100755 --- a/tests/2_integration/test_01_ftracepy_integration.py +++ b/tests/2_integration/test_01_ftracepy_integration.py @@ -19,18 +19,9 @@ class InstanceTestCase(unittest.TestCase): for i in range(25) : instance_name = 'test_instance_%s' % i - ft.create_instance(instance_name) + inst = ft.create_instance(instance_name) self.assertTrue(os.path.isdir(instances_dir + instance_name)) - for i in range(15) : - instance_name = 'test_instance_%s' % i - ft.destroy_instance(instance_name) - self.assertFalse(os.path.isdir(instances_dir + instance_name)) - - self.assertEqual(len(os.listdir(instances_dir)), 10) - ft.destroy_instance('all') - self.assertEqual(len(os.listdir(instances_dir)), 0) - def test_current_tracer(self): current = ft.get_current_tracer() self.assertEqual(current, 'nop') @@ -42,68 +33,67 @@ class InstanceTestCase(unittest.TestCase): ft.set_current_tracer() instance_name = 'test_instance' - ft.create_instance(instance_name) - current = ft.get_current_tracer(instance=instance_name) + inst = ft.create_instance(instance_name) + current = ft.get_current_tracer(instance=inst) self.assertEqual(current, 'nop') - ft.tracing_OFF(instance=instance_name) - ft.set_current_tracer(instance=instance_name, tracer=name) - current = ft.get_current_tracer(instance=instance_name) + ft.tracing_OFF(instance=inst) + ft.set_current_tracer(instance=inst, tracer=name) + current = ft.get_current_tracer(instance=inst) self.assertEqual(current, name) - ft.destroy_instance('all') def test_enable_events(self): instance_name = 'test_instance' - ft.create_instance(instance_name) - systems = ft.available_event_systems(instance=instance_name) + inst = ft.create_instance(instance_name) + systems = ft.available_event_systems(instance=inst) systems.remove('ftrace') for s in systems: - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s) self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, + ft.enable_event(instance=inst, system=s) - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s) self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, + ft.disable_event(instance=inst, system=s) - events = ft.available_system_events(instance=instance_name, + events = ft.available_system_events(instance=inst, system=s) for e in events: - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s, event=e) self.assertEqual(ret, '0') - ft.enable_event(instance=instance_name, + ft.enable_event(instance=inst, system=s, event=e) - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s, event=e) self.assertEqual(ret, '1') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s) if e != events[-1]: self.assertEqual(ret, 'X') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s) self.assertEqual(ret, '1') - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s) self.assertEqual(ret, '1') - ft.disable_event(instance=instance_name, event='all') + ft.disable_event(instance=inst, event='all') for s in systems: - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s) self.assertEqual(ret, '0') - events = ft.available_system_events(instance=instance_name, + events = ft.available_system_events(instance=inst, system=s) for e in events: - ret = ft.event_is_enabled(instance=instance_name, + ret = ft.event_is_enabled(instance=inst, system=s, event=e) self.assertEqual(ret, '0') From patchwork Thu Aug 19 13:08:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 12447187 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 4E984C4338F for ; Thu, 19 Aug 2021 13:08:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3ADB161152 for ; Thu, 19 Aug 2021 13:08:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229670AbhHSNJW (ORCPT ); Thu, 19 Aug 2021 09:09:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52676 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239300AbhHSNJW (ORCPT ); Thu, 19 Aug 2021 09:09:22 -0400 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 D6ECDC06175F for ; Thu, 19 Aug 2021 06:08:45 -0700 (PDT) Received: by mail-wm1-x32c.google.com with SMTP id u1so3848410wmm.0 for ; Thu, 19 Aug 2021 06:08:45 -0700 (PDT) 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=exxhBB9HQJpIT3YeImkIDLdy1+Bj/A3dViZPXiYEuGI=; b=PNhGeDRZnKQ9XX+lEgqnTCUYQawSL4iH3TTV8U+78ws2AU/BlNlO+nufNRqm6wVYnn qM9yUpJmFXKsN8hnllf5quCzMPqfKesq+b1BkKsnGvn22dEq64wfQ6BaP+qjGusDU/PB rsv3hmabYVcorCVpbyV2lhvpF3oQ8k4hK85uJtLUuTxauOF3SmOBlZcwwEYf2tBAO2jS I4hAqlpCkU/mSr9Nv72ekYGi4diNBzBtStiLzPKi7Pl8XB23UyXsuEP5BwXYhD42BEMP nrx69WABVBjy9p7D1iQ5aGMAG6MzmDSPEtv39fTmFAJXj9UgGqP42c2dCLgzItWqUGhS ZEuw== 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=exxhBB9HQJpIT3YeImkIDLdy1+Bj/A3dViZPXiYEuGI=; b=FBpE1jEmZWjiCGSbxzy8e34d2vISn7MZOXKLsAOGvnPSisHRKYT1/RD7f/FTE2SGvG lo3JQ2VEpvSSragXhXweAczqe4hjLzNwD5VxvnBbLe1RpVhKT+9G7P1dK/1H7OjQj0uH xss55r6N9+Iri0WLCgUXW8FgZwoZ70kUBK4o9Nl7XzsSxj9gQlEi6BhF6+CSHz+GTWqh eumsFv3cy8HsonGGX5vLIv/XKVubs9V7jnRm89VDCVwYFzVLwxofI2rEVqffZYLetitT aCUG4fxhqfLjR309QMOeSquqXUsnMlToQs/Af7ziqLQYMLwdiyFSpjQH3Rfknrf4lHbw uuCA== X-Gm-Message-State: AOAM533uoVsCwyU6DNz0JnRyXRNqK76G2RzlsOmlHo/8hmmfaw7qDUE+ fI7wpkCrQy6qAsg1z7I2Vi/OVbCYVpQ= X-Google-Smtp-Source: ABdhPJy3TqHAn6KO/qTdQD1QSxAeB233dPEag22NcpvEmcGMPIZa+7Zzu/3ORoqzlO6/m33FyJG5Yg== X-Received: by 2002:a05:600c:3514:: with SMTP id h20mr9186643wmq.31.1629378524246; Thu, 19 Aug 2021 06:08:44 -0700 (PDT) Received: from crow.eng.vmware.com ([146.247.46.133]) by smtp.gmail.com with ESMTPSA id f17sm2889978wrt.49.2021.08.19.06.08.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 06:08:43 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: linux-trace-devel@vger.kernel.org Cc: "Yordan Karadzhov (VMware)" Subject: [PATCH v2 6/7] trace-cruncher: Define Python type for kprobes Date: Thu, 19 Aug 2021 16:08:26 +0300 Message-Id: <20210819130827.12327-7-y.karadz@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210819130827.12327-1-y.karadz@gmail.com> References: <20210819130827.12327-1-y.karadz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Adding this new Python type is a preparation for a general refactorung of the way kprobes are handled by trace-cruncher. Signed-off-by: Yordan Karadzhov (VMware) --- src/ftracepy-utils.c | 34 ++++++++++++++++++++++++++++++++++ src/ftracepy-utils.h | 14 ++++++++++++++ src/ftracepy.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c index 5d7d9af..b8bcb4c 100644 --- a/src/ftracepy-utils.c +++ b/src/ftracepy-utils.c @@ -1366,6 +1366,40 @@ PyObject *PyFtrace_tc_event_system(PyObject *self) return PyUnicode_FromString(TC_SYS); } +struct ftracepy_kprobe { + char *event; + char *function; + char *probe; +}; + +PyObject *PyKprobe_event(PyKprobe *self) +{ + return PyUnicode_FromString(self->ptrObj->event); +} + +PyObject *PyKprobe_system(PyKprobe *self) +{ + return PyUnicode_FromString(TC_SYS); +} + +PyObject *PyKprobe_function(PyKprobe *self) +{ + return PyUnicode_FromString(self->ptrObj->function); +} + +PyObject *PyKprobe_probe(PyKprobe *self) +{ + return PyUnicode_FromString(self->ptrObj->probe); +} + +void ftracepy_kprobe_free(struct ftracepy_kprobe *kp) +{ + free(kp->event); + free(kp->function); + free(kp->probe); + free(kp); +} + static int unregister_kprobe(const char *event) { return tracefs_kprobe_clear_probe(TC_SYS, event, true); diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h index 04de1f3..17e07e5 100644 --- a/src/ftracepy-utils.h +++ b/src/ftracepy-utils.h @@ -24,6 +24,12 @@ C_OBJECT_WRAPPER_DECLARE(tep_handle, PyTep) C_OBJECT_WRAPPER_DECLARE(tracefs_instance, PyTfsInstance) +struct ftracepy_kprobe; + +void ftracepy_kprobe_free(struct ftracepy_kprobe *kp); + +C_OBJECT_WRAPPER_DECLARE(ftracepy_kprobe, PyKprobe); + PyObject *PyTepRecord_time(PyTepRecord* self); PyObject *PyTepRecord_cpu(PyTepRecord* self); @@ -48,6 +54,14 @@ PyObject *PyTep_get_event(PyTep *self, PyObject *args, PyObject *PyTfsInstance_dir(PyTfsInstance *self); +PyObject *PyKprobe_event(PyKprobe *self); + +PyObject *PyKprobe_system(PyKprobe *self); + +PyObject *PyKprobe_function(PyKprobe *self); + +PyObject *PyKprobe_probe(PyKprobe *self); + PyObject *PyFtrace_dir(PyObject *self); PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs); diff --git a/src/ftracepy.c b/src/ftracepy.c index 3c55e50..c434af9 100644 --- a/src/ftracepy.c +++ b/src/ftracepy.c @@ -86,6 +86,34 @@ C_OBJECT_WRAPPER(tracefs_instance, PyTfsInstance, tracefs_instance_destroy, tracefs_instance_free) +static PyMethodDef PyKprobe_methods[] = { + {"event", + (PyCFunction) PyKprobe_event, + METH_NOARGS, + "Get the name of the kprobe event." + }, + {"system", + (PyCFunction) PyKprobe_system, + METH_NOARGS, + "Get the system name of the kprobe event." + }, + {"function", + (PyCFunction) PyKprobe_function, + METH_NOARGS, + "Get the function name of the kprobe event." + }, + {"probe", + (PyCFunction) PyKprobe_probe, + METH_NOARGS, + "Get the kprobe event definition." + }, + {NULL, NULL, 0, NULL} +}; + +C_OBJECT_WRAPPER(ftracepy_kprobe, PyKprobe, + NO_DESTROY, + ftracepy_kprobe_free) + static PyMethodDef ftracepy_methods[] = { {"dir", (PyCFunction) PyFtrace_dir, @@ -322,6 +350,9 @@ PyMODINIT_FUNC PyInit_ftracepy(void) if (!PyTfsInstanceTypeInit()) return NULL; + if (!PyKprobeTypeInit()) + return NULL; + TFS_ERROR = PyErr_NewException("tracecruncher.ftracepy.tfs_error", NULL, NULL); @@ -337,6 +368,7 @@ PyMODINIT_FUNC PyInit_ftracepy(void) PyModule_AddObject(module, "tep_event", (PyObject *) &PyTepEventType); PyModule_AddObject(module, "tep_record", (PyObject *) &PyTepRecordType); PyModule_AddObject(module, "tracefs_instance", (PyObject *) &PyTfsInstanceType); + PyModule_AddObject(module, "ftracepy_kprobe", (PyObject *) &PyKprobeType); PyModule_AddObject(module, "tfs_error", TFS_ERROR); PyModule_AddObject(module, "tep_error", TEP_ERROR); From patchwork Thu Aug 19 13:08:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yordan Karadzhov X-Patchwork-Id: 12447191 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 6D729C432BE for ; Thu, 19 Aug 2021 13:08:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 55EE86108D for ; Thu, 19 Aug 2021 13:08:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239334AbhHSNJX (ORCPT ); Thu, 19 Aug 2021 09:09:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52684 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239300AbhHSNJX (ORCPT ); Thu, 19 Aug 2021 09:09:23 -0400 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3E32C061575 for ; Thu, 19 Aug 2021 06:08:46 -0700 (PDT) Received: by mail-wm1-x331.google.com with SMTP id l24-20020a05600c089800b002e71a10130eso768847wmp.5 for ; Thu, 19 Aug 2021 06:08:46 -0700 (PDT) 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=af0/veNZR2GRMAsWeYJBmwt/TJhy86GjtwveRyzlLTw=; b=BAPyGkWLiny55YOG7qPd2kRKBVtrydHPEutGDf04a/ZZ6tQssdNRIBrzpn9HvQLmzH 1tJl2PeTvuys0c5uy8p4cjBRpRG/38l41c5cE3HiWK6NHK1kiQH/CwYp1qrUlwL2ZKsp WrZ8rs61zd2oCW75qf8qVpEkOCSxtL/gESQN+IglYK2V1ItHD7tuO5XHd6opHr4qQUdS AfhW9t/5TxnxvV2wuZAqFtjVcA1Ccl0R4mrLhWjtQFNnW4zDiI7INnnnosyPNXu/5wZi Gag4mn+N39dMz6z/nfx2meAlU/05fv5m89sO8uFiDvBmmpE0ncd4YdQ+zgzcmf+YYlgA X8pA== 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=af0/veNZR2GRMAsWeYJBmwt/TJhy86GjtwveRyzlLTw=; b=Ux2V8VVZUs+IaSsVNGEgbj6JW/4cWqJIozKjgcwSubGcwwf5rN2hcV3J0AORidcFNf 59rWUV4Z3KLIG7ZzdQeFrpCRhfyDJvsn92i6W+iPki5YK3h6E3g5urP7qd0JtKaQ9XoG mv6UPgW1ETYELggR6CM5+wvDSbrm9Cpi6jP+zginCiqTfx0noZftOnWkG6xW4FzBFarY Ay/PVlOAiLoYhRjhRZ0Lsz1e9VJ4pFcCf8qk4hePqpnUKSMqz8g7o5gRdLuDOQYIQKEQ 4QiWpQzdq8FDaospBrLTZXq231k2Tsc5kUMxPnTRn6y5dygnqtL95neYJjdben6IHyzj kt9w== X-Gm-Message-State: AOAM532ofoekv0R5Sg9nR9HqyOZt/oaOLAkS7tfzn2UqlCaRzTAS1Q9Q 0wJQd6BeEjjJb3tbrpeJFZObinse5P8= X-Google-Smtp-Source: ABdhPJxdzJ+qizHZ7yXwxX1HT5Y7iMZGTxREwuElqP+Qgcah3DFQ2XzthxotUOdO39IkI9WWLBC7bw== X-Received: by 2002:a1c:9dd0:: with SMTP id g199mr13966586wme.12.1629378525075; Thu, 19 Aug 2021 06:08:45 -0700 (PDT) Received: from crow.eng.vmware.com ([146.247.46.133]) by smtp.gmail.com with ESMTPSA id f17sm2889978wrt.49.2021.08.19.06.08.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 06:08:44 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: linux-trace-devel@vger.kernel.org Cc: "Yordan Karadzhov (VMware)" Subject: [PATCH v2 7/7] trace-cruncher: Refactor the way kprobes are handled Date: Thu, 19 Aug 2021 16:08:27 +0300 Message-Id: <20210819130827.12327-8-y.karadz@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210819130827.12327-1-y.karadz@gmail.com> References: <20210819130827.12327-1-y.karadz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Currently all kprobes, created by trace-cruncher, are stored in a binary search tree. The ordering in the tree is based on a string comparison. The tree is used for bookkeeping and to cleanup all created kprobes when the module exits (garbage collection). In this refactoring we eliminate the need of the tree by switching to using the custom Python type for kprobes. The new type is defined in the C extension of the module. Signed-off-by: Yordan Karadzhov (VMware) --- src/ftracepy-utils.c | 260 ++++++++++---------------- src/ftracepy-utils.h | 39 ++-- src/ftracepy.c | 69 +++---- tests/1_unit/test_01_ftracepy_unit.py | 53 ++---- tracecruncher/ft_utils.py | 14 +- 5 files changed, 165 insertions(+), 270 deletions(-) diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c index b8bcb4c..581432d 100644 --- a/src/ftracepy-utils.c +++ b/src/ftracepy-utils.c @@ -1349,16 +1349,6 @@ PyObject *PyFtrace_supported_options(PyObject *self, PyObject *args, return get_option_list(instance, false); } -static void *kprobe_root = NULL; - -static int kprobe_compare(const void *a, const void *b) -{ - const char *ca = (const char *) a; - const char *cb = (const char *) b; - - return strcmp(ca, cb); -} - #define TC_SYS "tcrunch" PyObject *PyFtrace_tc_event_system(PyObject *self) @@ -1372,6 +1362,43 @@ struct ftracepy_kprobe { char *probe; }; +static bool register_kprobe(const char *event, + const char *function, + const char *probe) +{ + if (tracefs_kprobe_raw(TC_SYS, event, function, probe) < 0) { + PyErr_Format(TFS_ERROR, "Failed to register kprobe \'%s\'.", + event); + return false; + } + + return true; +} + +static bool register_kretprobe(const char *event, + const char *function, + const char *probe) +{ + if (tracefs_kretprobe_raw(TC_SYS, event, function, probe) < 0) { + PyErr_Format(TFS_ERROR, "Failed to register kretprobe \'%s\'.", + event); + return false; + } + + return true; +} + +static bool unregister_kprobe(const char *event) +{ + if (tracefs_kprobe_clear_probe(TC_SYS, event, true) < 0) { + PyErr_Format(TFS_ERROR, "Failed to unregister kprobe \'%s\'.", + event); + return false; + } + + return true; +} + PyObject *PyKprobe_event(PyKprobe *self) { return PyUnicode_FromString(self->ptrObj->event); @@ -1392,6 +1419,11 @@ PyObject *PyKprobe_probe(PyKprobe *self) return PyUnicode_FromString(self->ptrObj->probe); } +void ftracepy_kprobe_destroy(struct ftracepy_kprobe *kp) +{ + unregister_kprobe(kp->event); +} + void ftracepy_kprobe_free(struct ftracepy_kprobe *kp) { free(kp->event); @@ -1400,46 +1432,41 @@ void ftracepy_kprobe_free(struct ftracepy_kprobe *kp) free(kp); } -static int unregister_kprobe(const char *event) -{ - return tracefs_kprobe_clear_probe(TC_SYS, event, true); -} - -void kprobe_free(void *kp) +static struct ftracepy_kprobe * +kprobe_new(const char *event, const char *function, const char *probe, + bool retprobe) { - char *event = kp; + struct ftracepy_kprobe *new_kprobe; - if (unregister_kprobe(event) < 0) - fprintf(stderr, "\ntfs_error: Failed to unregister kprobe \'%s\'.\n", - event); - - free(kp); -} + if (retprobe) { + if (!register_kretprobe(event, function, probe)) + return NULL; + } else { + if (!register_kprobe(event, function, probe)) + return NULL; + } -static void destroy_all_kprobes(void) -{ - tdestroy(kprobe_root, kprobe_free); - kprobe_root = NULL; -} + new_kprobe = calloc(1, sizeof(*new_kprobe)); + if (!new_kprobe) { + MEM_ERROR; + unregister_kprobe(event); -bool store_new_kprobe(const char *event) -{ - char *ptr = strdup(event); - char **val; + return NULL; + } - if (!ptr) { + new_kprobe->event = strdup(event); + new_kprobe->function = strdup(function); + new_kprobe->probe = strdup(probe); + if (!new_kprobe->event || + !new_kprobe->function || + !new_kprobe->probe) { MEM_ERROR; - return false; - } + ftracepy_kprobe_free(new_kprobe); - val = tsearch(ptr, &kprobe_root, kprobe_compare); - if (!val || strcmp(*val, ptr) != 0) { - PyErr_Format(TFS_ERROR, "Failed to store new kprobe \'%s\'.", - event); - return false; + return NULL; } - return true; + return new_kprobe; } PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args, @@ -1447,6 +1474,7 @@ PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args, { static char *kwlist[] = {"event", "function", "probe", NULL}; const char *event, *function, *probe; + struct ftracepy_kprobe *kprobe; if (!PyArg_ParseTupleAndKeywords(args, kwargs, @@ -1458,16 +1486,11 @@ PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args, return NULL; } - if (tracefs_kprobe_raw(TC_SYS, event, function, probe) < 0) { - PyErr_Format(TFS_ERROR, "Failed to register kprobe \'%s\'.", - event); - return NULL; - } - - if (!store_new_kprobe(event)) + kprobe = kprobe_new(event, function, probe, false); + if (!kprobe) return NULL; - Py_RETURN_NONE; + return PyKprobe_New(kprobe); } PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args, @@ -1475,6 +1498,7 @@ PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args, { static char *kwlist[] = {"event", "function", "probe", NULL}; const char *event, *function, *probe = "$retval"; + struct ftracepy_kprobe *kprobe; if (!PyArg_ParseTupleAndKeywords(args, kwargs, @@ -1486,102 +1510,26 @@ PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args, return NULL; } - if (tracefs_kretprobe_raw(TC_SYS, event, function, probe) < 0) { - PyErr_Format(TFS_ERROR, "Failed to register kretprobe \'%s\'.", - event); + kprobe = kprobe_new(event, function, probe, true); + if (!kprobe) return NULL; - } - - if (!store_new_kprobe(event)) - return NULL; - - Py_RETURN_NONE; -} - -PyObject *PyFtrace_unregister_kprobe(PyObject *self, PyObject *args, - PyObject *kwargs) -{ - static char *kwlist[] = {"event", "force", NULL}; - const char *event; - int force = false; - - if (!PyArg_ParseTupleAndKeywords(args, - kwargs, - "s|p", - kwlist, - &event, - &force)) { - return NULL; - } - - if (is_all(event)) { - if (force) { - /* Clear all register kprobes. */ - if (tracefs_kprobe_clear_all(force) < 0) - goto fail; - } else { - /* - * Clear only the kprobes registered by - * trace-cruncher. - */ - destroy_all_kprobes(); - } - } else { - tdelete(event, &kprobe_root, kprobe_compare); - if (unregister_kprobe(event) < 0) - goto fail; - } - - Py_RETURN_NONE; - fail: - PyErr_Format(TFS_ERROR, "Failed to unregister kprobe \'%s\'.", event); - return NULL; -} - -PyObject *PyFtrace_registered_kprobe_names(PyObject *self) -{ - char **list = tracefs_get_kprobes(TRACEFS_ALL_KPROBES); - return tfs_list2py_list(list); + return PyKprobe_New(kprobe); } -PyObject *PyFtrace_registered_kprobes(PyObject *self) -{ - const char *file = "kprobe_events"; - PyObject *list = PyList_New(0); - char *probes, *token; - int size; - - size = read_from_file(NULL, file, &probes); - if (size < 0) - return NULL; - - if (size == 0 || !probes) - return list; - - token = strtok(probes, "\n"); - while (token != NULL) { - PyList_Append(list, PyUnicode_FromString(token)); - token = strtok(NULL, "\n"); - } - - return list; -} - -PyObject *PyFtrace_set_kprobe_filter(PyObject *self, PyObject *args, - PyObject *kwargs) +PyObject *PyKprobe_set_filter(PyKprobe *self, PyObject *args, + PyObject *kwargs) { struct tracefs_instance *instance; PyObject *py_inst = NULL; - const char *event, *filter; + const char *filter; char path[PATH_MAX]; - static char *kwlist[] = {"event", "filter", "instance", NULL}; + static char *kwlist[] = {"filter", "instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ss|O", + "s|O", kwlist, - &event, &filter, &py_inst)) { return NULL; @@ -1590,7 +1538,7 @@ PyObject *PyFtrace_set_kprobe_filter(PyObject *self, PyObject *args, if (!get_optional_instance(py_inst, &instance)) return NULL; - sprintf(path, "events/%s/%s/filter", TC_SYS, event); + sprintf(path, "events/%s/%s/filter", TC_SYS, self->ptrObj->event); if (!write_to_file_and_check(instance, path, filter)) { PyErr_SetString(TFS_ERROR, "Failed to set kprobe filter."); return NULL; @@ -1599,20 +1547,18 @@ PyObject *PyFtrace_set_kprobe_filter(PyObject *self, PyObject *args, Py_RETURN_NONE; } -PyObject *PyFtrace_clear_kprobe_filter(PyObject *self, PyObject *args, - PyObject *kwargs) +PyObject *PyKprobe_clear_filter(PyKprobe *self, PyObject *args, + PyObject *kwargs) { struct tracefs_instance *instance; PyObject *py_inst = NULL; char path[PATH_MAX]; - const char *event; - static char *kwlist[] = {"event", "instance", NULL}; + static char *kwlist[] = {"instance", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|O", + "|O", kwlist, - &event, &py_inst)) { return NULL; } @@ -1620,7 +1566,7 @@ PyObject *PyFtrace_clear_kprobe_filter(PyObject *self, PyObject *args, if (!get_optional_instance(py_inst, &instance)) return NULL; - sprintf(path, "events/%s/%s/filter", TC_SYS, event); + sprintf(path, "events/%s/%s/filter", TC_SYS, self->ptrObj->event); if (!write_to_file(instance, path, OFF)) { PyErr_SetString(TFS_ERROR, "Failed to clear kprobe filter."); return NULL; @@ -1629,19 +1575,17 @@ PyObject *PyFtrace_clear_kprobe_filter(PyObject *self, PyObject *args, Py_RETURN_NONE; } -static bool enable_kprobe(PyObject *self, PyObject *args, PyObject *kwargs, +static bool enable_kprobe(PyKprobe *self, PyObject *args, PyObject *kwargs, bool enable) { - static char *kwlist[] = {"event", "instance", NULL}; + static char *kwlist[] = {"instance", NULL}; struct tracefs_instance *instance; PyObject *py_inst = NULL; - const char *event = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|O", + "|O", kwlist, - &event, &py_inst)) { return false; } @@ -1649,11 +1593,12 @@ static bool enable_kprobe(PyObject *self, PyObject *args, PyObject *kwargs, if (!get_optional_instance(py_inst, &instance)) return false; - return event_enable_disable(instance, TC_SYS, event, enable); + return event_enable_disable(instance, TC_SYS, self->ptrObj->event, + enable); } -PyObject *PyFtrace_enable_kprobe(PyObject *self, PyObject *args, - PyObject *kwargs) +PyObject *PyKprobe_enable(PyKprobe *self, PyObject *args, + PyObject *kwargs) { if (!enable_kprobe(self, args, kwargs, true)) return NULL; @@ -1661,8 +1606,8 @@ PyObject *PyFtrace_enable_kprobe(PyObject *self, PyObject *args, Py_RETURN_NONE; } -PyObject *PyFtrace_disable_kprobe(PyObject *self, PyObject *args, - PyObject *kwargs) +PyObject *PyKprobe_disable(PyKprobe *self, PyObject *args, + PyObject *kwargs) { if (!enable_kprobe(self, args, kwargs, false)) return NULL; @@ -1670,19 +1615,17 @@ PyObject *PyFtrace_disable_kprobe(PyObject *self, PyObject *args, Py_RETURN_NONE; } -PyObject *PyFtrace_kprobe_is_enabled(PyObject *self, PyObject *args, - PyObject *kwargs) +PyObject *PyKprobe_is_enabled(PyKprobe *self, PyObject *args, + PyObject *kwargs) { - static char *kwlist[] = {"event", "instance", NULL}; + static char *kwlist[] = {"instance", NULL}; struct tracefs_instance *instance; PyObject *py_inst = NULL; - const char *event = NO_ARG; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|O", + "|O", kwlist, - &event, &py_inst)) { return NULL; } @@ -1690,7 +1633,7 @@ PyObject *PyFtrace_kprobe_is_enabled(PyObject *self, PyObject *args, if (!get_optional_instance(py_inst, &instance)) return NULL; - return event_is_enabled(instance, TC_SYS, event); + return event_is_enabled(instance, TC_SYS, self->ptrObj->event); } PyObject *PyFtrace_set_ftrace_loglevel(PyObject *self, PyObject *args, @@ -2110,5 +2053,4 @@ PyObject *PyFtrace_hook2pid(PyObject *self, PyObject *args, PyObject *kwargs) void PyFtrace_at_exit(void) { - destroy_all_kprobes(); } diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h index 17e07e5..4e04fb0 100644 --- a/src/ftracepy-utils.h +++ b/src/ftracepy-utils.h @@ -26,6 +26,8 @@ C_OBJECT_WRAPPER_DECLARE(tracefs_instance, PyTfsInstance) struct ftracepy_kprobe; +void ftracepy_kprobe_destroy(struct ftracepy_kprobe *kp); + void ftracepy_kprobe_free(struct ftracepy_kprobe *kp); C_OBJECT_WRAPPER_DECLARE(ftracepy_kprobe, PyKprobe); @@ -62,6 +64,21 @@ PyObject *PyKprobe_function(PyKprobe *self); PyObject *PyKprobe_probe(PyKprobe *self); +PyObject *PyKprobe_set_filter(PyKprobe *self, PyObject *args, + PyObject *kwargs); + +PyObject *PyKprobe_clear_filter(PyKprobe *self, PyObject *args, + PyObject *kwargs); + +PyObject *PyKprobe_enable(PyKprobe *self, PyObject *args, + PyObject *kwargs); + +PyObject *PyKprobe_disable(PyKprobe *self, PyObject *args, + PyObject *kwargs); + +PyObject *PyKprobe_is_enabled(PyKprobe *self, PyObject *args, + PyObject *kwargs); + PyObject *PyFtrace_dir(PyObject *self); PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs); @@ -143,28 +160,6 @@ PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args, PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args, PyObject *kwargs); -PyObject *PyFtrace_unregister_kprobe(PyObject *self, PyObject *args, - PyObject *kwargs); - -PyObject *PyFtrace_registered_kprobes(PyObject *self); - -PyObject *PyFtrace_registered_kprobe_names(PyObject *self); - -PyObject *PyFtrace_set_kprobe_filter(PyObject *self, PyObject *args, - PyObject *kwargs); - -PyObject *PyFtrace_clear_kprobe_filter(PyObject *self, PyObject *args, - PyObject *kwargs); - -PyObject *PyFtrace_enable_kprobe(PyObject *self, PyObject *args, - PyObject *kwargs); - -PyObject *PyFtrace_disable_kprobe(PyObject *self, PyObject *args, - PyObject *kwargs); - -PyObject *PyFtrace_kprobe_is_enabled(PyObject *self, PyObject *args, - PyObject *kwargs); - PyObject *PyFtrace_set_ftrace_loglevel(PyObject *self, PyObject *args, PyObject *kwargs); diff --git a/src/ftracepy.c b/src/ftracepy.c index c434af9..a4fba01 100644 --- a/src/ftracepy.c +++ b/src/ftracepy.c @@ -107,11 +107,36 @@ static PyMethodDef PyKprobe_methods[] = { METH_NOARGS, "Get the kprobe event definition." }, + {"set_filter", + (PyCFunction) PyKprobe_set_filter, + METH_VARARGS | METH_KEYWORDS, + "Define a filter for a kprobe." + }, + {"clear_filter", + (PyCFunction) PyKprobe_clear_filter, + METH_VARARGS | METH_KEYWORDS, + "Clear the filter of a kprobe." + }, + {"enable", + (PyCFunction) PyKprobe_enable, + METH_VARARGS | METH_KEYWORDS, + "Enable kprobe event." + }, + {"disable", + (PyCFunction) PyKprobe_disable, + METH_VARARGS | METH_KEYWORDS, + "Disable kprobe event." + }, + {"is_enabled", + (PyCFunction) PyKprobe_is_enabled, + METH_VARARGS | METH_KEYWORDS, + "Check if kprobe event is enabled." + }, {NULL, NULL, 0, NULL} }; C_OBJECT_WRAPPER(ftracepy_kprobe, PyKprobe, - NO_DESTROY, + ftracepy_kprobe_destroy, ftracepy_kprobe_free) static PyMethodDef ftracepy_methods[] = { @@ -255,46 +280,6 @@ static PyMethodDef ftracepy_methods[] = { METH_VARARGS | METH_KEYWORDS, "Define a kretprobe." }, - {"unregister_kprobe", - (PyCFunction) PyFtrace_unregister_kprobe, - METH_VARARGS | METH_KEYWORDS, - "Define a kprobe." - }, - {"registered_kprobes", - (PyCFunction) PyFtrace_registered_kprobes, - METH_NOARGS, - "Get all registered kprobes." - }, - {"registered_kprobe_names", - (PyCFunction) PyFtrace_registered_kprobe_names, - METH_NOARGS, - "Get the names of all registered kprobes." - }, - {"set_kprobe_filter", - (PyCFunction) PyFtrace_set_kprobe_filter, - METH_VARARGS | METH_KEYWORDS, - "Define a filter for a kprobe." - }, - {"clear_kprobe_filter", - (PyCFunction) PyFtrace_clear_kprobe_filter, - METH_VARARGS | METH_KEYWORDS, - "Clear the filter of a kprobe." - }, - {"enable_kprobe", - (PyCFunction) PyFtrace_enable_kprobe, - METH_VARARGS | METH_KEYWORDS, - "Enable kprobe event." - }, - {"disable_kprobe", - (PyCFunction) PyFtrace_disable_kprobe, - METH_VARARGS | METH_KEYWORDS, - "Disable kprobe event." - }, - {"kprobe_is_enabled", - (PyCFunction) PyFtrace_kprobe_is_enabled, - METH_VARARGS | METH_KEYWORDS, - "Check if kprobe event is enabled." - }, {"set_ftrace_loglevel", (PyCFunction) PyFtrace_set_ftrace_loglevel, METH_VARARGS | METH_KEYWORDS, @@ -362,7 +347,7 @@ PyMODINIT_FUNC PyInit_ftracepy(void) TRACECRUNCHER_ERROR = PyErr_NewException("tracecruncher.tc_error", NULL, NULL); - PyObject *module = PyModule_Create(&ftracepy_module); + PyObject *module = PyModule_Create(&ftracepy_module); PyModule_AddObject(module, "tep_handle", (PyObject *) &PyTepType); PyModule_AddObject(module, "tep_event", (PyObject *) &PyTepEventType); diff --git a/tests/1_unit/test_01_ftracepy_unit.py b/tests/1_unit/test_01_ftracepy_unit.py index 57db0ad..3411b3f 100644 --- a/tests/1_unit/test_01_ftracepy_unit.py +++ b/tests/1_unit/test_01_ftracepy_unit.py @@ -403,34 +403,17 @@ class KprobeTestCase(unittest.TestCase): evt2_func = 'do_sys_openat2' evt2_prove = 'file=+u0($arg2):ustring' - ft.register_kprobe(event=evt1, function=evt1_func, - probe=evt1_prove) - all_kprobes = ft.registered_kprobes() - self.assertEqual(len(all_kprobes), 1) - self.assertTrue(evt1 in all_kprobes[0]) - self.assertTrue(evt1_func in all_kprobes[0]) - self.assertTrue(evt1_prove in all_kprobes[0]) - - ft.unregister_kprobe(event=evt1) - all_kprobes = ft.registered_kprobes() - self.assertEqual(len(all_kprobes), 0) - - ft.register_kprobe(event=evt1, function=evt1_func, - probe=evt1_prove) - ft.register_kprobe(event=evt2, function=evt2_func, - probe=evt2_prove) - all_kprobes = ft.registered_kprobes() - self.assertEqual(len(all_kprobes), 2) - self.assertTrue(evt1 in all_kprobes[0]) - self.assertTrue(evt1_func in all_kprobes[0]) - self.assertTrue(evt1_prove in all_kprobes[0]) - self.assertTrue(evt2 in all_kprobes[1]) - self.assertTrue(evt2_func in all_kprobes[1]) - self.assertTrue(evt2_prove in all_kprobes[1]) - - ft.unregister_kprobe(event='ALL') - all_kprobes = ft.registered_kprobes() - self.assertEqual(len(all_kprobes), 0) + kp1 = ft.register_kprobe(event=evt1, function=evt1_func, + probe=evt1_prove) + self.assertEqual(evt1, kp1.event()) + self.assertEqual(evt1_func, kp1.function()) + self.assertEqual(evt1_prove, kp1.probe()) + + kp2 = ft.register_kprobe(event=evt2, function=evt2_func, + probe=evt2_prove) + self.assertEqual(evt2, kp2.event()) + self.assertEqual(evt2_func, kp2.function()) + self.assertEqual(evt2_prove, kp2.probe()) def test_enable_kprobe(self): @@ -438,19 +421,17 @@ class KprobeTestCase(unittest.TestCase): evt1_func = 'do_mkdirat' evt1_prove = 'path=+u0($arg2):ustring' - ft.register_kprobe(event=evt1, function=evt1_func, - probe=evt1_prove) + kp1 = ft.register_kprobe(event=evt1, function=evt1_func, + probe=evt1_prove) inst = ft.create_instance(instance_name) - ft.enable_kprobe(instance=inst, event=evt1) - ret = ft.kprobe_is_enabled(instance=inst, event=evt1) + kp1.enable(instance=inst) + ret = kp1.is_enabled(instance=inst) self.assertEqual(ret, '1') - ft.disable_kprobe(instance=inst, event=evt1) - ret = ft.kprobe_is_enabled(instance=inst, event=evt1) + kp1.disable(instance=inst) + ret = kp1.is_enabled(instance=inst) self.assertEqual(ret, '0') - ft.unregister_kprobe(event='ALL') - class TracingOnTestCase(unittest.TestCase): def test_ON_OF(self): diff --git a/tracecruncher/ft_utils.py b/tracecruncher/ft_utils.py index 8c245b1..5caaa76 100644 --- a/tracecruncher/ft_utils.py +++ b/tracecruncher/ft_utils.py @@ -99,21 +99,13 @@ class kprobe_base(event): """ super().__init__(system=ft.tc_event_system(), name=name, static=False) self.func = func + self.kp = None def set_function(self, name): """ Set the name of the function to be traced. """ self.func = name - def unregister(self): - """ Unregister this probe from Ftrace. - """ - inst_list = self.instance_list.copy() - for instance in inst_list: - self.disable(instance) - - ft.unregister_kprobe(event=self.name); - class kprobe(kprobe_base): def __init__(self, name, func=''): @@ -176,7 +168,7 @@ class kprobe(kprobe_base): """ probe = ' '.join('{!s}={!s}'.format(key,val) for (key, val) in self.fields.items()) - ft.register_kprobe(event=self.name, function=self.func, probe=probe); + self.kp = ft.register_kprobe(event=self.name, function=self.func, probe=probe); self.evt_id = find_event_id(system=ft.tc_event_system(), event=self.name) @@ -206,5 +198,5 @@ class kretval_probe(kprobe_base): def register(self): """ Register this probe to Ftrace. """ - ft.register_kprobe(event=self.name, function=self.func); + self.kp = ft.register_kprobe(event=self.name, function=self.func); self.evt_id = find_event_id(system=ft.tc_event_system(), event=self.name)