perf buildid-cache: Add --purge FILE to remove all caches of FILE
Add --purge FILE to remove all caches of FILE. Since the current --remove FILE removes a cache which has same build-id of given FILE. Since the command takes a FILE path, it can confuse user who tries to remove cache about FILE path. ----- # ./perf buildid-cache -v --add ./perf Adding 133b7b5486d987a5ab5c3ebf4ea14941f45d4d4f ./perf: Ok # (update the ./perf binary) # ./perf buildid-cache -v --remove ./perf Removing 305bbd1be68f66eca7e2d78db294653031edfa79 ./perf: FAIL ./perf wasn't in the cache ----- Actually, the --remove's FAIL is not shown, it just silently fails. So, this patch adds --purge FILE action for such usecase. perf buildid-cache --purge FILE removes all caches which has same FILE path. In other words, it removes all caches including old binaries. ----- # ./perf buildid-cache -v --add ./perf Adding 133b7b5486d987a5ab5c3ebf4ea14941f45d4d4f ./perf: Ok # (update the ./perf binary) # ./perf buildid-cache -v --purge ./perf Removing 133b7b5486d987a5ab5c3ebf4ea14941f45d4d4f ./perf: Ok ----- BTW, if you want to purge all the caches, remove ~/.debug/* . Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Borislav Petkov <bp@suse.de> Cc: Hemant Kumar <hemant@linux.vnet.ibm.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/20150227045026.1999.64084.stgit@localhost.localdomain [ s/dirname/dir_name/g to fix build on fedora14, where dirname is a global ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
7335399a6a
commit
8d8c8e4cb3
4 changed files with 136 additions and 21 deletions
|
@ -12,9 +12,9 @@ SYNOPSIS
|
|||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
This command manages the build-id cache. It can add and remove files to/from
|
||||
the cache. In the future it should as well purge older entries, set upper
|
||||
limits for the space used by the cache, etc.
|
||||
This command manages the build-id cache. It can add, remove, update and purge
|
||||
files to/from the cache. In the future it should as well set upper limits for
|
||||
the space used by the cache, etc.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
@ -36,7 +36,12 @@ OPTIONS
|
|||
actually made.
|
||||
-r::
|
||||
--remove=::
|
||||
Remove specified file from the cache.
|
||||
Remove a cached binary which has same build-id of specified file
|
||||
from the cache.
|
||||
-p::
|
||||
--purge=::
|
||||
Purge all cached binaries including older caches which have specified
|
||||
path from the cache.
|
||||
-M::
|
||||
--missing=::
|
||||
List missing build ids in the cache for the specified file.
|
||||
|
|
|
@ -223,6 +223,33 @@ static int build_id_cache__remove_file(const char *filename)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int build_id_cache__purge_path(const char *pathname)
|
||||
{
|
||||
struct strlist *list;
|
||||
struct str_node *pos;
|
||||
int err;
|
||||
|
||||
err = build_id_cache__list_build_ids(pathname, &list);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
strlist__for_each(pos, list) {
|
||||
err = build_id_cache__remove_s(pos->s);
|
||||
if (verbose)
|
||||
pr_info("Removing %s %s: %s\n", pos->s, pathname,
|
||||
err ? "FAIL" : "Ok");
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
strlist__delete(list);
|
||||
|
||||
out:
|
||||
if (verbose)
|
||||
pr_info("Purging %s: %s\n", pathname, err ? "FAIL" : "Ok");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
|
@ -285,6 +312,7 @@ int cmd_buildid_cache(int argc, const char **argv,
|
|||
bool force = false;
|
||||
char const *add_name_list_str = NULL,
|
||||
*remove_name_list_str = NULL,
|
||||
*purge_name_list_str = NULL,
|
||||
*missing_filename = NULL,
|
||||
*update_name_list_str = NULL,
|
||||
*kcore_filename = NULL;
|
||||
|
@ -302,6 +330,8 @@ int cmd_buildid_cache(int argc, const char **argv,
|
|||
"file", "kcore file to add"),
|
||||
OPT_STRING('r', "remove", &remove_name_list_str, "file list",
|
||||
"file(s) to remove"),
|
||||
OPT_STRING('p', "purge", &purge_name_list_str, "path list",
|
||||
"path(s) to remove (remove old caches too)"),
|
||||
OPT_STRING('M', "missing", &missing_filename, "file",
|
||||
"to find missing build ids in the cache"),
|
||||
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
|
||||
|
@ -368,6 +398,24 @@ int cmd_buildid_cache(int argc, const char **argv,
|
|||
}
|
||||
}
|
||||
|
||||
if (purge_name_list_str) {
|
||||
list = strlist__new(true, purge_name_list_str);
|
||||
if (list) {
|
||||
strlist__for_each(pos, list)
|
||||
if (build_id_cache__purge_path(pos->s)) {
|
||||
if (errno == ENOENT) {
|
||||
pr_debug("%s wasn't in the cache\n",
|
||||
pos->s);
|
||||
continue;
|
||||
}
|
||||
pr_warning("Couldn't remove %s: %s\n",
|
||||
pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
|
||||
}
|
||||
|
||||
strlist__delete(list);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_filename)
|
||||
ret = build_id_cache__fprintf_missing(session, stdout);
|
||||
|
||||
|
|
|
@ -281,35 +281,93 @@ void disable_buildid_cache(void)
|
|||
no_buildid_cache = true;
|
||||
}
|
||||
|
||||
static char *build_id_cache__dirname_from_path(const char *name,
|
||||
bool is_kallsyms, bool is_vdso)
|
||||
{
|
||||
char *realname = (char *)name, *filename;
|
||||
bool slash = is_kallsyms || is_vdso;
|
||||
|
||||
if (!slash) {
|
||||
realname = realpath(name, NULL);
|
||||
if (!realname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
|
||||
is_vdso ? DSO__NAME_VDSO : realname) < 0)
|
||||
filename = NULL;
|
||||
|
||||
if (!slash)
|
||||
free(realname);
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
int build_id_cache__list_build_ids(const char *pathname,
|
||||
struct strlist **result)
|
||||
{
|
||||
struct strlist *list;
|
||||
char *dir_name;
|
||||
DIR *dir;
|
||||
struct dirent *d;
|
||||
int ret = 0;
|
||||
|
||||
list = strlist__new(true, NULL);
|
||||
dir_name = build_id_cache__dirname_from_path(pathname, false, false);
|
||||
if (!list || !dir_name) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* List up all dirents */
|
||||
dir = opendir(dir_name);
|
||||
if (!dir) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while ((d = readdir(dir)) != NULL) {
|
||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||
continue;
|
||||
strlist__add(list, d->d_name);
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
out:
|
||||
free(dir_name);
|
||||
if (ret)
|
||||
strlist__delete(list);
|
||||
else
|
||||
*result = list;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int build_id_cache__add_s(const char *sbuild_id, const char *name,
|
||||
bool is_kallsyms, bool is_vdso)
|
||||
{
|
||||
const size_t size = PATH_MAX;
|
||||
char *realname, *filename = zalloc(size),
|
||||
char *realname = NULL, *filename = NULL, *dir_name = NULL,
|
||||
*linkname = zalloc(size), *targetname, *tmp;
|
||||
int len, err = -1;
|
||||
bool slash = is_kallsyms || is_vdso;
|
||||
int err = -1;
|
||||
|
||||
if (is_kallsyms) {
|
||||
if (symbol_conf.kptr_restrict) {
|
||||
pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
|
||||
err = 0;
|
||||
if (!is_kallsyms) {
|
||||
realname = realpath(name, NULL);
|
||||
if (!realname)
|
||||
goto out_free;
|
||||
}
|
||||
realname = (char *) name;
|
||||
} else
|
||||
realname = realpath(name, NULL);
|
||||
|
||||
if (realname == NULL || filename == NULL || linkname == NULL)
|
||||
dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
|
||||
if (!dir_name)
|
||||
goto out_free;
|
||||
|
||||
len = scnprintf(filename, size, "%s%s%s",
|
||||
buildid_dir, slash ? "/" : "",
|
||||
is_vdso ? DSO__NAME_VDSO : realname);
|
||||
if (mkdir_p(filename, 0755))
|
||||
if (mkdir_p(dir_name, 0755))
|
||||
goto out_free;
|
||||
|
||||
snprintf(filename + len, size - len, "/%s", sbuild_id);
|
||||
if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
|
||||
filename = NULL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (access(filename, F_OK)) {
|
||||
if (is_kallsyms) {
|
||||
|
@ -337,6 +395,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
|
|||
if (!is_kallsyms)
|
||||
free(realname);
|
||||
free(filename);
|
||||
free(dir_name);
|
||||
free(linkname);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define BUILD_ID_SIZE 20
|
||||
|
||||
#include "tool.h"
|
||||
#include "strlist.h"
|
||||
#include <linux/types.h>
|
||||
|
||||
extern struct perf_tool build_id__mark_dso_hit_ops;
|
||||
|
@ -22,6 +23,8 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
|
|||
int perf_session__write_buildid_table(struct perf_session *session, int fd);
|
||||
int perf_session__cache_build_ids(struct perf_session *session);
|
||||
|
||||
int build_id_cache__list_build_ids(const char *pathname,
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue