aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2015-02-26 23:50:26 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-02-27 13:52:33 -0500
commit8d8c8e4cb3014fcc51f0e127b4316043306f5bb0 (patch)
tree1fe04d062c0cd6041fbeaf1324a3f57cf2ad0536 /tools
parent7335399a6a4bead9ef8b59ce7d811fc4e99ca98c (diff)
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>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt13
-rw-r--r--tools/perf/builtin-buildid-cache.c48
-rw-r--r--tools/perf/util/build-id.c93
-rw-r--r--tools/perf/util/build-id.h3
4 files changed, 136 insertions, 21 deletions
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index cec6b57e8be6..dd07b55f58d8 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -12,9 +12,9 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command manages the build-id cache. It can add and remove files to/from 15This command manages the build-id cache. It can add, remove, update and purge
16the cache. In the future it should as well purge older entries, set upper 16files to/from the cache. In the future it should as well set upper limits for
17limits for the space used by the cache, etc. 17the space used by the cache, etc.
18 18
19OPTIONS 19OPTIONS
20------- 20-------
@@ -36,7 +36,12 @@ OPTIONS
36 actually made. 36 actually made.
37-r:: 37-r::
38--remove=:: 38--remove=::
39 Remove specified file from the cache. 39 Remove a cached binary which has same build-id of specified file
40 from the cache.
41-p::
42--purge=::
43 Purge all cached binaries including older caches which have specified
44 path from the cache.
40-M:: 45-M::
41--missing=:: 46--missing=::
42 List missing build ids in the cache for the specified file. 47 List missing build ids in the cache for the specified file.
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index e7568f5844ad..86f9d78195a4 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -223,6 +223,33 @@ static int build_id_cache__remove_file(const char *filename)
223 return err; 223 return err;
224} 224}
225 225
226static int build_id_cache__purge_path(const char *pathname)
227{
228 struct strlist *list;
229 struct str_node *pos;
230 int err;
231
232 err = build_id_cache__list_build_ids(pathname, &list);
233 if (err)
234 goto out;
235
236 strlist__for_each(pos, list) {
237 err = build_id_cache__remove_s(pos->s);
238 if (verbose)
239 pr_info("Removing %s %s: %s\n", pos->s, pathname,
240 err ? "FAIL" : "Ok");
241 if (err)
242 break;
243 }
244 strlist__delete(list);
245
246out:
247 if (verbose)
248 pr_info("Purging %s: %s\n", pathname, err ? "FAIL" : "Ok");
249
250 return err;
251}
252
226static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) 253static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
227{ 254{
228 char filename[PATH_MAX]; 255 char filename[PATH_MAX];
@@ -285,6 +312,7 @@ int cmd_buildid_cache(int argc, const char **argv,
285 bool force = false; 312 bool force = false;
286 char const *add_name_list_str = NULL, 313 char const *add_name_list_str = NULL,
287 *remove_name_list_str = NULL, 314 *remove_name_list_str = NULL,
315 *purge_name_list_str = NULL,
288 *missing_filename = NULL, 316 *missing_filename = NULL,
289 *update_name_list_str = NULL, 317 *update_name_list_str = NULL,
290 *kcore_filename = NULL; 318 *kcore_filename = NULL;
@@ -302,6 +330,8 @@ int cmd_buildid_cache(int argc, const char **argv,
302 "file", "kcore file to add"), 330 "file", "kcore file to add"),
303 OPT_STRING('r', "remove", &remove_name_list_str, "file list", 331 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
304 "file(s) to remove"), 332 "file(s) to remove"),
333 OPT_STRING('p', "purge", &purge_name_list_str, "path list",
334 "path(s) to remove (remove old caches too)"),
305 OPT_STRING('M', "missing", &missing_filename, "file", 335 OPT_STRING('M', "missing", &missing_filename, "file",
306 "to find missing build ids in the cache"), 336 "to find missing build ids in the cache"),
307 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 337 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -368,6 +398,24 @@ int cmd_buildid_cache(int argc, const char **argv,
368 } 398 }
369 } 399 }
370 400
401 if (purge_name_list_str) {
402 list = strlist__new(true, purge_name_list_str);
403 if (list) {
404 strlist__for_each(pos, list)
405 if (build_id_cache__purge_path(pos->s)) {
406 if (errno == ENOENT) {
407 pr_debug("%s wasn't in the cache\n",
408 pos->s);
409 continue;
410 }
411 pr_warning("Couldn't remove %s: %s\n",
412 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
413 }
414
415 strlist__delete(list);
416 }
417 }
418
371 if (missing_filename) 419 if (missing_filename)
372 ret = build_id_cache__fprintf_missing(session, stdout); 420 ret = build_id_cache__fprintf_missing(session, stdout);
373 421
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0bc33be5a78c..ffdc338df925 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -281,35 +281,93 @@ void disable_buildid_cache(void)
281 no_buildid_cache = true; 281 no_buildid_cache = true;
282} 282}
283 283
284static char *build_id_cache__dirname_from_path(const char *name,
285 bool is_kallsyms, bool is_vdso)
286{
287 char *realname = (char *)name, *filename;
288 bool slash = is_kallsyms || is_vdso;
289
290 if (!slash) {
291 realname = realpath(name, NULL);
292 if (!realname)
293 return NULL;
294 }
295
296 if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
297 is_vdso ? DSO__NAME_VDSO : realname) < 0)
298 filename = NULL;
299
300 if (!slash)
301 free(realname);
302
303 return filename;
304}
305
306int build_id_cache__list_build_ids(const char *pathname,
307 struct strlist **result)
308{
309 struct strlist *list;
310 char *dir_name;
311 DIR *dir;
312 struct dirent *d;
313 int ret = 0;
314
315 list = strlist__new(true, NULL);
316 dir_name = build_id_cache__dirname_from_path(pathname, false, false);
317 if (!list || !dir_name) {
318 ret = -ENOMEM;
319 goto out;
320 }
321
322 /* List up all dirents */
323 dir = opendir(dir_name);
324 if (!dir) {
325 ret = -errno;
326 goto out;
327 }
328
329 while ((d = readdir(dir)) != NULL) {
330 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
331 continue;
332 strlist__add(list, d->d_name);
333 }
334 closedir(dir);
335
336out:
337 free(dir_name);
338 if (ret)
339 strlist__delete(list);
340 else
341 *result = list;
342
343 return ret;
344}
345
284int build_id_cache__add_s(const char *sbuild_id, const char *name, 346int build_id_cache__add_s(const char *sbuild_id, const char *name,
285 bool is_kallsyms, bool is_vdso) 347 bool is_kallsyms, bool is_vdso)
286{ 348{
287 const size_t size = PATH_MAX; 349 const size_t size = PATH_MAX;
288 char *realname, *filename = zalloc(size), 350 char *realname = NULL, *filename = NULL, *dir_name = NULL,
289 *linkname = zalloc(size), *targetname, *tmp; 351 *linkname = zalloc(size), *targetname, *tmp;
290 int len, err = -1; 352 int err = -1;
291 bool slash = is_kallsyms || is_vdso;
292 353
293 if (is_kallsyms) { 354 if (!is_kallsyms) {
294 if (symbol_conf.kptr_restrict) {
295 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
296 err = 0;
297 goto out_free;
298 }
299 realname = (char *) name;
300 } else
301 realname = realpath(name, NULL); 355 realname = realpath(name, NULL);
356 if (!realname)
357 goto out_free;
358 }
302 359
303 if (realname == NULL || filename == NULL || linkname == NULL) 360 dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
361 if (!dir_name)
304 goto out_free; 362 goto out_free;
305 363
306 len = scnprintf(filename, size, "%s%s%s", 364 if (mkdir_p(dir_name, 0755))
307 buildid_dir, slash ? "/" : "",
308 is_vdso ? DSO__NAME_VDSO : realname);
309 if (mkdir_p(filename, 0755))
310 goto out_free; 365 goto out_free;
311 366
312 snprintf(filename + len, size - len, "/%s", sbuild_id); 367 if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
368 filename = NULL;
369 goto out_free;
370 }
313 371
314 if (access(filename, F_OK)) { 372 if (access(filename, F_OK)) {
315 if (is_kallsyms) { 373 if (is_kallsyms) {
@@ -337,6 +395,7 @@ out_free:
337 if (!is_kallsyms) 395 if (!is_kallsyms)
338 free(realname); 396 free(realname);
339 free(filename); 397 free(filename);
398 free(dir_name);
340 free(linkname); 399 free(linkname);
341 return err; 400 return err;
342} 401}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 2a094982f954..85011222cc14 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -4,6 +4,7 @@
4#define BUILD_ID_SIZE 20 4#define BUILD_ID_SIZE 20
5 5
6#include "tool.h" 6#include "tool.h"
7#include "strlist.h"
7#include <linux/types.h> 8#include <linux/types.h>
8 9
9extern struct perf_tool build_id__mark_dso_hit_ops; 10extern 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);
22int perf_session__write_buildid_table(struct perf_session *session, int fd); 23int perf_session__write_buildid_table(struct perf_session *session, int fd);
23int perf_session__cache_build_ids(struct perf_session *session); 24int perf_session__cache_build_ids(struct perf_session *session);
24 25
26int build_id_cache__list_build_ids(const char *pathname,
27 struct strlist **result);
25bool build_id_cache__cached(const char *sbuild_id); 28bool build_id_cache__cached(const char *sbuild_id);
26int build_id_cache__add_s(const char *sbuild_id, 29int build_id_cache__add_s(const char *sbuild_id,
27 const char *name, bool is_kallsyms, bool is_vdso); 30 const char *name, bool is_kallsyms, bool is_vdso);