Commit 61d67d56 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes:

User visible changes:

  - Beautify the perf_event_open() syscall in 'perf trace'. (Arnaldo Carvalho de Melo)

  - Error out unsupported group leader immediately in 'perf stat'. (Kan Liang)

  - Amend some 'perf record' option summaries (period, etc). (Peter Zijlstra)

  - Avoid possible race condition in copyfile() in 'perf buildid-cache'. (Milos Vyletel)

Infrastructure changes:

  - Display 0x for hex values when printing the attribute. (Adrian Hunter)

  - Update MANIFEST per files removed from kernel. (David Ahern)

Build fixes:

  - Fix PRIu64 printf related failure on 32-bit arch. (He Kuang)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 028c63b5 c8ad7063
...@@ -152,12 +152,16 @@ OPTIONS ...@@ -152,12 +152,16 @@ OPTIONS
-d:: -d::
--data:: --data::
Sample addresses. Record the sample addresses.
-T:: -T::
--timestamp:: --timestamp::
Sample timestamps. Use it with 'perf report -D' to see the timestamps, Record the sample timestamps. Use it with 'perf report -D' to see the
for instance. timestamps, for instance.
-P::
--period::
Record the sample period.
-n:: -n::
--no-samples:: --no-samples::
......
...@@ -50,24 +50,20 @@ include/asm-generic/bitops/const_hweight.h ...@@ -50,24 +50,20 @@ include/asm-generic/bitops/const_hweight.h
include/asm-generic/bitops/fls64.h include/asm-generic/bitops/fls64.h
include/asm-generic/bitops/__fls.h include/asm-generic/bitops/__fls.h
include/asm-generic/bitops/fls.h include/asm-generic/bitops/fls.h
include/linux/const.h
include/linux/perf_event.h include/linux/perf_event.h
include/linux/rbtree.h include/linux/rbtree.h
include/linux/list.h include/linux/list.h
include/linux/hash.h include/linux/hash.h
include/linux/stringify.h include/linux/stringify.h
lib/find_next_bit.c
lib/hweight.c lib/hweight.c
lib/rbtree.c lib/rbtree.c
include/linux/swab.h include/linux/swab.h
arch/*/include/asm/unistd*.h arch/*/include/asm/unistd*.h
arch/*/include/asm/perf_regs.h
arch/*/include/uapi/asm/unistd*.h arch/*/include/uapi/asm/unistd*.h
arch/*/include/uapi/asm/perf_regs.h arch/*/include/uapi/asm/perf_regs.h
arch/*/lib/memcpy*.S arch/*/lib/memcpy*.S
arch/*/lib/memset*.S arch/*/lib/memset*.S
include/linux/poison.h include/linux/poison.h
include/linux/magic.h
include/linux/hw_breakpoint.h include/linux/hw_breakpoint.h
include/linux/rbtree_augmented.h include/linux/rbtree_augmented.h
include/uapi/linux/perf_event.h include/uapi/linux/perf_event.h
......
...@@ -1027,10 +1027,9 @@ struct option __record_options[] = { ...@@ -1027,10 +1027,9 @@ struct option __record_options[] = {
OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
"per thread counts"), "per thread counts"),
OPT_BOOLEAN('d', "data", &record.opts.sample_address, OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
"Sample addresses"), OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Record the sample timestamps"),
OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
"don't sample"), "don't sample"),
OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
......
...@@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, ...@@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
fprintf(stdout, "#\n# Total Lost Samples: %lu\n#\n", evlist->stats.total_lost_samples); fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
evlist__for_each(evlist, pos) { evlist__for_each(evlist, pos) {
struct hists *hists = evsel__hists(pos); struct hists *hists = evsel__hists(pos);
const char *evname = perf_evsel__name(pos); const char *evname = perf_evsel__name(pos);
......
...@@ -549,7 +549,10 @@ static int __run_perf_stat(int argc, const char **argv) ...@@ -549,7 +549,10 @@ static int __run_perf_stat(int argc, const char **argv)
ui__warning("%s event is not supported by the kernel.\n", ui__warning("%s event is not supported by the kernel.\n",
perf_evsel__name(counter)); perf_evsel__name(counter));
counter->supported = false; counter->supported = false;
continue;
if ((counter->leader != counter) ||
!(counter->leader->nr_members > 1))
continue;
} }
perf_evsel__open_strerror(counter, &target, perf_evsel__open_strerror(counter, &target,
......
...@@ -68,6 +68,23 @@ ...@@ -68,6 +68,23 @@
# define MSG_CMSG_CLOEXEC 0x40000000 # define MSG_CMSG_CLOEXEC 0x40000000
#endif #endif
#ifndef PERF_FLAG_FD_NO_GROUP
# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
#endif
#ifndef PERF_FLAG_FD_OUTPUT
# define PERF_FLAG_FD_OUTPUT (1UL << 1)
#endif
#ifndef PERF_FLAG_PID_CGROUP
# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
#endif
#ifndef PERF_FLAG_FD_CLOEXEC
# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
#endif
struct tp_field { struct tp_field {
int offset; int offset;
union { union {
...@@ -358,6 +375,14 @@ static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, ...@@ -358,6 +375,14 @@ static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
#define SCA_HEX syscall_arg__scnprintf_hex #define SCA_HEX syscall_arg__scnprintf_hex
static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
struct syscall_arg *arg)
{
return scnprintf(bf, size, "%d", arg->val);
}
#define SCA_INT syscall_arg__scnprintf_int
static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
struct syscall_arg *arg) struct syscall_arg *arg)
{ {
...@@ -810,6 +835,34 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, ...@@ -810,6 +835,34 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
struct syscall_arg *arg)
{
int printed = 0, flags = arg->val;
if (flags == 0)
return 0;
#define P_FLAG(n) \
if (flags & PERF_FLAG_##n) { \
printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
flags &= ~PERF_FLAG_##n; \
}
P_FLAG(FD_NO_GROUP);
P_FLAG(FD_OUTPUT);
P_FLAG(PID_CGROUP);
P_FLAG(FD_CLOEXEC);
#undef P_FLAG
if (flags)
printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
return printed;
}
#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
struct syscall_arg *arg) struct syscall_arg *arg)
{ {
...@@ -1077,6 +1130,11 @@ static struct syscall_fmt { ...@@ -1077,6 +1130,11 @@ static struct syscall_fmt {
{ .name = "openat", .errmsg = true, { .name = "openat", .errmsg = true,
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
[2] = SCA_OPEN_FLAGS, /* flags */ }, }, [2] = SCA_OPEN_FLAGS, /* flags */ }, },
{ .name = "perf_event_open", .errmsg = true,
.arg_scnprintf = { [1] = SCA_INT, /* pid */
[2] = SCA_INT, /* cpu */
[3] = SCA_FD, /* group_fd */
[4] = SCA_PERF_FLAGS, /* flags */ }, },
{ .name = "pipe2", .errmsg = true, { .name = "pipe2", .errmsg = true,
.arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
{ .name = "poll", .errmsg = true, .timeout = true, }, { .name = "poll", .errmsg = true, .timeout = true, },
......
...@@ -1058,7 +1058,7 @@ static void __p_read_format(char *buf, size_t size, u64 value) ...@@ -1058,7 +1058,7 @@ static void __p_read_format(char *buf, size_t size, u64 value)
#define BUF_SIZE 1024 #define BUF_SIZE 1024
#define p_hex(val) snprintf(buf, BUF_SIZE, "%"PRIx64, (uint64_t)(val)) #define p_hex(val) snprintf(buf, BUF_SIZE, "%#"PRIx64, (uint64_t)(val))
#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) #define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val)) #define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) #define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
......
...@@ -1299,7 +1299,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session) ...@@ -1299,7 +1299,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
drop_rate = (double)stats->total_lost_samples / drop_rate = (double)stats->total_lost_samples /
(double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples);
if (drop_rate > 0.05) { if (drop_rate > 0.05) {
ui__warning("Processed %lu samples and lost %3.2f%% samples!\n\n", ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n",
stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples,
drop_rate * 100.0); drop_rate * 100.0);
} }
......
...@@ -115,20 +115,17 @@ int rm_rf(char *path) ...@@ -115,20 +115,17 @@ int rm_rf(char *path)
return rmdir(path); return rmdir(path);
} }
static int slow_copyfile(const char *from, const char *to, mode_t mode) static int slow_copyfile(const char *from, const char *to)
{ {
int err = -1; int err = -1;
char *line = NULL; char *line = NULL;
size_t n; size_t n;
FILE *from_fp = fopen(from, "r"), *to_fp; FILE *from_fp = fopen(from, "r"), *to_fp;
mode_t old_umask;
if (from_fp == NULL) if (from_fp == NULL)
goto out; goto out;
old_umask = umask(mode ^ 0777);
to_fp = fopen(to, "w"); to_fp = fopen(to, "w");
umask(old_umask);
if (to_fp == NULL) if (to_fp == NULL)
goto out_fclose_from; goto out_fclose_from;
...@@ -178,29 +175,48 @@ int copyfile_mode(const char *from, const char *to, mode_t mode) ...@@ -178,29 +175,48 @@ int copyfile_mode(const char *from, const char *to, mode_t mode)
int fromfd, tofd; int fromfd, tofd;
struct stat st; struct stat st;
int err = -1; int err = -1;
char *tmp = NULL, *ptr = NULL;
if (stat(from, &st)) if (stat(from, &st))
goto out; goto out;
if (st.st_size == 0) /* /proc? do it slowly... */ /* extra 'x' at the end is to reserve space for '.' */
return slow_copyfile(from, to, mode); if (asprintf(&tmp, "%s.XXXXXXx", to) < 0) {
tmp = NULL;
fromfd = open(from, O_RDONLY);
if (fromfd < 0)
goto out; goto out;
}
ptr = strrchr(tmp, '/');
if (!ptr)
goto out;
ptr = memmove(ptr + 1, ptr, strlen(ptr) - 1);
*ptr = '.';
tofd = creat(to, mode); tofd = mkstemp(tmp);
if (tofd < 0) if (tofd < 0)
goto out_close_from; goto out;
if (fchmod(tofd, mode))
goto out_close_to;
if (st.st_size == 0) { /* /proc? do it slowly... */
err = slow_copyfile(from, tmp);
goto out_close_to;
}
fromfd = open(from, O_RDONLY);
if (fromfd < 0)
goto out_close_to;
err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size); err = copyfile_offset(fromfd, 0, tofd, 0, st.st_size);
close(tofd);
if (err)
unlink(to);
out_close_from:
close(fromfd); close(fromfd);
out_close_to:
close(tofd);
if (!err)
err = link(tmp, to);
unlink(tmp);
out: out:
free(tmp);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment