mirror of https://gitee.com/openkylin/linux.git
perf buildid-cache: Support binary objects from other namespaces
Teach buildid-cache how to add, remove, and update binary objects from other mount namespaces. Allow probe events tracing binaries in different namespaces to add their objects to the probe and build-id caches too. As a handy side effect, this also lets us access SDT probes in binaries from alternate mount namespaces. 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-5-git-send-email-kjlx@templeofstupid.com [ Add util/namespaces.c to tools/perf/util/python-ext-sources, to fix the python binding 'perf test' ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
544abd44c7
commit
f045b8c4b3
|
@ -61,6 +61,11 @@ OPTIONS
|
|||
--verbose::
|
||||
Be more verbose.
|
||||
|
||||
--target-ns=PID:
|
||||
Obtain mount namespace information from the target pid. This is
|
||||
used when creating a uprobe for a process that resides in a
|
||||
different mount namespace from the perf(1) utility.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-buildid-list[1]
|
||||
|
|
|
@ -273,6 +273,11 @@ Add a uprobe to a target process running in a different mount namespace
|
|||
|
||||
./perf probe --target-ns <target pid> -x /lib64/libc.so.6 malloc
|
||||
|
||||
Add a USDT probe to a target process running in a different mount namespace
|
||||
|
||||
./perf probe --target-ns <target pid> -x /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.121-0.b13.el7_3.x86_64/jre/lib/amd64/server/libjvm.so %sdt_hotspot:thread__sleep__end
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <unistd.h>
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "namespaces.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/header.h"
|
||||
|
@ -165,33 +166,41 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int build_id_cache__add_file(const char *filename)
|
||||
static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi)
|
||||
{
|
||||
char sbuild_id[SBUILD_ID_SIZE];
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
int err;
|
||||
struct nscookie nsc;
|
||||
|
||||
if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
err = filename__read_build_id(filename, &build_id, sizeof(build_id));
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (err < 0) {
|
||||
pr_debug("Couldn't read a build-id in %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
|
||||
err = build_id_cache__add_s(sbuild_id, filename,
|
||||
err = build_id_cache__add_s(sbuild_id, filename, nsi,
|
||||
false, false);
|
||||
pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
|
||||
err ? "FAIL" : "Ok");
|
||||
return err;
|
||||
}
|
||||
|
||||
static int build_id_cache__remove_file(const char *filename)
|
||||
static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi)
|
||||
{
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
char sbuild_id[SBUILD_ID_SIZE];
|
||||
struct nscookie nsc;
|
||||
|
||||
int err;
|
||||
|
||||
if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
err = filename__read_build_id(filename, &build_id, sizeof(build_id));
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (err < 0) {
|
||||
pr_debug("Couldn't read a build-id in %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
@ -204,13 +213,13 @@ static int build_id_cache__remove_file(const char *filename)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int build_id_cache__purge_path(const char *pathname)
|
||||
static int build_id_cache__purge_path(const char *pathname, struct nsinfo *nsi)
|
||||
{
|
||||
struct strlist *list;
|
||||
struct str_node *pos;
|
||||
int err;
|
||||
|
||||
err = build_id_cache__list_build_ids(pathname, &list);
|
||||
err = build_id_cache__list_build_ids(pathname, nsi, &list);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -256,24 +265,30 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int build_id_cache__update_file(const char *filename)
|
||||
static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi)
|
||||
{
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
char sbuild_id[SBUILD_ID_SIZE];
|
||||
struct nscookie nsc;
|
||||
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
err = filename__read_build_id(filename, &build_id, sizeof(build_id));
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (err < 0) {
|
||||
pr_debug("Couldn't read a build-id in %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
err = 0;
|
||||
|
||||
build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
|
||||
if (build_id_cache__cached(sbuild_id))
|
||||
err = build_id_cache__remove_s(sbuild_id);
|
||||
|
||||
if (!err)
|
||||
err = build_id_cache__add_s(sbuild_id, filename, false, false);
|
||||
err = build_id_cache__add_s(sbuild_id, filename, nsi, false,
|
||||
false);
|
||||
|
||||
pr_debug("Updating %s %s: %s\n", sbuild_id, filename,
|
||||
err ? "FAIL" : "Ok");
|
||||
|
@ -286,6 +301,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
struct strlist *list;
|
||||
struct str_node *pos;
|
||||
int ret = 0;
|
||||
int ns_id = -1;
|
||||
bool force = false;
|
||||
char const *add_name_list_str = NULL,
|
||||
*remove_name_list_str = NULL,
|
||||
|
@ -299,6 +315,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
.mode = PERF_DATA_MODE_READ,
|
||||
};
|
||||
struct perf_session *session = NULL;
|
||||
struct nsinfo *nsi = NULL;
|
||||
|
||||
const struct option buildid_cache_options[] = {
|
||||
OPT_STRING('a', "add", &add_name_list_str,
|
||||
|
@ -315,6 +332,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
OPT_STRING('u', "update", &update_name_list_str, "file list",
|
||||
"file(s) to update"),
|
||||
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
|
||||
OPT_INTEGER(0, "target-ns", &ns_id, "target pid for namespace context"),
|
||||
OPT_END()
|
||||
};
|
||||
const char * const buildid_cache_usage[] = {
|
||||
|
@ -330,6 +348,9 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
!missing_filename && !update_name_list_str))
|
||||
usage_with_options(buildid_cache_usage, buildid_cache_options);
|
||||
|
||||
if (ns_id > 0)
|
||||
nsi = nsinfo__new(ns_id);
|
||||
|
||||
if (missing_filename) {
|
||||
file.path = missing_filename;
|
||||
file.force = force;
|
||||
|
@ -348,7 +369,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
list = strlist__new(add_name_list_str, NULL);
|
||||
if (list) {
|
||||
strlist__for_each_entry(pos, list)
|
||||
if (build_id_cache__add_file(pos->s)) {
|
||||
if (build_id_cache__add_file(pos->s, nsi)) {
|
||||
if (errno == EEXIST) {
|
||||
pr_debug("%s already in the cache\n",
|
||||
pos->s);
|
||||
|
@ -366,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
list = strlist__new(remove_name_list_str, NULL);
|
||||
if (list) {
|
||||
strlist__for_each_entry(pos, list)
|
||||
if (build_id_cache__remove_file(pos->s)) {
|
||||
if (build_id_cache__remove_file(pos->s, nsi)) {
|
||||
if (errno == ENOENT) {
|
||||
pr_debug("%s wasn't in the cache\n",
|
||||
pos->s);
|
||||
|
@ -384,7 +405,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
list = strlist__new(purge_name_list_str, NULL);
|
||||
if (list) {
|
||||
strlist__for_each_entry(pos, list)
|
||||
if (build_id_cache__purge_path(pos->s)) {
|
||||
if (build_id_cache__purge_path(pos->s, nsi)) {
|
||||
if (errno == ENOENT) {
|
||||
pr_debug("%s wasn't in the cache\n",
|
||||
pos->s);
|
||||
|
@ -405,7 +426,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
list = strlist__new(update_name_list_str, NULL);
|
||||
if (list) {
|
||||
strlist__for_each_entry(pos, list)
|
||||
if (build_id_cache__update_file(pos->s)) {
|
||||
if (build_id_cache__update_file(pos->s, nsi)) {
|
||||
if (errno == ENOENT) {
|
||||
pr_debug("%s wasn't in the cache\n",
|
||||
pos->s);
|
||||
|
@ -424,6 +445,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
|
||||
out:
|
||||
perf_session__delete(session);
|
||||
nsinfo__zput(nsi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -416,7 +416,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
|
|||
}
|
||||
|
||||
strlist__for_each_entry(nd, bidlist) {
|
||||
cache = probe_cache__new(nd->s);
|
||||
cache = probe_cache__new(nd->s, NULL);
|
||||
if (!cache)
|
||||
continue;
|
||||
if (probe_cache__filter_purge(cache, filter) < 0 ||
|
||||
|
|
|
@ -33,7 +33,7 @@ static int build_id_cache__add_file(const char *filename)
|
|||
}
|
||||
|
||||
build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
|
||||
err = build_id_cache__add_s(sbuild_id, filename, false, false);
|
||||
err = build_id_cache__add_s(sbuild_id, filename, NULL, false, false);
|
||||
if (err < 0)
|
||||
pr_debug("Failed to add build id cache of %s\n", filename);
|
||||
return err;
|
||||
|
@ -54,7 +54,7 @@ static char *get_self_path(void)
|
|||
static int search_cached_probe(const char *target,
|
||||
const char *group, const char *event)
|
||||
{
|
||||
struct probe_cache *cache = probe_cache__new(target);
|
||||
struct probe_cache *cache = probe_cache__new(target, NULL);
|
||||
int ret = 0;
|
||||
|
||||
if (!cache) {
|
||||
|
|
|
@ -534,13 +534,14 @@ char *build_id_cache__complement(const char *incomplete_sbuild_id)
|
|||
}
|
||||
|
||||
char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
|
||||
bool is_kallsyms, bool is_vdso)
|
||||
struct nsinfo *nsi, bool is_kallsyms,
|
||||
bool is_vdso)
|
||||
{
|
||||
char *realname = (char *)name, *filename;
|
||||
bool slash = is_kallsyms || is_vdso;
|
||||
|
||||
if (!slash) {
|
||||
realname = realpath(name, NULL);
|
||||
realname = nsinfo__realpath(name, nsi);
|
||||
if (!realname)
|
||||
return NULL;
|
||||
}
|
||||
|
@ -556,13 +557,13 @@ char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
|
|||
return filename;
|
||||
}
|
||||
|
||||
int build_id_cache__list_build_ids(const char *pathname,
|
||||
int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi,
|
||||
struct strlist **result)
|
||||
{
|
||||
char *dir_name;
|
||||
int ret = 0;
|
||||
|
||||
dir_name = build_id_cache__cachedir(NULL, pathname, false, false);
|
||||
dir_name = build_id_cache__cachedir(NULL, pathname, nsi, false, false);
|
||||
if (!dir_name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -576,16 +577,20 @@ int build_id_cache__list_build_ids(const char *pathname,
|
|||
|
||||
#if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT)
|
||||
static int build_id_cache__add_sdt_cache(const char *sbuild_id,
|
||||
const char *realname)
|
||||
const char *realname,
|
||||
struct nsinfo *nsi)
|
||||
{
|
||||
struct probe_cache *cache;
|
||||
int ret;
|
||||
struct nscookie nsc;
|
||||
|
||||
cache = probe_cache__new(sbuild_id);
|
||||
cache = probe_cache__new(sbuild_id, nsi);
|
||||
if (!cache)
|
||||
return -1;
|
||||
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
ret = probe_cache__scan_sdt(cache, realname);
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (ret >= 0) {
|
||||
pr_debug4("Found %d SDTs in %s\n", ret, realname);
|
||||
if (probe_cache__commit(cache) < 0)
|
||||
|
@ -595,11 +600,11 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
|
|||
return ret;
|
||||
}
|
||||
#else
|
||||
#define build_id_cache__add_sdt_cache(sbuild_id, realname) (0)
|
||||
#define build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) (0)
|
||||
#endif
|
||||
|
||||
int build_id_cache__add_s(const char *sbuild_id, const char *name,
|
||||
bool is_kallsyms, bool is_vdso)
|
||||
struct nsinfo *nsi, bool is_kallsyms, bool is_vdso)
|
||||
{
|
||||
const size_t size = PATH_MAX;
|
||||
char *realname = NULL, *filename = NULL, *dir_name = NULL,
|
||||
|
@ -607,13 +612,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
|
|||
int err = -1;
|
||||
|
||||
if (!is_kallsyms) {
|
||||
realname = realpath(name, NULL);
|
||||
if (!is_vdso)
|
||||
realname = nsinfo__realpath(name, nsi);
|
||||
else
|
||||
realname = realpath(name, NULL);
|
||||
if (!realname)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
dir_name = build_id_cache__cachedir(sbuild_id, name,
|
||||
is_kallsyms, is_vdso);
|
||||
dir_name = build_id_cache__cachedir(sbuild_id, name, nsi, is_kallsyms,
|
||||
is_vdso);
|
||||
if (!dir_name)
|
||||
goto out_free;
|
||||
|
||||
|
@ -634,7 +642,10 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
|
|||
|
||||
if (access(filename, F_OK)) {
|
||||
if (is_kallsyms) {
|
||||
if (copyfile("/proc/kallsyms", filename))
|
||||
if (copyfile("/proc/kallsyms", filename))
|
||||
goto out_free;
|
||||
} else if (nsi && nsi->need_setns) {
|
||||
if (copyfile_ns(name, filename, nsi))
|
||||
goto out_free;
|
||||
} else if (link(realname, filename) && errno != EEXIST &&
|
||||
copyfile(name, filename))
|
||||
|
@ -657,7 +668,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
|
|||
err = 0;
|
||||
|
||||
/* Update SDT cache : error is just warned */
|
||||
if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
|
||||
if (realname &&
|
||||
build_id_cache__add_sdt_cache(sbuild_id, realname, nsi) < 0)
|
||||
pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
|
||||
|
||||
out_free:
|
||||
|
@ -670,14 +682,15 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
|
|||
}
|
||||
|
||||
static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
|
||||
const char *name, bool is_kallsyms,
|
||||
bool is_vdso)
|
||||
const char *name, struct nsinfo *nsi,
|
||||
bool is_kallsyms, bool is_vdso)
|
||||
{
|
||||
char sbuild_id[SBUILD_ID_SIZE];
|
||||
|
||||
build_id__sprintf(build_id, build_id_size, sbuild_id);
|
||||
|
||||
return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso);
|
||||
return build_id_cache__add_s(sbuild_id, name, nsi, is_kallsyms,
|
||||
is_vdso);
|
||||
}
|
||||
|
||||
bool build_id_cache__cached(const char *sbuild_id)
|
||||
|
@ -743,7 +756,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine)
|
|||
name = nm;
|
||||
}
|
||||
return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
|
||||
is_kallsyms, is_vdso);
|
||||
dso->nsinfo, is_kallsyms, is_vdso);
|
||||
}
|
||||
|
||||
static int __dsos__cache_build_ids(struct list_head *head,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1)
|
||||
|
||||
#include "tool.h"
|
||||
#include "namespaces.h"
|
||||
#include <linux/types.h>
|
||||
|
||||
extern struct perf_tool build_id__mark_dso_hit_ops;
|
||||
|
@ -31,17 +32,19 @@ int perf_session__cache_build_ids(struct perf_session *session);
|
|||
char *build_id_cache__origname(const char *sbuild_id);
|
||||
char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
|
||||
char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
|
||||
bool is_kallsyms, bool is_vdso);
|
||||
struct nsinfo *nsi, bool is_kallsyms,
|
||||
bool is_vdso);
|
||||
|
||||
struct strlist;
|
||||
|
||||
struct strlist *build_id_cache__list_all(bool validonly);
|
||||
char *build_id_cache__complement(const char *incomplete_sbuild_id);
|
||||
int build_id_cache__list_build_ids(const char *pathname,
|
||||
int build_id_cache__list_build_ids(const char *pathname, struct nsinfo *nsi,
|
||||
struct strlist **result);
|
||||
bool build_id_cache__cached(const char *sbuild_id);
|
||||
int build_id_cache__add_s(const char *sbuild_id,
|
||||
const char *name, bool is_kallsyms, bool is_vdso);
|
||||
const char *name, struct nsinfo *nsi,
|
||||
bool is_kallsyms, bool is_vdso);
|
||||
int build_id_cache__remove_s(const char *sbuild_id);
|
||||
|
||||
extern char buildid_dir[];
|
||||
|
|
|
@ -504,7 +504,14 @@ static void check_data_close(void);
|
|||
*/
|
||||
static int open_dso(struct dso *dso, struct machine *machine)
|
||||
{
|
||||
int fd = __open_dso(dso, machine);
|
||||
int fd;
|
||||
struct nscookie nsc;
|
||||
|
||||
if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
|
||||
nsinfo__mountns_enter(dso->nsinfo, &nsc);
|
||||
fd = __open_dso(dso, machine);
|
||||
if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
|
||||
if (fd >= 0) {
|
||||
dso__list_add(dso);
|
||||
|
@ -1302,6 +1309,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
|
|||
{
|
||||
bool have_build_id = false;
|
||||
struct dso *pos;
|
||||
struct nscookie nsc;
|
||||
|
||||
list_for_each_entry(pos, head, node) {
|
||||
if (with_hits && !pos->hit && !dso__is_vdso(pos))
|
||||
|
@ -1310,11 +1318,13 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
|
|||
have_build_id = true;
|
||||
continue;
|
||||
}
|
||||
nsinfo__mountns_enter(pos->nsinfo, &nsc);
|
||||
if (filename__read_build_id(pos->long_name, pos->build_id,
|
||||
sizeof(pos->build_id)) > 0) {
|
||||
have_build_id = true;
|
||||
pos->has_build_id = true;
|
||||
}
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
}
|
||||
|
||||
return have_build_id;
|
||||
|
|
|
@ -2124,7 +2124,7 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
|
|||
return;
|
||||
}
|
||||
strlist__for_each_entry(nd, bidlist) {
|
||||
pcache = probe_cache__new(nd->s);
|
||||
pcache = probe_cache__new(nd->s, NULL);
|
||||
if (!pcache)
|
||||
continue;
|
||||
list_for_each_entry(ent, &pcache->entries, node) {
|
||||
|
|
|
@ -2769,7 +2769,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
|
|||
if (ret == -EINVAL && pev->uprobes)
|
||||
warn_uprobe_event_compat(tev);
|
||||
if (ret == 0 && probe_conf.cache) {
|
||||
cache = probe_cache__new(pev->target);
|
||||
cache = probe_cache__new(pev->target, pev->nsi);
|
||||
if (!cache ||
|
||||
probe_cache__add_entry(cache, pev, tevs, ntevs) < 0 ||
|
||||
probe_cache__commit(cache) < 0)
|
||||
|
@ -3119,7 +3119,7 @@ static int find_cached_events(struct perf_probe_event *pev,
|
|||
int ntevs = 0;
|
||||
int ret = 0;
|
||||
|
||||
cache = probe_cache__new(target);
|
||||
cache = probe_cache__new(target, pev->nsi);
|
||||
/* Return 0 ("not found") if the target has no probe cache. */
|
||||
if (!cache)
|
||||
return 0;
|
||||
|
@ -3209,7 +3209,7 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
|
|||
else
|
||||
return find_cached_events(pev, tevs, pev->target);
|
||||
}
|
||||
cache = probe_cache__new(pev->target);
|
||||
cache = probe_cache__new(pev->target, pev->nsi);
|
||||
if (!cache)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -412,13 +412,15 @@ int probe_cache_entry__get_event(struct probe_cache_entry *entry,
|
|||
}
|
||||
|
||||
/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
|
||||
static int probe_cache__open(struct probe_cache *pcache, const char *target)
|
||||
static int probe_cache__open(struct probe_cache *pcache, const char *target,
|
||||
struct nsinfo *nsi)
|
||||
{
|
||||
char cpath[PATH_MAX];
|
||||
char sbuildid[SBUILD_ID_SIZE];
|
||||
char *dir_name = NULL;
|
||||
bool is_kallsyms = false;
|
||||
int ret, fd;
|
||||
struct nscookie nsc;
|
||||
|
||||
if (target && build_id_cache__cached(target)) {
|
||||
/* This is a cached buildid */
|
||||
|
@ -431,8 +433,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
|
|||
target = DSO__NAME_KALLSYMS;
|
||||
is_kallsyms = true;
|
||||
ret = sysfs__sprintf_build_id("/", sbuildid);
|
||||
} else
|
||||
} else {
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
ret = filename__sprintf_build_id(target, sbuildid);
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
pr_debug("Failed to get build-id from %s.\n", target);
|
||||
|
@ -441,7 +446,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
|
|||
|
||||
/* If we have no buildid cache, make it */
|
||||
if (!build_id_cache__cached(sbuildid)) {
|
||||
ret = build_id_cache__add_s(sbuildid, target,
|
||||
ret = build_id_cache__add_s(sbuildid, target, nsi,
|
||||
is_kallsyms, NULL);
|
||||
if (ret < 0) {
|
||||
pr_debug("Failed to add build-id cache: %s\n", target);
|
||||
|
@ -449,7 +454,7 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
|
|||
}
|
||||
}
|
||||
|
||||
dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
|
||||
dir_name = build_id_cache__cachedir(sbuildid, target, nsi, is_kallsyms,
|
||||
false);
|
||||
found:
|
||||
if (!dir_name) {
|
||||
|
@ -554,7 +559,7 @@ void probe_cache__delete(struct probe_cache *pcache)
|
|||
free(pcache);
|
||||
}
|
||||
|
||||
struct probe_cache *probe_cache__new(const char *target)
|
||||
struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi)
|
||||
{
|
||||
struct probe_cache *pcache = probe_cache__alloc();
|
||||
int ret;
|
||||
|
@ -562,7 +567,7 @@ struct probe_cache *probe_cache__new(const char *target)
|
|||
if (!pcache)
|
||||
return NULL;
|
||||
|
||||
ret = probe_cache__open(pcache, target);
|
||||
ret = probe_cache__open(pcache, target, nsi);
|
||||
if (ret < 0) {
|
||||
pr_debug("Cache open error: %d\n", ret);
|
||||
goto out_err;
|
||||
|
@ -974,7 +979,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
|
|||
return -EINVAL;
|
||||
}
|
||||
strlist__for_each_entry(nd, bidlist) {
|
||||
pcache = probe_cache__new(nd->s);
|
||||
pcache = probe_cache__new(nd->s, NULL);
|
||||
if (!pcache)
|
||||
continue;
|
||||
if (!list_empty(&pcache->entries)) {
|
||||
|
|
|
@ -51,7 +51,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist);
|
|||
int probe_cache_entry__get_event(struct probe_cache_entry *entry,
|
||||
struct probe_trace_event **tevs);
|
||||
|
||||
struct probe_cache *probe_cache__new(const char *target);
|
||||
struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi);
|
||||
int probe_cache__add_entry(struct probe_cache *pcache,
|
||||
struct perf_probe_event *pev,
|
||||
struct probe_trace_event *tevs, int ntevs);
|
||||
|
@ -69,7 +69,7 @@ int probe_cache__show_all_caches(struct strfilter *filter);
|
|||
bool probe_type_is_available(enum probe_type type);
|
||||
bool kretprobe_offset_is_supported(void);
|
||||
#else /* ! HAVE_LIBELF_SUPPORT */
|
||||
static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
|
||||
static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused, struct nsinfo *nsi __maybe_unused)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ util/ctype.c
|
|||
util/evlist.c
|
||||
util/evsel.c
|
||||
util/cpumap.c
|
||||
util/namespaces.c
|
||||
../lib/bitmap.c
|
||||
../lib/find_bit.c
|
||||
../lib/hweight.c
|
||||
|
|
|
@ -1464,7 +1464,6 @@ static int dso__find_perf_map(char *filebuf, size_t bufsz,
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int dso__load(struct dso *dso, struct map *map)
|
||||
{
|
||||
char *name;
|
||||
|
@ -1565,6 +1564,8 @@ int dso__load(struct dso *dso, struct map *map)
|
|||
for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
|
||||
struct symsrc *ss = &ss_[ss_pos];
|
||||
bool next_slot = false;
|
||||
bool is_reg;
|
||||
int sirc;
|
||||
|
||||
enum dso_binary_type symtab_type = binary_type_symtab[i];
|
||||
|
||||
|
@ -1575,12 +1576,20 @@ int dso__load(struct dso *dso, struct map *map)
|
|||
root_dir, name, PATH_MAX))
|
||||
continue;
|
||||
|
||||
if (!is_regular_file(name))
|
||||
continue;
|
||||
if (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
|
||||
/* Name is now the name of the next image to try */
|
||||
if (symsrc__init(ss, dso, name, symtab_type) < 0)
|
||||
is_reg = is_regular_file(name);
|
||||
sirc = symsrc__init(ss, dso, name, symtab_type);
|
||||
|
||||
if (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
|
||||
nsinfo__mountns_enter(dso->nsinfo, &nsc);
|
||||
|
||||
if (!is_reg || sirc < 0) {
|
||||
if (sirc >= 0)
|
||||
symsrc__destroy(ss);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!syms_ss && symsrc__has_symtab(ss)) {
|
||||
syms_ss = ss;
|
||||
|
|
|
@ -143,13 +143,17 @@ struct strlist *lsdir(const char *name,
|
|||
return list;
|
||||
}
|
||||
|
||||
static int slow_copyfile(const char *from, const char *to)
|
||||
static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi)
|
||||
{
|
||||
int err = -1;
|
||||
char *line = NULL;
|
||||
size_t n;
|
||||
FILE *from_fp = fopen(from, "r"), *to_fp;
|
||||
FILE *from_fp, *to_fp;
|
||||
struct nscookie nsc;
|
||||
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
from_fp = fopen(from, "r");
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (from_fp == NULL)
|
||||
goto out;
|
||||
|
||||
|
@ -198,15 +202,21 @@ int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
|
|||
return size ? -1 : 0;
|
||||
}
|
||||
|
||||
int copyfile_mode(const char *from, const char *to, mode_t mode)
|
||||
static int copyfile_mode_ns(const char *from, const char *to, mode_t mode,
|
||||
struct nsinfo *nsi)
|
||||
{
|
||||
int fromfd, tofd;
|
||||
struct stat st;
|
||||
int err = -1;
|
||||
int err;
|
||||
char *tmp = NULL, *ptr = NULL;
|
||||
struct nscookie nsc;
|
||||
|
||||
if (stat(from, &st))
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
err = stat(from, &st);
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (err)
|
||||
goto out;
|
||||
err = -1;
|
||||
|
||||
/* extra 'x' at the end is to reserve space for '.' */
|
||||
if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
|
||||
|
@ -227,11 +237,13 @@ int copyfile_mode(const char *from, const char *to, mode_t mode)
|
|||
goto out_close_to;
|
||||
|
||||
if (st.st_size == 0) { /* /proc? do it slowly... */
|
||||
err = slow_copyfile(from, tmp);
|
||||
err = slow_copyfile(from, tmp, nsi);
|
||||
goto out_close_to;
|
||||
}
|
||||
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
fromfd = open(from, O_RDONLY);
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (fromfd < 0)
|
||||
goto out_close_to;
|
||||
|
||||
|
@ -248,6 +260,16 @@ int copyfile_mode(const char *from, const char *to, mode_t mode)
|
|||
return err;
|
||||
}
|
||||
|
||||
int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi)
|
||||
{
|
||||
return copyfile_mode_ns(from, to, 0755, nsi);
|
||||
}
|
||||
|
||||
int copyfile_mode(const char *from, const char *to, mode_t mode)
|
||||
{
|
||||
return copyfile_mode_ns(from, to, mode, NULL);
|
||||
}
|
||||
|
||||
int copyfile(const char *from, const char *to)
|
||||
{
|
||||
return copyfile_mode(from, to, 0755);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include "namespaces.h"
|
||||
|
||||
/* General helper functions */
|
||||
void usage(const char *err) __noreturn;
|
||||
|
@ -33,6 +34,7 @@ struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dire
|
|||
bool lsdir_no_dot_filter(const char *name, struct dirent *d);
|
||||
int copyfile(const char *from, const char *to);
|
||||
int copyfile_mode(const char *from, const char *to, mode_t mode);
|
||||
int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
|
||||
int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
|
||||
|
||||
ssize_t readn(int fd, void *buf, size_t n);
|
||||
|
|
Loading…
Reference in New Issue