server: convert iolog in place instead of copy allocating it

Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/client.c b/client.c
index c49e9a1..f7b050b 100644
--- a/client.c
+++ b/client.c
@@ -963,6 +963,7 @@
 	unsigned long total;
 	z_stream stream;
 	void *p;
+	int i;
 
 	stream.zalloc = Z_NULL;
 	stream.zfree = Z_NULL;
@@ -974,17 +975,20 @@
 		return NULL;
 
 	/*
-	 * Everything beyond the first entry is compressed.
+	 * Get header first, it's not compressed
 	 */
 	nr_samples = le32_to_cpu(pdu->nr_samples);
 
-	total = sizeof(*pdu) + nr_samples * sizeof(struct io_sample);
-	ret = malloc(total);
+	total = nr_samples * sizeof(struct io_sample);
+	ret = malloc(total + sizeof(*pdu));
 	ret->nr_samples = nr_samples;
-	p = (void *) ret + sizeof(pdu->nr_samples);
+	ret->log_type = le32_to_cpu(pdu->log_type);
+	strcpy((char *) ret->name, (char *) pdu->name);
 
-	stream.avail_in = cmd->pdu_len - sizeof(pdu->nr_samples);
-	stream.next_in = (void *) pdu + sizeof(pdu->nr_samples);
+	p = (void *) ret + sizeof(*pdu);
+
+	stream.avail_in = cmd->pdu_len - sizeof(*pdu);
+	stream.next_in = (void *) pdu + sizeof(*pdu);
 	while (stream.avail_in) {
 		unsigned int this_chunk = 65536;
 		unsigned int this_len;
@@ -998,6 +1002,8 @@
 		err = inflate(&stream, Z_NO_FLUSH);
 		if (err != Z_OK) {
 			log_err("fio: inflate error %d\n", err);
+			free(ret);
+			ret = NULL;
 			goto out;
 		}
 
@@ -1006,7 +1012,15 @@
 		total -= this_len;
 	}
 
-	ret->log_type = cpu_to_le32(ret->log_type);
+	for (i = 0; i < ret->nr_samples; i++) {
+		struct io_sample *s = &ret->samples[i];
+
+		s->time	= le64_to_cpu(s->time);
+		s->val	= le64_to_cpu(s->val);
+		s->ddir	= le32_to_cpu(s->ddir);
+		s->bs	= le32_to_cpu(s->bs);
+	}
+
 out:
 	inflateEnd(&stream);
 	return ret;
diff --git a/iolog.c b/iolog.c
index 88adbf7..7b212bb 100644
--- a/iolog.c
+++ b/iolog.c
@@ -536,10 +536,12 @@
 	snprintf(file_name, 200, "%s_%s.log", prefix, postfix);
 	p = basename(file_name);
 
-	if (td->client_type == FIO_CLIENT_TYPE_GUI)
+	if (td->client_type == FIO_CLIENT_TYPE_GUI) {
 		fio_send_iolog(td, log, p);
-
-	__finish_log(log, p);
+		free(log->log);
+		free(log);
+	} else
+		__finish_log(log, p);
 }
 
 void finish_log(struct thread_data *td, struct io_log *log, const char *name)
diff --git a/server.c b/server.c
index 4e1f39b..b57c8b2 100644
--- a/server.c
+++ b/server.c
@@ -853,27 +853,23 @@
 
 int fio_send_iolog(struct thread_data *td, struct io_log *log, const char *name)
 {
-	struct cmd_iolog_pdu *pdu;
+	struct cmd_iolog_pdu pdu;
 	struct fio_net_cmd cmd;
 	z_stream stream;
 	void *out_pdu;
-	size_t p_size;
 	int i;
 
-	p_size = sizeof(*pdu) + log->nr_samples * sizeof(struct io_sample);
-	pdu = malloc(p_size);
-
-	pdu->nr_samples = __cpu_to_le32(log->nr_samples);
-	pdu->log_type = cpu_to_le32(log->log_type);
-	strcpy((char *) pdu->name, name);
+	pdu.nr_samples = __cpu_to_le32(log->nr_samples);
+	pdu.log_type = cpu_to_le32(log->log_type);
+	strcpy((char *) pdu.name, name);
 
 	for (i = 0; i < log->nr_samples; i++) {
-		struct io_sample *s = &pdu->samples[i];
+		struct io_sample *s = &log->log[i];
 
-		s->time	= cpu_to_le64(log->log[i].time);
-		s->val	= cpu_to_le64(log->log[i].val);
-		s->ddir	= cpu_to_le32(log->log[i].ddir);
-		s->bs	= cpu_to_le32(log->log[i].bs);
+		s->time	= cpu_to_le64(s->time);
+		s->val	= cpu_to_le64(s->val);
+		s->ddir	= cpu_to_le32(s->ddir);
+		s->bs	= cpu_to_le32(s->bs);
 	}
 
 	/*
@@ -889,29 +885,27 @@
 
 	if (deflateInit(&stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
 		free(out_pdu);
-		free(pdu);
 		return 1;
 	}
 
 	/*
-	 * Don't compress the nr samples entry, we want to know on the
-	 * client side how much data to allocate before starting inflate.
+	 * Send header first, it's not compressed.
 	 */
-	__fio_init_net_cmd(&cmd, FIO_NET_CMD_IOLOG, sizeof(pdu->nr_samples), 0);
+	__fio_init_net_cmd(&cmd, FIO_NET_CMD_IOLOG, sizeof(pdu), 0);
 	cmd.flags = __cpu_to_le32(FIO_NET_CMD_F_MORE);
-	fio_net_cmd_crc_pdu(&cmd, pdu);
+	fio_net_cmd_crc_pdu(&cmd, &pdu);
 	fio_send_data(server_fd, &cmd, sizeof(cmd));
-	fio_send_data(server_fd, pdu, sizeof(pdu->nr_samples));
+	fio_send_data(server_fd, &pdu, sizeof(pdu));
 
-	stream.next_in = (void *) pdu + sizeof(pdu->nr_samples);
-	stream.avail_in = p_size - sizeof(pdu->nr_samples);
+	stream.next_in = (void *) log->log;
+	stream.avail_in = log->nr_samples * sizeof(struct io_sample);
 
 	do {
 		unsigned int this_len;
 
 		stream.avail_out = FIO_SERVER_MAX_FRAGMENT_PDU;
 		stream.next_out = out_pdu;
-		deflate(&stream, Z_FINISH);
+		assert(deflate(&stream, Z_FINISH) == Z_OK);
 
 		this_len = FIO_SERVER_MAX_FRAGMENT_PDU - stream.avail_out;
 
@@ -926,7 +920,6 @@
 		fio_send_data(server_fd, out_pdu, this_len);
 	} while (stream.avail_in);
 
-	free(pdu);
 	free(out_pdu);
 	deflateEnd(&stream);
 	return 0;