+static int fio_client_handle_iolog(struct fio_client *client,
+ struct fio_net_cmd *cmd)
+{
+ struct cmd_iolog_pdu *pdu = NULL;
+ bool store_direct;
+ char *log_pathname = NULL;
+ int ret = 0;
+
+ pdu = convert_iolog(cmd, &store_direct);
+ if (!pdu) {
+ log_err("fio: failed converting IO log\n");
+ ret = 1;
+ goto out;
+ }
+
+ /* allocate buffer big enough for next sprintf() call */
+ log_pathname = malloc(10 + strlen((char *)pdu->name) +
+ strlen(client->hostname));
+ if (!log_pathname) {
+ log_err("fio: memory allocation of unique pathname failed\n");
+ ret = -1;
+ goto out;
+ }
+ /* generate a unique pathname for the log file using hostname */
+ sprintf(log_pathname, "%s.%s", pdu->name, client->hostname);
+
+ if (store_direct) {
+ ssize_t wrote;
+ size_t sz;
+ int fd;
+
+ fd = open((const char *) log_pathname,
+ O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0) {
+ log_err("fio: open log %s: %s\n",
+ log_pathname, strerror(errno));
+ ret = 1;
+ goto out;
+ }
+
+ sz = cmd->pdu_len - sizeof(*pdu);
+ wrote = write(fd, pdu->samples, sz);
+ close(fd);
+
+ if (wrote != sz) {
+ log_err("fio: short write on compressed log\n");
+ ret = 1;
+ goto out;
+ }
+
+ ret = 0;
+ } else {
+ FILE *f;
+ f = fopen((const char *) log_pathname, "w");
+ if (!f) {
+ log_err("fio: fopen log %s : %s\n",
+ log_pathname, strerror(errno));
+ ret = 1;
+ goto out;
+ }
+
+ if (pdu->log_type == IO_LOG_TYPE_HIST) {
+ client_flush_hist_samples(f, pdu->log_hist_coarseness, pdu->samples,
+ pdu->nr_samples * sizeof(struct io_sample));
+ } else {
+ flush_samples(f, pdu->samples,
+ pdu->nr_samples * sizeof(struct io_sample));
+ }
+ fclose(f);
+ ret = 0;
+ }
+
+out:
+ if (pdu && pdu != (void *) cmd->payload)
+ free(pdu);
+
+ if (log_pathname)
+ free(log_pathname);
+
+ return ret;