For RFC, this patch is full of hacks:
- non-generic vdso_mnt -- it will not built on !x86_64
- used externs in trace_uprobe.c, rather than clean header-includes

This patch converts vdsofs from lookup-less, renames vdso file name
to just "64". It also adds support to uprobe_events for setting uprobe
to vdso image file.

One can set vdso uprobe now like this:
echo 'p:gettimeofday :vdso:/64:0xc50' >> uprobe_events

Signed-off-by: Dmitry Safonov <dsafo...@virtuozzo.com>
---
 arch/x86/entry/vdso/vma.c   | 28 ++++++++++++++-------------
 kernel/trace/trace_uprobe.c | 46 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index e83830e422ae..9e966b649028 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -39,7 +39,7 @@ void __init init_vdso_image(const struct vdso_image *image)
                                                image->alt_len));
 }
 
-static struct vfsmount *vdso_mnt;
+struct vfsmount *vdso_mnt;
 struct file *vdso_file_64;
 
 struct linux_binprm;
@@ -401,38 +401,40 @@ static __init struct file *init_vdso_file(const struct 
vdso_image *vdso_image,
                                        const char *name)
 {
        struct super_block *sb;
-       struct qstr name_str;
        struct inode *inode;
        struct path path;
        struct file *res;
+       int ret;
 
        if (IS_ERR(vdso_mnt))
                return ERR_CAST(vdso_mnt);
        sb = vdso_mnt->mnt_sb;
 
-       name_str.hash = 0;
-       name_str.len = strlen(name);
-       name_str.name = name;
-
        res = ERR_PTR(-ENOMEM);
        path.mnt = mntget(vdso_mnt);
-       path.dentry = d_alloc_pseudo(sb, &name_str);
-       if (!path.dentry)
+       path.dentry = d_alloc_name(vdso_mnt->mnt_root, name);
+       if (!path.dentry) {
+               pr_err("Failed to allocate dentry for %s vdso file\n", name);
                goto put_path;
+       }
        d_set_d_op(path.dentry, &vdso_dops);
 
        res = ERR_PTR(-ENOSPC);
        inode = ramfs_get_inode(sb, NULL, S_IFREG | S_IRUGO | S_IXUGO, 0);
-       if (!inode)
+       if (!inode) {
+               pr_err("Failed to get inode for %s vdso file\n", name);
                goto put_path;
+       }
 
        inode->i_flags |= S_PRIVATE;
-       d_instantiate(path.dentry, inode);
+       d_add(path.dentry, inode);
        inode->i_size = vdso_image->size;
 
-       res = ERR_PTR(add_vdso_pages_to_page_cache(vdso_image, inode));
-       if (IS_ERR(res))
+       ret = add_vdso_pages_to_page_cache(vdso_image, inode);
+       if (ret) {
+               pr_err("Failed to put %s pages in page cache: %d\n", name, ret);
                goto put_path;
+       }
 
        res = alloc_file(&path, FMODE_READ, &ramfs_file_operations);
        if (!IS_ERR(res))
@@ -475,7 +477,7 @@ static int __init init_vdso(void)
 
        BUG_ON(init_vdso_fs());
 
-       vdso_file_64 = init_vdso_file(&vdso_image_64, "vdso_image_64");
+       vdso_file_64 = init_vdso_file(&vdso_image_64, "64");
        BUG_ON(IS_ERR(vdso_file_64));
 
        /* notifier priority > KVM */
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index a74f2d9ff379..3d4dc6c6ddd9 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -23,6 +23,7 @@
 #include <linux/uprobes.h>
 #include <linux/namei.h>
 #include <linux/string.h>
+#include <linux/mount.h>
 
 #include "trace_probe.h"
 
@@ -352,6 +353,9 @@ end:
  *
  *  - Remove uprobe: -:[GRP/]EVENT
  */
+extern struct vfsmount *vdso_mnt;
+extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
+                          const char *, unsigned int, struct path *);
 static int create_trace_uprobe(int argc, char **argv)
 {
        struct trace_uprobe *tu;
@@ -427,15 +431,41 @@ static int create_trace_uprobe(int argc, char **argv)
                pr_info("Probe point is not specified.\n");
                return -EINVAL;
        }
-       arg = strchr(argv[1], ':');
-       if (!arg) {
-               ret = -EINVAL;
-               goto fail_address_parse;
-       }
+       if (argv[1][0] == ':') {
+               arg = strchr(&argv[1][1], ':');
+               if (!arg) {
+                       ret = -EINVAL;
+                       goto fail_address_parse;
+               }
+               *arg++ = '\0';
+               if (strcmp(&argv[1][1], "vdso")) {
+                       ret = -EINVAL;
+                       goto fail_address_parse;
+               }
+               filename = arg;
+               arg = strchr(filename, ':');
+               if (!filename) {
+                       ret = -EINVAL;
+                       goto fail_address_parse;
+               }
+               *arg++ = '\0';
+               if (!vdso_mnt) {
+                       ret = -ENODEV;
+                       goto fail_address_parse;
+               }
+               ret = vfs_path_lookup(vdso_mnt->mnt_root, vdso_mnt,
+                               filename, LOOKUP_FOLLOW, &path);
+       } else {
+               arg = strchr(argv[1], ':');
+               if (!arg) {
+                       ret = -EINVAL;
+                       goto fail_address_parse;
+               }
 
-       *arg++ = '\0';
-       filename = argv[1];
-       ret = kern_path(filename, LOOKUP_FOLLOW, &path);
+               *arg++ = '\0';
+               filename = argv[1];
+               ret = kern_path(filename, LOOKUP_FOLLOW, &path);
+       }
        if (ret)
                goto fail_address_parse;
 
-- 
2.9.0

Reply via email to