diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2015-02-26 23:50:26 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-02-27 13:52:33 -0500 |
commit | 8d8c8e4cb3014fcc51f0e127b4316043306f5bb0 (patch) | |
tree | 1fe04d062c0cd6041fbeaf1324a3f57cf2ad0536 /tools | |
parent | 7335399a6a4bead9ef8b59ce7d811fc4e99ca98c (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.txt | 13 | ||||
-rw-r--r-- | tools/perf/builtin-buildid-cache.c | 48 | ||||
-rw-r--r-- | tools/perf/util/build-id.c | 93 | ||||
-rw-r--r-- | tools/perf/util/build-id.h | 3 |
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 | ||
13 | DESCRIPTION | 13 | DESCRIPTION |
14 | ----------- | 14 | ----------- |
15 | This command manages the build-id cache. It can add and remove files to/from | 15 | This command manages the build-id cache. It can add, remove, update and purge |
16 | the cache. In the future it should as well purge older entries, set upper | 16 | files to/from the cache. In the future it should as well set upper limits for |
17 | limits for the space used by the cache, etc. | 17 | the space used by the cache, etc. |
18 | 18 | ||
19 | OPTIONS | 19 | OPTIONS |
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 | ||
226 | static 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 | |||
246 | out: | ||
247 | if (verbose) | ||
248 | pr_info("Purging %s: %s\n", pathname, err ? "FAIL" : "Ok"); | ||
249 | |||
250 | return err; | ||
251 | } | ||
252 | |||
226 | static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) | 253 | static 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 | ||
284 | static 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 | |||
306 | int 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 | |||
336 | out: | ||
337 | free(dir_name); | ||
338 | if (ret) | ||
339 | strlist__delete(list); | ||
340 | else | ||
341 | *result = list; | ||
342 | |||
343 | return ret; | ||
344 | } | ||
345 | |||
284 | int build_id_cache__add_s(const char *sbuild_id, const char *name, | 346 | int 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 | ||
9 | extern struct perf_tool build_id__mark_dso_hit_ops; | 10 | 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); | |||
22 | int perf_session__write_buildid_table(struct perf_session *session, int fd); | 23 | int perf_session__write_buildid_table(struct perf_session *session, int fd); |
23 | int perf_session__cache_build_ids(struct perf_session *session); | 24 | int perf_session__cache_build_ids(struct perf_session *session); |
24 | 25 | ||
26 | int build_id_cache__list_build_ids(const char *pathname, | ||
27 | struct strlist **result); | ||
25 | bool build_id_cache__cached(const char *sbuild_id); | 28 | bool build_id_cache__cached(const char *sbuild_id); |
26 | int build_id_cache__add_s(const char *sbuild_id, | 29 | int 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); |