lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 10 Oct 2017 10:20:14 -0700
From:   kan.liang@...el.com
To:     acme@...nel.org, peterz@...radead.org, mingo@...hat.com,
        linux-kernel@...r.kernel.org
Cc:     jolsa@...nel.org, wangnan0@...wei.com, hekuang@...wei.com,
        namhyung@...nel.org, alexander.shishkin@...ux.intel.com,
        adrian.hunter@...el.com, ak@...ux.intel.com,
        Kan Liang <kan.liang@...el.com>
Subject: [PATCH 01/10] perf record: new interfaces to read ring buffer to file

From: Kan Liang <kan.liang@...el.com>

Factor out the mmap_read related codes into separate functions and move
them to evlist.c
struct perf_mmap_read is introduced to store the specific range of ring
buffer information.

The way to read specific range of ring buffer into file is as below,
  perf_mmap__read_init
  perf_mmap__read_to_file
  perf_mmap__consume

There is no functional change.

Signed-off-by: Kan Liang <kan.liang@...el.com>
---
 tools/perf/builtin-record.c | 111 ++++++++------------------------------------
 tools/perf/util/evlist.c    | 111 ++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.h    |  15 ++++++
 3 files changed, 146 insertions(+), 91 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 234fdf4..df555e9 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -105,6 +105,17 @@ static bool switch_output_time(struct record *rec)
 	       trigger_is_ready(&switch_output_trigger);
 }
 
+static void update_output_size(struct record *rec, size_t size)
+{
+	if (size == 0)
+		return;
+
+	rec->bytes_written += size;
+
+	if (switch_output_size(rec))
+		trigger_hit(&switch_output_trigger);
+}
+
 static int record__write(struct record *rec, void *bf, size_t size)
 {
 	if (perf_data_file__write(rec->session->file, bf, size) < 0) {
@@ -112,10 +123,7 @@ static int record__write(struct record *rec, void *bf, size_t size)
 		return -1;
 	}
 
-	rec->bytes_written += size;
-
-	if (switch_output_size(rec))
-		trigger_hit(&switch_output_trigger);
+	update_output_size(rec, size);
 
 	return 0;
 }
@@ -130,106 +138,27 @@ static int process_synthesized_event(struct perf_tool *tool,
 }
 
 static int
-backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
-{
-	struct perf_event_header *pheader;
-	u64 evt_head = head;
-	int size = mask + 1;
-
-	pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head);
-	pheader = (struct perf_event_header *)(buf + (head & mask));
-	*start = head;
-	while (true) {
-		if (evt_head - head >= (unsigned int)size) {
-			pr_debug("Finished reading backward ring buffer: rewind\n");
-			if (evt_head - head > (unsigned int)size)
-				evt_head -= pheader->size;
-			*end = evt_head;
-			return 0;
-		}
-
-		pheader = (struct perf_event_header *)(buf + (evt_head & mask));
-
-		if (pheader->size == 0) {
-			pr_debug("Finished reading backward ring buffer: get start\n");
-			*end = evt_head;
-			return 0;
-		}
-
-		evt_head += pheader->size;
-		pr_debug3("move evt_head: %"PRIx64"\n", evt_head);
-	}
-	WARN_ONCE(1, "Shouldn't get here\n");
-	return -1;
-}
-
-static int
-rb_find_range(void *data, int mask, u64 head, u64 old,
-	      u64 *start, u64 *end, bool backward)
-{
-	if (!backward) {
-		*start = old;
-		*end = head;
-		return 0;
-	}
-
-	return backward_rb_find_range(data, mask, head, start, end);
-}
-
-static int
 record__mmap_read(struct record *rec, struct perf_mmap *md,
 		  bool overwrite, bool backward)
 {
-	u64 head = perf_mmap__read_head(md);
-	u64 old = md->prev;
-	u64 end = head, start = old;
-	unsigned char *data = md->base + page_size;
-	unsigned long size;
-	void *buf;
-	int rc = 0;
+	struct perf_mmap_read read;
 
-	if (rb_find_range(data, md->mask, head,
-			  old, &start, &end, backward))
+	if (perf_mmap__read_init(md, &read, overwrite, backward))
 		return -1;
 
-	if (start == end)
+	if (read.start == read.end)
 		return 0;
 
 	rec->samples++;
 
-	size = end - start;
-	if (size > (unsigned long)(md->mask) + 1) {
-		WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
-
-		md->prev = head;
-		perf_mmap__consume(md, overwrite || backward);
-		return 0;
-	}
-
-	if ((start & md->mask) + size != (end & md->mask)) {
-		buf = &data[start & md->mask];
-		size = md->mask + 1 - (start & md->mask);
-		start += size;
-
-		if (record__write(rec, buf, size) < 0) {
-			rc = -1;
-			goto out;
-		}
-	}
+	if (perf_mmap__read_to_file(&read, rec->session->file) < 0)
+		return -1;
 
-	buf = &data[start & md->mask];
-	size = end - start;
-	start += size;
+	update_output_size(rec, read.size);
 
-	if (record__write(rec, buf, size) < 0) {
-		rc = -1;
-		goto out;
-	}
-
-	md->prev = head;
 	perf_mmap__consume(md, overwrite || backward);
-out:
-	return rc;
+
+	return 0;
 }
 
 static volatile int done;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6a0d7ff..33b8837 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -704,6 +704,117 @@ static int perf_evlist__resume(struct perf_evlist *evlist)
 	return perf_evlist__set_paused(evlist, false);
 }
 
