X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=server.c;h=ac6c2fb8969da75f15c05def7e313f01ca162137;hp=cf3a48ef25058288f698cab03471d5810a91ab71;hb=38fdef226f1a1fa053ab53005abbc184143bff65;hpb=7f868316a7244cad23735e44e6ef66e5779c9660 diff --git a/server.c b/server.c index cf3a48ef..ac6c2fb8 100644 --- a/server.c +++ b/server.c @@ -33,6 +33,33 @@ static char *fio_server_arg; static char *bind_sock; static struct sockaddr_in saddr_in; +static const char *fio_server_ops[FIO_NET_CMD_NR] = { + "", + "QUIT", + "EXIT", + "JOB", + "JOBLINE", + "TEXT", + "TS", + "GS", + "SEND_ETA", + "ETA", + "PROBE", + "START", + "STOP" +}; + +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) { assert(len <= sizeof(struct fio_net_cmd) + FIO_SERVER_MAX_PDU); @@ -50,6 +77,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 +102,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) @@ -243,7 +274,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 +284,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 +332,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 +372,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 +384,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 +398,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) @@ -379,7 +446,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 +469,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; } @@ -525,12 +593,12 @@ out: return exitval; } -int fio_server_text_output(const char *buf, unsigned int len) +int fio_server_text_output(const char *buf, size_t len) { if (server_fd != -1) return fio_net_send_cmd(server_fd, FIO_NET_CMD_TEXT, buf, len, 0); - return fwrite(buf, len, 1, f_err); + return log_local_buf(buf, len); } static void convert_io_stat(struct io_stat *dst, struct io_stat *src) @@ -758,7 +826,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,52 +971,101 @@ static int fio_server(void) return ret; } -static void sig_int(int sig) +void fio_server_got_signal(int signal) +{ + 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) { - fio_terminate_threads(TERMINATE_ALL); - exit_backend = 1; + struct stat sb; + char buf[16]; + pid_t pid; + FILE *f; + + if (stat(pidfile, &sb)) + return 0; + + f = fopen(pidfile, "r"); + if (!f) + return 0; + + if (fread(buf, sb.st_size, 1, f) <= 0) { + fclose(f); + return 1; + } + fclose(f); + + pid = atoi(buf); + if (kill(pid, SIGCONT) < 0) + return errno != ESRCH; + + return 1; } -static void server_signal_handler(void) +static int write_pid(pid_t pid, const char *pidfile) { - struct sigaction act; + FILE *fpid; - memset(&act, 0, sizeof(act)); - act.sa_handler = sig_int; - act.sa_flags = SA_RESTART; - sigaction(SIGINT, &act, NULL); + fpid = fopen(pidfile, "w"); + if (!fpid) { + log_err("fio: failed opening pid file %s\n", pidfile); + return 1; + } - memset(&act, 0, sizeof(act)); - act.sa_handler = sig_int; - act.sa_flags = SA_RESTART; - sigaction(SIGTERM, &act, NULL); + fprintf(fpid, "%u\n", (unsigned int) pid); + fclose(fpid); + return 0; } -int fio_start_server(int daemonize) +/* + * If pidfile is specified, background us. + */ +int fio_start_server(char *pidfile) { pid_t pid; + int ret; - server_signal_handler(); - - if (!daemonize) + if (!pidfile) return fio_server(); - openlog("fio", LOG_NDELAY|LOG_NOWAIT|LOG_PID, LOG_USER); + if (check_existing_pidfile(pidfile)) { + log_err("fio: pidfile %s exists and server appears alive\n", + pidfile); + return -1; + } + pid = fork(); if (pid < 0) { - syslog(LOG_ERR, "failed server fork"); + log_err("fio: failed server fork: %s", strerror(errno)); + free(pidfile); return -1; - } else if (pid) - exit(0); + } else if (pid) { + int ret = write_pid(pid, pidfile); + + exit(ret); + } setsid(); + openlog("fio", LOG_NDELAY|LOG_NOWAIT|LOG_PID, LOG_USER); + log_syslog = 1; close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); f_out = NULL; f_err = NULL; - log_syslog = 1; - return fio_server(); + + ret = fio_server(); + + closelog(); + unlink(pidfile); + free(pidfile); + return ret; } void fio_server_set_arg(const char *arg)