Rework webprobe module 48/93748/2
authorAnatolii Nikulin <nikulin.a@samsung.com>
Tue, 25 Oct 2016 12:59:07 +0000 (15:59 +0300)
committerAnatolii Nikulin <nikulin.a@samsung.com>
Tue, 25 Oct 2016 15:33:11 +0000 (18:33 +0300)
Implement webprobe probes like probes in NSP module

Change-Id: I467f1cb84be43ca21da257b4b601dbe382190ad5
Signed-off-by: Anatolii Nikulin <nikulin.a@samsung.com>
webprobe/Kbuild
webprobe/webprobe.c
webprobe/webprobe.h [moved from webprobe/webprobe_prof.h with 74% similarity]
webprobe/webprobe_debugfs.c
webprobe/webprobe_prof.c [deleted file]

index b6eef32..fd39693 100644 (file)
@@ -3,5 +3,4 @@ EXTRA_CFLAGS := $(extra_cflags)
 obj-m := swap_webprobe.o
 swap_webprobe-y := webprobe.o \
                    webprobe_debugfs.o \
-                   webprobe_prof.o \
                    web_msg.o
index e6d0231..c213184 100644 (file)
  * Web application profiling
  */
 
+#include <linux/module.h>
+#include <linux/slab.h>
 #include <us_manager/us_manager.h>
-#include <us_manager/sspt/sspt_ip.h>
-#include <us_manager/probes/register_probes.h>
-#include <us_manager/sspt/sspt.h>
+#include <us_manager/pf/pf_group.h>
+#include <us_manager/probes/probe_info_new.h>
 #include <uprobe/swap_uprobes.h>
 #include <parser/msg_cmd.h>
-#include <linux/module.h>
-#include <linux/slab.h>
 #include <master/swap_initializer.h>
 
+#include "webprobe.h"
 #include "webprobe_debugfs.h"
-#include "webprobe_prof.h"
 #include "web_msg.h"
 
-static unsigned long inspserver_addr_local;
-static unsigned long tick_addr_local;
+struct web_prof_data {
+       struct dentry *app_dentry;
+       struct dentry *lib_dentry;
+       struct pf_group *pfg;
+       u64 inspserver_addr;
+       u64 tick_addr;
+       bool enable;
+};
 
-static int webprobe_copy(struct probe_info *dest,
-                        const struct probe_info *source)
+static DEFINE_MUTEX(web_mutex);
+static const char *CHROMIUM_EWK = "/usr/lib/libchromium-ewk.so";
+static struct web_prof_data *web_data;
+
+/* function tick handler */
+static int tick_handler(struct uprobe *p, struct pt_regs *regs);
+static struct probe_desc pin_tick_handler = MAKE_UPROBE(tick_handler);
+static struct probe_new tick_probe = {
+       .desc = &pin_tick_handler
+};
+
+/* function inspector port */
+static int insport_rhandler(struct uretprobe_instance *ri,
+                           struct pt_regs *regs);
+static struct probe_desc pin_insport_rhandler =
+                               MAKE_URPROBE(NULL, insport_rhandler, 0);
+static struct probe_new insport_probe = {
+       .desc = &pin_insport_rhandler
+};
+
+static int insport_rhandler(struct uretprobe_instance *ri,
+                           struct pt_regs *regs)
 {
-       memcpy(dest, source, sizeof(*source));
+       set_wrt_launcher_port((int)regs_return_value(regs));
 
        return 0;
 }
 
-static void webprobe_cleanup(struct probe_info *probe_i)
+static int tick_handler(struct uprobe *p, struct pt_regs *regs)
 {
-}
+       web_sample_msg(regs);
 
-static struct uprobe *webprobe_get_uprobe(struct sspt_ip *ip)
-{
-       return &ip->retprobe.up;
+       return 0;
 }
 
-static int webprobe_register_probe(struct sspt_ip *ip)
+u64 *web_prof_addr_ptr(enum web_prof_addr_t type)
 {
-       return swap_register_uretprobe(&ip->retprobe);
-}
+       u64 *addr_ptr;
 