+static int
+backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
+{
+	struct perf_event_header *pheader;
+	u64 evt_head = head;
+	int size = mask + 1;
+
+	pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head);
+	pheader = (struct perf_event_header *)(buf + (head & mask));
+	*start = head;
+	while (true) {
+		if (evt_head - head >= (unsigned int)size) {
+			pr_debug("Finished reading backward ring buffer: rewind\n");
+			if (evt_head - head > (unsigned int)size)
+				evt_head -= pheader->size;
+			*end = evt_head;
+			return 0;
+		}
+
+		pheader = (struct perf_event_header *)(buf + (evt_head & mask));
+
+		if (pheader->size == 0) {
+			pr_debug("Finished reading backward ring buffer: get start\n");
+			*end = evt_head;
+			return 0;
+		}
+
+		evt_head += pheader->size;
+		pr_debug3("move evt_head: %"PRIx64"\n", evt_head);
+	}
+	WARN_ONCE(1, "Shouldn't get here\n");
+	return -1;
+}
+
+static int
+rb_find_range(void *data, int mask, u64 head, u64 old,
+	      u64 *start, u64 *end, bool backward)
+{
+	if (!backward) {
+		*start = old;
+		*end = head;
+		return 0;
+	}
+
+	return backward_rb_find_range(data, mask, head, start, end);
+}
+
+/*
+ * Initialize struct perf_mmap_read
+ * Calculate the range of ring buffer to read
+ */
+int perf_mmap__read_init(struct perf_mmap *md, struct perf_mmap_read *read,
+			 bool overwrite, bool backward)
+{
+	unsigned char *data = md->base + page_size;
+
+	read->md = md;
+	read->head = perf_mmap__read_head(md);
+	read->overwrite = overwrite;
+	read->backward = backward;
+	read->size = 0;
+	return rb_find_range(data, md->mask, read->head, md->prev,
+			     &read->start, &read->end, backward);
+}
+
+/*
+ * Read the ring buffer in the range which specified in struct perf_mmap_read,
+ * and write to file.
+ * Used by perf record.
+ */
+int perf_mmap__read_to_file(struct perf_mmap_read *read,
+			    struct perf_data_file *file)
+{
+	struct perf_mmap *md = read->md;
+	unsigned char *data = md->base + page_size;
+	unsigned long size;
+	void *buf;
+
+	size = read->end - read->start;
+	if (size > (unsigned long)(md->mask) + 1) {
+		WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
+		read->size = 0;
+		goto out;
+	}
+
+	if ((read->start & md->mask) + size != (read->end & md->mask)) {
+		buf = &data[read->start & md->mask];
+		size = md->mask + 1 - (read->start & md->mask);
+		read->start += size;
+		read->size += size;
+
+		if (perf_data_file__write(file, buf, size) < 0) {
+			pr_err("failed to write %s, error: %m\n", file->path);
+			return -1;
+		}
+	}
+
+	buf = &data[read->start & md->mask];
+	size = read->end - read->start;
+	read->start += size;
+	read->size += size;
+
+	if (perf_data_file__write(file, buf, size) < 0) {
+		pr_err("failed to write %s, error: %m\n", file->path);
+		return -1;
+	}
+out:
+	md->prev = read->head;
+	return 0;
+}
+
 /* When check_messup is true, 'end' must points to a good entry */
 static union perf_event *
 perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index b1c14f1..1ce4857 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -39,6 +39,16 @@ struct perf_mmap {
 	char		 event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
 };
 
+struct perf_mmap_read {
+	struct perf_mmap	*md;
+	u64			head;
+	u64			start;
+	u64			end;
+	bool			overwrite;
+	bool			backward;
+	unsigned long		size;
+};
+
 static inline size_t
 perf_mmap__mmap_len(struct perf_mmap *map)
 {
@@ -193,6 +203,11 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
 
 void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
 
+int perf_mmap__read_init(struct perf_mmap *md, struct perf_mmap_read *read,
+			 bool overwrite, bool backward);
+int perf_mmap__read_to_file(struct perf_mmap_read *read,
+			    struct perf_data_file *file);
+
 int perf_evlist__open(struct perf_evlist *evlist);
 void perf_evlist__close(struct perf_evlist *evlist);
 
-- 
2.5.5

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