perf/core improvements and fixes:

perf test:
 
 - Add watchpoint entry (Ravi Bangoria)
 
 Build fixes:
 
 - Initialize perf_data_file fd field to fix building the CTF (trace format)
   converter with with gcc 4.8.4 on Ubuntu 14.04 (Jérémie Galarneau)
 
 - Use -Wno-redundant-decls to build with PYTHON=python3 to
   build the python binding, fixing the build in systems such
   as Clear Linux (Arnaldo Carvalho de Melo)
 
 Hardware tracing:
 
 - Suppress AUX/OVERWRITE records (Alexander Shishkin)
 
 Infrastructure:
 
 - Adopt PTR_ERR_OR_ZERO from the kernel and use it in
   the bpf-loader instead of open coded equivalent (Ding Xiang)
 
 - Improve the event ordering code to make it clear and fix
   a bug related to freeing of events when using pipe mode
   from 'record' to 'inject' (Jiri Olsa)
 
 - Some prep work to facilitate per-cpu threads to write
   record data to per-cpu files (Jiri Olsa)
 
 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQR2GiIUctdOfX2qHhGyPKLppCJ+JwUCW6JP9wAKCRCyPKLppCJ+
 J9vjAQDfizmUwoCqgZD4q9d9hIx1KWrFK5q6EJOPsY+l0288BQEAzgx3Q0c7zFS1
 WB0DjtGgEntudoH57vqsswrT7VPKPAE=
 =Ee8x
 -----END PGP SIGNATURE-----

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

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

perf test improvements:

- Add watchpoint entry (Ravi Bangoria)

Build fixes:

- Initialize perf_data_file fd field to fix building the CTF (trace format)
  converter with with gcc 4.8.4 on Ubuntu 14.04 (Jérémie Galarneau)

- Use -Wno-redundant-decls to build with PYTHON=python3 to
  build the python binding, fixing the build in systems such
  as Clear Linux (Arnaldo Carvalho de Melo)

Hardware tracing improvements:

- Suppress AUX/OVERWRITE records (Alexander Shishkin)

Infrastructure changes:

- Adopt PTR_ERR_OR_ZERO from the kernel and use it in
  the bpf-loader instead of open coded equivalent (Ding Xiang)

- Improve the event ordering code to make it clear and fix
  a bug related to freeing of events when using pipe mode
  from 'record' to 'inject' (Jiri Olsa)

- Some prep work to facilitate per-cpu threads to write
  record data to per-cpu files (Jiri Olsa)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2018-09-25 11:20:01 +02:00
commit 9835bf7ff8
30 changed files with 519 additions and 230 deletions

View File

@ -459,10 +459,20 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
if (size || handle->aux_flags) {
/*
* Only send RECORD_AUX if we have something useful to communicate
*
* Note: the OVERWRITE records by themselves are not considered
* useful, as they don't communicate any *new* information,
* aside from the short-lived offset, that becomes history at
* the next event sched-in and therefore isn't useful.
* The userspace that needs to copy out AUX data in overwrite
* mode should know to use user_page::aux_head for the actual
* offset. So, from now on we don't output AUX records that
* have *only* OVERWRITE flag set.
*/
perf_event_aux_event(handle->event, aux_head, size,
handle->aux_flags);
if (handle->aux_flags & ~(u64)PERF_AUX_FLAG_OVERWRITE)
perf_event_aux_event(handle->event, aux_head, size,
handle->aux_flags);
}
rb->user_page->aux_head = rb->aux_head;

View File

@ -52,4 +52,11 @@ static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr);
}
static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
{
if (IS_ERR(ptr))
return PTR_ERR(ptr);
else
return 0;
}
#endif /* _LINUX_ERR_H */

View File

@ -283,12 +283,11 @@ out_put:
return ret;
}
static int process_feature_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int process_feature_event(struct perf_session *session,
union perf_event *event)
{
if (event->feat.feat_id < HEADER_LAST_FEATURE)
return perf_event__process_feature(tool, event, session);
return perf_event__process_feature(session, event);
return 0;
}

View File

