perf: Add pipe-specific header read/write and event processing code
This patch makes several changes to allow the perf event stream to be sent and received over a pipe: - adds pipe-specific versions of the header read/write code - adds pipe-specific version of the event processing code - adds a range of event types to be used for header or other pseudo events, above the range used by the kernel - checks the return value of event handlers, which they can use to skip over large events during event processing rather than actually reading them into event objects. - unifies the multiple do_read() functions and updates its users. Note that none of these changes affect the existing perf data file format or processing - this code only comes into play if perf output is sent to stdout (or is read from stdin). Signed-off-by: Tom Zanussi <tzanussi@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-2-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -427,6 +427,25 @@ out_free:
|
||||
return err;
|
||||
}
|
||||
|
||||
int perf_header__write_pipe(int fd)
|
||||
{
|
||||
struct perf_pipe_file_header f_header;
|
||||
int err;
|
||||
|
||||
f_header = (struct perf_pipe_file_header){
|
||||
.magic = PERF_MAGIC,
|
||||
.size = sizeof(f_header),
|
||||
};
|
||||
|
||||
err = do_write(fd, &f_header, sizeof(f_header));
|
||||
if (err < 0) {
|
||||
pr_debug("failed to write perf pipe header\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int perf_header__write(struct perf_header *self, int fd, bool at_exit)
|
||||
{
|
||||
struct perf_file_header f_header;
|
||||
@@ -518,25 +537,10 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_read(int fd, void *buf, size_t size)
|
||||
{
|
||||
while (size) {
|
||||
int ret = read(fd, buf, size);
|
||||
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
|
||||
size -= ret;
|
||||
buf += ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int perf_header__getbuffer64(struct perf_header *self,
|
||||
int fd, void *buf, size_t size)
|
||||
{
|
||||
if (do_read(fd, buf, size))
|
||||
if (do_read(fd, buf, size) <= 0)
|
||||
return -1;
|
||||
|
||||
if (self->needs_swap)
|
||||
@@ -592,7 +596,7 @@ int perf_file_header__read(struct perf_file_header *self,
|
||||
{
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
if (do_read(fd, self, sizeof(*self)) ||
|
||||
if (do_read(fd, self, sizeof(*self)) <= 0 ||
|
||||
memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
|
||||
return -1;
|
||||
|
||||
@@ -662,13 +666,51 @@ static int perf_file_section__process(struct perf_file_section *self,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int perf_header__read(struct perf_header *self, int fd)
|
||||
static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
|
||||
struct perf_header *ph, int fd)
|
||||
{
|
||||
if (do_read(fd, self, sizeof(*self)) <= 0 ||
|
||||
memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
|
||||
return -1;
|
||||
|
||||
if (self->size != sizeof(*self)) {
|
||||
u64 size = bswap_64(self->size);
|
||||
|
||||
if (size != sizeof(*self))
|
||||
return -1;
|
||||
|
||||
ph->needs_swap = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int perf_header__read_pipe(struct perf_session *session, int fd)
|
||||
{
|
||||
struct perf_header *self = &session->header;
|
||||
struct perf_pipe_file_header f_header;
|
||||
|
||||
if (perf_file_header__read_pipe(&f_header, self, fd) < 0) {
|
||||
pr_debug("incompatible file format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
session->fd = fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int perf_header__read(struct perf_session *session, int fd)
|
||||
{
|
||||
struct perf_header *self = &session->header;
|
||||
struct perf_file_header f_header;
|
||||
struct perf_file_attr f_attr;
|
||||
u64 f_id;
|
||||
int nr_attrs, nr_ids, i, j;
|
||||
|
||||
if (session->fd_pipe)
|
||||
return perf_header__read_pipe(session, fd);
|
||||
|
||||
if (perf_file_header__read(&f_header, self, fd) < 0) {
|
||||
pr_debug("incompatible file format\n");
|
||||
return -EINVAL;
|
||||
|
Reference in New Issue
Block a user