From b9d2f30a214ebd274340f888739be250838d63c2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 8 Mar 2012 20:36:28 +0100 Subject: [PATCH] Separate the act of adding and starting a job CMD_JOB or CMD_JOB_LINE only adds the necessary jobs, which will automatically return the job option info to the client. Let the client do what it wants with the options, then have the client send a CMD_RUN command to actually start the jobs. Next we'll have a command for passing back edited options, so that the client can update existing options. This adds a new button to gfio, to note this split of add and run as well. Signed-off-by: Jens Axboe --- client.c | 40 +++++++++++++++++++++++++++++----------- client.h | 11 +++++++++++ fio.c | 6 ++++-- gfio.c | 43 ++++++++++++++++++++++++++++--------------- server.c | 54 ++++++++++++++++++++++++++++++------------------------ server.h | 7 ++++--- 6 files changed, 106 insertions(+), 55 deletions(-) diff --git a/client.c b/client.c index a77dc935..10dc53be 100644 --- a/client.c +++ b/client.c @@ -40,15 +40,6 @@ struct client_ops fio_client_ops = { static struct timeval eta_tv; -enum { - Client_created = 0, - Client_connected = 1, - Client_started = 2, - Client_running = 3, - Client_stopped = 4, - Client_exited = 5, -}; - static FLIST_HEAD(client_list); static FLIST_HEAD(eta_list); @@ -469,6 +460,33 @@ int fio_clients_connect(void) return !nr_clients; } +int fio_start_client(struct fio_client *client) +{ + dprint(FD_NET, "client: start %s\n", client->hostname); + return fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_RUN, 0, NULL); +} + +int fio_start_all_clients(void) +{ + struct fio_client *client; + struct flist_head *entry, *tmp; + int ret; + + dprint(FD_NET, "client: start all\n"); + + flist_for_each_safe(entry, tmp, &client_list) { + client = flist_entry(entry, struct fio_client, list); + + ret = fio_start_client(client); + if (ret) { + remove_client(client); + continue; + } + } + + return flist_empty(&client_list); +} + /* * Send file contents to server backend. We could use sendfile(), but to remain * more portable lets just read/write the darn thing. @@ -891,8 +909,8 @@ int fio_handle_client(struct fio_client *client) if (!cmd) return 0; - dprint(FD_NET, "client: got cmd op %s from %s\n", - fio_server_op(cmd->opcode), client->hostname); + dprint(FD_NET, "client: got cmd op %s from %s (pdu=%u)\n", + fio_server_op(cmd->opcode), client->hostname, cmd->pdu_len); switch (cmd->opcode) { case FIO_NET_CMD_QUIT: diff --git a/client.h b/client.h index eccac922..9157affd 100644 --- a/client.h +++ b/client.h @@ -11,6 +11,15 @@ struct fio_net_cmd; struct client_ops; +enum { + Client_created = 0, + Client_connected = 1, + Client_started = 2, + Client_running = 3, + Client_stopped = 4, + Client_exited = 5, +}; + struct fio_client { struct flist_head list; struct flist_head hash_list; @@ -93,6 +102,8 @@ enum { }; extern int fio_clients_connect(void); +extern int fio_start_client(struct fio_client *); +extern int fio_start_all_clients(void); extern int fio_clients_send_ini(const char *); extern int fio_handle_clients(struct client_ops *); extern int fio_client_add(struct client_ops *, const char *, void **); diff --git a/fio.c b/fio.c index d628cfcd..9a6c31a6 100644 --- a/fio.c +++ b/fio.c @@ -45,8 +45,10 @@ int main(int argc, char *argv[], char *envp[]) if (parse_options(argc, argv)) return 1; - if (nr_clients) + if (nr_clients) { + if (fio_start_all_clients()) + return 1; return fio_handle_clients(&fio_client_ops); - else + } else return fio_backend(); } diff --git a/gfio.c b/gfio.c index 4521f75d..877438a5 100644 --- a/gfio.c +++ b/gfio.c @@ -44,6 +44,7 @@ typedef void (*clickfunction)(GtkWidget *widget, gpointer data); static void connect_clicked(GtkWidget *widget, gpointer data); static void start_job_clicked(GtkWidget *widget, gpointer data); +static void send_clicked(GtkWidget *widget, gpointer data); static struct button_spec { const char *buttontext; @@ -52,10 +53,11 @@ static struct button_spec { const int start_insensitive; } buttonspeclist[] = { #define CONNECT_BUTTON 0 -#define START_JOB_BUTTON 1 +#define SEND_BUTTON 1 +#define START_JOB_BUTTON 2 { "Connect", connect_clicked, "Connect to host", 0 }, - { "Start Job", - start_job_clicked, + { "Send", send_clicked, "Send job description to host", 1 }, + { "Start Job", start_job_clicked, "Send current fio job to fio server to be executed", 1 }, }; @@ -114,13 +116,14 @@ struct gui { struct graph *iops_graph; struct graph *bandwidth_graph; - struct fio_client *client; + struct gfio_client *client; int nr_job_files; char **job_files; } ui; struct gfio_client { struct gui *ui; + struct fio_client *client; GtkWidget *results_widget; GtkWidget *disk_util_frame; GtkWidget *err_entry; @@ -223,13 +226,14 @@ static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, dou static void gfio_set_connected(struct gui *ui, int connected) { if (connected) { - gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1); + gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 1); ui->connected = 1; gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Disconnect"); gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1); } else { ui->connected = 0; gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Connect"); + gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 0); gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0); gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1); } @@ -1321,15 +1325,6 @@ static int send_job_files(struct gui *ui) return ret; } -static void start_job_thread(struct gui *ui) -{ - if (send_job_files(ui)) { - printf("Yeah, I didn't really like those options too much.\n"); - gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1); - return; - } -} - static void *server_thread(void *arg) { is_backend = 1; @@ -1352,9 +1347,10 @@ static void start_job_clicked(__attribute__((unused)) GtkWidget *widget, gpointer data) { struct gui *ui = data; + struct gfio_client *gc = ui->client; gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0); - start_job_thread(ui); + fio_net_send_simple_cmd(gc->client->fd, FIO_NET_CMD_RUN, 0, NULL); } static void file_open(GtkWidget *w, gpointer data); @@ -1371,6 +1367,7 @@ static void connect_clicked(GtkWidget *widget, gpointer data) if (!fio_clients_connect()) { pthread_create(&ui->t, NULL, job_thread, NULL); gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 0); + gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 1); } } else { fio_clients_terminate(); @@ -1379,6 +1376,19 @@ static void connect_clicked(GtkWidget *widget, gpointer data) } } +static void send_clicked(GtkWidget *widget, gpointer data) +{ + struct gui *ui = data; + + if (send_job_files(ui)) { + printf("Yeah, I didn't really like those options too much.\n"); + gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1); + } + + gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 0); + gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1); +} + static void add_button(struct gui *ui, int i, GtkWidget *buttonbox, struct button_spec *buttonspec) { @@ -1575,6 +1585,9 @@ static void gfio_client_added(struct gui *ui, struct fio_client *client) gc = malloc(sizeof(*gc)); memset(gc, 0, sizeof(*gc)); gc->ui = ui; + gc->client = client; + + ui->client = gc; client->client_data = gc; } diff --git a/server.c b/server.c index dfbe3377..10851805 100644 --- a/server.c +++ b/server.c @@ -51,8 +51,9 @@ static const char *fio_server_ops[FIO_NET_CMD_NR] = { "START", "STOP", "DISK_UTIL", - "RUN", + "SERVER_START", "ADD_JOB", + "CMD_RUN" }; const char *fio_server_op(unsigned int op) @@ -68,7 +69,7 @@ const char *fio_server_op(unsigned int op) int fio_send_data(int sk, const void *p, unsigned int len) { - assert(len <= sizeof(struct fio_net_cmd) + FIO_SERVER_MAX_PDU); + assert(len <= sizeof(struct fio_net_cmd) + FIO_SERVER_MAX_FRAGMENT_PDU); do { int ret = send(sk, p, len, 0); @@ -146,7 +147,7 @@ static int verify_convert_cmd(struct fio_net_cmd *cmd) return 1; } - if (cmd->pdu_len > FIO_SERVER_MAX_PDU) { + if (cmd->pdu_len > FIO_SERVER_MAX_FRAGMENT_PDU) { log_err("fio: command payload too large: %u\n", cmd->pdu_len); return 1; } @@ -262,8 +263,8 @@ int fio_net_send_cmd(int fd, uint16_t opcode, const void *buf, off_t size, do { this_len = size; - if (this_len > FIO_SERVER_MAX_PDU) - this_len = FIO_SERVER_MAX_PDU; + if (this_len > FIO_SERVER_MAX_FRAGMENT_PDU) + this_len = FIO_SERVER_MAX_FRAGMENT_PDU; if (!cmd || cur_len < sizeof(*cmd) + this_len) { if (cmd) @@ -339,21 +340,11 @@ static int fio_server_send_quit_cmd(void) return fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_QUIT, 0, NULL); } -static int handle_job_cmd(struct fio_net_cmd *cmd) +static int handle_run_cmd(struct fio_net_cmd *cmd) { - char *buf = (char *) cmd->payload; - struct cmd_start_pdu spdu; struct cmd_end_pdu epdu; int ret; - if (parse_jobs_ini(buf, 1, 0)) { - fio_server_send_quit_cmd(); - return -1; - } - - spdu.jobs = cpu_to_le32(thread_number); - fio_net_send_cmd(server_fd, FIO_NET_CMD_START, &spdu, sizeof(spdu), 0); - ret = fio_backend(); epdu.error = ret; @@ -365,14 +356,30 @@ static int handle_job_cmd(struct fio_net_cmd *cmd) return ret; } +static int handle_job_cmd(struct fio_net_cmd *cmd) +{ + char *buf = (char *) cmd->payload; + struct cmd_start_pdu spdu; + + if (parse_jobs_ini(buf, 1, 0)) { + fio_server_send_quit_cmd(); + return -1; + } + + spdu.jobs = cpu_to_le32(thread_number); + fio_net_send_cmd(server_fd, FIO_NET_CMD_START, &spdu, sizeof(spdu), 0); + return 0; +} + static int handle_jobline_cmd(struct fio_net_cmd *cmd) { void *pdu = cmd->payload; struct cmd_single_line_pdu *cslp; struct cmd_line_pdu *clp; unsigned long offset; + struct cmd_start_pdu spdu; char **argv; - int ret, i; + int i; clp = pdu; clp->lines = le16_to_cpu(clp->lines); @@ -397,13 +404,9 @@ static int handle_jobline_cmd(struct fio_net_cmd *cmd) free(argv); - fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_START, 0, NULL); - - ret = fio_backend(); - fio_server_send_quit_cmd(); - reset_fio_state(); - first_cmd_check = 0; - return ret; + spdu.jobs = cpu_to_le32(thread_number); + fio_net_send_cmd(server_fd, FIO_NET_CMD_START, &spdu, sizeof(spdu), 0); + return 0; } static int handle_probe_cmd(struct fio_net_cmd *cmd) @@ -498,6 +501,9 @@ static int handle_command(struct fio_net_cmd *cmd) case FIO_NET_CMD_SEND_ETA: ret = handle_send_eta_cmd(cmd); break; + case FIO_NET_CMD_RUN: + ret = handle_run_cmd(cmd); + break; default: log_err("fio: unknown opcode: %s\n",fio_server_op(cmd->opcode)); ret = 1; diff --git a/server.h b/server.h index bc044e9b..7a801bf0 100644 --- a/server.h +++ b/server.h @@ -38,9 +38,9 @@ struct fio_net_int_cmd { }; enum { - FIO_SERVER_VER = 9, + FIO_SERVER_VER = 10, - FIO_SERVER_MAX_PDU = 1024, + FIO_SERVER_MAX_FRAGMENT_PDU = 1024, FIO_NET_CMD_QUIT = 1, FIO_NET_CMD_EXIT = 2, @@ -57,7 +57,8 @@ enum { FIO_NET_CMD_DU = 13, FIO_NET_CMD_SERVER_START = 14, FIO_NET_CMD_ADD_JOB = 15, - FIO_NET_CMD_NR = 16, + FIO_NET_CMD_RUN = 16, + FIO_NET_CMD_NR = 17, FIO_NET_CMD_F_MORE = 1UL << 0, -- 2.25.1