@ -86,12 +86,10 @@ static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused,
}
#endif
static int perf_event__repipe_op2_synth(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session
__maybe_unused)
static int perf_event__repipe_op2_synth(struct perf_session *session,
union perf_event *event)
{
return perf_event__repipe_synth(tool, event);
return perf_event__repipe_synth(session->tool, event);
}
static int perf_event__repipe_attr(struct perf_tool *tool,
@ -133,10 +131,10 @@ static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
return 0;
}
static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static s64 perf_event__repipe_auxtrace(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_inject *inject = container_of(tool, struct perf_inject,
tool);
int ret;
@ -174,9 +172,8 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
#else
static s64
perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
perf_event__repipe_auxtrace(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
pr_err("AUX area tracing not supported\n");
return -EINVAL;
@ -362,26 +359,24 @@ static int perf_event__repipe_exit(struct perf_tool *tool,
return err;
}
static int perf_event__repipe_tracing_data(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int perf_event__repipe_tracing_data(struct perf_session *session,
union perf_event *event)
{
int err;
perf_event__repipe_synth(tool, event);
err = perf_event__process_tracing_data(tool, event, session);
perf_event__repipe_synth(session->tool, event);
err = perf_event__process_tracing_data(session, event);
return err;
}
static int perf_event__repipe_id_index(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int perf_event__repipe_id_index(struct perf_session *session,
union perf_event *event)
{
int err;
perf_event__repipe_synth(tool, event);
err = perf_event__process_id_index(tool, event, session);
perf_event__repipe_synth(session->tool, event);
err = perf_event__process_id_index(session, event);
return err;
}

View File

@ -106,9 +106,12 @@ static bool switch_output_time(struct record *rec)
trigger_is_ready(&switch_output_trigger);
}
static int record__write(struct record *rec, void *bf, size_t size)
static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
void *bf, size_t size)
{
if (perf_data__write(rec->session->data, bf, size) < 0) {
struct perf_data_file *file = &rec->session->data->file;
if (perf_data_file__write(file, bf, size) < 0) {
pr_err("failed to write perf data, error: %m\n");
return -1;
}
@ -127,15 +130,15 @@ static int process_synthesized_event(struct perf_tool *tool,
struct machine *machine __maybe_unused)
{
struct record *rec = container_of(tool, struct record, tool);
return record__write(rec, event, event->header.size);
return record__write(rec, NULL, event, event->header.size);
}
static int record__pushfn(void *to, void *bf, size_t size)
static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size)
{
struct record *rec = to;
rec->samples++;
return record__write(rec, bf, size);
return record__write(rec, map, bf, size);
}
static volatile int done;
@ -170,6 +173,7 @@ static void record__sig_exit(void)
#ifdef HAVE_AUXTRACE_SUPPORT
static int record__process_auxtrace(struct perf_tool *tool,
struct perf_mmap *map,
union perf_event *event, void *data1,
size_t len1, void *data2, size_t len2)
{
@ -197,21 +201,21 @@ static int record__process_auxtrace(struct perf_tool *tool,
if (padding)
padding = 8 - padding;
record__write(rec, event, event->header.size);
record__write(rec, data1, len1);
record__write(rec, map, event, event->header.size);
record__write(rec, map, data1, len1);
if (len2)
record__write(rec, data2, len2);
record__write(rec, &pad, padding);
record__write(rec, map, data2, len2);
record__write(rec, map, &pad, padding);
return 0;
}
static int record__auxtrace_mmap_read(struct record *rec,
struct auxtrace_mmap *mm)
struct perf_mmap *map)
{
int ret;
ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
record__process_auxtrace);
if (ret < 0)
return ret;
@ -223,11 +227,11 @@ static int record__auxtrace_mmap_read(struct record *rec,
}
static int record__auxtrace_mmap_read_snapshot(struct record *rec,
struct auxtrace_mmap *mm)
struct perf_mmap *map)
{
int ret;
ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
record__process_auxtrace,
rec->opts.auxtrace_snapshot_size);
if (ret < 0)
@ -245,13 +249,12 @@ static int record__auxtrace_read_snapshot_all(struct record *rec)
int rc = 0;
for (i = 0; i < rec->evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm =
&rec->evlist->mmap[i].auxtrace_mmap;
struct perf_mmap *map = &rec->evlist->mmap[i];
if (!mm->base)
if (!map->auxtrace_mmap.base)
continue;
if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
rc = -1;
goto out;
}
@ -295,7 +298,7 @@ static int record__auxtrace_init(struct record *rec)
static inline
int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
struct auxtrace_mmap *mm __maybe_unused)
struct perf_mmap *map __maybe_unused)
{
return 0;
}
@ -529,17 +532,17 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
return 0;
for (i = 0; i < evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
struct perf_mmap *map = &maps[i];
if (maps[i].base) {
if (perf_mmap__push(&maps[i], rec, record__pushfn) != 0) {
if (map->base) {
if (perf_mmap__push(map, rec, record__pushfn) != 0) {
rc = -1;
goto out;
}
}
if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
record__auxtrace_mmap_read(rec, mm) != 0) {
if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
record__auxtrace_mmap_read(rec, map) != 0) {
rc = -1;
goto out;
}
@ -550,7 +553,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
* at least one event.
*/
if (bytes_written != rec->bytes_written)
rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
if (overwrite)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);

View File

@ -201,14 +201,13 @@ static void setup_forced_leader(struct report *report,
perf_evlist__force_leader(evlist);
}
static int process_feature_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
static int process_feature_event(struct perf_session *session,
union perf_event *event)
{
struct report *rep = container_of(tool, struct report, tool);
struct report *rep = container_of(session->tool, struct report, tool);
if (event->feat.feat_id < HEADER_LAST_FEATURE)
return perf_event__process_feature(tool, event, session);
return perf_event__process_feature(session, event);
if (event->feat.feat_id != HEADER_LAST_FEATURE) {
pr_err("failed: wrong feature ID: %" PRIu64 "\n",

View File

@ -2965,9 +2965,8 @@ static void script__setup_sample_type(struct perf_script *script)
}
}
static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
static int process_stat_round_event(struct perf_session *session,
union perf_event *event)
{
struct stat_round_event *round = &event->stat_round;
struct perf_evsel *counter;
@ -2981,9 +2980,8 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
return 0;
}
static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session __maybe_unused)
static int process_stat_config_event(struct perf_session *session __maybe_unused,
union perf_event *event)
{
perf_event__read_stat_config(&stat_config, &event->stat_config);
return 0;
@ -3009,10 +3007,10 @@ static int set_maps(struct perf_script *script)
}
static
int process_thread_map_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
int process_thread_map_event(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_script *script = container_of(tool, struct perf_script, tool);
if (script->threads) {
@ -3028,10 +3026,10 @@ int process_thread_map_event(struct perf_tool *tool,
}
static
int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session __maybe_unused)
int process_cpu_map_event(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_script *script = container_of(tool, struct perf_script, tool);
if (script->cpus) {
@ -3046,21 +3044,21 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
return set_maps(script);
}
static int process_feature_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int process_feature_event(struct perf_session *session,
union perf_event *event)
{
if (event->feat.feat_id < HEADER_LAST_FEATURE)
return perf_event__process_feature(tool, event, session);
return perf_event__process_feature(session, event);
return 0;
}
#ifdef HAVE_AUXTRACE_SUPPORT
static int perf_script__process_auxtrace_info(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int perf_script__process_auxtrace_info(struct perf_session *session,
union perf_event *event)
{
int ret = perf_event__process_auxtrace_info(tool, event, session);
struct perf_tool *tool = session->tool;
int ret = perf_event__process_auxtrace_info(session, event);
if (ret == 0) {
struct perf_script *script = container_of(tool, struct perf_script, tool);

View File

@ -1354,9 +1354,8 @@ static int __cmd_record(int argc, const char **argv)
return argc;
}
static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
static int process_stat_round_event(struct perf_session *session,
union perf_event *event)
{
struct stat_round_event *stat_round = &event->stat_round;
struct perf_evsel *counter;
@ -1381,10 +1380,10 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
}
static
int process_stat_config_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
int process_stat_config_event(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_stat *st = container_of(tool, struct perf_stat, tool);
perf_event__read_stat_config(&stat_config, &event->stat_config);
@ -1424,10 +1423,10 @@ static int set_maps(struct perf_stat *st)
}
static
int process_thread_map_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
int process_thread_map_event(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_stat *st = container_of(tool, struct perf_stat, tool);
if (st->threads) {
@ -1443,10 +1442,10 @@ int process_thread_map_event(struct perf_tool *tool,
}
static
int process_cpu_map_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
int process_cpu_map_event(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_stat *st = container_of(tool, struct perf_stat, tool);
struct cpu_map *cpus;

View File

@ -21,6 +21,7 @@ perf-y += python-use.o
perf-y += bp_signal.o
perf-y += bp_signal_overflow.o
perf-y += bp_account.o
perf-y += wp.o
perf-y += task-exit.o
perf-y += sw-clock.o
perf-y += mmap-thread-lookup.o

View File

@ -120,6 +120,15 @@ static struct test generic_tests[] = {
.func = test__bp_accounting,
.is_supported = test__bp_signal_is_supported,
},
{
.desc = "Watchpoint",
.func = test__wp,
.subtest = {
.skip_if_fail = false,
.get_nr = test__wp_subtest_get_nr,
.get_desc = test__wp_subtest_get_desc,
},
},
{
.desc = "Number of exit events of a simple workload",
.func = test__task_exit,

View File

@ -59,6 +59,9 @@ int test__python_use(struct test *test, int subtest);
int test__bp_signal(struct test *test, int subtest);
int test__bp_signal_overflow(struct test *test, int subtest);
int test__bp_accounting(struct test *test, int subtest);
int test__wp(struct test *test, int subtest);
const char *test__wp_subtest_get_desc(int subtest);
int test__wp_subtest_get_nr(void);
int test__task_exit(struct test *test, int subtest);
int test__mem(struct test *test, int subtest);
int test__sw_clock_freq(struct test *test, int subtest);

229
tools/perf/tests/wp.c Normal file
View File

@ -0,0 +1,229 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/hw_breakpoint.h>
#include "tests.h"
#include "debug.h"
#include "cloexec.h"
#define WP_TEST_ASSERT_VAL(fd, text, val) \
do { \
long long count; \
wp_read(fd, &count, sizeof(long long)); \
TEST_ASSERT_VAL(text, count == val); \
} while (0)
volatile u64 data1;
volatile u8 data2[3];
static int wp_read(int fd, long long *count, int size)
{
int ret = read(fd, count, size);
if (ret != size) {
pr_debug("failed to read: %d\n", ret);
return -1;
}
return 0;
}
static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type,
void *wp_addr, unsigned long wp_len)
{
memset(attr, 0, sizeof(struct perf_event_attr));
attr->type = PERF_TYPE_BREAKPOINT;
attr->size = sizeof(struct perf_event_attr);
attr->config = 0;
attr->bp_type = wp_type;
attr->bp_addr = (unsigned long)wp_addr;
attr->bp_len = wp_len;
attr->sample_period = 1;
attr->sample_type = PERF_SAMPLE_IP;
attr->exclude_kernel = 1;
attr->exclude_hv = 1;
}
static int __event(int wp_type, void *wp_addr, unsigned long wp_len)
{
int fd;
struct perf_event_attr attr;
get__perf_event_attr(&attr, wp_type, wp_addr, wp_len);
fd = sys_perf_event_open(&attr, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0)
pr_debug("failed opening event %x\n", attr.bp_type);
return fd;
}
static int wp_ro_test(void)
{
int fd;
unsigned long tmp, tmp1 = rand();
fd = __event(HW_BREAKPOINT_R, (void *)&data1, sizeof(data1));
if (fd < 0)
return -1;
tmp = data1;
WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
data1 = tmp1 + tmp;
WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
close(fd);
return 0;
}
static int wp_wo_test(void)
{
int fd;
unsigned long tmp, tmp1 = rand();
fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
if (fd < 0)
return -1;
tmp = data1;
WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 0);
data1 = tmp1 + tmp;
WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 1);
close(fd);
return 0;
}
static int wp_rw_test(void)
{
int fd;
unsigned long tmp, tmp1 = rand();
fd = __event(HW_BREAKPOINT_R | HW_BREAKPOINT_W, (void *)&data1,
sizeof(data1));
if (fd < 0)
return -1;
tmp = data1;
WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 1);
data1 = tmp1 + tmp;
WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 2);
close(fd);
return 0;
}
static int wp_modify_test(void)
{
int fd, ret;
unsigned long tmp = rand();
struct perf_event_attr new_attr;
fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
if (fd < 0)
return -1;
data1 = tmp;
WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
/* Modify watchpoint with disabled = 1 */
get__perf_event_attr(&new_attr, HW_BREAKPOINT_W, (void *)&data2[0],
sizeof(u8) * 2);
new_attr.disabled = 1;
ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr);
if (ret < 0) {
pr_debug("ioctl(PERF_EVENT_IOC_MODIFY_ATTRIBUTES) failed\n");
close(fd);
return ret;
}
data2[1] = tmp; /* Not Counted */
WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
/* Enable the event */
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
if (ret < 0) {
pr_debug("Failed to enable event\n");
close(fd);
return ret;
}
data2[1] = tmp; /* Counted */
WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
data2[2] = tmp; /* Not Counted */
WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
close(fd);
return 0;
}
static bool wp_ro_supported(void)
{
#if defined (__x86_64__) || defined (__i386__)
return false;
#else
return true;
#endif
}
static void wp_ro_skip_msg(void)
{
#if defined (__x86_64__) || defined (__i386__)
pr_debug("Hardware does not support read only watchpoints.\n");
#endif
}
static struct {
const char *desc;
int (*target_func)(void);
bool (*is_supported)(void);
void (*skip_msg)(void);
} wp_testcase_table[] = {
{
.desc = "Read Only Watchpoint",
.target_func = &wp_ro_test,
.is_supported = &wp_ro_supported,
.skip_msg = &wp_ro_skip_msg,
},
{
.desc = "Write Only Watchpoint",
.target_func = &wp_wo_test,
},
{
.desc = "Read / Write Watchpoint",
.target_func = &wp_rw_test,
},
{
.desc = "Modify Watchpoint",
.target_func = &wp_modify_test,
},
};
int test__wp_subtest_get_nr(void)
{
return (int)ARRAY_SIZE(wp_testcase_table);
}
const char *test__wp_subtest_get_desc(int i)
{
if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table))
return NULL;
return wp_testcase_table[i].desc;
}
int test__wp(struct test *test __maybe_unused, int i)
{
if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table))
return TEST_FAIL;
if (wp_testcase_table[i].is_supported &&
!wp_testcase_table[i].is_supported()) {
wp_testcase_table[i].skip_msg();
return TEST_SKIP;
}
return !wp_testcase_table[i].target_func() ? TEST_OK : TEST_FAIL;
}

