Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Masami Hiramatsu and committed by
Arnaldo Carvalho de Melo
8d8c8e4c 7335399a

+136 -21
+9 -4
tools/perf/Documentation/perf-buildid-cache.txt
··· 12 12 13 13 DESCRIPTION 14 14 ----------- 15 - This command manages the build-id cache. It can add and remove files to/from 16 - the cache. In the future it should as well purge older entries, set upper 17 - limits for the space used by the cache, etc. 15 + This command manages the build-id cache. It can add, remove, update and purge 16 + files to/from the cache. In the future it should as well set upper limits for 17 + the space used by the cache, etc. 18 18 19 19 OPTIONS 20 20 ------- ··· 36 36 actually made. 37 37 -r:: 38 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 45 -M:: 41 46 --missing=:: 42 47 List missing build ids in the cache for the specified file.
+48
tools/perf/builtin-buildid-cache.c
··· 223 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 253 static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) 227 254 { 228 255 char filename[PATH_MAX]; ··· 312 285 bool force = false; 313 286 char const *add_name_list_str = NULL, 314 287 *remove_name_list_str = NULL, 288 + *purge_name_list_str = NULL, 315 289 *missing_filename = NULL, 316 290 *update_name_list_str = NULL, 317 291 *kcore_filename = NULL; ··· 330 302 "file", "kcore file to add"), 331 303 OPT_STRING('r', "remove", &remove_name_list_str, "file list", 332 304 "file(s) to remove"), 305 + OPT_STRING('p', "purge", &purge_name_list_str, "path list", 306 + "path(s) to remove (remove old caches too)"), 333 307 OPT_STRING('M', "missing", &missing_filename, "file", 334 308 "to find missing build ids in the cache"), 335 309 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), ··· 385 355 if (list) { 386 356 strlist__for_each(pos, list) 387 357 if (build_id_cache__remove_file(pos->s)) { 358 + if (errno == ENOENT) { 359 + pr_debug("%s wasn't in the cache\n", 360 + pos->s); 361 + continue; 362 + } 363 + pr_warning("Couldn't remove %s: %s\n", 364 + pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); 365 + } 366 + 367 + strlist__delete(list); 368 + } 369 + } 370 + 371 + if (purge_name_list_str) { 372 + list = strlist__new(true, purge_name_list_str); 373 + if (list) { 374 + strlist__for_each(pos, list) 375 + if (build_id_cache__purge_path(pos->s)) { 388 376 if (errno == ENOENT) { 389 377 pr_debug("%s wasn't in the cache\n", 390 378 pos->s);
+76 -17
tools/perf/util/build-id.c
··· 281 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 346 int build_id_cache__add_s(const char *sbuild_id, const char *name, 285 347 bool is_kallsyms, bool is_vdso) 286 348 { 287 349 const size_t size = PATH_MAX; 288 - char *realname, *filename = zalloc(size), 350 + char *realname = NULL, *filename = NULL, *dir_name = NULL, 289 351 *linkname = zalloc(size), *targetname, *tmp; 290 - int len, err = -1; 291 - bool slash = is_kallsyms || is_vdso; 352 + int err = -1; 292 353 293 - 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 354 + if (!is_kallsyms) { 301 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 362 goto out_free; 305 363 306 - len = scnprintf(filename, size, "%s%s%s", 307 - buildid_dir, slash ? "/" : "", 308 - is_vdso ? DSO__NAME_VDSO : realname); 309 - if (mkdir_p(filename, 0755)) 364 + if (mkdir_p(dir_name, 0755)) 310 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 372 if (access(filename, F_OK)) { 315 373 if (is_kallsyms) { ··· 395 337 if (!is_kallsyms) 396 338 free(realname); 397 339 free(filename); 340 + free(dir_name); 398 341 free(linkname); 399 342 return err; 400 343 }
+3
tools/perf/util/build-id.h
··· 4 4 #define BUILD_ID_SIZE 20 5 5 6 6 #include "tool.h" 7 + #include "strlist.h" 7 8 #include <linux/types.h> 8 9 9 10 extern struct perf_tool build_id__mark_dso_hit_ops; ··· 23 22 int perf_session__write_buildid_table(struct perf_session *session, int fd); 24 23 int perf_session__cache_build_ids(struct perf_session *session); 25 24 25 + int build_id_cache__list_build_ids(const char *pathname, 26 + struct strlist **result); 26 27 bool build_id_cache__cached(const char *sbuild_id); 27 28 int build_id_cache__add_s(const char *sbuild_id, 28 29 const char *name, bool is_kallsyms, bool is_vdso);