-static void webprobe_unregister_probe(struct sspt_ip *ip, int disarm)
-{
-       if (ip->orig_addr == inspserver_addr_local)
-               web_func_inst_remove(INSPSERVER_START);
-       else if (ip->orig_addr == tick_addr_local)
-               web_func_inst_remove(TICK_PROBE);
+       mutex_lock(&web_mutex);
+       switch (type) {
+       case INSPSERVER_START:
+               addr_ptr = &web_data->inspserver_addr;
+               break;
+       case TICK_PROBE:
+               addr_ptr = &web_data->tick_addr;
+               break;
+       default:
+               pr_err("ERROR: WEB_PROF_ADDR_PTR_TYPE=0x%x\n", type);
+               addr_ptr = NULL;
+       }
+       mutex_unlock(&web_mutex);
 
-       __swap_unregister_uretprobe(&ip->retprobe, disarm);
+       return addr_ptr;
 }
 
-static int web_entry_handler(struct uretprobe_instance *ri,
-                            struct pt_regs *regs)
+int web_prof_data_set(char *app_path, char *app_id)
 {
-       struct uretprobe *rp = ri->rp;
-       struct sspt_ip *ip;
-       unsigned long vaddr, page_vaddr;
-       struct vm_area_struct *vma;
-
-       if (!rp)
-               return 0;
-
-       ip = container_of(rp, struct sspt_ip, retprobe);
-       vaddr = (unsigned long)ip->orig_addr;
-       page_vaddr = vaddr & PAGE_MASK;
-
-       vma = find_vma_intersection(current->mm, page_vaddr, page_vaddr + 1);
-       if (vma && check_vma(vma)) {
-               unsigned long addr = vaddr - vma->vm_start;
-               struct dentry *d = vma->vm_file->f_path.dentry;
-
-               if (addr == web_prof_addr(TICK_PROBE) &&
-                   d == web_prof_lib_dentry()) {
-                       tick_addr_local = ip->orig_addr;
-                       web_sample_msg(regs);
-               }
+       int ret = 0;
+
+       mutex_lock(&web_mutex);
+       web_data->app_dentry = dentry_by_path(app_path);
+       if (!web_data->app_dentry) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       web_data->lib_dentry = dentry_by_path(CHROMIUM_EWK);
+       if (!web_data->lib_dentry) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       if (web_data->pfg)
+               put_pf_group(web_data->pfg);
+
+       web_data->pfg = get_pf_group_by_comm(app_id, web_data->app_dentry);
+       if (!web_data->pfg) {
+               ret = -EFAULT;
+               goto out;
        }
 
+out:
+       mutex_unlock(&web_mutex);
+
        return 0;
 }
 
-static int web_ret_handler(struct uretprobe_instance *ri, struct pt_regs *regs)
+bool web_prof_enabled(void)
 {
-       struct uretprobe *rp = ri->rp;
-       struct sspt_ip *ip;
-       unsigned long vaddr, page_vaddr;
-       struct vm_area_struct *vma;
-
-       if (!rp)
-               return 0;
-
-       ip = container_of(rp, struct sspt_ip, retprobe);
-       vaddr = (unsigned long)ip->orig_addr;
-       page_vaddr = vaddr & PAGE_MASK;
-
-       vma = find_vma_intersection(current->mm, page_vaddr, page_vaddr + 1);
-       if (vma && check_vma(vma)) {
-               unsigned long addr = vaddr - vma->vm_start;
-               struct dentry *d = vma->vm_file->f_path.dentry;
-
-               if (addr == web_prof_addr(INSPSERVER_START) &&
-                   d == web_prof_lib_dentry()) {
-                       inspserver_addr_local = ip->orig_addr;
-                       set_wrt_launcher_port((int)regs_return_value(regs));
-               }
-       }
+       bool ret;
 
-       return 0;
+       mutex_lock(&web_mutex);
+       ret = web_data->enable;
+       mutex_unlock(&web_mutex);
+
+       return ret;
 }
 
-static void webprobe_init(struct sspt_ip *ip)
+static void __web_prof_disable(struct web_prof_data *data)
 {
-       ip->retprobe.entry_handler = web_entry_handler;
-       ip->retprobe.handler = web_ret_handler;
-       ip->retprobe.maxactive = 0;
+       pin_unregister(&tick_probe, data->pfg, data->lib_dentry);
+       pin_unregister(&insport_probe, data->pfg, data->lib_dentry);
 }
 
-static void webprobe_uninit(struct sspt_ip *ip)
+static int __web_prof_enable(struct web_prof_data *data)
 {
-       webprobe_cleanup(&ip->desc->info);
+       int ret;
+
+       tick_probe.offset = data->tick_addr;
+       ret = pin_register(&tick_probe, data->pfg, data->lib_dentry);
+       if (ret)
+               goto fail0;
+
+       insport_probe.offset = data->inspserver_addr;
+       ret = pin_register(&insport_probe, data->pfg, data->lib_dentry);
+       if (ret)
+               goto fail1;
+
+       return 0;
+
+fail1:
+       pin_unregister(&tick_probe, data->pfg, data->lib_dentry);
+fail0:
+       return ret;
 }
 
-static struct probe_iface webprobe_iface = {
-       .init = webprobe_init,
-       .uninit = webprobe_uninit,
-       .reg = webprobe_register_probe,
-       .unreg = webprobe_unregister_probe,
-       .get_uprobe = webprobe_get_uprobe,
-       .copy = webprobe_copy,
-       .cleanup = webprobe_cleanup
-};
+int web_prof_enable(void)
+{
+       int ret = 0;
 
-static int webprobe_module_init(void)
+       mutex_lock(&web_mutex);
+       if (web_data->enable) {
+               pr_err("ERROR: Web profiling is already enabled\n");
+               ret = -EBUSY;
+               goto out;
+       }
+
+       if (!web_data->inspserver_addr) {
+               pr_err("bad inspserver addr 0x%llx\n",
+                      web_data->inspserver_addr);
+               goto out;
+       }
+
+       if (!web_data->tick_addr) {
+               pr_err("bad tick addr 0x%llx\n", web_data->tick_addr);
+               goto out;
+       }
+
+       ret = __web_prof_enable(web_data);
+       if (ret) {
+               pr_err("failed to enable Web profiling\n");
+               goto out;
+       }
+
+       web_data->enable = true;
+
+out:
+       mutex_unlock(&web_mutex);
+
+       return ret;
+}
+
+int web_prof_disable(void)
 {
        int ret = 0;
 
-       ret = swap_register_probe_type(SWAP_WEBPROBE, &webprobe_iface);
-       if (ret)
-               pr_err("Cannot register probe type SWAP_WEBPROBE\n");
+       mutex_lock(&web_mutex);
+       if (!web_data->enable) {
+               pr_err("ERROR: Web profiling is already disabled\n");
+               ret = -EBUSY;
+               goto out;
+       }
 
+       __web_prof_disable(web_data);
+       web_data->enable = false;
+
+out:
+       mutex_unlock(&web_mutex);
        return ret;
 }
 
+static int webprobe_module_init(void)
+{
+       mutex_lock(&web_mutex);
+       web_data = kzalloc(sizeof(*web_data), GFP_KERNEL);
+       if (!web_data)
+               return -ENOMEM;
+
+       web_data->enable = false;
+       mutex_unlock(&web_mutex);
+
+       return 0;
+}
+
 static void webprobe_module_exit(void)
 {
-       swap_unregister_probe_type(SWAP_WEBPROBE);
+       mutex_lock(&web_mutex);
+       if (web_data->enable)
+               __web_prof_disable(web_data);
+
+       if (web_data->pfg)
+               put_pf_group(web_data->pfg);
+
+       kfree(web_data);
+       web_data = NULL;
+       mutex_unlock(&web_mutex);
 }
 
 SWAP_LIGHT_INIT_MODULE(NULL, webprobe_module_init, webprobe_module_exit,
similarity index 74%
rename from webprobe/webprobe_prof.h
rename to webprobe/webprobe.h
index 99e8fda..003931e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _WEBPROBE_PROF_H
-#define _WEBPROBE_PROF_H
+#ifndef _WEBPROBE_H
+#define _WEBPROBE_H
 
 /**
  * @file webprobe/webprobe_prof.h
@@ -31,20 +31,10 @@ enum web_prof_addr_t {
        TICK_PROBE
 };
 
-enum web_prof_state_t {
-       PROF_OFF,
-       PROF_ON
-};
-
-int web_prof_init(void);
-void web_prof_exit(void);
 int web_prof_enable(void);
 int web_prof_disable(void);
-enum web_prof_state_t web_prof_enabled(void);
-int web_func_inst_remove(enum web_prof_addr_t type);
+bool web_prof_enabled(void);
 u64 *web_prof_addr_ptr(enum web_prof_addr_t type);
-unsigned long web_prof_addr(enum web_prof_addr_t type);
 int web_prof_data_set(char *app_path, char *app_id);
-struct dentry *web_prof_lib_dentry(void);
 
-#endif /* _WEBPROBE_PROF_H */
+#endif /* _WEBPROBE_H */
index f1331f7..a27263b 100644 (file)
@@ -29,7 +29,7 @@
 #include <master/swap_initializer.h>
 
 #include "webprobe_debugfs.h"
-#include "webprobe_prof.h"
+#include "webprobe.h"
 
 static const char ENABLED_FILE[] =             "enabled";
 static const char APP_INFO_FILE[] =            "app_info";
@@ -49,7 +49,7 @@ static ssize_t read_enabled(struct file *file, char __user *user_buf,
 {
        char buf[2];
 
-       buf[0] = web_prof_enabled() == PROF_ON ? '1' : '0';
+       buf[0] = web_prof_enabled() ? '1' : '0';
        buf[1] = '\n';
 
        return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
@@ -167,10 +167,7 @@ static struct dentry *webprobe_dir;
 
 void webprobe_debugfs_exit(void)
 {
-       web_prof_exit();
-
        debugfs_remove_recursive(webprobe_dir);
-
        webprobe_dir = NULL;
 }
 
@@ -178,9 +175,6 @@ int webprobe_debugfs_init(void)
 {
        struct dentry *dentry;
 
-       if (web_prof_init())
-               goto fail;
-
        dentry = swap_debugfs_getdir();
        if (!dentry)
                return -ENOENT;
diff --git a/webprobe/webprobe_prof.c b/webprobe/webprobe_prof.c
deleted file mode 100644 (file)
index 5c80d74..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/**
- *  webprobe/webprobe_prof.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (C) Samsung Electronics, 2015
- *
- * 2015                 Anastasia Lyupa <a.lyupa@samsung.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-
-#include <us_manager/pf/pf_group.h>
-#include <us_manager/probes/probes.h>
-#include <us_manager/probes/probe_info_new.h>
-
-#include "webprobe_prof.h"
-
-static DEFINE_MUTEX(mutex_enable);
-
-struct web_prof_data {
-       struct dentry *app_dentry;
-       struct dentry *lib_dentry;
-       struct pf_group *pfg;
-       u64 inspserver_addr;
-       struct probe_desc *inspserver;
-       u64 tick_addr;
-       struct probe_desc *tick_probe;
-       enum web_prof_state_t enabled;
-};
-
-static const char *CHROMIUM_EWK = "/usr/lib/libchromium-ewk.so";
-static struct web_prof_data *web_data;
-
-u64 *web_prof_addr_ptr(enum web_prof_addr_t type)
-{
-       u64 *addr_ptr;
-
-       switch (type) {
-       case INSPSERVER_START:
-               addr_ptr = &web_data->inspserver_addr;
-               break;
-       case TICK_PROBE:
-               addr_ptr = &web_data->tick_addr;
-               break;
-       default:
-               pr_err("ERROR: WEB_PROF_ADDR_PTR_TYPE=0x%x\n", type);
-               addr_ptr = NULL;
-       }
-
-       return addr_ptr;
-}
-
-unsigned long web_prof_addr(enum web_prof_addr_t type)
-{
-       unsigned long addr;
-
-       switch (type) {
-       case INSPSERVER_START:
-               addr = web_data->inspserver_addr;
-               break;
-       case TICK_PROBE:
-               addr = web_data->tick_addr;
-               break;
-       default:
-               pr_err("ERROR: WEB_PROF_ADDR_TYPE=0x%x\n", type);
-               addr = 0;
-       }
-
-       return addr;
-}
-
-static struct probe_desc *web_func_inst_add(unsigned long addr)
-{
-       int ret;
-       struct probe_desc *probe = NULL;
-
-       probe = kmalloc(sizeof(*probe), GFP_KERNEL);
-
-       if (!probe)
-               return NULL;
-
-       memset(probe, 0, sizeof(*probe));
-       probe->type = SWAP_WEBPROBE;
-
-       ret = pf_register_probe(web_data->pfg, web_data->lib_dentry,
-                               addr, probe);
-
-       return probe;
-}
-
-static int __web_func_inst_remove(unsigned long addr, struct probe_desc *pd)
-{
-       int ret;
-
-       if (!addr || !pd)
-               return -EINVAL;
-
-       /* FIXME: check that address needs removing */
-       ret = pf_unregister_probe(web_data->pfg, web_data->lib_dentry,
-                                 addr, pd);
-
-       return ret;
-}
-
-int web_func_inst_remove(enum web_prof_addr_t type)
-{
-       unsigned long addr = 0;
-       struct probe_desc *pd = NULL;
-
-       switch (type) {
-       case INSPSERVER_START:
-               addr = web_data->inspserver_addr;
-               pd = web_data->inspserver;
-               break;
-       case TICK_PROBE:
-               addr = web_data->tick_addr;
-               pd = web_data->tick_probe;
-               break;
-       default:
-               pr_err("ERROR: WEB_PROF_ADDR_TYPE=0x%x\n", type);
-       }
-
-       return __web_func_inst_remove(addr, pd);
-}
-
-int web_prof_data_set(char *app_path, char *app_id)
-{
-       web_data->app_dentry = dentry_by_path(app_path);
-       if (!web_data->app_dentry)
-               return -EFAULT;
-
-       web_data->lib_dentry = dentry_by_path(CHROMIUM_EWK);
-       if (!web_data->lib_dentry)
-               return -EFAULT;
-
-       if (web_data->pfg)
-               put_pf_group(web_data->pfg);
-
-       web_data->pfg = get_pf_group_by_comm(app_id, web_data->app_dentry);
-       if (!web_data->pfg)
-               return -EFAULT;
-
-       return 0;
-}
-
-struct dentry *web_prof_lib_dentry(void)
-{
-       return web_data->lib_dentry;
-}
-
-enum web_prof_state_t web_prof_enabled(void)
-{
-       return web_data->enabled;
-}
-
-int web_prof_enable(void)
-{
-       int ret = 0;
-
-       mutex_lock(&mutex_enable);
-       if (web_data->enabled != PROF_OFF) {
-               pr_err("ERROR: Web profiling is already enabled\n");
-               goto out;
-       }
-
-       web_data->enabled = PROF_ON;
-
-       if (web_data->inspserver_addr) {
-               web_data->inspserver =
-                       web_func_inst_add(web_data->inspserver_addr);
-       }
-
-       if (web_data->tick_addr) {
-               web_data->tick_probe =
-                       web_func_inst_add(web_data->tick_addr);
-       }
-
-out:
-       mutex_unlock(&mutex_enable);
-
-       return ret;
-}
-
-int web_prof_disable(void)
-{
-       int ret = 0;
-
-       mutex_lock(&mutex_enable);
-       if (web_data->enabled != PROF_ON) {
-               pr_err("ERROR: Web profiling is already disabled\n");
-               ret = -EBUSY;
-               goto out;
-       }
-
-       web_data->enabled = PROF_OFF;
-
-       if (web_data->inspserver_addr) {
-               if (!__web_func_inst_remove(web_data->inspserver_addr,
-                                           web_data->inspserver)) {
-                       kfree(web_data->inspserver);
-                       web_data->inspserver = NULL;
-               }
-       }
-
-       if (web_data->tick_addr) {
-               if (!__web_func_inst_remove(web_data->tick_addr,
-                                           web_data->tick_probe)) {
-                       kfree(web_data->tick_probe);
-                       web_data->tick_probe = NULL;
-               }
-       }
-
-out:
-       mutex_unlock(&mutex_enable);
-
-       return ret;
-}
-
-int web_prof_init(void)
-{
-       web_data = kmalloc(sizeof(*web_data), GFP_KERNEL);
-       if (!web_data)
-               return -ENOMEM;
-
-       memset(web_data, 0, sizeof(struct web_prof_data));
-
-       web_data->enabled = PROF_OFF;
-
-       return 0;
-}
-
-void web_prof_exit(void)
-{
-       if (web_data->pfg)
-               put_pf_group(web_data->pfg);
-
-       kfree(web_data->inspserver);
-       kfree(web_data->tick_probe);
-       kfree(web_data);
-}