X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=server.c;h=4e1f39be52568ae3f55ff7f8d7913a125b5e50dd;hp=89422e96781dae80cd0fad5ec2ed473691820376;hb=1b42725f06f8906b9b99381da3490484f59df28a;hpb=ea51b956a15dd4aee047233be892bb3607f3adbd diff --git a/server.c b/server.c index 89422e96..4e1f39be 100644 --- a/server.c +++ b/server.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "fio.h" #include "server.h" @@ -248,15 +249,19 @@ struct fio_net_cmd *fio_net_recv_cmd(int sk) 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, @@ -846,6 +851,87 @@ void fio_server_send_du(void) } } +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;