View File

@ -906,9 +906,8 @@ out_free:
return err;
}
int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_auxtrace_info(struct perf_session *session,
union perf_event *event)
{
enum auxtrace_type type = event->auxtrace_info.type;
@ -932,9 +931,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
}
}
s64 perf_event__process_auxtrace(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
s64 perf_event__process_auxtrace(struct perf_session *session,
union perf_event *event)
{
s64 err;
@ -950,7 +948,7 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool,
if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE)
return -EINVAL;
err = session->auxtrace->process_auxtrace_event(session, event, tool);
err = session->auxtrace->process_auxtrace_event(session, event, session->tool);
if (err < 0)
return err;
@ -1185,9 +1183,8 @@ void events_stats__auxtrace_error_warn(const struct events_stats *stats)
}
}
int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_auxtrace_error(struct perf_session *session,
union perf_event *event)
{
if (auxtrace__dont_decode(session))
return 0;
@ -1196,11 +1193,12 @@ int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
return 0;
}
static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
static int __auxtrace_mmap__read(struct perf_mmap *map,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
bool snapshot, size_t snapshot_size)
{
struct auxtrace_mmap *mm = &map->auxtrace_mmap;
u64 head, old = mm->prev, offset, ref;
unsigned char *data = mm->base;
size_t size, head_off, old_off, len1, len2, padding;
@ -1287,7 +1285,7 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
ev.auxtrace.tid = mm->tid;
ev.auxtrace.cpu = mm->cpu;
if (fn(tool, &ev, data1, len1, data2, len2))
if (fn(tool, map, &ev, data1, len1, data2, len2))
return -1;
mm->prev = head;
@ -1306,18 +1304,18 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
return 1;
}
int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn)
{
return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0);
return __auxtrace_mmap__read(map, itr, tool, fn, false, 0);
}
int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
int auxtrace_mmap__read_snapshot(struct perf_mmap *map,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
size_t snapshot_size)
{
return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size);
return __auxtrace_mmap__read(map, itr, tool, fn, true, snapshot_size);
}
/**

View File

@ -33,6 +33,7 @@ union perf_event;
struct perf_session;
struct perf_evlist;
struct perf_tool;
struct perf_mmap;
struct option;
struct record_opts;
struct auxtrace_info_event;
@ -434,13 +435,14 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
bool per_cpu);
typedef int (*process_auxtrace_t)(struct perf_tool *tool,
struct perf_mmap *map,
union perf_event *event, void *data1,
size_t len1, void *data2, size_t len2);
int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn);
int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
int auxtrace_mmap__read_snapshot(struct perf_mmap *map,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
size_t snapshot_size);
@ -517,15 +519,12 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
struct perf_tool *tool,
struct perf_session *session,
perf_event__handler_t process);
int perf_event__process_auxtrace_info(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
s64 perf_event__process_auxtrace(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_auxtrace_error(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_auxtrace_info(struct perf_session *session,
union perf_event *event);
s64 perf_event__process_auxtrace(struct perf_session *session,
union perf_event *event);
int perf_event__process_auxtrace_error(struct perf_session *session,
union perf_event *event);
int itrace_parse_synth_opts(const struct option *opt, const char *str,
int unset);
void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts);

View File

@ -1615,7 +1615,7 @@ struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const cha
int bpf__setup_stdout(struct perf_evlist *evlist)
{
struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
return IS_ERR(evsel) ? PTR_ERR(evsel) : 0;
return PTR_ERR_OR_ZERO(evsel);
}
#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)

View File

@ -1578,7 +1578,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
{
struct perf_session *session;
struct perf_data data = {
.file.path = input,
.file = { .path = input, .fd = -1 },
.mode = PERF_DATA_MODE_READ,
.force = opts->force,
};

View File

@ -3448,10 +3448,10 @@ int perf_event__synthesize_features(struct perf_tool *tool,
return ret;
}
int perf_event__process_feature(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
int perf_event__process_feature(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct feat_fd ff = { .fd = 0 };
struct feature_event *fe = (struct feature_event *)event;
int type = fe->header.type;
@ -3856,9 +3856,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
return aligned_size;
}
int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_tracing_data(struct perf_session *session,
union perf_event *event)
{
ssize_t size_read, padding, size = event->tracing_data.size;
int fd = perf_data__fd(session->data);
@ -3924,9 +3923,8 @@ int perf_event__synthesize_build_id(struct perf_tool *tool,
return err;
}
int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_build_id(struct perf_session *session,
union perf_event *event)
{
__event_process_build_id(&event->build_id,
event->build_id.filename,

View File

@ -116,9 +116,8 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool,
perf_event__handler_t process,
bool is_pipe);
int perf_event__process_feature(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_feature(struct perf_session *session,
union perf_event *event);
int perf_event__synthesize_attr(struct perf_tool *tool,
struct perf_event_attr *attr, u32 ids, u64 *id,
@ -148,17 +147,15 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp);
int perf_event__synthesize_tracing_data(struct perf_tool *tool,
int fd, struct perf_evlist *evlist,
perf_event__handler_t process);
int perf_event__process_tracing_data(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_tracing_data(struct perf_session *session,
union perf_event *event);
int perf_event__synthesize_build_id(struct perf_tool *tool,
struct dso *pos, u16 misc,
perf_event__handler_t process,
struct machine *machine);
int perf_event__process_build_id(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_build_id(struct perf_session *session,
union perf_event *event);
bool is_perf_magic(u64 magic);
#define NAME_ALIGN 64

View File

@ -281,7 +281,7 @@ int perf_mmap__read_init(struct perf_mmap *map)
}
int perf_mmap__push(struct perf_mmap *md, void *to,
int push(void *to, void *buf, size_t size))
int push(struct perf_mmap *map, void *to, void *buf, size_t size))
{
u64 head = perf_mmap__read_head(md);
unsigned char *data = md->base + page_size;
@ -300,7 +300,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to,
size = md->mask + 1 - (md->start & md->mask);
md->start += size;
if (push(to, buf, size) < 0) {
if (push(md, to, buf, size) < 0) {
rc = -1;
goto out;
}
@ -310,7 +310,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to,
size = md->end - md->start;
md->start += size;
if (push(to, buf, size) < 0) {
if (push(md, to, buf, size) < 0) {
rc = -1;
goto out;
}

View File

@ -93,7 +93,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
union perf_event *perf_mmap__read_event(struct perf_mmap *map);
int perf_mmap__push(struct perf_mmap *md, void *to,
int push(void *to, void *buf, size_t size));
int push(struct perf_mmap *map, void *to, void *buf, size_t size));
size_t perf_mmap__mmap_len(struct perf_mmap *map);

View File

@ -80,14 +80,20 @@ static union perf_event *dup_event(struct ordered_events *oe,
return oe->copy_on_queue ? __dup_event(oe, event) : event;
}
static void free_dup_event(struct ordered_events *oe, union perf_event *event)
static void __free_dup_event(struct ordered_events *oe, union perf_event *event)
{
if (event && oe->copy_on_queue) {
if (event) {
oe->cur_alloc_size -= event->header.size;
free(event);
}
}
static void free_dup_event(struct ordered_events *oe, union perf_event *event)
{
if (oe->copy_on_queue)
__free_dup_event(oe, event);
}
#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
static struct ordered_event *alloc_event(struct ordered_events *oe,
union perf_event *event)
@ -95,21 +101,49 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
struct list_head *cache = &oe->cache;
struct ordered_event *new = NULL;
union perf_event *new_event;
size_t size;
new_event = dup_event(oe, event);
if (!new_event)
return NULL;
/*
* We maintain the following scheme of buffers for ordered
* event allocation:
*
* to_free list -> buffer1 (64K)
* buffer2 (64K)
* ...
*
* Each buffer keeps an array of ordered events objects:
* buffer -> event[0]
* event[1]
* ...
*
* Each allocated ordered event is linked to one of
* following lists:
* - time ordered list 'events'
* - list of currently removed events 'cache'
*
* Allocation of the ordered event uses the following order
* to get the memory:
* - use recently removed object from 'cache' list
* - use available object in current allocation buffer
* - allocate new buffer if the current buffer is full
*
* Removal of ordered event object moves it from events to
* the cache list.
*/
size = sizeof(*oe->buffer) + MAX_SAMPLE_BUFFER * sizeof(*new);
if (!list_empty(cache)) {
new = list_entry(cache->next, struct ordered_event, list);
list_del(&new->list);
} else if (oe->buffer) {
new = oe->buffer + oe->buffer_idx;
new = &oe->buffer->event[oe->buffer_idx];
if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
oe->buffer = NULL;
} else if (oe->cur_alloc_size < oe->max_alloc_size) {
size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
} else if ((oe->cur_alloc_size + size) < oe->max_alloc_size) {
oe->buffer = malloc(size);
if (!oe->buffer) {
free_dup_event(oe, new_event);
@ -122,11 +156,11 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
oe->cur_alloc_size += size;
list_add(&oe->buffer->list, &oe->to_free);
/* First entry is abused to maintain the to_free list. */
oe->buffer_idx = 2;
new = oe->buffer + 1;
oe->buffer_idx = 1;
new = &oe->buffer->event[0];
} else {
pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
return NULL;
}
new->event = new_event;
@ -300,15 +334,38 @@ void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t d
oe->deliver = deliver;
}
static void
ordered_events_buffer__free(struct ordered_events_buffer *buffer,
unsigned int max, struct ordered_events *oe)
{
if (oe->copy_on_queue) {
unsigned int i;
for (i = 0; i < max; i++)
__free_dup_event(oe, buffer->event[i].event);
}
free(buffer);
}
void ordered_events__free(struct ordered_events *oe)
{
while (!list_empty(&oe->to_free)) {
struct ordered_event *event;
struct ordered_events_buffer *buffer, *tmp;
event = list_entry(oe->to_free.next, struct ordered_event, list);
list_del(&event->list);
free_dup_event(oe, event->event);
free(event);
if (list_empty(&oe->to_free))
return;
/*
* Current buffer might not have all the events allocated
* yet, we need to free only allocated ones ...
*/
list_del(&oe->buffer->list);
ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
/* ... and continue with the rest */
list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
list_del(&buffer->list);
ordered_events_buffer__free(buffer, MAX_SAMPLE_BUFFER, oe);
}
}

