X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=server.c;h=7c4804adc17195675eaad8a101488a9746ab2ecf;hp=4f9c02310563604c08064209af92567a306acbe6;hb=72c27ff8f2eaf945ae34776dab4da3fee753707d;hpb=13755d946d034eb7395a818db7ace2c9cb60b4cb diff --git a/server.c b/server.c index 4f9c0231..7c4804ad 100644 --- a/server.c +++ b/server.c @@ -20,7 +20,7 @@ #include "fio.h" #include "server.h" #include "crc/crc16.h" -#include "ieee754.h" +#include "lib/ieee754.h" #include "fio_version.h" @@ -32,6 +32,36 @@ static int server_fd = -1; static char *fio_server_arg; static char *bind_sock; static struct sockaddr_in saddr_in; +static int first_cmd_check; + +static const char *fio_server_ops[FIO_NET_CMD_NR] = { + "", + "QUIT", + "EXIT", + "JOB", + "JOBLINE", + "TEXT", + "TS", + "GS", + "SEND_ETA", + "ETA", + "PROBE", + "START", + "STOP", + "DISK_UTIL", + "RUN", +}; + +const char *fio_server_op(unsigned int op) +{ + static char buf[32]; + + if (op < FIO_NET_CMD_NR) + return fio_server_ops[op]; + + sprintf(buf, "UNKNOWN/%d", op); + return buf; +} int fio_send_data(int sk, const void *p, unsigned int len) { @@ -50,6 +80,8 @@ int fio_send_data(int sk, const void *p, unsigned int len) break; else if (errno == EAGAIN || errno == EINTR) continue; + else + break; } while (!exit_backend); if (!len) @@ -73,6 +105,8 @@ int fio_recv_data(int sk, void *p, unsigned int len) break; else if (errno == EAGAIN || errno == EINTR) continue; + else + break; } while (!exit_backend); if (!len) @@ -149,8 +183,12 @@ struct fio_net_cmd *fio_net_recv_cmd(int sk) if (first) memcpy(cmdret, &cmd, sizeof(cmd)); - else - assert(cmdret->opcode == cmd.opcode); + else if (cmdret->opcode != cmd.opcode) { + log_err("fio: fragment opcode mismatch (%d != %d)\n", + cmdret->opcode, cmd.opcode); + ret = 1; + break; + } if (!cmd.pdu_len) break; @@ -243,7 +281,7 @@ int fio_net_send_cmd(int fd, uint16_t opcode, const void *buf, off_t size, return ret; } -int fio_net_send_simple_cmd(int sk, uint16_t opcode, uint64_t tag) +static int fio_net_send_simple_stack_cmd(int sk, uint16_t opcode, uint64_t tag) { struct fio_net_cmd cmd; @@ -253,10 +291,42 @@ int fio_net_send_simple_cmd(int sk, uint16_t opcode, uint64_t tag) return fio_send_data(sk, &cmd, sizeof(cmd)); } +/* + * If 'list' is non-NULL, then allocate and store the sent command for + * later verification. + */ +int fio_net_send_simple_cmd(int sk, uint16_t opcode, uint64_t tag, + struct flist_head *list) +{ + struct fio_net_int_cmd *cmd; + int ret; + + if (!list) + return fio_net_send_simple_stack_cmd(sk, opcode, tag); + + cmd = malloc(sizeof(*cmd)); + + fio_init_net_cmd(&cmd->cmd, opcode, NULL, 0, (uintptr_t) cmd); + fio_net_cmd_crc(&cmd->cmd); + + INIT_FLIST_HEAD(&cmd->list); + gettimeofday(&cmd->tv, NULL); + cmd->saved_tag = tag; + + ret = fio_send_data(sk, &cmd->cmd, sizeof(cmd->cmd)); + if (ret) { + free(cmd); + return ret; + } + + flist_add_tail(&cmd->list, list); + return 0; +} + static int fio_server_send_quit_cmd(void) { dprint(FD_NET, "server: sending quit\n"); - return fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_QUIT, 0); + return fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_QUIT, 0, NULL); } static int handle_job_cmd(struct fio_net_cmd *cmd) @@ -269,7 +339,7 @@ static int handle_job_cmd(struct fio_net_cmd *cmd) return -1; } - fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_START, 0); + fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_START, 0, NULL); ret = exec_run(); fio_server_send_quit_cmd(); @@ -309,7 +379,7 @@ static int handle_jobline_cmd(struct fio_net_cmd *cmd) free(argv); - fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_START, 0); + fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_START, 0, NULL); ret = exec_run(); fio_server_send_quit_cmd(); @@ -321,6 +391,8 @@ static int handle_probe_cmd(struct fio_net_cmd *cmd) { struct cmd_probe_pdu probe; + dprint(FD_NET, "server: sending probe reply\n"); + memset(&probe, 0, sizeof(probe)); gethostname((char *) probe.hostname, sizeof(probe.hostname)); #ifdef FIO_BIG_ENDIAN @@ -333,7 +405,9 @@ static int handle_probe_cmd(struct fio_net_cmd *cmd) probe.os = FIO_OS; probe.arch = FIO_ARCH; - return fio_net_send_cmd(server_fd, FIO_NET_CMD_PROBE, &probe, sizeof(probe), 0); + probe.bpp = sizeof(void *); + + return fio_net_send_cmd(server_fd, FIO_NET_CMD_PROBE, &probe, sizeof(probe), cmd->tag); } static int handle_send_eta_cmd(struct fio_net_cmd *cmd) @@ -342,7 +416,10 @@ static int handle_send_eta_cmd(struct fio_net_cmd *cmd) size_t size; int i; - size = sizeof(*je) + thread_number * sizeof(char); + if (!thread_number) + return 0; + + size = sizeof(*je) + thread_number * sizeof(char) + 1; je = malloc(size); memset(je, 0, size); @@ -379,7 +456,8 @@ static int handle_command(struct fio_net_cmd *cmd) { int ret; - dprint(FD_NET, "server: got opcode %d, pdu=%u\n", cmd->opcode, cmd->pdu_len); + dprint(FD_NET, "server: got op [%s], pdu=%u, tag=%lx\n", + fio_server_op(cmd->opcode), cmd->pdu_len, cmd->tag); switch (cmd->opcode) { case FIO_NET_CMD_QUIT: @@ -401,7 +479,7 @@ static int handle_command(struct fio_net_cmd *cmd) ret = handle_send_eta_cmd(cmd); break; default: - log_err("fio: unknown opcode: %d\n", cmd->opcode); + log_err("fio: unknown opcode: %s\n",fio_server_op(cmd->opcode)); ret = 1; } @@ -467,6 +545,8 @@ static int handle_connection(int sk, int block) void fio_server_idle_loop(void) { + if (!first_cmd_check) + fio_net_send_simple_cmd(server_fd, FIO_NET_CMD_RUN, 0, NULL); if (server_fd != -1) handle_connection(server_fd, 0); } @@ -600,9 +680,10 @@ void fio_server_send_ts(struct thread_stat *ts, struct group_run_stats *rs) p.ts.clat_percentiles = cpu_to_le64(ts->clat_percentiles); for (i = 0; i < FIO_IO_U_LIST_MAX_LEN; i++) { - fio_fp64_t *fp = &p.ts.percentile_list[i]; + fio_fp64_t *src = &ts->percentile_list[i]; + fio_fp64_t *dst = &p.ts.percentile_list[i]; - fp->u.i = __cpu_to_le64(fio_double_to_uint64(fp->u.f)); + dst->u.i = __cpu_to_le64(fio_double_to_uint64(src->u.f)); } for (i = 0; i < FIO_IO_U_MAP_NR; i++) { @@ -654,6 +735,61 @@ void fio_server_send_gs(struct group_run_stats *rs) fio_net_send_cmd(server_fd, FIO_NET_CMD_GS, &gs, sizeof(gs), 0); } +static void convert_agg(struct disk_util_agg *dst, struct disk_util_agg *src) +{ + int i; + + for (i = 0; i < 2; i++) { + dst->ios[i] = cpu_to_le32(src->ios[i]); + dst->merges[i] = cpu_to_le32(src->merges[i]); + dst->sectors[i] = cpu_to_le64(src->sectors[i]); + dst->ticks[i] = cpu_to_le32(src->ticks[i]); + } + + dst->io_ticks = cpu_to_le32(src->io_ticks); + dst->time_in_queue = cpu_to_le32(src->time_in_queue); + dst->slavecount = cpu_to_le32(src->slavecount); + dst->max_util.u.i = __cpu_to_le64(fio_double_to_uint64(src->max_util.u.f)); +} + +static void convert_dus(struct disk_util_stat *dst, struct disk_util_stat *src) +{ + int i; + + strcpy((char *) dst->name, (char *) src->name); + + for (i = 0; i < 2; i++) { + dst->ios[i] = cpu_to_le32(src->ios[i]); + dst->merges[i] = cpu_to_le32(src->merges[i]); + dst->sectors[i] = cpu_to_le64(src->sectors[i]); + dst->ticks[i] = cpu_to_le32(src->ticks[i]); + } + + dst->io_ticks = cpu_to_le32(src->io_ticks); + dst->time_in_queue = cpu_to_le32(src->time_in_queue); + dst->msec = cpu_to_le64(src->msec); +} + +void fio_server_send_du(void) +{ + struct disk_util *du; + struct flist_head *entry; + struct cmd_du_pdu pdu; + + dprint(FD_NET, "server: sending disk_util %d\n", !flist_empty(&disk_list)); + + memset(&pdu, 0, sizeof(pdu)); + + flist_for_each(entry, &disk_list) { + du = flist_entry(entry, struct disk_util, list); + + convert_dus(&pdu.dus, &du->dus); + convert_agg(&pdu.agg, &du->agg); + + fio_net_send_cmd(server_fd, FIO_NET_CMD_DU, &pdu, sizeof(pdu), 0); + } +} + int fio_server_log(const char *format, ...) { char buffer[1024]; @@ -758,7 +894,7 @@ static int fio_init_server_connection(void) log_info("fio: server listening on %s\n", bind_str); - if (listen(sk, 1) < 0) { + if (listen(sk, 0) < 0) { log_err("fio: listen: %s\n", strerror(errno)); return -1; } @@ -903,25 +1039,14 @@ static int fio_server(void) return ret; } -static void sig_int(int sig) -{ - fio_terminate_threads(TERMINATE_ALL); - exit_backend = 1; -} - -static void server_signal_handler(void) +void fio_server_got_signal(int signal) { - struct sigaction act; - - memset(&act, 0, sizeof(act)); - act.sa_handler = sig_int; - act.sa_flags = SA_RESTART; - sigaction(SIGINT, &act, NULL); - - memset(&act, 0, sizeof(act)); - act.sa_handler = sig_int; - act.sa_flags = SA_RESTART; - sigaction(SIGTERM, &act, NULL); + if (signal == SIGPIPE) + server_fd = -1; + else { + log_info("\nfio: terminating on signal %d\n", signal); + exit_backend = 1; + } } static int check_existing_pidfile(const char *pidfile) @@ -938,7 +1063,7 @@ static int check_existing_pidfile(const char *pidfile) if (!f) return 0; - if (fread(buf, sb.st_size, 1, f) < 0) { + if (fread(buf, sb.st_size, 1, f) <= 0) { fclose(f); return 1; } @@ -946,7 +1071,7 @@ static int check_existing_pidfile(const char *pidfile) pid = atoi(buf); if (kill(pid, SIGCONT) < 0) - return 0; + return errno != ESRCH; return 1; } @@ -974,8 +1099,6 @@ int fio_start_server(char *pidfile) pid_t pid; int ret; - server_signal_handler(); - if (!pidfile) return fio_server();