#include <netdb.h>
#include <syslog.h>
#include <signal.h>
+#include <zlib.h>
#include "fio.h"
#include "server.h"
return cmdret;
}
-void fio_net_cmd_crc(struct fio_net_cmd *cmd)
+void fio_net_cmd_crc_pdu(struct fio_net_cmd *cmd, void *pdu)
{
uint32_t pdu_len;
cmd->cmd_crc16 = __cpu_to_le16(fio_crc16(cmd, FIO_NET_CMD_CRC_SZ));
pdu_len = le32_to_cpu(cmd->pdu_len);
- if (pdu_len)
- cmd->pdu_crc16 = __cpu_to_le16(fio_crc16(cmd->payload, pdu_len));
+ cmd->pdu_crc16 = __cpu_to_le16(fio_crc16(pdu, pdu_len));
+}
+
+void fio_net_cmd_crc(struct fio_net_cmd *cmd)
+{
+ fio_net_cmd_crc_pdu(cmd, cmd->payload);
}
int fio_net_send_cmd(int fd, uint16_t opcode, const void *buf, off_t size,
}
}
+int fio_send_iolog(struct thread_data *td, struct io_log *log, const char *name)
+{
+ 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);
+
+ for (i = 0; i < log->nr_samples; i++) {
+ struct io_sample *s = &pdu->samples[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);
+ }
+
+ /*
+ * Dirty - since the log is potentially huge, compress it into
+ * FIO_SERVER_MAX_FRAGMENT_PDU chunks and let the receiving
+ * side defragment it.
+ */
+ out_pdu = malloc(FIO_SERVER_MAX_FRAGMENT_PDU);
+
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ 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.
+ */
+ __fio_init_net_cmd(&cmd, FIO_NET_CMD_IOLOG, sizeof(pdu->nr_samples), 0);
+ cmd.flags = __cpu_to_le32(FIO_NET_CMD_F_MORE);
+ 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));
+
+ stream.next_in = (void *) pdu + sizeof(pdu->nr_samples);
+ stream.avail_in = p_size - sizeof(pdu->nr_samples);
+
+ do {
+ unsigned int this_len;
+
+ stream.avail_out = FIO_SERVER_MAX_FRAGMENT_PDU;
+ stream.next_out = out_pdu;
+ deflate(&stream, Z_FINISH);
+
+ this_len = FIO_SERVER_MAX_FRAGMENT_PDU - stream.avail_out;
+
+ __fio_init_net_cmd(&cmd, FIO_NET_CMD_IOLOG, this_len, 0);
+
+ if (stream.avail_in)
+ cmd.flags = __cpu_to_le32(FIO_NET_CMD_F_MORE);
+
+ fio_net_cmd_crc_pdu(&cmd, out_pdu);
+
+ fio_send_data(server_fd, &cmd, sizeof(cmd));
+ fio_send_data(server_fd, out_pdu, this_len);
+ } while (stream.avail_in);
+
+ free(pdu);
+ free(out_pdu);
+ deflateEnd(&stream);
+ return 0;
+}
+
void fio_server_send_add_job(struct thread_options *o, const char *ioengine)
{
struct cmd_add_job_pdu pdu;