Linux Perf
util.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include "../perf.h"
3 #include "util.h"
4 #include "debug.h"
5 #include <api/fs/fs.h>
6 #include <sys/mman.h>
7 #include <sys/stat.h>
8 #include <sys/utsname.h>
9 #include <dirent.h>
10 #include <fcntl.h>
11 #include <inttypes.h>
12 #include <signal.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <limits.h>
18 #include <linux/kernel.h>
19 #include <linux/log2.h>
20 #include <linux/time64.h>
21 #include <unistd.h>
22 #include "strlist.h"
23 
24 /*
25  * XXX We need to find a better place for these things...
26  */
27 
28 bool perf_singlethreaded = true;
29 
31 {
32  perf_singlethreaded = true;
33 }
34 
36 {
37  perf_singlethreaded = false;
38 }
39 
40 unsigned int page_size;
41 
42 #ifdef _SC_LEVEL1_DCACHE_LINESIZE
43 #define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
44 #else
45 static void cache_line_size(int *cacheline_sizep)
46 {
47  if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
48  pr_debug("cannot determine cache line size");
49 }
50 #endif
51 
52 int cacheline_size(void)
53 {
54  static int size;
55 
56  if (!size)
57  cache_line_size(&size);
58 
59  return size;
60 }
61 
62 int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
63 int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
64 
66 {
67  int value;
68 
69  if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
71 
72  if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0)
74 
76 }
77 
79 
80 bool perf_host = true;
81 bool perf_guest = false;
82 
83 void event_attr_init(struct perf_event_attr *attr)
84 {
85  if (!perf_host)
86  attr->exclude_host = 1;
87  if (!perf_guest)
88  attr->exclude_guest = 1;
89  /* to capture ABI version */
90  attr->size = sizeof(*attr);
91 }
92 
93 int mkdir_p(char *path, mode_t mode)
94 {
95  struct stat st;
96  int err;
97  char *d = path;
98 
99  if (*d != '/')
100  return -1;
101 
102  if (stat(path, &st) == 0)
103  return 0;
104 
105  while (*++d == '/');
106 
107  while ((d = strchr(d, '/'))) {
108  *d = '\0';
109  err = stat(path, &st) && mkdir(path, mode);
110  *d++ = '/';
111  if (err)
112  return -1;
113  while (*d == '/')
114  ++d;
115  }
116  return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
117 }
118 
119 int rm_rf(const char *path)
120 {
121  DIR *dir;
122  int ret = 0;
123  struct dirent *d;
124  char namebuf[PATH_MAX];
125 
126  dir = opendir(path);
127  if (dir == NULL)
128  return 0;
129 
130  while ((d = readdir(dir)) != NULL && !ret) {
131  struct stat statbuf;
132 
133  if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
134  continue;
135 
136  scnprintf(namebuf, sizeof(namebuf), "%s/%s",
137  path, d->d_name);
138 
139  /* We have to check symbolic link itself */
140  ret = lstat(namebuf, &statbuf);
141  if (ret < 0) {
142  pr_debug("stat failed: %s\n", namebuf);
143  break;
144  }
145 
146  if (S_ISDIR(statbuf.st_mode))
147  ret = rm_rf(namebuf);
148  else
149  ret = unlink(namebuf);
150  }
151  closedir(dir);
152 
153  if (ret < 0)
154  return ret;
155 
156  return rmdir(path);
157 }
158 
159 /* A filter which removes dot files */
160 bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
161 {
162  return d->d_name[0] != '.';
163 }
164 
165 /* lsdir reads a directory and store it in strlist */
166 struct strlist *lsdir(const char *name,
167  bool (*filter)(const char *, struct dirent *))
168 {
169  struct strlist *list = NULL;
170  DIR *dir;
171  struct dirent *d;
172 
173  dir = opendir(name);
174  if (!dir)
175  return NULL;
176 
177  list = strlist__new(NULL, NULL);
178  if (!list) {
179  errno = ENOMEM;
180  goto out;
181  }
182 
183  while ((d = readdir(dir)) != NULL) {
184  if (!filter || filter(name, d))
185  strlist__add(list, d->d_name);
186  }
187 
188 out:
189  closedir(dir);
190  return list;
191 }
192 
193 static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi)
194 {
195  int err = -1;
196  char *line = NULL;
197  size_t n;
198  FILE *from_fp, *to_fp;
199  struct nscookie nsc;
200 
201  nsinfo__mountns_enter(nsi, &nsc);
202  from_fp = fopen(from, "r");
203  nsinfo__mountns_exit(&nsc);
204  if (from_fp == NULL)
205  goto out;
206 
207  to_fp = fopen(to, "w");
208  if (to_fp == NULL)
209  goto out_fclose_from;
210 
211  while (getline(&line, &n, from_fp) > 0)
212  if (fputs(line, to_fp) == EOF)
213  goto out_fclose_to;
214  err = 0;
215 out_fclose_to:
216  fclose(to_fp);
217  free(line);
218 out_fclose_from:
219  fclose(from_fp);
220 out:
221  return err;
222 }
223 
224 static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
225 {
226  void *ptr;
227  loff_t pgoff;
228 
229  pgoff = off_in & ~(page_size - 1);
230  off_in -= pgoff;
231 
232  ptr = mmap(NULL, off_in + size, PROT_READ, MAP_PRIVATE, ifd, pgoff);
233  if (ptr == MAP_FAILED)
234  return -1;
235 
236  while (size) {
237  ssize_t ret = pwrite(ofd, ptr + off_in, size, off_out);
238  if (ret < 0 && errno == EINTR)
239  continue;
240  if (ret <= 0)
241  break;
242 
243  size -= ret;
244  off_in += ret;
245  off_out += ret;
246  }
247  munmap(ptr, off_in + size);
248 
249  return size ? -1 : 0;
250 }
251 
252 static int copyfile_mode_ns(const char *from, const char *to, mode_t mode,
253  struct nsinfo *nsi)
254 {
255  int fromfd, tofd;
256  struct stat st;
257  int err;
258  char *tmp = NULL, *ptr = NULL;
259  struct nscookie nsc;
260 
261  nsinfo__mountns_enter(nsi, &nsc);
262  err = stat(from, &st);
263  nsinfo__mountns_exit(&nsc);
264  if (err)
265  goto out;
266  err = -1;
267 
268  /* extra 'x' at the end is to reserve space for '.' */
269  if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
270  tmp = NULL;
271  goto out;
272  }
273  ptr = strrchr(tmp, '/');
274  if (!ptr)
275  goto out;
276  ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1);
277  *ptr = '.';
278 
279  tofd = mkstemp(tmp);
280  if (tofd < 0)
281  goto out;
282 
283  if (fchmod(tofd, mode))
284  goto out_close_to;
285 
286  if (st.st_size == 0) { /* /proc? do it slowly... */
287  err = slow_copyfile(from, tmp, nsi);
288  goto out_close_to;
289  }
290 
291  nsinfo__mountns_enter(nsi, &nsc);
292  fromfd = open(from, O_RDONLY);
293  nsinfo__mountns_exit(&nsc);
294  if (fromfd < 0)
295  goto out_close_to;
296 
297  err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size);
298 
299  close(fromfd);
300 out_close_to:
301  close(tofd);
302  if (!err)
303  err = link(tmp, to);
304  unlink(tmp);
305 out:
306  free(tmp);
307  return err;
308 }
309 
310 int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi)
311 {
312  return copyfile_mode_ns(from, to, 0755, nsi);
313 }
314 
315 int copyfile_mode(const char *from, const char *to, mode_t mode)
316 {
317  return copyfile_mode_ns(from, to, mode, NULL);
318 }
319 
320 int copyfile(const char *from, const char *to)
321 {
322  return copyfile_mode(from, to, 0755);
323 }
324 
325 static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
326 {
327  void *buf_start = buf;
328  size_t left = n;
329 
330  while (left) {
331  /* buf must be treated as const if !is_read. */
332  ssize_t ret = is_read ? read(fd, buf, left) :
333  write(fd, buf, left);
334 
335  if (ret < 0 && errno == EINTR)
336  continue;
337  if (ret <= 0)
338  return ret;
339 
340  left -= ret;
341  buf += ret;
342  }
343 
344  BUG_ON((size_t)(buf - buf_start) != n);
345  return n;
346 }
347 
348 /*
349  * Read exactly 'n' bytes or return an error.
350  */
351 ssize_t readn(int fd, void *buf, size_t n)
352 {
353  return ion(true, fd, buf, n);
354 }
355 
356 /*
357  * Write exactly 'n' bytes or return an error.
358  */
359 ssize_t writen(int fd, const void *buf, size_t n)
360 {
361  /* ion does not modify buf. */
362  return ion(false, fd, (void *)buf, n);
363 }
364 
365 size_t hex_width(u64 v)
366 {
367  size_t n = 1;
368 
369  while ((v >>= 4))
370  ++n;
371 
372  return n;
373 }
374 
375 /*
376  * While we find nice hex chars, build a long_val.
377  * Return number of chars processed.
378  */
379 int hex2u64(const char *ptr, u64 *long_val)
380 {
381  char *p;
382 
383  *long_val = strtoull(ptr, &p, 16);
384 
385  return p - ptr;
386 }
387 
389 {
390  int value;
391 
392  if (sysctl__read_int("kernel/perf_event_paranoid", &value))
393  return INT_MAX;
394 
395  return value;
396 }
397 static int
398 fetch_ubuntu_kernel_version(unsigned int *puint)
399 {
400  ssize_t len;
401  size_t line_len = 0;
402  char *ptr, *line = NULL;
403  int version, patchlevel, sublevel, err;
404  FILE *vsig;
405 
406  if (!puint)
407  return 0;
408 
409  vsig = fopen("/proc/version_signature", "r");
410  if (!vsig) {
411  pr_debug("Open /proc/version_signature failed: %s\n",
412  strerror(errno));
413  return -1;
414  }
415 
416  len = getline(&line, &line_len, vsig);
417  fclose(vsig);
418  err = -1;
419  if (len <= 0) {
420  pr_debug("Reading from /proc/version_signature failed: %s\n",
421  strerror(errno));
422  goto errout;
423  }
424 
425  ptr = strrchr(line, ' ');
426  if (!ptr) {
427  pr_debug("Parsing /proc/version_signature failed: %s\n", line);
428  goto errout;
429  }
430 
431  err = sscanf(ptr + 1, "%d.%d.%d",
432  &version, &patchlevel, &sublevel);
433  if (err != 3) {
434  pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n",
435  line);
436  goto errout;
437  }
438 
439  *puint = (version << 16) + (patchlevel << 8) + sublevel;
440  err = 0;
441 errout:
442  free(line);
443  return err;
444 }
445 
446 int
447 fetch_kernel_version(unsigned int *puint, char *str,
448  size_t str_size)
449 {
450  struct utsname utsname;
451  int version, patchlevel, sublevel, err;
452  bool int_ver_ready = false;
453 
454  if (access("/proc/version_signature", R_OK) == 0)
455  if (!fetch_ubuntu_kernel_version(puint))
456  int_ver_ready = true;
457 
458  if (uname(&utsname))
459  return -1;
460 
461  if (str && str_size) {
462  strncpy(str, utsname.release, str_size);
463  str[str_size - 1] = '\0';
464  }
465 
466  if (!puint || int_ver_ready)
467  return 0;
468 
469  err = sscanf(utsname.release, "%d.%d.%d",
470  &version, &patchlevel, &sublevel);
471 
472  if (err != 3) {
473  pr_debug("Unable to get kernel version from uname '%s'\n",
474  utsname.release);
475  return -1;
476  }
477 
478  *puint = (version << 16) + (patchlevel << 8) + sublevel;
479  return 0;
480 }
481 
482 const char *perf_tip(const char *dirpath)
483 {
484  struct strlist *tips;
485  struct str_node *node;
486  char *tip = NULL;
487  struct strlist_config conf = {
488  .dirname = dirpath,
489  .file_only = true,
490  };
491 
492  tips = strlist__new("tips.txt", &conf);
493  if (tips == NULL)
494  return errno == ENOENT ? NULL :
495  "Tip: check path of tips.txt or get more memory! ;-p";
496 
497  if (strlist__nr_entries(tips) == 0)
498  goto out;
499 
500  node = strlist__entry(tips, random() % strlist__nr_entries(tips));
501  if (asprintf(&tip, "Tip: %s", node->s) < 0)
502  tip = (char *)"Tip: get more memory! ;-)";
503 
504 out:
505  strlist__delete(tips);
506 
507  return tip;
508 }
int fetch_kernel_version(unsigned int *puint, char *str, size_t str_size)
Definition: util.c:447
Definition: mem2node.c:7
int value
Definition: python.c:1143
static int copyfile_mode_ns(const char *from, const char *to, mode_t mode, struct nsinfo *nsi)
Definition: util.c:252
void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)
Definition: namespaces.c:180
static void cache_line_size(int *cacheline_sizep)
Definition: util.c:45
const char * perf_tip(const char *dirpath)
Definition: util.c:482
size_t size
Definition: evsel.c:60
static char * dir
Definition: attr.c:39
int hex2u64(const char *ptr, u64 *long_val)
Definition: util.c:379
int perf_event_paranoid(void)
Definition: util.c:388
static struct version version
unsigned int page_size
Definition: util.c:40
ssize_t readn(int fd, void *buf, size_t n)
Definition: util.c:351
def strerror(nr)
Definition: Util.py:86
void perf_set_singlethreaded(void)
Definition: util.c:30
int int err
Definition: 5sec.c:44
int strlist__add(struct strlist *slist, const char *new_entry)
Definition: strlist.c:64
static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
Definition: util.c:224
int copyfile_mode(const char *from, const char *to, mode_t mode)
Definition: util.c:315
static int fetch_ubuntu_kernel_version(unsigned int *puint)
Definition: util.c:398
static unsigned int strlist__nr_entries(const struct strlist *slist)
Definition: strlist.h:52
struct nsinfo * nsi
Definition: builtin-probe.c:61
void event_attr_init(struct perf_event_attr *attr)
Definition: util.c:83
int rm_rf(const char *path)
Definition: util.c:119
bool perf_host
Definition: util.c:80
int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi)
Definition: util.c:310
bool perf_guest
Definition: util.c:81
const char * name
void nsinfo__mountns_exit(struct nscookie *nc)
Definition: namespaces.c:221
static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
Definition: util.c:325
static int slow_copyfile(const char *from, const char *to, struct nsinfo *nsi)
Definition: util.c:193
#define pr_debug(fmt,...)
Definition: json.h:27
void perf_set_multithreaded(void)
Definition: util.c:35
struct str_node * strlist__entry(const struct strlist *slist, unsigned int idx)
Definition: strlist.c:199
#define PATH_MAX
Definition: jevents.c:1042
int cacheline_size(void)
Definition: util.c:52
static int str(yyscan_t scanner, int token)
size_t hex_width(u64 v)
Definition: util.c:365
int sysctl_perf_event_max_stack
Definition: util.c:62
int mkdir_p(char *path, mode_t mode)
Definition: util.c:93
struct strfilter * filter
Definition: builtin-probe.c:60
bool test_attr__enabled
Definition: util.c:78
int copyfile(const char *from, const char *to)
Definition: util.c:320
bool perf_singlethreaded
Definition: util.c:28
void strlist__delete(struct strlist *slist)
Definition: strlist.c:193
const char * dirname
Definition: strlist.h:29
void free(void *)
bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
Definition: util.c:160
ssize_t writen(int fd, const void *buf, size_t n)
Definition: util.c:359
int sysctl_perf_event_max_contexts_per_stack
Definition: util.c:63
Definition: attr.py:1
struct strlist * lsdir(const char *name, bool(*filter)(const char *, struct dirent *))
Definition: util.c:166
const char * s
Definition: strlist.h:12
struct strlist * strlist__new(const char *list, const struct strlist_config *config)
Definition: strlist.c:160
int sysctl__max_stack(void)
Definition: util.c:65