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>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
843ff37bb5
commit
bf2e710b3c
@@ -40,18 +40,23 @@ void namespaces__free(struct namespaces *namespaces)
|
||||
free(namespaces);
|
||||
}
|
||||
|
||||
void nsinfo__init(struct nsinfo *nsi)
|
||||
int nsinfo__init(struct nsinfo *nsi)
|
||||
{
|
||||
char oldns[PATH_MAX];
|
||||
char spath[PATH_MAX];
|
||||
char *newns = NULL;
|
||||
char *statln = NULL;
|
||||
struct stat old_stat;
|
||||
struct stat new_stat;
|
||||
FILE *f = NULL;
|
||||
size_t linesz = 0;
|
||||
int rv = -1;
|
||||
|
||||
if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
|
||||
return;
|
||||
return rv;
|
||||
|
||||
if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1)
|
||||
return;
|
||||
return rv;
|
||||
|
||||
if (stat(oldns, &old_stat) < 0)
|
||||
goto out;
|
||||
@@ -68,24 +73,89 @@ void nsinfo__init(struct nsinfo *nsi)
|
||||
newns = NULL;
|
||||
}
|
||||
|
||||
/* If we're dealing with a process that is in a different PID namespace,
|
||||
* attempt to work out the innermost tgid for the process.
|
||||
*/
|
||||
if (snprintf(spath, PATH_MAX, "/proc/%d/status", nsi->pid) >= PATH_MAX)
|
||||
goto out;
|
||||
|
||||
f = fopen(spath, "r");
|
||||
if (f == NULL)
|
||||
goto out;
|
||||
|
||||
while (getline(&statln, &linesz, f) != -1) {
|
||||
/* Use tgid if CONFIG_PID_NS is not defined. */
|
||||
if (strstr(statln, "Tgid:") != NULL) {
|
||||
nsi->tgid = (pid_t)strtol(strrchr(statln, '\t'),
|
||||
NULL, 10);
|
||||
nsi->nstgid = nsi->tgid;
|
||||
}
|
||||
|
||||
if (strstr(statln, "NStgid:") != NULL) {
|
||||
nsi->nstgid = (pid_t)strtol(strrchr(statln, '\t'),
|
||||
NULL, 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rv = 0;
|
||||
|
||||
out:
|
||||
if (f != NULL)
|
||||
(void) fclose(f);
|
||||
free(statln);
|
||||
free(newns);
|
||||
return rv;
|
||||
}
|
||||
|
||||
struct nsinfo *nsinfo__new(pid_t pid)
|
||||
{
|
||||
struct nsinfo *nsi = calloc(1, sizeof(*nsi));
|
||||
struct nsinfo *nsi;
|
||||
|
||||
if (pid == 0)
|
||||
return NULL;
|
||||
|
||||
nsi = calloc(1, sizeof(*nsi));
|
||||
if (nsi != NULL) {
|
||||
nsi->pid = pid;
|
||||
nsi->tgid = pid;
|
||||
nsi->nstgid = pid;
|
||||
nsi->need_setns = false;
|
||||
nsinfo__init(nsi);
|
||||
/* Init may fail if the process exits while we're trying to look
|
||||
* at its proc information. In that case, save the pid but
|
||||
* don't try to enter the namespace.
|
||||
*/
|
||||
if (nsinfo__init(nsi) == -1)
|
||||
nsi->need_setns = false;
|
||||
|
||||
refcount_set(&nsi->refcnt, 1);
|
||||
}
|
||||
|
||||
return nsi;
|
||||
}
|
||||
|
||||
struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
|
||||
{
|
||||
struct nsinfo *nnsi;
|
||||
|
||||
nnsi = calloc(1, sizeof(*nnsi));
|
||||
if (nnsi != NULL) {
|
||||
nnsi->pid = nsi->pid;
|
||||
nnsi->tgid = nsi->tgid;
|
||||
nnsi->nstgid = nsi->nstgid;
|
||||
nnsi->need_setns = nsi->need_setns;
|
||||
if (nsi->mntns_path) {
|
||||
nnsi->mntns_path = strdup(nsi->mntns_path);
|
||||
if (!nnsi->mntns_path) {
|
||||
free(nnsi);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
refcount_set(&nnsi->refcnt, 1);
|
||||
}
|
||||
|
||||
return nnsi;
|
||||
}
|
||||
|
||||
void nsinfo__delete(struct nsinfo *nsi)
|
||||
{
|
||||
zfree(&nsi->mntns_path);
|
||||
@@ -105,7 +175,8 @@ void nsinfo__put(struct nsinfo *nsi)
|
||||
nsinfo__delete(nsi);
|
||||
}
|
||||
|
||||
void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)
|
||||
void nsinfo__mountns_enter(struct nsinfo *nsi,
|
||||
struct nscookie *nc)
|
||||
{
|
||||
char curpath[PATH_MAX];
|
||||
int oldns = -1;
|
||||
|
Reference in New Issue
Block a user