@@ -283,18 +283,27 @@ 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 = BUFSIZ;
tsize_t size = 0;
char buf[BUFSIZ];
stsize_t r;
do {
- r = read(fd, buf, BUFSIZ);
+ if (max && rsize > max)
+ rsize = max;
+
+ r = read(fd, buf, rsize);
if (r > 0) {
size += r;
if (do_write_check(handle, buf, r))
return 0;
+ if (max) {
+ max -= r;
+ if (!max)
+ break;
+ }
}
} while (r > 0);
@@ -312,12 +321,62 @@ 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 PAGES_IN_CHUNK 10
+__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;
+ unsigned long long size;
+ int ret;
+
+ if (handle->compress) {
+ rsize = max;
+ ret = tracecmd_compress_copy_from(handle->compress, fd,
+ PAGES_IN_CHUNK * handle->page_size,
+ &rsize, &wsize);
+ if (ret < 0)
+ return 0;
+
+ size = rsize;
+ if (write_size)
+ *write_size = wsize;
+ } else {
+ size = copy_file_fd(handle, fd, max);
+ if (write_size)
+ *write_size = size;
+ }
+
+ 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.
@@ -513,7 +572,7 @@ static int read_header_files(struct tracecmd_output *handle, bool compress)
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);
@@ -539,7 +598,7 @@ static int read_header_files(struct tracecmd_output *handle, bool compress)
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);
@@ -2181,7 +2240,7 @@ __hidden int out_write_cpu_data(struct tracecmd_output *handle,
if (data[i].size) {
if (lseek64(data[i].fd, data[i].offset, SEEK_SET) == (off64_t)-1)
goto out_free;
- read_size = copy_file_fd(handle, data[i].fd);
+ read_size = copy_file_fd(handle, data[i].fd, data[i].size);
if (read_size != data_files[i].file_size) {
errno = EINVAL;
tracecmd_warning("did not match size of %lld to %lld",
The newly added helper functions read data from a file and compress it, before writing into the trace file. The trace data is compressed in chunks, which are page aligned. A new local define is introduced: PAGES_IN_CHUNK which can be used to tune how big a compression chunk is. Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> --- lib/trace-cmd/trace-output.c | 71 +++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 6 deletions(-)