pid_t pid;
};
-/* Created on fork on new connection */
-static FLIST_HEAD(conn_list);
-
-/* Created on job fork from connection */
-static FLIST_HEAD(job_list);
-
static const char *fio_server_ops[FIO_NET_CMD_NR] = {
"",
"QUIT",
flist_add_tail(&ffi->list, list);
}
-static void fio_server_add_conn_pid(pid_t pid)
+static void fio_server_add_conn_pid(struct flist_head *conn_list, pid_t pid)
{
dprint(FD_NET, "server: forked off connection job (pid=%u)\n", (int) pid);
- fio_server_add_fork_item(pid, &conn_list);
+ fio_server_add_fork_item(pid, conn_list);
}
-static void fio_server_add_job_pid(pid_t pid)
+static void fio_server_add_job_pid(struct flist_head *job_list, pid_t pid)
{
dprint(FD_NET, "server: forked off job job (pid=%u)\n", (int) pid);
- fio_server_add_fork_item(pid, &job_list);
+ fio_server_add_fork_item(pid, job_list);
}
static void fio_server_check_fork_item(struct fio_fork_item *ffi)
}
}
-static void fio_server_check_jobs(void)
+static void fio_server_check_jobs(struct flist_head *job_list)
{
- fio_server_check_fork_items(&job_list);
+ fio_server_check_fork_items(job_list);
}
-static void fio_server_check_conns(void)
+static void fio_server_check_conns(struct flist_head *conn_list)
{
- fio_server_check_fork_items(&conn_list);
+ fio_server_check_fork_items(conn_list);
}
-static int handle_run_cmd(struct fio_net_cmd *cmd)
+static int handle_run_cmd(struct flist_head *job_list, struct fio_net_cmd *cmd)
{
pid_t pid;
int ret;
pid = fork();
if (pid) {
- fio_server_add_job_pid(pid);
+ fio_server_add_job_pid(job_list, pid);
return 0;
}
return 0;
}
-static int handle_command(struct fio_net_cmd *cmd)
+static int handle_command(struct flist_head *job_list, struct fio_net_cmd *cmd)
{
int ret;
ret = handle_send_eta_cmd(cmd);
break;
case FIO_NET_CMD_RUN:
- ret = handle_run_cmd(cmd);
+ ret = handle_run_cmd(job_list, cmd);
break;
case FIO_NET_CMD_UPDATE_JOB:
ret = handle_update_job_cmd(cmd);
static int handle_connection(int sk)
{
struct fio_net_cmd *cmd = NULL;
+ FLIST_HEAD(job_list);
int ret = 0;
reset_fio_state();
- INIT_FLIST_HEAD(&job_list);
server_fd = sk;
/* read forever */
log_err("fio: poll: %s\n", strerror(errno));
break;
} else if (!ret) {
- fio_server_check_jobs();
+ fio_server_check_jobs(&job_list);
continue;
}
}
} while (!exit_backend);
- fio_server_check_jobs();
+ fio_server_check_jobs(&job_list);
if (ret < 0)
break;
break;
}
- ret = handle_command(cmd);
+ ret = handle_command(&job_list, cmd);
if (ret)
break;
static int accept_loop(int listen_sk)
{
struct sockaddr_in addr;
- socklen_t len = sizeof(addr);
+ struct sockaddr_in6 addr6;
+ socklen_t len = use_ipv6 ? sizeof(addr6) : sizeof(addr);
struct pollfd pfd;
int ret = 0, sk, flags, exitval = 0;
+ FLIST_HEAD(conn_list);
dprint(FD_NET, "server enter accept loop\n");
fcntl(listen_sk, F_SETFL, flags);
while (!exit_backend) {
+ const char *from;
+ char buf[64];
pid_t pid;
pfd.fd = listen_sk;
log_err("fio: poll: %s\n", strerror(errno));
break;
} else if (!ret) {
- fio_server_check_conns();
+ fio_server_check_conns(&conn_list);
continue;
}
break;
} while (!exit_backend);
- fio_server_check_conns();
+ fio_server_check_conns(&conn_list);
if (exit_backend || ret < 0)
break;
- sk = accept(listen_sk, (struct sockaddr *) &addr, &len);
+ if (use_ipv6)
+ sk = accept(listen_sk, (struct sockaddr *) &addr6, &len);
+ else
+ sk = accept(listen_sk, (struct sockaddr *) &addr, &len);
+
if (sk < 0) {
log_err("fio: accept: %s\n", strerror(errno));
return -1;
}
- dprint(FD_NET, "server: connect from %s\n", inet_ntoa(addr.sin_addr));
+ if (use_ipv6)
+ from = inet_ntop(AF_INET6, (struct sockaddr *) &addr6.sin6_addr, buf, sizeof(buf));
+ else
+ from = inet_ntop(AF_INET, (struct sockaddr *) &addr.sin_addr, buf, sizeof(buf));
+
+ dprint(FD_NET, "server: connect from %s\n", from);
pid = fork();
if (pid) {
close(sk);
- fio_server_add_conn_pid(pid);
+ fio_server_add_conn_pid(&conn_list, pid);
continue;
}
memset(&p, 0, sizeof(p));
- strcpy(p.ts.name, ts->name);
- strcpy(p.ts.verror, ts->verror);
- strcpy(p.ts.description, ts->description);
+ strncpy(p.ts.name, ts->name, FIO_JOBNAME_SIZE - 1);
+ strncpy(p.ts.verror, ts->verror, FIO_VERROR_SIZE - 1);
+ strncpy(p.ts.description, ts->description, FIO_JOBDESC_SIZE - 1);
p.ts.error = cpu_to_le32(ts->error);
p.ts.thread_number = cpu_to_le32(ts->thread_number);
p.ts.kb_base = cpu_to_le32(ts->kb_base);
p.ts.unit_base = cpu_to_le32(ts->unit_base);
+ p.ts.latency_depth = cpu_to_le32(ts->latency_depth);
+ p.ts.latency_target = cpu_to_le64(ts->latency_target);
+ p.ts.latency_window = cpu_to_le64(ts->latency_window);
+ p.ts.latency_percentile.u.i = __cpu_to_le64(fio_double_to_uint64(ts->latency_percentile.u.f));
+
convert_gs(&p.rs, rs);
fio_net_send_cmd(server_fd, FIO_NET_CMD_TS, &p, sizeof(p), NULL, NULL);
struct fio_net_cmd cmd;
struct iovec iov[2];
- iov[0].iov_base = &cmd;
+ iov[0].iov_base = (void *) &cmd;
iov[0].iov_len = sizeof(cmd);
iov[1].iov_base = (void *) buf;
iov[1].iov_len = size;
{
struct sockaddr *addr;
socklen_t socklen;
+ char buf[80];
+ const char *str;
int sk, opt;
if (use_ipv6)
#endif
if (use_ipv6) {
+ const void *src = &saddr_in6.sin6_addr;
+
addr = (struct sockaddr *) &saddr_in6;
socklen = sizeof(saddr_in6);
saddr_in6.sin6_family = AF_INET6;
+ str = inet_ntop(AF_INET6, src, buf, sizeof(buf));
} else {
+ const void *src = &saddr_in.sin_addr;
+
addr = (struct sockaddr *) &saddr_in;
socklen = sizeof(saddr_in);
saddr_in.sin_family = AF_INET;
+ str = inet_ntop(AF_INET, src, buf, sizeof(buf));
}
if (bind(sk, addr, socklen) < 0) {
log_err("fio: bind: %s\n", strerror(errno));
+ log_info("fio: failed with IPv%c %s\n", use_ipv6 ? '6' : '4', str);
close(sk);
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, bind_sock);
- unlink(bind_sock);
len = sizeof(addr.sun_family) + strlen(bind_sock) + 1;
return sk;
}
-int fio_server_parse_host(const char *host, int *ipv6, struct in_addr *inp,
+int fio_server_parse_host(const char *host, int ipv6, struct in_addr *inp,
struct in6_addr *inp6)
{
int ret = 0;
- if (*ipv6)
+ if (ipv6)
ret = inet_pton(AF_INET6, host, inp6);
else
ret = inet_pton(AF_INET, host, inp);
if (ret != 1) {
- struct hostent *hent;
+ struct addrinfo hints, *res;
- hent = gethostbyname(host);
- if (!hent) {
- log_err("fio: failed to resolve <%s>\n", host);
- return 0;
- }
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = ipv6 ? AF_INET6 : AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
- if (*ipv6) {
- if (hent->h_addrtype != AF_INET6) {
- log_info("fio: falling back to IPv4\n");
- *ipv6 = 0;
- } else
- memcpy(inp6, hent->h_addr_list[0], 16);
- }
- if (!*ipv6) {
- if (hent->h_addrtype != AF_INET) {
- log_err("fio: lookup type mismatch\n");
- return 0;
- }
- memcpy(inp, hent->h_addr_list[0], 4);
+ ret = getaddrinfo(host, NULL, &hints, &res);
+ if (ret) {
+ log_err("fio: failed to resolve <%s> (%s)\n", host,
+ gai_strerror(ret));
+ return 1;
}
+
+ if (ipv6)
+ memcpy(inp6, &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr, sizeof(*inp6));
+ else
+ memcpy(inp, &((struct sockaddr_in *) res->ai_addr)->sin_addr, sizeof(*inp));
+
ret = 1;
+ freeaddrinfo(res);
}
return !(ret == 1);
}
/*
- * If no port seen yet, check if there's a last ':' at the end
+ * If no port seen yet, check if there's a last ',' at the end
*/
if (!lport) {
portp = strchr(host, ',');
*ptr = strdup(host);
- if (fio_server_parse_host(*ptr, ipv6, inp, inp6)) {
+ if (fio_server_parse_host(*ptr, *ipv6, inp, inp6)) {
free(*ptr);
*ptr = NULL;
return 1;
return ret;
}
+static void sig_int(int sig)
+{
+ if (bind_sock)
+ unlink(bind_sock);
+}
+
+static void set_sig_handlers(void)
+{
+ struct sigaction act;
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sig_int;
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGINT, &act, NULL);
+}
+
static int fio_server(void)
{
int sk, ret;
if (sk < 0)
return -1;
+ set_sig_handlers();
+
ret = accept_loop(sk);
close(sk);