Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
fa1195c
Documentation
arch
block
certs
crypto
drivers
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
accounting
arch
bpf
build
cgroup
firewire
gpio
hv
iio
include
kvm
laptop
leds
lib
nfsd
objtool
pci
pcmcia
perf
Documentation
arch
bench
jvmti
pmu-events
python
scripts
tests
trace
ui
util
c++
include
intel-pt-decoder
libunwind
scripting-engines
Build
PERF-VERSION-GEN
annotate.c
annotate.h
auxtrace.c
auxtrace.h
block-range.c
block-range.h
bpf-loader.c
bpf-loader.h
bpf-prologue.c
bpf-prologue.h
branch.c
branch.h
build-id.c
build-id.h
cache.h
call-path.c
call-path.h
callchain.c
callchain.h
cgroup.c
cgroup.h
cloexec.c
cloexec.h
color.c
color.h
comm.c
comm.h
compress.h
config.c
config.h
counts.c
counts.h
cpumap.c
cpumap.h
cs-etm.h
ctype.c
data-convert-bt.c
data-convert-bt.h
data-convert.h
data.c
data.h
db-export.c
db-export.h
debug.c
debug.h
demangle-java.c
demangle-java.h
demangle-rust.c
demangle-rust.h
drv_configs.c
drv_configs.h
dso.c
dso.h
dump-insn.c
dump-insn.h
dwarf-aux.c
dwarf-aux.h
dwarf-regs.c
env.c
env.h
event.c
event.h
evlist.c
evlist.h
evsel.c
evsel.h
evsel_fprintf.c
expr.h
expr.y
find-vdso-map.c
genelf.c
genelf.h
genelf_debug.c
generate-cmdlist.sh
group.h
header.c
header.h
help-unknown-cmd.c
help-unknown-cmd.h
hist.c
hist.h
intel-bts.c
intel-bts.h
intel-pt.c
intel-pt.h
intlist.c
intlist.h
jit.h
jitdump.c
jitdump.h
kvm-stat.h
levenshtein.c
levenshtein.h
llvm-utils.c
llvm-utils.h
lzma.c
machine.c
machine.h
map.c
map.h
mem-events.c
mem-events.h
memswap.c
memswap.h
metricgroup.c
metricgroup.h
mmap.c
mmap.h
namespaces.c
namespaces.h
ordered-events.c
ordered-events.h
parse-branch-options.c
parse-branch-options.h
parse-events.c
parse-events.h
parse-events.l
parse-events.y
parse-regs-options.c
parse-regs-options.h
path.c
path.h
perf-hooks-list.h
perf-hooks.c
perf-hooks.h
perf_regs.c
perf_regs.h
pmu.c
pmu.h
pmu.l
pmu.y
print_binary.c
print_binary.h
probe-event.c
probe-event.h
probe-file.c
probe-file.h
probe-finder.c
probe-finder.h
pstack.c
pstack.h
python-ext-sources
python.c
quote.c
quote.h
rb_resort.h
rblist.c
rblist.h
record.c
rwsem.c
rwsem.h
sane_ctype.h
session.c
session.h
setns.c
setup.py
smt.c
smt.h
sort.c
sort.h
srcline.c
srcline.h
stat-shadow.c
stat.c
stat.h
strbuf.c
strbuf.h
strfilter.c
strfilter.h
string.c
string2.h
strlist.c
strlist.h
svghelper.c
svghelper.h
symbol-elf.c
symbol-minimal.c
symbol.c
symbol.h
symbol_fprintf.c
syscalltbl.c
syscalltbl.h
target.c
target.h
term.c
term.h
thread-stack.c
thread-stack.h
thread.c
thread.h
thread_map.c
thread_map.h
time-utils.c
time-utils.h
tool.h
top.c
top.h
trace-event-info.c
trace-event-parse.c
trace-event-read.c
trace-event-scripting.c
trace-event.c
trace-event.h
trigger.h
tsc.c
tsc.h
units.c
units.h
unwind-libdw.c
unwind-libdw.h
unwind-libunwind-local.c
unwind-libunwind.c
unwind.h
usage.c
util-cxx.h
util.c
util.h
values.c
values.h
vdso.c
vdso.h
xyarray.c
xyarray.h
zlib.c
.gitignore
Build
CREDITS
MANIFEST
Makefile
Makefile.config
Makefile.perf
builtin-annotate.c
builtin-bench.c
builtin-buildid-cache.c
builtin-buildid-list.c
builtin-c2c.c
builtin-config.c
builtin-data.c
builtin-diff.c
builtin-evlist.c
builtin-ftrace.c
builtin-help.c
builtin-inject.c
builtin-kallsyms.c
builtin-kmem.c
builtin-kvm.c
builtin-list.c
builtin-lock.c
builtin-mem.c
builtin-probe.c
builtin-record.c
builtin-report.c
builtin-sched.c
builtin-script.c
builtin-stat.c
builtin-timechart.c
builtin-top.c
builtin-trace.c
builtin-version.c
builtin.h
check-headers.sh
command-list.txt
design.txt
perf-archive.sh
perf-completion.sh
perf-read-vdso.c
perf-sys.h
perf-with-kcore.sh
perf.c
perf.h
power
scripts
spi
testing
thermal
time
usb
virtio
vm
wmi
Makefile
usr
virt
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
tools
/
perf
/
util
/
util.c
Copy path
Blame
Blame
Latest commit
History
History
496 lines (406 loc) · 9.05 KB
Breadcrumbs
linux
/
tools
/
perf
/
util
/
util.c
Top
File metadata and controls
Code
Blame
496 lines (406 loc) · 9.05 KB
Raw
// SPDX-License-Identifier: GPL-2.0 #include "../perf.h" #include "util.h" #include "debug.h" #include <api/fs/fs.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/utsname.h> #include <dirent.h> #include <fcntl.h> #include <inttypes.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <limits.h> #include <linux/kernel.h> #include <linux/log2.h> #include <linux/time64.h> #include <unistd.h> #include "strlist.h" /* * XXX We need to find a better place for these things... */ bool perf_singlethreaded = true; void perf_set_singlethreaded(void) { perf_singlethreaded = true; } void perf_set_multithreaded(void) { perf_singlethreaded = false; } unsigned int page_size; int cacheline_size; int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK; bool test_attr__enabled; bool perf_host = true; bool perf_guest = false; void event_attr_init(struct perf_event_attr *attr) { if (!perf_host) attr->exclude_host = 1; if (!perf_guest) attr->exclude_guest = 1; /* to capture ABI version */ attr->size = sizeof(*attr); } int mkdir_p(char *path, mode_t mode) { struct stat st; int err; char *d = path; if (*d != '/') return -1; if (stat(path, &st) == 0) return 0; while (*++d == '/'); while ((d = strchr(d, '/'))) { *d = '\0'; err = stat(path, &st) && mkdir(path, mode); *d++ = '/'; if (err) return -1; while (*d == '/') ++d; } return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; } int rm_rf(const char *path) { DIR *dir; int ret = 0; struct dirent *d; char namebuf[PATH_MAX]; dir = opendir(path); if (dir == NULL) return 0; while ((d = readdir(dir)) != NULL && !ret) { struct stat statbuf; if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; scnprintf(namebuf, sizeof(namebuf), "%s/%s", path, d->d_name); /* We have to check symbolic link itself */ ret = lstat(namebuf, &statbuf); if (ret < 0) { pr_debug("stat failed: %s\n", namebuf); break; } if (S_ISDIR(statbuf.st_mode)) ret = rm_rf(namebuf); else ret = unlink(namebuf); } closedir(dir); if (ret < 0) return ret; return rmdir(path); } /* A filter which removes dot files */ bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d) { return d->d_name[0] != '.'; } /* lsdir reads a directory and store it in strlist */ struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *)) { struct strlist *list = NULL; DIR *dir; struct dirent *d; dir = opendir(name); if (!dir) return NULL; list = strlist__new(NULL, NULL); if (!list) { errno = ENOMEM; goto out; } while ((d = readdir(dir)) != NULL) { if (!filter || filter(name, d)) strlist__add(list, d->d_name); } out: closedir(dir); return list; } 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, *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; to_fp = fopen(to, "w"); if (to_fp == NULL) goto out_fclose_from; while (getline(&line, &n, from_fp) > 0) if (fputs(line, to_fp) == EOF) goto out_fclose_to; err = 0; out_fclose_to: fclose(to_fp); free(line); out_fclose_from: fclose(from_fp); out: return err; } static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) { void *ptr; loff_t pgoff; pgoff = off_in & ~(page_size - 1); off_in -= pgoff; ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff); if (ptr == MAP_FAILED) return -1; while (size) { ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out); if (ret < 0 && errno == EINTR) continue; if (ret <= 0) break; size -= ret; off_in += ret; off_out += ret; } munmap(ptr, off_in + size); return size ? -1 : 0; } 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; char *tmp = NULL, *ptr = NULL; struct nscookie nsc; 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) { tmp = NULL; goto out; } ptr = strrchr(tmp, '/'); if (!ptr) goto out; ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1); *ptr = '.'; tofd = mkstemp(tmp); if (tofd < 0) goto out; if (fchmod(tofd, mode)) goto out_close_to; if (st.st_size == 0) { /* /proc? do it slowly... */ 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; err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size); close(fromfd); out_close_to: close(tofd); if (!err) err = link(tmp, to); unlink(tmp); out: free(tmp); 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); } static ssize_t ion(bool is_read, int fd, void *buf, size_t n) { void *buf_start = buf; size_t left = n; while (left) { /* buf must be treated as const if !is_read. */ ssize_t ret = is_read ? read(fd, buf, left) : write(fd, buf, left); if (ret < 0 && errno == EINTR) continue; if (ret <= 0) return ret; left -= ret; buf += ret; } BUG_ON((size_t)(buf - buf_start) != n); return n; } /* * Read exactly 'n' bytes or return an error. */ ssize_t readn(int fd, void *buf, size_t n) { return ion(true, fd, buf, n); } /* * Write exactly 'n' bytes or return an error. */ ssize_t writen(int fd, const void *buf, size_t n) { /* ion does not modify buf. */ return ion(false, fd, (void *)buf, n); } size_t hex_width(u64 v) { size_t n = 1; while ((v >>= 4)) ++n; return n; } static int hex(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; if ((ch >= 'A') && (ch <= 'F')) return ch - 'A' + 10; return -1; } /* * While we find nice hex chars, build a long_val. * Return number of chars processed. */ int hex2u64(const char *ptr, u64 *long_val) { const char *p = ptr; *long_val = 0; while (*p) { const int hex_val = hex(*p); if (hex_val < 0) break; *long_val = (*long_val << 4) | hex_val; p++; } return p - ptr; } int perf_event_paranoid(void) { int value; if (sysctl__read_int("kernel/perf_event_paranoid", &value)) return INT_MAX; return value; } static int fetch_ubuntu_kernel_version(unsigned int *puint) { ssize_t len; size_t line_len = 0; char *ptr, *line = NULL; int version, patchlevel, sublevel, err; FILE *vsig; if (!puint) return 0; vsig = fopen("/proc/version_signature", "r"); if (!vsig) { pr_debug("Open /proc/version_signature failed: %s\n", strerror(errno)); return -1; } len = getline(&line, &line_len, vsig); fclose(vsig); err = -1; if (len <= 0) { pr_debug("Reading from /proc/version_signature failed: %s\n", strerror(errno)); goto errout; } ptr = strrchr(line, ' '); if (!ptr) { pr_debug("Parsing /proc/version_signature failed: %s\n", line); goto errout; } err = sscanf(ptr + 1, "%d.%d.%d", &version, &patchlevel, &sublevel); if (err != 3) { pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n", line); goto errout; } *puint = (version << 16) + (patchlevel << 8) + sublevel; err = 0; errout: free(line); return err; } int fetch_kernel_version(unsigned int *puint, char *str, size_t str_size) { struct utsname utsname; int version, patchlevel, sublevel, err; bool int_ver_ready = false; if (access("/proc/version_signature", R_OK) == 0) if (!fetch_ubuntu_kernel_version(puint)) int_ver_ready = true; if (uname(&utsname)) return -1; if (str && str_size) { strncpy(str, utsname.release, str_size); str[str_size - 1] = '\0'; } if (!puint || int_ver_ready) return 0; err = sscanf(utsname.release, "%d.%d.%d", &version, &patchlevel, &sublevel); if (err != 3) { pr_debug("Unable to get kernel version from uname '%s'\n", utsname.release); return -1; } *puint = (version << 16) + (patchlevel << 8) + sublevel; return 0; } const char *perf_tip(const char *dirpath) { struct strlist *tips; struct str_node *node; char *tip = NULL; struct strlist_config conf = { .dirname = dirpath, .file_only = true, }; tips = strlist__new("tips.txt", &conf); if (tips == NULL) return errno == ENOENT ? NULL : "Tip: check path of tips.txt or get more memory! ;-p"; if (strlist__nr_entries(tips) == 0) goto out; node = strlist__entry(tips, random() % strlist__nr_entries(tips)); if (asprintf(&tip, "Tip: %s", node->s) < 0) tip = (char *)"Tip: get more memory! ;-)"; out: strlist__delete(tips); return tip; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
You can’t perform that action at this time.