[PATCH v6 36/45] trace-cmd library: Refactor the logic for writing CPU trace data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Refactored the internal library logic for writing trace CPU data in the
trace file. The existing logic copies trace data from a temporary file
into the trace file. In order to reuse the code, modify it to support
copying the trace data not only from temporary file, but from given fd
at given offset. These changes will be used in extending the
tracecmd_copy API.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@xxxxxxxxx>
---
 lib/trace-cmd/include/trace-cmd-local.h |  13 +++
 lib/trace-cmd/trace-output.c            | 142 +++++++++++++++++-------
 2 files changed, 114 insertions(+), 41 deletions(-)

diff --git a/lib/trace-cmd/include/trace-cmd-local.h b/lib/trace-cmd/include/trace-cmd-local.h
index 2e5682c0..970087c7 100644
--- a/lib/trace-cmd/include/trace-cmd-local.h
+++ b/lib/trace-cmd/include/trace-cmd-local.h
@@ -53,10 +53,23 @@ int in_uncompress_block(struct tracecmd_input *handle);
 
 void out_set_file_state(struct tracecmd_output *handle, int new_state);
 void out_save_options_offset(struct tracecmd_output *handle);
+unsigned long long out_copy_fd_compress(struct tracecmd_output *handle,
+					int fd, unsigned long long max,
+					unsigned long long *write_size);
+
 
 int write_buffers_description_v7(struct tracecmd_output *handle);
 int write_buffers_description_v6(struct tracecmd_output *handle);
 
 long long do_write_check(struct tracecmd_output *handle, const void *data, long long size);
 
+struct cpu_data_source {
+	int fd;
+	int size;
+	off64_t offset;
+};
+
+int out_write_cpu_data(struct tracecmd_output *handle, int cpus,
+		       struct cpu_data_source *data);
+
 #endif /* _TRACE_CMD_LOCAL_H */
diff --git a/lib/trace-cmd/trace-output.c b/lib/trace-cmd/trace-output.c
index 95ca483c..e5da4cdb 100644
--- a/lib/trace-cmd/trace-output.c
+++ b/lib/trace-cmd/trace-output.c
@@ -286,18 +286,26 @@ static unsigned long get_size(const char *file)
 	return size;
 }
 
-static tsize_t copy_file_fd(struct tracecmd_output *handle, int fd)
+static tsize_t copy_file_fd(struct tracecmd_output *handle, int fd, unsigned long long max)
 {
+	tsize_t rsize = 0;
 	tsize_t size = 0;
 	char buf[BUFSIZ];
 	stsize_t r;
 
 	do {
-		r = read(fd, buf, BUFSIZ);
+		if (max > 0 && (max - size) < BUFSIZ)
+			rsize = (max - size);
+		else
+			rsize = BUFSIZ;
+
+		r = read(fd, buf, rsize);
 		if (r > 0) {
 			size += r;
 			if (do_write_check(handle, buf, r))
 				return 0;
+			if (max > 0 && size >= max)
+				break;
 		}
 	} while (r > 0);
 
@@ -315,47 +323,61 @@ static tsize_t copy_file(struct tracecmd_output *handle,
 		tracecmd_warning("Can't read '%s'", file);
 		return 0;
 	}
-	size = copy_file_fd(handle, fd);
+	size = copy_file_fd(handle, fd, 0);
 	close(fd);
 
 	return size;
 }
 
 #define COMPRESS_CHUNK_SIZE (1*1024*1024)
-static tsize_t copy_file_compress(struct tracecmd_output *handle,
-				  const char *file, unsigned long long *write_size)
+__hidden unsigned long long out_copy_fd_compress(struct tracecmd_output *handle,
+						 int fd, unsigned long long max,
+						 unsigned long long *write_size)
 {
 	unsigned long long rsize = 0;
 	unsigned long long wsize = 0;
-	tsize_t size;
+	unsigned long long size;
 	int ret;
-	int fd;
-
-	fd = open(file, O_RDONLY);
-	if (fd < 0) {
-		tracecmd_warning("Can't read '%s'", file);
-		return 0;
-	}
 
 	if (handle->file_version >= 7) {
+		rsize = max;
 		ret = tracecmd_compress_copy_from(handle->compress, fd,
 						  COMPRESS_CHUNK_SIZE, &rsize, &wsize);
-		if (ret < 0) {
-			tracecmd_warning("Can't compress '%s'", file);
-			close(fd);
+		if (ret < 0)
 			return 0;
-		}
+
 		size = rsize;
-		*write_size = wsize;
+		if (write_size)
+			*write_size = wsize;
 	} else {
-		size = copy_file_fd(handle, fd);
-		*write_size = size;
+		size = copy_file_fd(handle, fd, max);
+		if (write_size)
+			*write_size = size;
 	}
 
-	close(fd);
 	return size;
 }
 