View File

@ -25,23 +25,28 @@ struct ordered_events;
typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
struct ordered_event *event);
struct ordered_events_buffer {
struct list_head list;
struct ordered_event event[0];
};
struct ordered_events {
u64 last_flush;
u64 next_flush;
u64 max_timestamp;
u64 max_alloc_size;
u64 cur_alloc_size;
struct list_head events;
struct list_head cache;
struct list_head to_free;
struct ordered_event *buffer;
struct ordered_event *last;
ordered_events__deliver_t deliver;
int buffer_idx;
unsigned int nr_events;
enum oe_flush last_flush_type;
u32 nr_unordered_events;
bool copy_on_queue;
u64 last_flush;
u64 next_flush;
u64 max_timestamp;
u64 max_alloc_size;
u64 cur_alloc_size;
struct list_head events;
struct list_head cache;
struct list_head to_free;
struct ordered_events_buffer *buffer;
struct ordered_event *last;
ordered_events__deliver_t deliver;
int buffer_idx;
unsigned int nr_events;
enum oe_flush last_flush_type;
u32 nr_unordered_events;
bool copy_on_queue;
};
int ordered_events__queue(struct ordered_events *oe, union perf_event *event,

View File

@ -199,12 +199,10 @@ void perf_session__delete(struct perf_session *session)
free(session);
}
static int process_event_synth_tracing_data_stub(struct perf_tool *tool
static int process_event_synth_tracing_data_stub(struct perf_session *session
__maybe_unused,
union perf_event *event
__maybe_unused,
struct perf_session *session
__maybe_unused)
__maybe_unused)
{
dump_printf(": unhandled!\n");
return 0;
@ -277,10 +275,8 @@ static int skipn(int fd, off_t n)
return 0;
}
static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session
__maybe_unused)
static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused,
union perf_event *event)
{
dump_printf(": unhandled!\n");
if (perf_data__is_pipe(session->data))
@ -288,9 +284,8 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
return event->auxtrace.size;
}
static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
static int process_event_op2_stub(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
dump_printf(": unhandled!\n");
return 0;
@ -298,9 +293,8 @@ static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
static
int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
int process_event_thread_map_stub(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
if (dump_trace)
perf_event__fprintf_thread_map(event, stdout);
@ -310,9 +304,8 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
}
static
int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
int process_event_cpu_map_stub(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
if (dump_trace)
perf_event__fprintf_cpu_map(event, stdout);
@ -322,9 +315,8 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
}
static
int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
int process_event_stat_config_stub(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
if (dump_trace)
perf_event__fprintf_stat_config(event, stdout);
@ -333,10 +325,8 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
return 0;
}
static int process_stat_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *perf_session
__maybe_unused)
static int process_stat_stub(struct perf_session *perf_session __maybe_unused,
union perf_event *event)
{
if (dump_trace)
perf_event__fprintf_stat(event, stdout);
@ -345,10 +335,8 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
return 0;
}
static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *perf_session
__maybe_unused)
static int process_stat_round_stub(struct perf_session *perf_session __maybe_unused,
union perf_event *event)
{
if (dump_trace)
perf_event__fprintf_stat_round(event, stdout);
@ -1374,37 +1362,37 @@ static s64 perf_session__process_user_event(struct perf_session *session,
case PERF_RECORD_HEADER_TRACING_DATA:
/* setup for reading amidst mmap */
lseek(fd, file_offset, SEEK_SET);
return tool->tracing_data(tool, event, session);
return tool->tracing_data(session, event);
case PERF_RECORD_HEADER_BUILD_ID:
return tool->build_id(tool, event, session);
return tool->build_id(session, event);
case PERF_RECORD_FINISHED_ROUND:
return tool->finished_round(tool, event, oe);
case PERF_RECORD_ID_INDEX:
return tool->id_index(tool, event, session);
return tool->id_index(session, event);
case PERF_RECORD_AUXTRACE_INFO:
return tool->auxtrace_info(tool, event, session);
return tool->auxtrace_info(session, event);
case PERF_RECORD_AUXTRACE:
/* setup for reading amidst mmap */
lseek(fd, file_offset + event->header.size, SEEK_SET);
return tool->auxtrace(tool, event, session);
return tool->auxtrace(session, event);
case PERF_RECORD_AUXTRACE_ERROR:
perf_session__auxtrace_error_inc(session, event);
return tool->auxtrace_error(tool, event, session);
return tool->auxtrace_error(session, event);
case PERF_RECORD_THREAD_MAP:
return tool->thread_map(tool, event, session);
return tool->thread_map(session, event);
case PERF_RECORD_CPU_MAP:
return tool->cpu_map(tool, event, session);
return tool->cpu_map(session, event);
case PERF_RECORD_STAT_CONFIG:
return tool->stat_config(tool, event, session);
return tool->stat_config(session, event);
case PERF_RECORD_STAT:
return tool->stat(tool, event, session);
return tool->stat(session, event);
case PERF_RECORD_STAT_ROUND:
return tool->stat_round(tool, event, session);
return tool->stat_round(session, event);
case PERF_RECORD_TIME_CONV:
session->time_conv = event->time_conv;
return tool->time_conv(tool, event, session);
return tool->time_conv(session, event);
case PERF_RECORD_HEADER_FEATURE:
return tool->feature(tool, event, session);
return tool->feature(session, event);
default:
return -EINVAL;
}
@ -2133,9 +2121,8 @@ out:
return err;
}
int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_id_index(struct perf_session *session,
union perf_event *event)
{
struct perf_evlist *evlist = session->evlist;
struct id_index_event *ie = &event->id_index;

View File

@ -120,9 +120,8 @@ int perf_session__deliver_synth_event(struct perf_session *session,
union perf_event *event,
struct perf_sample *sample);
int perf_event__process_id_index(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_id_index(struct perf_session *session,
union perf_event *event);
int perf_event__synthesize_id_index(struct perf_tool *tool,
perf_event__handler_t process,

View File

@ -35,7 +35,7 @@ class install_lib(_install_lib):
cflags = getenv('CFLAGS', '').split()
# switch off several checks (need to be at the end of cflags list)
cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ]
cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-redundant-decls' ]
if cc != "clang":
cflags += ['-Wno-cast-function-type' ]

View File

@ -374,9 +374,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
return 0;
}
int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_stat_event(struct perf_session *session,
union perf_event *event)
{
struct perf_counts_values count;
struct stat_event *st = &event->stat;

View File

@ -199,9 +199,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
struct perf_tool;
union perf_event;
struct perf_session;
int perf_event__process_stat_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_stat_event(struct perf_session *session,
union perf_event *event);
size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);

View File

@ -26,15 +26,12 @@ typedef int (*event_attr_op)(struct perf_tool *tool,
union perf_event *event,
struct perf_evlist **pevlist);
typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
struct perf_session *session);
typedef int (*event_op2)(struct perf_session *session, union perf_event *event);
typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event);
typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
struct ordered_events *oe);
typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event,
struct perf_session *session);
enum show_feature_header {
SHOW_FEAT_NO_HEADER = 0,
SHOW_FEAT_HEADER,

View File

@ -221,7 +221,7 @@ out:
return err;
}
static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
{
void *ptr;
loff_t pgoff;

View File

@ -6,6 +6,7 @@
/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
#define _DEFAULT_SOURCE 1
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
@ -35,6 +36,7 @@ bool lsdir_no_dot_filter(const char *name, struct dirent *d);
int copyfile(const char *from, const char *to);
int copyfile_mode(const char *from, const char *to, mode_t mode);
int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size);
ssize_t readn(int fd, void *buf, size_t n);
ssize_t writen(int fd, const void *buf, size_t n);