aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/namespaces.c
diff options
context:
space:
mode:
authorKrister Johansen <kjlx@templeofstupid.com>2017-07-05 21:48:09 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-07-18 22:14:09 -0400
commitbf2e710b3cb8445c052f2ff50b4875a2523bb279 (patch)
tree404a86734bb7b7275638b1d5c7a49a136d6e4766 /tools/perf/util/namespaces.c
parent843ff37bb59edbe51d64e77ba1b3245a15a4dd9f (diff)
perf maps: Lookup maps in both intitial mountns and inner mountns.
If a process is in a mountns and has symbols in /tmp/perf-<pid>.map, look first in the namespace using the tgid for the pidns that the process might be in. If the map isn't found there, try looking in the mountns where perf is running, and use the tgid that's appropriate for perf's pid namespace. If all else fails, use the original pid. This allows us to locate a symbol map file in the mount namespace, if it was generated there. However, we also try the tool's /tmp in case it's there instead. Signed-off-by: Krister Johansen <kjlx@templeofstupid.com> Tested-by: Brendan Gregg <brendan.d.gregg@gmail.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas-Mich Richter <tmricht@linux.vnet.ibm.com> Link: http://lkml.kernel.org/r/1499305693-1599-3-git-send-email-kjlx@templeofstupid.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/namespaces.c')
-rw-r--r--tools/perf/util/namespaces.c83
1 files changed, 77 insertions, 6 deletions
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index bcc6bb19cf10..fc5f398779a4 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -40,18 +40,23 @@ void namespaces__free(struct namespaces *namespaces)
40 free(namespaces); 40 free(namespaces);
41} 41}
42 42
43void nsinfo__init(struct nsinfo *nsi) 43int nsinfo__init(struct nsinfo *nsi)
44{ 44{
45 char oldns[PATH_MAX]; 45 char oldns[PATH_MAX];
46 char spath[PATH_MAX];
46 char *newns = NULL; 47 char *newns = NULL;
48 char *statln = NULL;
47 struct stat old_stat; 49 struct stat old_stat;
48 struct stat new_stat; 50 struct stat new_stat;
51 FILE *f = NULL;
52 size_t linesz = 0;
53 int rv = -1;
49 54
50 if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX) 55 if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
51 return; 56 return rv;
52 57
53 if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1) 58 if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1)
54 return; 59 return rv;
55 60
56 if (stat(oldns, &old_stat) < 0) 61 if (stat(oldns, &old_stat) < 0)
57 goto out; 62 goto out;
@@ -68,24 +73,89 @@ void nsinfo__init(struct nsinfo *nsi)
68 newns = NULL; 73 newns = NULL;
69 } 74 }
70 75
76 /* If we're dealing with a process that is in a different PID namespace,
77 * attempt to work out the innermost tgid for the process.
78 */
79 if (snprintf(spath, PATH_MAX, "/proc/%d/status", nsi->pid) >= PATH_MAX)
80 goto out;
81
82 f = fopen(spath, "r");
83 if (f == NULL)
84 goto out;
85
86 while (getline(&statln, &linesz, f) != -1) {
87 /* Use tgid if CONFIG_PID_NS is not defined. */
88 if (strstr(statln, "Tgid:") != NULL) {
89 nsi->tgid = (pid_t)strtol(strrchr(statln, '\t'),
90 NULL, 10);
91 nsi->nstgid = nsi->tgid;
92 }
93
94 if (strstr(statln, "NStgid:") != NULL) {
95 nsi->nstgid = (pid_t)strtol(strrchr(statln, '\t'),
96 NULL, 10);
97 break;
98 }
99 }
100 rv = 0;
101
71out: 102out:
103 if (f != NULL)
104 (void) fclose(f);
105 free(statln);
72 free(newns); 106 free(newns);
107 return rv;
73} 108}
74 109
75struct nsinfo *nsinfo__new(pid_t pid) 110struct nsinfo *nsinfo__new(pid_t pid)
76{ 111{
77 struct nsinfo *nsi = calloc(1, sizeof(*nsi)); 112 struct nsinfo *nsi;
78 113
114 if (pid == 0)
115 return NULL;
116
117 nsi = calloc(1, sizeof(*nsi));
79 if (nsi != NULL) { 118 if (nsi != NULL) {
80 nsi->pid = pid; 119 nsi->pid = pid;
120 nsi->tgid = pid;
121 nsi->nstgid = pid;
81 nsi->need_setns = false; 122 nsi->need_setns = false;
82 nsinfo__init(nsi); 123 /* Init may fail if the process exits while we're trying to look
124 * at its proc information. In that case, save the pid but
125 * don't try to enter the namespace.
126 */
127 if (nsinfo__init(nsi) == -1)
128 nsi->need_setns = false;
129
83 refcount_set(&nsi->refcnt, 1); 130 refcount_set(&nsi->refcnt, 1);
84 } 131 }
85 132
86 return nsi; 133 return nsi;
87} 134}
88 135
136struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
137{
138 struct nsinfo *nnsi;
139
140 nnsi = calloc(1, sizeof(*nnsi));
141 if (nnsi != NULL) {
142 nnsi->pid = nsi->pid;
143 nnsi->tgid = nsi->tgid;
144 nnsi->nstgid = nsi->nstgid;
145 nnsi->need_setns = nsi->need_setns;
146 if (nsi->mntns_path) {
147 nnsi->mntns_path = strdup(nsi->mntns_path);
148 if (!nnsi->mntns_path) {
149 free(nnsi);
150 return NULL;
151 }
152 }
153 refcount_set(&nnsi->refcnt, 1);
154 }
155
156 return nnsi;
157}
158
89void nsinfo__delete(struct nsinfo *nsi) 159void nsinfo__delete(struct nsinfo *nsi)
90{ 160{
91 zfree(&nsi->mntns_path); 161 zfree(&nsi->mntns_path);
@@ -105,7 +175,8 @@ void nsinfo__put(struct nsinfo *nsi)
105 nsinfo__delete(nsi); 175 nsinfo__delete(nsi);
106} 176}
107 177
108void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc) 178void nsinfo__mountns_enter(struct nsinfo *nsi,
179 struct nscookie *nc)
109{ 180{
110 char curpath[PATH_MAX]; 181 char curpath[PATH_MAX];
111 int oldns = -1; 182 int oldns = -1;