client.c revision bebe639808147d587bbe776566d390b9ff98773f
1132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <stdio.h>
2132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <stdlib.h>
3132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <unistd.h>
4132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <limits.h>
5132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <errno.h>
6132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <fcntl.h>
7132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <sys/poll.h>
8132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <sys/types.h>
9132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <sys/stat.h>
10132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <sys/wait.h>
11d05c4a03365f1b677c05840865e67ffaf2c5b05bJens Axboe#include <sys/socket.h>
1287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe#include <sys/un.h>
13132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <netinet/in.h>
14132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <arpa/inet.h>
15132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include <netdb.h>
169e22ecb0271038f61e00e448d8839f0c1bf6017eJens Axboe#include <signal.h>
17132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
18132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include "fio.h"
19132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include "server.h"
20b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe#include "flist.h"
213c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe#include "hash.h"
22132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
23b66570dce15587a37a64685f8ab72c3018771b2bJens Axboestruct fio_client {
24b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct flist_head list;
25bebe639808147d587bbe776566d390b9ff98773fJens Axboe	struct flist_head hash_list;
26b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct sockaddr_in addr;
2787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	struct sockaddr_un addr_un;
28b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	char *hostname;
29bebe639808147d587bbe776566d390b9ff98773fJens Axboe	int port;
30b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	int fd;
3181179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
3281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	int state;
3317dd17648d337479104cbdbe177214ddb69a18ceJens Axboe	int skip_newline;
3487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	int is_sock;
3581179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
3681179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	uint16_t argc;
3781179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	char **argv;
3881179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe};
3981179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
4081179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboeenum {
415c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe	Client_created		= 0,
4281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	Client_connected	= 1,
4381179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	Client_started		= 2,
4481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	Client_stopped		= 3,
455c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe	Client_exited		= 4,
46b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe};
47b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
48b66570dce15587a37a64685f8ab72c3018771b2bJens Axboestatic FLIST_HEAD(client_list);
49b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
503c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe#define FIO_CLIENT_HASH_BITS	7
513c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe#define FIO_CLIENT_HASH_SZ	(1 << FIO_CLIENT_HASH_BITS)
523c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe#define FIO_CLIENT_HASH_MASK	(FIO_CLIENT_HASH_SZ - 1)
53bebe639808147d587bbe776566d390b9ff98773fJens Axboestatic struct flist_head client_hash[FIO_CLIENT_HASH_SZ];
543c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
55e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboestatic int handle_client(struct fio_client *client);
560b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe
57bebe639808147d587bbe776566d390b9ff98773fJens Axboestatic void fio_client_add_hash(struct fio_client *client)
583c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe{
593c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	int bucket = hash_long(client->fd, FIO_CLIENT_HASH_BITS);
603c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
613c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	bucket &= FIO_CLIENT_HASH_MASK;
62bebe639808147d587bbe776566d390b9ff98773fJens Axboe	flist_add(&client->hash_list, &client_hash[bucket]);
633c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe}
643c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
65bebe639808147d587bbe776566d390b9ff98773fJens Axboestatic void fio_client_remove_hash(struct fio_client *client)
663c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe{
67bebe639808147d587bbe776566d390b9ff98773fJens Axboe	if (!flist_empty(&client->hash_list))
68bebe639808147d587bbe776566d390b9ff98773fJens Axboe		flist_del_init(&client->hash_list);
693c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe}
703c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
713c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboestatic void fio_init fio_client_hash_init(void)
723c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe{
733c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	int i;
743c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
75bebe639808147d587bbe776566d390b9ff98773fJens Axboe	for (i = 0; i < FIO_CLIENT_HASH_SZ; i++)
76bebe639808147d587bbe776566d390b9ff98773fJens Axboe		INIT_FLIST_HEAD(&client_hash[i]);
773c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe}
783c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
79b66570dce15587a37a64685f8ab72c3018771b2bJens Axboestatic struct fio_client *find_client_by_fd(int fd)
80b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe{
813c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	int bucket = hash_long(fd, FIO_CLIENT_HASH_BITS) & FIO_CLIENT_HASH_MASK;
82b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct fio_client *client;
83b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct flist_head *entry;
84b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
85bebe639808147d587bbe776566d390b9ff98773fJens Axboe	flist_for_each(entry, &client_hash[bucket]) {
86bebe639808147d587bbe776566d390b9ff98773fJens Axboe		client = flist_entry(entry, struct fio_client, hash_list);
87b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
88b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe		if (client->fd == fd)
89b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			return client;
90b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	}
91b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
92b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	return NULL;
93b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe}
94b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
95b66570dce15587a37a64685f8ab72c3018771b2bJens Axboestatic void remove_client(struct fio_client *client)
96b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe{
9739e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	dprint(FD_NET, "client: removed <%s>\n", client->hostname);
98b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	flist_del(&client->list);
993c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
100bebe639808147d587bbe776566d390b9ff98773fJens Axboe	fio_client_remove_hash(client);
10181179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
102b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	free(client->hostname);
10381179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	if (client->argv)
10481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe		free(client->argv);
10581179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
106b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	free(client);
1073c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	nr_clients--;
108b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe}
109132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
1107a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboestatic int __fio_client_add_cmd_option(struct fio_client *client,
1117a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe				       const char *opt)
11281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe{
11339e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	int index;
11439e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe
1157a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe	if (client->argc == FIO_NET_CMD_JOBLINE_ARGV) {
1167a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe		log_err("fio: max cmd line number reached.\n");
1177a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe		log_err("fio: cmd line <%s> has been ignored.\n", opt);
1187a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe		return 1;
1197a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe	}
1207a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe
12139e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	index = client->argc++;
12281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	client->argv = realloc(client->argv, sizeof(char *) * client->argc);
12339e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	client->argv[index] = strdup(opt);
12439e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	dprint(FD_NET, "client: add cmd %d: %s\n", index, opt);
1257a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe	return 0;
12681179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe}
12781179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
128bebe639808147d587bbe776566d390b9ff98773fJens Axboeint fio_client_add_cmd_option(void *cookie, const char *opt)
12981179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe{
130bebe639808147d587bbe776566d390b9ff98773fJens Axboe	struct fio_client *client = cookie;
13181179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
132bebe639808147d587bbe776566d390b9ff98773fJens Axboe	if (!client || !opt)
1337a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe		return 0;
13481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
1357a4b824059d9ce4b5151e904219c9b5e757ffd3bJens Axboe	return __fio_client_add_cmd_option(client, opt);
13681179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe}
13781179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
138bebe639808147d587bbe776566d390b9ff98773fJens Axboeint fio_client_add(const char *hostname, void **cookie)
139132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe{
140b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct fio_client *client;
141132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
142b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	client = malloc(sizeof(*client));
143a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	memset(client, 0, sizeof(*client));
14481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
1453c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	INIT_FLIST_HEAD(&client->list);
146bebe639808147d587bbe776566d390b9ff98773fJens Axboe	INIT_FLIST_HEAD(&client->hash_list);
1473c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
148bebe639808147d587bbe776566d390b9ff98773fJens Axboe	if (fio_server_parse_string(hostname, &client->hostname,
149bebe639808147d587bbe776566d390b9ff98773fJens Axboe					&client->is_sock, &client->port,
150bebe639808147d587bbe776566d390b9ff98773fJens Axboe					&client->addr.sin_addr))
151bebe639808147d587bbe776566d390b9ff98773fJens Axboe		return -1;
15287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
153bebe639808147d587bbe776566d390b9ff98773fJens Axboe	printf("%s %d %d\n", client->hostname, client->is_sock, client->port);
15481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
155bebe639808147d587bbe776566d390b9ff98773fJens Axboe	client->fd = -1;
1563c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
15781179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	__fio_client_add_cmd_option(client, "fio");
15881179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
159a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	flist_add(&client->list, &client_list);
160a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	nr_clients++;
161bebe639808147d587bbe776566d390b9ff98773fJens Axboe	dprint(FD_NET, "client: added <%s>\n", client->hostname);
162bebe639808147d587bbe776566d390b9ff98773fJens Axboe	*cookie = client;
163bebe639808147d587bbe776566d390b9ff98773fJens Axboe	return 0;
164a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe}
165a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
16687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboestatic int fio_client_connect_ip(struct fio_client *client)
167a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe{
168a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	int fd;
169132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
170b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	client->addr.sin_family = AF_INET;
171bebe639808147d587bbe776566d390b9ff98773fJens Axboe	client->addr.sin_port = htons(client->port);
172132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
173132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	fd = socket(AF_INET, SOCK_STREAM, 0);
174132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	if (fd < 0) {
175132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		log_err("fio: socket: %s\n", strerror(errno));
17687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		return -1;
177132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	}
178132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
179b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	if (connect(fd, (struct sockaddr *) &client->addr, sizeof(client->addr)) < 0) {
180132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		log_err("fio: connect: %s\n", strerror(errno));
181cdf54d85054858d9e3fc4d7ee8ea5c6a418f1b43Jens Axboe		log_err("fio: failed to connect to %s\n", client->hostname);
182b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
18387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		return -1;
18487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	}
18587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
18687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	return fd;
18787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe}
18887aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
18987aa8f1901e26bc377f3035a485d35c417d0255aJens Axboestatic int fio_client_connect_sock(struct fio_client *client)
19087aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe{
19187aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	struct sockaddr_un *addr = &client->addr_un;
19287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	fio_socklen_t len;
19387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	int fd;
19487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
19587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	memset(addr, 0, sizeof(*addr));
19687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	addr->sun_family = AF_UNIX;
19787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	strcpy(addr->sun_path, client->hostname);
19887aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
19987aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	fd = socket(AF_UNIX, SOCK_STREAM, 0);
20087aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	if (fd < 0) {
20187aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		log_err("fio: socket: %s\n", strerror(errno));
20287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		return -1;
20387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	}
20487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
20587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
20687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	if (connect(fd, (struct sockaddr *) addr, len) < 0) {
20787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		log_err("fio: connect; %s\n", strerror(errno));
208b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
20987aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		return -1;
210132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	}
211132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
21287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	return fd;
21387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe}
21487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
21587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboestatic int fio_client_connect(struct fio_client *client)
21687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe{
21787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	int fd;
21887aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
21987aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	dprint(FD_NET, "client: connect to host %s\n", client->hostname);
22087aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
22187aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	memset(&client->addr, 0, sizeof(client->addr));
22287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
22387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	if (client->is_sock)
22487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		fd = fio_client_connect_sock(client);
22587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	else
22687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		fd = fio_client_connect_ip(client);
22787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
22887aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	if (fd < 0)
22987aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		return 1;
23087aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
231b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	client->fd = fd;
232bebe639808147d587bbe776566d390b9ff98773fJens Axboe	fio_client_add_hash(client);
23381179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	client->state = Client_connected;
234132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	return 0;
235132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe}
236132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
237cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboevoid fio_clients_terminate(void)
238cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe{
239cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	struct flist_head *entry;
240cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	struct fio_client *client;
241cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
24260efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe	dprint(FD_NET, "client: terminate clients\n");
24360efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
244cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	flist_for_each(entry, &client_list) {
245cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe		client = flist_entry(entry, struct fio_client, list);
246cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
247cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe		fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_QUIT, 0);
248cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	}
249cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe}
250cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
251cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboestatic void sig_int(int sig)
252cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe{
253bebe639808147d587bbe776566d390b9ff98773fJens Axboe	dprint(FD_NET, "client: got signal %d\n", sig);
254cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	fio_clients_terminate();
255cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe}
256cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
257cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboestatic void client_signal_handler(void)
258cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe{
259cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	struct sigaction act;
260cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
261cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	memset(&act, 0, sizeof(act));
262cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	act.sa_handler = sig_int;
263cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	act.sa_flags = SA_RESTART;
264cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	sigaction(SIGINT, &act, NULL);
265cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
266cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	memset(&act, 0, sizeof(act));
267cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	act.sa_handler = sig_int;
268cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	act.sa_flags = SA_RESTART;
269cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	sigaction(SIGTERM, &act, NULL);
270cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe}
271cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
2720b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboestatic void probe_client(struct fio_client *client)
2730b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe{
27460efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe	dprint(FD_NET, "client: send probe\n");
27560efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
2760b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe	fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_PROBE, 0);
277e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	handle_client(client);
2780b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe}
2790b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe
28081179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboestatic int send_client_cmd_line(struct fio_client *client)
28181179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe{
28281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	struct cmd_line_pdu *pdu;
28381179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	int i, ret;
28481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
28539e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	dprint(FD_NET, "client: send cmdline %d\n", client->argc);
28660efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
28781179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	pdu = malloc(sizeof(*pdu));
28881179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	for (i = 0; i < client->argc; i++)
28981179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe		strcpy((char *) pdu->argv[i], client->argv[i]);
29081179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
29181179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	pdu->argc = cpu_to_le16(client->argc);
29281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	ret = fio_net_send_cmd(client->fd, FIO_NET_CMD_JOBLINE, pdu, sizeof(*pdu));
29381179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	free(pdu);
29481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	return ret;
29581179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe}
29681179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
297a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboeint fio_clients_connect(void)
298a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe{
299a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	struct fio_client *client;
300a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	struct flist_head *entry, *tmp;
301a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	int ret;
302a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
30360efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe	dprint(FD_NET, "client: connect all\n");
30460efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
305cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	client_signal_handler();
306cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
307a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	flist_for_each_safe(entry, tmp, &client_list) {
308a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe		client = flist_entry(entry, struct fio_client, list);
309a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
310a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe		ret = fio_client_connect(client);
3110b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		if (ret) {
312a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe			remove_client(client);
3130b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe			continue;
3140b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		}
3150b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe
3160b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		probe_client(client);
31781179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
31881179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe		if (client->argc > 1)
31981179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe			send_client_cmd_line(client);
320a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	}
321a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
322a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	return !nr_clients;
323a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe}
324a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
325132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe/*
326132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe * Send file contents to server backend. We could use sendfile(), but to remain
327132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe * more portable lets just read/write the darn thing.
328132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe */
329a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboestatic int fio_client_send_ini(struct fio_client *client, const char *filename)
330132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe{
331132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	struct stat sb;
332132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	char *p, *buf;
333132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	off_t len;
334132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	int fd, ret;
335132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
33646c48f1f9b8ce94132c13638e4c83c13e1d392daJens Axboe	dprint(FD_NET, "send ini %s to %s\n", filename, client->hostname);
33746c48f1f9b8ce94132c13638e4c83c13e1d392daJens Axboe
338132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	fd = open(filename, O_RDONLY);
339132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	if (fd < 0) {
340e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		log_err("fio: job file <%s> open: %s\n", filename, strerror(errno));
341132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		return 1;
342132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	}
343132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
344132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	if (fstat(fd, &sb) < 0) {
345132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		log_err("fio: job file stat: %s\n", strerror(errno));
346b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
347132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		return 1;
348132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	}
349132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
350132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	buf = malloc(sb.st_size);
351132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
352132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	len = sb.st_size;
353132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	p = buf;
354132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	do {
355132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		ret = read(fd, p, len);
356132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		if (ret > 0) {
357132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			len -= ret;
358132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			if (!len)
359132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe				break;
360132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			p += ret;
361132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			continue;
362132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		} else if (!ret)
363132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			break;
364132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		else if (errno == EAGAIN || errno == EINTR)
365132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			continue;
366132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	} while (1);
367132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
3680b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe	if (len) {
3690b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		log_err("fio: failed reading job file %s\n", filename);
370b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
3710b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		return 1;
3720b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe	}
3730b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe
37481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	ret = fio_net_send_cmd(client->fd, FIO_NET_CMD_JOB, buf, sb.st_size);
375132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	free(buf);
376b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe	close(fd);
377132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	return ret;
378132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe}
37937db14feece08eb6e43de87c404180650ed5aa6fJens Axboe
380a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboeint fio_clients_send_ini(const char *filename)
381a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe{
382a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	struct fio_client *client;
383a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	struct flist_head *entry, *tmp;
384a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
385a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	flist_for_each_safe(entry, tmp, &client_list) {
386a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe		client = flist_entry(entry, struct fio_client, list);
387a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
388a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe		if (fio_client_send_ini(client, filename))
389a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe			remove_client(client);
390a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	}
391a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
392a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	return !nr_clients;
393a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe}
394a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
395a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboestatic void convert_io_stat(struct io_stat *dst, struct io_stat *src)
396a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
397a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->max_val	= le64_to_cpu(src->max_val);
398a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->min_val	= le64_to_cpu(src->min_val);
399a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->samples	= le64_to_cpu(src->samples);
400802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe
401802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	/*
402802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	 * Floats arrive as IEEE 754 encoded uint64_t, convert back to double
403802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	 */
404802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	dst->mean.u.f	= fio_uint64_to_double(le64_to_cpu(dst->mean.u.i));
405802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	dst->S.u.f	= fio_uint64_to_double(le64_to_cpu(dst->S.u.i));
406a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
407a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
408a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboestatic void convert_ts(struct thread_stat *dst, struct thread_stat *src)
409a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
410a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	int i, j;
411a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
412a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->error	= le32_to_cpu(src->error);
413a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->groupid	= le32_to_cpu(src->groupid);
414a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->pid	= le32_to_cpu(src->pid);
415a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->members	= le32_to_cpu(src->members);
416a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
417a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 2; i++) {
418a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		convert_io_stat(&dst->clat_stat[i], &src->clat_stat[i]);
419a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		convert_io_stat(&dst->slat_stat[i], &src->slat_stat[i]);
420a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		convert_io_stat(&dst->lat_stat[i], &src->lat_stat[i]);
421a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		convert_io_stat(&dst->bw_stat[i], &src->bw_stat[i]);
422a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
423a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
424a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->usr_time		= le64_to_cpu(src->usr_time);
425a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->sys_time		= le64_to_cpu(src->sys_time);
426a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->ctx		= le64_to_cpu(src->ctx);
427a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->minf		= le64_to_cpu(src->minf);
428a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->majf		= le64_to_cpu(src->majf);
429a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->clat_percentiles	= le64_to_cpu(src->clat_percentiles);
430802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe
431802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	for (i = 0; i < FIO_IO_U_LIST_MAX_LEN; i++) {
432802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe		fio_fp64_t *fps = &src->percentile_list[i];
433802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe		fio_fp64_t *fpd = &dst->percentile_list[i];
434802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe
435802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe		fpd->u.f = fio_uint64_to_double(le64_to_cpu(fps->u.i));
436802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	}
437a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
438a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < FIO_IO_U_MAP_NR; i++) {
439a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_map[i]	= le32_to_cpu(src->io_u_map[i]);
440a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_submit[i]	= le32_to_cpu(src->io_u_submit[i]);
441a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_complete[i]	= le32_to_cpu(src->io_u_complete[i]);
442a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
443a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
444a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < FIO_IO_U_LAT_U_NR; i++) {
445a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_lat_u[i]	= le32_to_cpu(src->io_u_lat_u[i]);
446a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_lat_m[i]	= le32_to_cpu(src->io_u_lat_m[i]);
447a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
448a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
449a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 2; i++)
450a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		for (j = 0; j < FIO_IO_U_PLAT_NR; j++)
451a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe			dst->io_u_plat[i][j] = le32_to_cpu(src->io_u_plat[i][j]);
452a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
453a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 3; i++) {
454a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->total_io_u[i]	= le64_to_cpu(src->total_io_u[i]);
45593eee04aef9ed39070ce2e69bd1f661a95b1d50aJens Axboe		dst->short_io_u[i]	= le64_to_cpu(src->short_io_u[i]);
456a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
457a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
458a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->total_submit	= le64_to_cpu(src->total_submit);
459a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->total_complete	= le64_to_cpu(src->total_complete);
460a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
461a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 2; i++) {
462a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_bytes[i]	= le64_to_cpu(src->io_bytes[i]);
463a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->runtime[i]		= le64_to_cpu(src->runtime[i]);
464a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
465a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
466a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->total_run_time	= le64_to_cpu(src->total_run_time);
467a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->continue_on_error	= le16_to_cpu(src->continue_on_error);
468a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->total_err_count	= le64_to_cpu(src->total_err_count);
469ddcc0b69aa4ed04c8681f447a1a6274bb8837a14Jens Axboe	dst->first_error	= le32_to_cpu(src->first_error);
470ddcc0b69aa4ed04c8681f447a1a6274bb8837a14Jens Axboe	dst->kb_base		= le32_to_cpu(src->kb_base);
471a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
472a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
473a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboestatic void convert_gs(struct group_run_stats *dst, struct group_run_stats *src)
474a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
475a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	int i;
476a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
477a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 2; i++) {
478a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->max_run[i]		= le64_to_cpu(src->max_run[i]);
479a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->min_run[i]		= le64_to_cpu(src->min_run[i]);
480a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->max_bw[i]		= le64_to_cpu(src->max_bw[i]);
481a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->min_bw[i]		= le64_to_cpu(src->min_bw[i]);
482a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_kb[i]		= le64_to_cpu(src->io_kb[i]);
483a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->agg[i]		= le64_to_cpu(src->agg[i]);
484a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
485a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
486a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->kb_base	= le32_to_cpu(src->kb_base);
487a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->groupid	= le32_to_cpu(src->groupid);
488a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
489a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
490a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboestatic void handle_ts(struct fio_net_cmd *cmd)
491a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
492a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload;
493a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
494a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	convert_ts(&p->ts, &p->ts);
495a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	convert_gs(&p->rs, &p->rs);
496a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
497a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	show_thread_status(&p->ts, &p->rs);
498a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
499a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
500a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboestatic void handle_gs(struct fio_net_cmd *cmd)
501a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
502a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	struct group_run_stats *gs = (struct group_run_stats *) cmd->payload;
503a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
504a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	convert_gs(gs, gs);
505a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	show_group_stats(gs);
506a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
507a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
508cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboestatic void handle_eta(struct fio_net_cmd *cmd)
509cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe{
510cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	struct jobs_eta *je = (struct jobs_eta *) cmd->payload;
511cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	int i;
512cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
513cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->nr_running		= le32_to_cpu(je->nr_running);
514cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->nr_ramp		= le32_to_cpu(je->nr_ramp);
515cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->nr_pending		= le32_to_cpu(je->nr_pending);
516cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->files_open		= le32_to_cpu(je->files_open);
517cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->m_rate		= le32_to_cpu(je->m_rate);
518cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->t_rate		= le32_to_cpu(je->t_rate);
519cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->m_iops		= le32_to_cpu(je->m_iops);
520cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->t_iops		= le32_to_cpu(je->t_iops);
521cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
522cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	for (i = 0; i < 2; i++) {
523cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe		je->rate[i]	= le32_to_cpu(je->rate[i]);
524cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe		je->iops[i]	= le32_to_cpu(je->iops[i]);
525cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	}
526cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
527cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->elapsed_sec		= le32_to_cpu(je->nr_running);
528cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->eta_sec		= le64_to_cpu(je->eta_sec);
529cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
530cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	display_thread_status(je);
531cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe}
532cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
5332e03b4b2a072b79946b0ee651dff38273868473aJens Axboestatic void handle_probe(struct fio_net_cmd *cmd)
5342e03b4b2a072b79946b0ee651dff38273868473aJens Axboe{
5352e03b4b2a072b79946b0ee651dff38273868473aJens Axboe	struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload;
5362e03b4b2a072b79946b0ee651dff38273868473aJens Axboe
5376eb2479194603184f393057ea10326643edc7169Jens Axboe	log_info("Probe: hostname=%s, be=%u, fio ver %u.%u.%u\n",
5386eb2479194603184f393057ea10326643edc7169Jens Axboe		probe->hostname, probe->bigendian, probe->fio_major,
5396eb2479194603184f393057ea10326643edc7169Jens Axboe		probe->fio_minor, probe->fio_patch);
5402e03b4b2a072b79946b0ee651dff38273868473aJens Axboe}
5412e03b4b2a072b79946b0ee651dff38273868473aJens Axboe
542e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboestatic int handle_client(struct fio_client *client)
54337db14feece08eb6e43de87c404180650ed5aa6fJens Axboe{
54437db14feece08eb6e43de87c404180650ed5aa6fJens Axboe	struct fio_net_cmd *cmd;
54537db14feece08eb6e43de87c404180650ed5aa6fJens Axboe
54660efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe	dprint(FD_NET, "client: handle %s\n", client->hostname);
54760efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
548e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	cmd = fio_net_recv_cmd(client->fd);
549e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	if (!cmd)
550e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		return 0;
551c2c9458515bda1f77e25f95122ef6ec8d8cc3ec7Jens Axboe
552e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	dprint(FD_NET, "client: got cmd op %d from %s\n",
553c2c9458515bda1f77e25f95122ef6ec8d8cc3ec7Jens Axboe					cmd->opcode, client->hostname);
55446c48f1f9b8ce94132c13638e4c83c13e1d392daJens Axboe
555e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	switch (cmd->opcode) {
556e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_QUIT:
557e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		remove_client(client);
558e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
559e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
560e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_TEXT: {
561e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		const char *buf = (const char *) cmd->payload;
562e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		int fio_unused ret;
563e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe
564e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		if (!client->skip_newline)
565e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe			fprintf(f_out, "<%s> ", client->hostname);
566e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		ret = fwrite(buf, cmd->pdu_len, 1, f_out);
567e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		fflush(f_out);
568e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		client->skip_newline = strchr(buf, '\n') == NULL;
569e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
570e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
57137db14feece08eb6e43de87c404180650ed5aa6fJens Axboe		}
572e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_TS:
573e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		handle_ts(cmd);
574e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
575e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
576e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_GS:
577e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		handle_gs(cmd);
578e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
579e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
580e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_ETA:
581e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		handle_eta(cmd);
582e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
583e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
584e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_PROBE:
585e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		handle_probe(cmd);
586e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
587e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
588e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_START:
589e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		client->state = Client_started;
590e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
591e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
592e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_STOP:
593e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		client->state = Client_stopped;
594e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
595e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
596e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	default:
597e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		log_err("fio: unknown client op: %d\n", cmd->opcode);
598e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
599e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
60037db14feece08eb6e43de87c404180650ed5aa6fJens Axboe	}
60137db14feece08eb6e43de87c404180650ed5aa6fJens Axboe
602e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	return 1;
60337db14feece08eb6e43de87c404180650ed5aa6fJens Axboe}
604b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
605b66570dce15587a37a64685f8ab72c3018771b2bJens Axboeint fio_handle_clients(void)
606b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe{
607b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct fio_client *client;
608b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct flist_head *entry;
609b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct pollfd *pfds;
61082a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe	int i, ret = 0;
611b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
612b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	pfds = malloc(nr_clients * sizeof(struct pollfd));
613b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
61482a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe	while (!exit_backend && nr_clients) {
61582a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe		i = 0;
61682a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe		flist_for_each(entry, &client_list) {
61782a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe			client = flist_entry(entry, struct fio_client, list);
618b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
61982a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe			pfds[i].fd = client->fd;
62082a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe			pfds[i].events = POLLIN;
62182a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe			i++;
62282a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe		}
62382a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe
62482a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe		assert(i == nr_clients);
625b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
6265c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe		do {
6275c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe			ret = poll(pfds, nr_clients, 100);
6285c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe			if (ret < 0) {
6295c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe				if (errno == EINTR)
6305c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe					continue;
6315c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe				log_err("fio: poll clients: %s\n", strerror(errno));
6325c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe				break;
6335c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe			} else if (!ret)
634b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe				continue;
6355c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe		} while (ret <= 0);
636b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
637b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe		for (i = 0; i < nr_clients; i++) {
638b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			if (!(pfds[i].revents & POLLIN))
639b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe				continue;
640b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
641b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			client = find_client_by_fd(pfds[i].fd);
642b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			if (!client) {
6433c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe				log_err("fio: unknown client fd %d\n", pfds[i].fd);
644b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe				continue;
645b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			}
646e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe			if (!handle_client(client)) {
64728d3ab07f7c68afe9ad3b07bb9c288f3e94957daJens Axboe				log_info("client: host=%s disconnected\n",
64828d3ab07f7c68afe9ad3b07bb9c288f3e94957daJens Axboe						client->hostname);
64928d3ab07f7c68afe9ad3b07bb9c288f3e94957daJens Axboe				remove_client(client);
65028d3ab07f7c68afe9ad3b07bb9c288f3e94957daJens Axboe			}
651b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe		}
652b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	}
653b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
654b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	free(pfds);
655b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	return 0;
656b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe}
657