client: fix double removal of client on job file open failure
[fio.git] / client.c
index 27a764da8389b60d587ca11062dab60d3c202ee4..6bc114541062231f24d9bc0215e47102e05ec868 100644 (file)
--- a/client.c
+++ b/client.c
@@ -33,6 +33,8 @@ static void handle_text(struct fio_client *client, struct fio_net_cmd *cmd);
 static void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd);
 static void handle_start(struct fio_client *client, struct fio_net_cmd *cmd);
 
+static void convert_text(struct fio_net_cmd *cmd);
+
 struct client_ops fio_client_ops = {
        .text           = handle_text,
        .disk_util      = handle_du,
@@ -215,12 +217,32 @@ static int fio_client_dec_jobs_eta(struct client_eta *eta, client_eta_op eta_fn)
        return 1;
 }
 
+static void fio_drain_client_text(struct fio_client *client)
+{
+       do {
+               struct fio_net_cmd *cmd;
+
+               cmd = fio_net_recv_cmd(client->fd, false);
+               if (!cmd)
+                       break;
+
+               if (cmd->opcode == FIO_NET_CMD_TEXT) {
+                       convert_text(cmd);
+                       client->ops->text(client, cmd);
+               }
+
+               free(cmd);
+       } while (1);
+}
+
 static void remove_client(struct fio_client *client)
 {
        assert(client->refs);
 
        dprint(FD_NET, "client: removed <%s>\n", client->hostname);
 
+       fio_drain_client_text(client);
+
        if (!flist_empty(&client->list))
                flist_del_init(&client->list);
 
@@ -794,6 +816,8 @@ int fio_clients_send_ini(const char *filename)
        struct flist_head *entry, *tmp;
 
        flist_for_each_safe(entry, tmp, &client_list) {
+               bool failed = false;
+
                client = flist_entry(entry, struct fio_client, list);
 
                if (client->nr_files) {
@@ -805,12 +829,13 @@ int fio_clients_send_ini(const char *filename)
                                cf = &client->files[i];
 
                                if (fio_client_send_cf(client, cf)) {
+                                       failed = true;
                                        remove_client(client);
                                        break;
                                }
                        }
                }
-               if (client->sent_job)
+               if (client->sent_job || failed)
                        continue;
                if (!filename || fio_client_send_ini(client, filename, 0))
                        remove_client(client);
@@ -1226,14 +1251,17 @@ static void handle_eta(struct fio_client *client, struct fio_net_cmd *cmd)
        fio_client_dec_jobs_eta(eta, client->ops->eta);
 }
 
-void fio_client_handle_iolog(struct fio_client *client, struct fio_net_cmd *cmd)
+static int fio_client_handle_iolog(struct fio_client *client,
+                                  struct fio_net_cmd *cmd)
 {
        struct cmd_iolog_pdu *pdu;
        bool store_direct;
 
        pdu = convert_iolog(cmd, &store_direct);
-       if (!pdu)
-               return;
+       if (!pdu) {
+               log_err("fio: failed converting IO log\n");
+               return 1;
+       }
 
        if (store_direct) {
                ssize_t ret;
@@ -1243,26 +1271,33 @@ void fio_client_handle_iolog(struct fio_client *client, struct fio_net_cmd *cmd)
                fd = open((const char *) pdu->name,
                                O_WRONLY | O_CREAT | O_TRUNC, 0644);
                if (fd < 0) {
-                       perror("open log");
-                       return;
+                       log_err("fio: open log: %s\n", strerror(errno));
+                       return 1;
                }
+
                sz = cmd->pdu_len - sizeof(*pdu);
                ret = write(fd, pdu->samples, sz);
-               if (ret != sz)
-                       log_err("fio: short write on compressed log\n");
                close(fd);
+
+               if (ret != sz) {
+                       log_err("fio: short write on compressed log\n");
+                       return 1;
+               }
+
+               return 0;
        } else {
                FILE *f;
 
                f = fopen((const char *) pdu->name, "w");
                if (!f) {
-                       perror("fopen log");
-                       return;
+                       log_err("fio: fopen log: %s\n", strerror(errno));
+                       return 1;
                }
 
                flush_samples(f, pdu->samples,
                                pdu->nr_samples * sizeof(struct io_sample));
                fclose(f);
+               return 0;
        }
 }
 
@@ -1428,7 +1463,6 @@ static struct cmd_iolog_pdu *convert_iolog(struct fio_net_cmd *cmd,
                return NULL;
 #endif
                ret = convert_iolog_gz(cmd, pdu);
-               printf("compressed iolog, %p\n", ret);
                if (!ret) {
                        log_err("fio: failed decompressing log\n");
                        return NULL;
@@ -1475,8 +1509,8 @@ static void sendfile_reply(int fd, struct cmd_sendfile_reply *rep,
        fio_net_send_cmd(fd, FIO_NET_CMD_SENDFILE, rep, size, &tag, NULL);
 }
 
-static int send_file(struct fio_client *client, struct cmd_sendfile *pdu,
-                    uint64_t tag)
+static int fio_send_file(struct fio_client *client, struct cmd_sendfile *pdu,
+                        uint64_t tag)
 {
        struct cmd_sendfile_reply *rep;
        struct stat sb;
@@ -1516,7 +1550,7 @@ int fio_handle_client(struct fio_client *client)
 
        dprint(FD_NET, "client: handle %s\n", client->hostname);
 
-       cmd = fio_net_recv_cmd(client->fd);
+       cmd = fio_net_recv_cmd(client->fd, true);
        if (!cmd)
                return 0;
 
@@ -1626,7 +1660,7 @@ int fio_handle_client(struct fio_client *client)
                }
        case FIO_NET_CMD_SENDFILE: {
                struct cmd_sendfile *pdu = (struct cmd_sendfile *) cmd->payload;
-               send_file(client, pdu, cmd->tag);
+               fio_send_file(client, pdu, cmd->tag);
                break;
                }
        case FIO_NET_CMD_JOB_OPT: {