+static tsize_t copy_file_compress(struct tracecmd_output *handle,
+				  const char *file, unsigned long long *write_size)
+{
+	int ret;
+	int fd;
+
+	fd = open(file, O_RDONLY);
+	if (fd < 0) {
+		tracecmd_warning("Can't read '%s'", file);
+		return 0;
+	}
+
+	ret = out_copy_fd_compress(handle, fd, 0, write_size);
+	if (!ret)
+		tracecmd_warning("Can't compress '%s'", file);
+
+	close(fd);
+	return ret;
+}
+
 /*
  * Finds the path to the debugfs/tracing
  * Allocates the string and stores it.
@@ -467,7 +489,7 @@ static int read_header_files(struct tracecmd_output *handle)
 	endian8 = convert_endian_8(handle, size);
 	if (do_write_check(handle, &endian8, 8))
 		goto out_close;
-	check_size = copy_file_fd(handle, fd);
+	check_size = copy_file_fd(handle, fd, 0);
 	close(fd);
 	if (size != check_size) {
 		tracecmd_warning("wrong size for '%s' size=%lld read=%lld", path, size, check_size);
@@ -493,7 +515,7 @@ static int read_header_files(struct tracecmd_output *handle)
 	endian8 = convert_endian_8(handle, size);
 	if (do_write_check(handle, &endian8, 8))
 		goto out_close;
-	check_size = copy_file_fd(handle, fd);
+	check_size = copy_file_fd(handle, fd, 0);
 	close(fd);
 	if (size != check_size) {
 		tracecmd_warning("wrong size for '%s'", path);
@@ -1671,8 +1693,8 @@ struct data_file_write {
 	off64_t doffset;
 };
 
-int tracecmd_write_cpu_data(struct tracecmd_output *handle,
-			    int cpus, char * const *cpu_data_files)
+__hidden int out_write_cpu_data(struct tracecmd_output *handle,
+				int cpus, struct cpu_data_source *data)
 {
 	struct data_file_write *data_files = NULL;
 	off64_t offset;
@@ -1680,8 +1702,6 @@ int tracecmd_write_cpu_data(struct tracecmd_output *handle,
 	unsigned long long read_size;
 	unsigned long long write_size;
 	char *clock = NULL;
-	char *file;
-	struct stat st;
 	int ret;
 	int i;
 
@@ -1705,14 +1725,7 @@ int tracecmd_write_cpu_data(struct tracecmd_output *handle,
 
 	/* Write 0 for trace data offset and size and store offsets of these fields */
 	for (i = 0; i < cpus; i++) {
-		file = cpu_data_files[i];
-		ret = stat(file, &st);
-		if (ret < 0) {
-			tracecmd_warning("can not stat '%s'", file);
-			goto out_free;
-		}
-		data_files[i].file_size = st.st_size;
-
+		data_files[i].file_size = data[i].size;
 		endian8 = 0;
 		data_files[i].doffset = lseek64(handle->fd, 0, SEEK_CUR);
 		if (do_write_check(handle, &endian8, 8))
@@ -1736,13 +1749,19 @@ int tracecmd_write_cpu_data(struct tracecmd_output *handle,
 		if (!tracecmd_get_quiet(handle))
 			fprintf(stderr, "CPU%d data recorded at offset=0x%llx\n",
 				i, (unsigned long long) data_files[i].data_offset);
-
-		read_size = copy_file_compress(handle, cpu_data_files[i], &write_size);
-		if (read_size != data_files[i].file_size) {
-			errno = EINVAL;
-			tracecmd_warning("did not match size of %lld to %lld",
-					 read_size, data_files[i].file_size);
+		offset = lseek64(data[i].fd, data[i].offset, SEEK_SET);
+		if (offset == (off64_t)-1)
 			goto out_free;
+		if (data[i].size) {
+			read_size = out_copy_fd_compress(handle, data[i].fd, data[i].size, &write_size);
+			if (read_size != data_files[i].file_size) {
+				errno = EINVAL;
+				tracecmd_warning("did not match size of %lld to %lld",
+						 read_size, data_files[i].file_size);
+				goto out_free;
+			}
+		} else {
+			write_size = 0;
 		}
 		/* Write the real CPU data offset inthe file */
 		offset = lseek64(handle->fd, data_files[i].doffset, SEEK_SET);
@@ -1775,6 +1794,47 @@ int tracecmd_write_cpu_data(struct tracecmd_output *handle,
 	return -1;
 }
 
+int tracecmd_write_cpu_data(struct tracecmd_output *handle,
+			    int cpus, char * const *cpu_data_files)
+{
+	struct cpu_data_source *data;
+	struct stat st;
+	int ret;
+	int i;
+
+	data = calloc(cpus, sizeof(struct cpu_data_source));
+	if (!data)
+		return -1;
+	for (i = 0; i < cpus; i++)
+		data[i].fd = -1;
+	for (i = 0; i < cpus; i++) {
+		ret = stat(cpu_data_files[i], &st);
+		if (ret < 0) {
+			tracecmd_warning("can not stat '%s'", cpu_data_files[i]);
+			break;
+		}
+		data[i].fd = open(cpu_data_files[i], O_RDONLY);
+		if (data[i].fd < 0) {
+			tracecmd_warning("Can't read '%s'", data[i].fd);
+			break;
+		}
+
+		data[i].size = st.st_size;
+		data[i].offset = 0;
+	}
+
+	if (i < cpus)
+		ret = -1;
+	else
+		ret = out_write_cpu_data(handle, cpus, data);
+	for (i = 0; i < cpus; i++) {
+		if (data[i].fd >= 0)
+			close(data[i].fd);
+	}
+	free(data);
+	return ret;
+}
+
 int tracecmd_append_cpu_data(struct tracecmd_output *handle,
 			     int cpus, char * const *cpu_data_files)
 {
-- 
2.31.1




[Index of Archives]     [Linux USB Development]     [Linux USB Development]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux