summaryrefslogtreecommitdiffstats
path: root/tapset/dentry.stp
blob: bae022da5e6d2d198d911ff286f0e219320696ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// dentry tapset
// Copyright (c) 2009 Red Hat Inc.
//
// This file is part of systemtap, and is free software.  You can
// redistribute it and/or modify it under the terms of the GNU General
// Public License (GPL); either version 2, or (at your option) any
// later version.
 

function __dentry_IS_ROOT:long(dentry:long)
{
        return (@cast(dentry, "dentry")->d_parent == dentry)
}


function __dentry_prepend:string(dentry:long,name:string)
{
        dname = d_name(dentry)

        /*
         * In case we are following down a mount point trigger, we can get
         * multiple instances of a root mount.
         */
        c = substr(name, strlen(name)-1, strlen(name)-1)
        if (dname == "/" && c == "/")
                return name;

        return sprintf("%s/%s", dname, name);
}



/**
 *   sfunction d_name - get the dirent name
 *
 *   Returns the dirent name (path basename).
 *   @dentry: Pointer to dentry.
 */
function d_name:string(dentry:long)
{
        len = @cast(dentry, "dentry")->d_name->len;
        return kernel_string_n(@cast(dentry, "dentry")->d_name->name, len);
}



/**
 *   sfunction reverse_path_walk - get the full dirent path
 *
 *   Returns the path name (partial path to mount point).
 *   @dentry: Pointer to dentry.
 */
function reverse_path_walk:string(dentry:long)
{
        while(1) {
                name = __dentry_prepend(dentry, name);
                dentry = @cast(dentry, "dentry")->d_parent;
                if (__dentry_IS_ROOT(dentry))
                        return name;
        }
}



/**
 *   sfunction d_path - get the full nameidata path
 *
 *   Returns the full dirent name (full path to the root), like
 *   the kernel d_path function.
 *   @nd: Pointer to nameidata.
 */
function d_path:string(nd:long)
{
        root = & @cast(task_current(), "task_struct")->fs->root
	dentry = (@defined(@cast(nd,"nameidata")->path->dentry)
	    ? @cast(nd,"nameidata")->path->dentry
	    : @cast(nd,"nameidata")->dentry)
	vfsmnt = (@defined(@cast(nd,"nameidata")->path->mnt)
	    ? @cast(nd,"nameidata")->path->mnt
	    : @cast(nd,"nameidata")->mnt)
        while (1) {
                if (dentry == @cast(root, "path")->dentry &&
                    vfsmnt == @cast(root, "path")->mnt)
                        break;

                if (dentry == @cast(vfsmnt, "vfsmount")->mnt_root ||
                    __dentry_IS_ROOT(dentry)) {
                        /* Global root? */
                        if (@cast(vfsmnt, "vfsmount")->mnt_parent == vfsmnt)
                                return sprintf("/%s", name);

                        dentry = @cast(vfsmnt, "vfsmount")->mnt_mountpoint;
                        vfsmnt = @cast(vfsmnt, "vfsmount")->mnt_parent;
                        continue;
                }
                name = __dentry_prepend(dentry, name);
                dentry = @cast(dentry, "dentry")->d_parent;
        }

        return sprintf("/%s", name);
}