client.c revision 3c3ed070502bbfec387ded2c43d5e4559ca24a63
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>
171b42725f06f8906b9b99381da3490484f59df28aJens Axboe#include <zlib.h>
18132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
19132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include "fio.h"
20dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameron#include "client.h"
21132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe#include "server.h"
22b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe#include "flist.h"
233c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe#include "hash.h"
24132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
25dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameronstatic void handle_du(struct fio_client *client, struct fio_net_cmd *cmd);
2689e5fad91bc33f1687cca6b1bf5aa3084c424650Jens Axboestatic void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd);
2789e5fad91bc33f1687cca6b1bf5aa3084c424650Jens Axboestatic void handle_gs(struct fio_client *client, struct fio_net_cmd *cmd);
28dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameronstatic void handle_probe(struct fio_client *client, struct fio_net_cmd *cmd);
29084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboestatic void handle_text(struct fio_client *client, struct fio_net_cmd *cmd);
306b79c80c14766df7b0507c4ec679507a315ad61aJens Axboestatic void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd);
3185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboestatic void handle_start(struct fio_client *client, struct fio_net_cmd *cmd);
32dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameron
33dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameronstruct client_ops fio_client_ops = {
3435c0ba7ff55bbd438cdc171945c61d501a4e693eJens Axboe	.text		= handle_text,
350420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	.disk_util	= handle_du,
360420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	.thread_status	= handle_ts,
370420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	.group_stats	= handle_gs,
386b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe	.stop		= handle_stop,
3985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	.start		= handle_start,
40a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe	.eta		= display_thread_status,
410420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	.probe		= handle_probe,
426433ee054a5dc6533066e105baee4ff85197d392Jens Axboe	.eta_msec	= FIO_CLIENT_DEF_ETA_MSEC,
4346bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	.client_type	= FIO_CLIENT_TYPE_CLI,
44dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameron};
45dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameron
46af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboestatic struct timeval eta_tv;
4748fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe
48b66570dce15587a37a64685f8ab72c3018771b2bJens Axboestatic FLIST_HEAD(client_list);
4982c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboestatic FLIST_HEAD(eta_list);
50b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
513f3a4542887ba038231144be08b2c36d7cc83424Jens Axboestatic FLIST_HEAD(arg_list);
523f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe
533650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboestruct thread_stat client_ts;
543650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboestruct group_run_stats client_gs;
553650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboeint sum_stat_clients;
563650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe
5737f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboestatic int sum_stat_nr;
5837f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe
593c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe#define FIO_CLIENT_HASH_BITS	7
603c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe#define FIO_CLIENT_HASH_SZ	(1 << FIO_CLIENT_HASH_BITS)
613c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe#define FIO_CLIENT_HASH_MASK	(FIO_CLIENT_HASH_SZ - 1)
62bebe639808147d587bbe776566d390b9ff98773fJens Axboestatic struct flist_head client_hash[FIO_CLIENT_HASH_SZ];
633c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
64bebe639808147d587bbe776566d390b9ff98773fJens Axboestatic void fio_client_add_hash(struct fio_client *client)
653c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe{
663c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	int bucket = hash_long(client->fd, FIO_CLIENT_HASH_BITS);
673c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
683c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	bucket &= FIO_CLIENT_HASH_MASK;
69bebe639808147d587bbe776566d390b9ff98773fJens Axboe	flist_add(&client->hash_list, &client_hash[bucket]);
703c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe}
713c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
72bebe639808147d587bbe776566d390b9ff98773fJens Axboestatic void fio_client_remove_hash(struct fio_client *client)
733c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe{
74bebe639808147d587bbe776566d390b9ff98773fJens Axboe	if (!flist_empty(&client->hash_list))
75bebe639808147d587bbe776566d390b9ff98773fJens Axboe		flist_del_init(&client->hash_list);
763c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe}
773c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
783c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboestatic void fio_init fio_client_hash_init(void)
793c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe{
803c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	int i;
813c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
82bebe639808147d587bbe776566d390b9ff98773fJens Axboe	for (i = 0; i < FIO_CLIENT_HASH_SZ; i++)
83bebe639808147d587bbe776566d390b9ff98773fJens Axboe		INIT_FLIST_HEAD(&client_hash[i]);
843c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe}
853c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
86b66570dce15587a37a64685f8ab72c3018771b2bJens Axboestatic struct fio_client *find_client_by_fd(int fd)
87b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe{
883c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	int bucket = hash_long(fd, FIO_CLIENT_HASH_BITS) & FIO_CLIENT_HASH_MASK;
89b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct fio_client *client;
90b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct flist_head *entry;
91b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
92bebe639808147d587bbe776566d390b9ff98773fJens Axboe	flist_for_each(entry, &client_hash[bucket]) {
93bebe639808147d587bbe776566d390b9ff98773fJens Axboe		client = flist_entry(entry, struct fio_client, hash_list);
94b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
95e55f8f307385e77ea561e7bbf9c76842ead9d7a3Jens Axboe		if (client->fd == fd) {
96e55f8f307385e77ea561e7bbf9c76842ead9d7a3Jens Axboe			client->refs++;
97b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			return client;
98e55f8f307385e77ea561e7bbf9c76842ead9d7a3Jens Axboe		}
99b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	}
100b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
101b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	return NULL;
102b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe}
103b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
1043af452010d32267d085ba1612ebc0a40812c28a9Jens Axboevoid fio_put_client(struct fio_client *client)
105b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe{
1065121a9aa0299a2c23b3c50bf110ab4a05677c740Jens Axboe	if (--client->refs)
1075121a9aa0299a2c23b3c50bf110ab4a05677c740Jens Axboe		return;
1085121a9aa0299a2c23b3c50bf110ab4a05677c740Jens Axboe
1093af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe	free(client->hostname);
1103af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe	if (client->argv)
1113af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe		free(client->argv);
1123af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe	if (client->name)
1133af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe		free(client->name);
1143af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe
1153af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe	free(client);
1163af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe}
1173af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe
1183af452010d32267d085ba1612ebc0a40812c28a9Jens Axboestatic void remove_client(struct fio_client *client)
1193af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe{
1203af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe	assert(client->refs);
1213af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe
12239e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	dprint(FD_NET, "client: removed <%s>\n", client->hostname);
1233af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe
1243af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe	if (!flist_empty(&client->list))
1253af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe		flist_del_init(&client->list);
1263c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
127bebe639808147d587bbe776566d390b9ff98773fJens Axboe	fio_client_remove_hash(client);
12881179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
12982c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe	if (!flist_empty(&client->eta_list)) {
13082c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe		flist_del_init(&client->eta_list);
131a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe		fio_client_dec_jobs_eta(client->eta_in_flight, client->ops->eta);
13282c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe	}
133af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
1341e0c184e7cf03c8126e6e8dff4c45584283e6b9bJens Axboe	close(client->fd);
1351e0c184e7cf03c8126e6e8dff4c45584283e6b9bJens Axboe	client->fd = -1;
1361e0c184e7cf03c8126e6e8dff4c45584283e6b9bJens Axboe
1370cf3ece062d6856bd79b89770780296c99937a98Jens Axboe	if (client->ops->removed)
1380cf3ece062d6856bd79b89770780296c99937a98Jens Axboe		client->ops->removed(client);
1390cf3ece062d6856bd79b89770780296c99937a98Jens Axboe
1403c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	nr_clients--;
1415fd0acbd212296542d396b07e1873b9e3093b76fJens Axboe	sum_stat_clients--;
142132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
1433af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe	fio_put_client(client);
1445121a9aa0299a2c23b3c50bf110ab4a05677c740Jens Axboe}
1455121a9aa0299a2c23b3c50bf110ab4a05677c740Jens Axboe
146343cb4a98200757bdcb0c5203e9120bb777625a8Jens Axboestruct fio_client *fio_get_client(struct fio_client *client)
147343cb4a98200757bdcb0c5203e9120bb777625a8Jens Axboe{
148343cb4a98200757bdcb0c5203e9120bb777625a8Jens Axboe	client->refs++;
149343cb4a98200757bdcb0c5203e9120bb777625a8Jens Axboe	return client;
150343cb4a98200757bdcb0c5203e9120bb777625a8Jens Axboe}
151343cb4a98200757bdcb0c5203e9120bb777625a8Jens Axboe
152fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboestatic void __fio_client_add_cmd_option(struct fio_client *client,
153fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe					const char *opt)
15481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe{
15539e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	int index;
15639e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe
15739e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	index = client->argc++;
15881179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	client->argv = realloc(client->argv, sizeof(char *) * client->argc);
15939e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	client->argv[index] = strdup(opt);
16039e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	dprint(FD_NET, "client: add cmd %d: %s\n", index, opt);
16181179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe}
16281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
163fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboevoid fio_client_add_cmd_option(void *cookie, const char *opt)
16481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe{
165bebe639808147d587bbe776566d390b9ff98773fJens Axboe	struct fio_client *client = cookie;
1663f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	struct flist_head *entry;
16781179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
168bebe639808147d587bbe776566d390b9ff98773fJens Axboe	if (!client || !opt)
169fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe		return;
17081179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
171fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	__fio_client_add_cmd_option(client, opt);
1723f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe
1733f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	/*
1743f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	 * Duplicate arguments to shared client group
1753f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	 */
1763f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	flist_for_each(entry, &arg_list) {
1773f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		client = flist_entry(entry, struct fio_client, arg_list);
1783f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe
1793f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		__fio_client_add_cmd_option(client, opt);
1803f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	}
18181179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe}
18281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
183a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboestruct fio_client *fio_client_add_explicit(struct client_ops *ops,
184a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe					   const char *hostname, int type,
1853ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe					   int port)
1863ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe{
1873ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	struct fio_client *client;
1883ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
1893ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	client = malloc(sizeof(*client));
1903ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	memset(client, 0, sizeof(*client));
1913ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
1923ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	INIT_FLIST_HEAD(&client->list);
1933ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	INIT_FLIST_HEAD(&client->hash_list);
1943ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	INIT_FLIST_HEAD(&client->arg_list);
1953ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	INIT_FLIST_HEAD(&client->eta_list);
1963ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	INIT_FLIST_HEAD(&client->cmd_list);
1973ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
1983ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	client->hostname = strdup(hostname);
1993ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
2003ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	if (type == Fio_client_socket)
2013ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe		client->is_sock = 1;
2023ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	else {
2033ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe		int ipv6;
2043ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
2053ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe		ipv6 = type == Fio_client_ipv6;
2063ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe		if (fio_server_parse_host(hostname, &ipv6,
2073ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe						&client->addr.sin_addr,
2083ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe						&client->addr6.sin6_addr))
2093ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe			goto err;
2103ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
2113ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe		client->port = port;
2123ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	}
2133ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
2143ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	client->fd = -1;
215a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe	client->ops = ops;
2165121a9aa0299a2c23b3c50bf110ab4a05677c740Jens Axboe	client->refs = 1;
21746bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	client->type = ops->client_type;
2183ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
2193ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	__fio_client_add_cmd_option(client, "fio");
2203ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
2213ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	flist_add(&client->list, &client_list);
2223ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	nr_clients++;
2233ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	dprint(FD_NET, "client: added <%s>\n", client->hostname);
2243ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	return client;
2253ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboeerr:
2263ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	free(client);
2273ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	return NULL;
2283ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe}
2293ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
230a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboeint fio_client_add(struct client_ops *ops, const char *hostname, void **cookie)
231132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe{
2323f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	struct fio_client *existing = *cookie;
233b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct fio_client *client;
234132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
2353f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	if (existing) {
2363f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		/*
2373f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		 * We always add our "exec" name as the option, hence 1
2383f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		 * means empty.
2393f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		 */
2403f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		if (existing->argc == 1)
2413f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe			flist_add_tail(&existing->arg_list, &arg_list);
2423f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		else {
2433f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe			while (!flist_empty(&arg_list))
2443f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe				flist_del_init(arg_list.next);
2453f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe		}
2463f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	}
2473f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe
248b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	client = malloc(sizeof(*client));
249a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	memset(client, 0, sizeof(*client));
25081179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
2513c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe	INIT_FLIST_HEAD(&client->list);
252bebe639808147d587bbe776566d390b9ff98773fJens Axboe	INIT_FLIST_HEAD(&client->hash_list);
2533f3a4542887ba038231144be08b2c36d7cc83424Jens Axboe	INIT_FLIST_HEAD(&client->arg_list);
25482c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe	INIT_FLIST_HEAD(&client->eta_list);
25589c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	INIT_FLIST_HEAD(&client->cmd_list);
2563c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
257bebe639808147d587bbe776566d390b9ff98773fJens Axboe	if (fio_server_parse_string(hostname, &client->hostname,
258bebe639808147d587bbe776566d390b9ff98773fJens Axboe					&client->is_sock, &client->port,
259811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe					&client->addr.sin_addr,
260811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe					&client->addr6.sin6_addr,
261811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe					&client->ipv6))
262bebe639808147d587bbe776566d390b9ff98773fJens Axboe		return -1;
26387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
264bebe639808147d587bbe776566d390b9ff98773fJens Axboe	client->fd = -1;
265a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe	client->ops = ops;
2665121a9aa0299a2c23b3c50bf110ab4a05677c740Jens Axboe	client->refs = 1;
26746bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	client->type = ops->client_type;
2683c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe
26981179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	__fio_client_add_cmd_option(client, "fio");
27081179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
271a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	flist_add(&client->list, &client_list);
272a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	nr_clients++;
273bebe639808147d587bbe776566d390b9ff98773fJens Axboe	dprint(FD_NET, "client: added <%s>\n", client->hostname);
274bebe639808147d587bbe776566d390b9ff98773fJens Axboe	*cookie = client;
275bebe639808147d587bbe776566d390b9ff98773fJens Axboe	return 0;
276a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe}
277a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
278d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboestatic void probe_client(struct fio_client *client)
279d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboe{
280d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboe	dprint(FD_NET, "client: send probe\n");
281d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboe
282d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboe	fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_PROBE, 0, &client->cmd_list);
283d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboe}
284d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboe
28587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboestatic int fio_client_connect_ip(struct fio_client *client)
286a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe{
287811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe	struct sockaddr *addr;
288811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe	fio_socklen_t socklen;
289811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe	int fd, domain;
290811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe
291811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe	if (client->ipv6) {
292811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		client->addr6.sin6_family = AF_INET6;
293811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		client->addr6.sin6_port = htons(client->port);
294811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		domain = AF_INET6;
295811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		addr = (struct sockaddr *) &client->addr6;
296811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		socklen = sizeof(client->addr6);
297811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe	} else {
298811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		client->addr.sin_family = AF_INET;
299811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		client->addr.sin_port = htons(client->port);
300811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		domain = AF_INET;
301811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		addr = (struct sockaddr *) &client->addr;
302811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe		socklen = sizeof(client->addr);
303811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe	}
304132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
305811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe	fd = socket(domain, SOCK_STREAM, 0);
306132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	if (fd < 0) {
30725095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		int ret = -errno;
30825095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe
309132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		log_err("fio: socket: %s\n", strerror(errno));
31025095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		return ret;
311132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	}
312132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
313811826be429fd6fc5154d9b04ced1cd22bd66758Jens Axboe	if (connect(fd, addr, socklen) < 0) {
31425095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		int ret = -errno;
31525095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe
316132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		log_err("fio: connect: %s\n", strerror(errno));
317a7de0a1163e63cb6fa0a6bad773c415d06d154acJens Axboe		log_err("fio: failed to connect to %s:%u\n", client->hostname,
318a7de0a1163e63cb6fa0a6bad773c415d06d154acJens Axboe								client->port);
319b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
32025095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		return ret;
32187aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	}
32287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
32387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	return fd;
32487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe}
32587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
32687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboestatic int fio_client_connect_sock(struct fio_client *client)
32787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe{
32887aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	struct sockaddr_un *addr = &client->addr_un;
32987aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	fio_socklen_t len;
33087aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	int fd;
33187aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
33287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	memset(addr, 0, sizeof(*addr));
33387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	addr->sun_family = AF_UNIX;
33487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	strcpy(addr->sun_path, client->hostname);
33587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
33687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	fd = socket(AF_UNIX, SOCK_STREAM, 0);
33787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	if (fd < 0) {
33825095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		int ret = -errno;
33925095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe
34087aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		log_err("fio: socket: %s\n", strerror(errno));
34125095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		return ret;
34287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	}
34387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
34487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	len = sizeof(addr->sun_family) + strlen(addr->sun_path) + 1;
34587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	if (connect(fd, (struct sockaddr *) addr, len) < 0) {
34625095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		int ret = -errno;
34725095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe
34887aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		log_err("fio: connect; %s\n", strerror(errno));
349b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
35025095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		return ret;
351132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	}
352132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
35387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	return fd;
35487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe}
35587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
3562f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboeint fio_client_connect(struct fio_client *client)
35787aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe{
35887aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	int fd;
35987aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
36087aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	dprint(FD_NET, "client: connect to host %s\n", client->hostname);
36187aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
36287aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	if (client->is_sock)
36387aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		fd = fio_client_connect_sock(client);
36487aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	else
36587aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe		fd = fio_client_connect_ip(client);
36687aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
36789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	dprint(FD_NET, "client: %s connected %d\n", client->hostname, fd);
36889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
36987aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe	if (fd < 0)
370a1a3ed5143e7fe153d114f9ff96bfbc5dc14a156Jens Axboe		return fd;
37187aa8f1901e26bc377f3035a485d35c417d0255aJens Axboe
372b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	client->fd = fd;
373bebe639808147d587bbe776566d390b9ff98773fJens Axboe	fio_client_add_hash(client);
37481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	client->state = Client_connected;
375d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboe
376d824c3b8b5847e8de80511f3aafda939a3f61bb8Jens Axboe	probe_client(client);
377132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	return 0;
378132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe}
379132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
3800cf3ece062d6856bd79b89770780296c99937a98Jens Axboeint fio_client_terminate(struct fio_client *client)
3812f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe{
3820cf3ece062d6856bd79b89770780296c99937a98Jens Axboe	return fio_net_send_quit(client->fd);
3832f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe}
3842f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
385cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboevoid fio_clients_terminate(void)
386cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe{
387cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	struct flist_head *entry;
388cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	struct fio_client *client;
389cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
39060efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe	dprint(FD_NET, "client: terminate clients\n");
39160efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
392cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	flist_for_each(entry, &client_list) {
393cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe		client = flist_entry(entry, struct fio_client, list);
3942f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe		fio_client_terminate(client);
395cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	}
396cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe}
397cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
398cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboestatic void sig_int(int sig)
399cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe{
400bebe639808147d587bbe776566d390b9ff98773fJens Axboe	dprint(FD_NET, "client: got signal %d\n", sig);
401cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	fio_clients_terminate();
402cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe}
403cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
404cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboestatic void client_signal_handler(void)
405cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe{
406cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	struct sigaction act;
407cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
408cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	memset(&act, 0, sizeof(act));
409cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	act.sa_handler = sig_int;
410cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	act.sa_flags = SA_RESTART;
411cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	sigaction(SIGINT, &act, NULL);
412cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
413cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	memset(&act, 0, sizeof(act));
414cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	act.sa_handler = sig_int;
415cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	act.sa_flags = SA_RESTART;
416cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	sigaction(SIGTERM, &act, NULL);
417cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe}
418cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
41981179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboestatic int send_client_cmd_line(struct fio_client *client)
42081179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe{
421fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	struct cmd_single_line_pdu *cslp;
422fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	struct cmd_line_pdu *clp;
423fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	unsigned long offset;
4247f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe	unsigned int *lens;
425fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	void *pdu;
426fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	size_t mem;
42781179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	int i, ret;
42881179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
42939e8e01691c9d5765795417ee49a40d5ae08cb8bJens Axboe	dprint(FD_NET, "client: send cmdline %d\n", client->argc);
43060efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
4317f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe	lens = malloc(client->argc * sizeof(unsigned int));
4327f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe
433fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	/*
434fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	 * Find out how much mem we need
435fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	 */
4367f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe	for (i = 0, mem = 0; i < client->argc; i++) {
4377f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe		lens[i] = strlen(client->argv[i]) + 1;
4387f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe		mem += lens[i];
4397f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe	}
440fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe
441fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	/*
442fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	 * We need one cmd_line_pdu, and argc number of cmd_single_line_pdu
443fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	 */
444fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	mem += sizeof(*clp) + (client->argc * sizeof(*cslp));
445fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe
446fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	pdu = malloc(mem);
447fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	clp = pdu;
448fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	offset = sizeof(*clp);
449fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe
450fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	for (i = 0; i < client->argc; i++) {
4517f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe		uint16_t arg_len = lens[i];
452fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe
453fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe		cslp = pdu + offset;
454fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe		strcpy((char *) cslp->text, client->argv[i]);
455fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe		cslp->len = cpu_to_le16(arg_len);
456fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe		offset += sizeof(*cslp) + arg_len;
457fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	}
45881179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
4597f868316a7244cad23735e44e6ef66e5779c9660Jens Axboe	free(lens);
460fa2ea806de0d6410320abd97599bc52f5a3e72ccJens Axboe	clp->lines = cpu_to_le16(client->argc);
46146bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	clp->client_type = __cpu_to_le16(client->type);
462af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	ret = fio_net_send_cmd(client->fd, FIO_NET_CMD_JOBLINE, pdu, mem, 0);
46381179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	free(pdu);
46481179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe	return ret;
46581179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe}
46681179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe
467a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboeint fio_clients_connect(void)
468a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe{
469a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	struct fio_client *client;
470a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	struct flist_head *entry, *tmp;
471a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	int ret;
472a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
47393bcfd20e37cef8cec350fe06d3a086724c9f257Bruce Cran#ifdef WIN32
47493bcfd20e37cef8cec350fe06d3a086724c9f257Bruce Cran	WSADATA wsd;
4753c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe	WSAStartup(MAKEWORD(2, 2), &wsd);
47693bcfd20e37cef8cec350fe06d3a086724c9f257Bruce Cran#endif
47793bcfd20e37cef8cec350fe06d3a086724c9f257Bruce Cran
47860efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe	dprint(FD_NET, "client: connect all\n");
47960efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
480cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe	client_signal_handler();
481cc0df00ad5076d4adbc439899f24d9b0db26075dJens Axboe
482a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	flist_for_each_safe(entry, tmp, &client_list) {
483a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe		client = flist_entry(entry, struct fio_client, list);
484a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
485a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe		ret = fio_client_connect(client);
4860b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		if (ret) {
487a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe			remove_client(client);
4880b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe			continue;
4890b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		}
4900b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe
49181179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe		if (client->argc > 1)
49281179eec4a84ff25c190a8a6a685b0b3b4dd2a37Jens Axboe			send_client_cmd_line(client);
493a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	}
494a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
495a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	return !nr_clients;
496a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe}
497a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
498b9d2f30a214ebd274340f888739be250838d63c2Jens Axboeint fio_start_client(struct fio_client *client)
499b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe{
500b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	dprint(FD_NET, "client: start %s\n", client->hostname);
501b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	return fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_RUN, 0, NULL);
502b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe}
503b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe
504b9d2f30a214ebd274340f888739be250838d63c2Jens Axboeint fio_start_all_clients(void)
505b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe{
506b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	struct fio_client *client;
507b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	struct flist_head *entry, *tmp;
508b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	int ret;
509b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe
510b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	dprint(FD_NET, "client: start all\n");
511b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe
512b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	flist_for_each_safe(entry, tmp, &client_list) {
513b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe		client = flist_entry(entry, struct fio_client, list);
514b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe
515b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe		ret = fio_start_client(client);
516b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe		if (ret) {
517b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe			remove_client(client);
518b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe			continue;
519b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe		}
520b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	}
521b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe
522b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	return flist_empty(&client_list);
523b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe}
524b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe
525132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe/*
526132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe * Send file contents to server backend. We could use sendfile(), but to remain
527132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe * more portable lets just read/write the darn thing.
528132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe */
5299988ca70151a191c477179be7999300ddff16230Jens Axboestatic int __fio_client_send_ini(struct fio_client *client, const char *filename)
530132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe{
53146bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	struct cmd_job_pdu *pdu;
53246bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	size_t p_size;
533132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	struct stat sb;
53446bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	char *p;
53546bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	void *buf;
536132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	off_t len;
537132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	int fd, ret;
538132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
53946c48f1f9b8ce94132c13638e4c83c13e1d392daJens Axboe	dprint(FD_NET, "send ini %s to %s\n", filename, client->hostname);
54046c48f1f9b8ce94132c13638e4c83c13e1d392daJens Axboe
541132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	fd = open(filename, O_RDONLY);
542132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	if (fd < 0) {
54325095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		int ret = -errno;
54425095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe
545e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		log_err("fio: job file <%s> open: %s\n", filename, strerror(errno));
54625095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		return ret;
547132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	}
548132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
549132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	if (fstat(fd, &sb) < 0) {
55025095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		int ret = -errno;
55125095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe
552132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		log_err("fio: job file stat: %s\n", strerror(errno));
553b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
55425095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe		return ret;
555132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	}
556132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
55746bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	p_size = sb.st_size + sizeof(*pdu);
55846bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	pdu = malloc(p_size);
55946bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	buf = pdu->buf;
560132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
561132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	len = sb.st_size;
562132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	p = buf;
563132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	do {
564132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		ret = read(fd, p, len);
565132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		if (ret > 0) {
566132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			len -= ret;
567132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			if (!len)
568132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe				break;
569132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			p += ret;
570132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			continue;
571132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		} else if (!ret)
572132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			break;
573132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe		else if (errno == EAGAIN || errno == EINTR)
574132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe			continue;
575132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	} while (1);
576132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe
5770b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe	if (len) {
5780b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		log_err("fio: failed reading job file %s\n", filename);
579b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe		close(fd);
580c524ef72414f227ae4fcbfc95b832b3e6a95ae51Jens Axboe		free(buf);
5810b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe		return 1;
5820b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe	}
5830b8f30a5691b9e600a06ded035996e79c2100d77Jens Axboe
58446bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	pdu->buf_len = __cpu_to_le32(sb.st_size);
58546bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	pdu->client_type = cpu_to_le32(client->type);
58646bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe
587c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe	client->sent_job = 1;
58846bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	ret = fio_net_send_cmd(client->fd, FIO_NET_CMD_JOB, pdu, p_size, 0);
58946bcd498f7b3fb55f7f048bf299f36bd8c8f7db1Jens Axboe	free(pdu);
590b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe	close(fd);
591132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe	return ret;
592132159a5a062cabfe963b3d57e82a80741bf5506Jens Axboe}
59337db14feece08eb6e43de87c404180650ed5aa6fJens Axboe
5949988ca70151a191c477179be7999300ddff16230Jens Axboeint fio_client_send_ini(struct fio_client *client, const char *filename)
5959988ca70151a191c477179be7999300ddff16230Jens Axboe{
59625095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe	int ret;
59725095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe
59825095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe	ret = __fio_client_send_ini(client, filename);
5993af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe	if (!ret)
6003af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe		client->sent_job = 1;
6019988ca70151a191c477179be7999300ddff16230Jens Axboe
60225095e1bbcdc9f79f7052f6ff79e4b7245cce955Jens Axboe	return ret;
6039988ca70151a191c477179be7999300ddff16230Jens Axboe}
6049988ca70151a191c477179be7999300ddff16230Jens Axboe
605a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboeint fio_clients_send_ini(const char *filename)
606a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe{
607a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	struct fio_client *client;
608a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	struct flist_head *entry, *tmp;
609a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
610a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	flist_for_each_safe(entry, tmp, &client_list) {
611a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe		client = flist_entry(entry, struct fio_client, list);
612a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
6133af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe		if (fio_client_send_ini(client, filename))
6143af452010d32267d085ba1612ebc0a40812c28a9Jens Axboe			remove_client(client);
615a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	}
616a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
617a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe	return !nr_clients;
618a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe}
619a37f69b72a74cbde6151458b890aab8d093f0c9fJens Axboe
620a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboestatic void convert_io_stat(struct io_stat *dst, struct io_stat *src)
621a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
622a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->max_val	= le64_to_cpu(src->max_val);
623a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->min_val	= le64_to_cpu(src->min_val);
624a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->samples	= le64_to_cpu(src->samples);
625802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe
626802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	/*
627802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	 * Floats arrive as IEEE 754 encoded uint64_t, convert back to double
628802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	 */
629802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	dst->mean.u.f	= fio_uint64_to_double(le64_to_cpu(dst->mean.u.i));
630802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	dst->S.u.f	= fio_uint64_to_double(le64_to_cpu(dst->S.u.i));
631a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
632a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
633a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboestatic void convert_ts(struct thread_stat *dst, struct thread_stat *src)
634a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
635a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	int i, j;
636a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
6372f122b135b7319ff8dd04dadf31ff28b301051a3Jens Axboe	dst->error		= le32_to_cpu(src->error);
6382f122b135b7319ff8dd04dadf31ff28b301051a3Jens Axboe	dst->thread_number	= le32_to_cpu(src->thread_number);
6392f122b135b7319ff8dd04dadf31ff28b301051a3Jens Axboe	dst->groupid		= le32_to_cpu(src->groupid);
6402f122b135b7319ff8dd04dadf31ff28b301051a3Jens Axboe	dst->pid		= le32_to_cpu(src->pid);
6412f122b135b7319ff8dd04dadf31ff28b301051a3Jens Axboe	dst->members		= le32_to_cpu(src->members);
642a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
643a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 2; i++) {
644a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		convert_io_stat(&dst->clat_stat[i], &src->clat_stat[i]);
645a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		convert_io_stat(&dst->slat_stat[i], &src->slat_stat[i]);
646a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		convert_io_stat(&dst->lat_stat[i], &src->lat_stat[i]);
647a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		convert_io_stat(&dst->bw_stat[i], &src->bw_stat[i]);
648a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
649a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
650a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->usr_time		= le64_to_cpu(src->usr_time);
651a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->sys_time		= le64_to_cpu(src->sys_time);
652a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->ctx		= le64_to_cpu(src->ctx);
653a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->minf		= le64_to_cpu(src->minf);
654a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->majf		= le64_to_cpu(src->majf);
655a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->clat_percentiles	= le64_to_cpu(src->clat_percentiles);
656802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe
657802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	for (i = 0; i < FIO_IO_U_LIST_MAX_LEN; i++) {
658802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe		fio_fp64_t *fps = &src->percentile_list[i];
659802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe		fio_fp64_t *fpd = &dst->percentile_list[i];
660802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe
661802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe		fpd->u.f = fio_uint64_to_double(le64_to_cpu(fps->u.i));
662802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe	}
663a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
664a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < FIO_IO_U_MAP_NR; i++) {
665a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_map[i]	= le32_to_cpu(src->io_u_map[i]);
666a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_submit[i]	= le32_to_cpu(src->io_u_submit[i]);
667a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_complete[i]	= le32_to_cpu(src->io_u_complete[i]);
668a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
669a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
670a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < FIO_IO_U_LAT_U_NR; i++) {
671a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_lat_u[i]	= le32_to_cpu(src->io_u_lat_u[i]);
672a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_u_lat_m[i]	= le32_to_cpu(src->io_u_lat_m[i]);
673a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
674a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
675a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 2; i++)
676a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		for (j = 0; j < FIO_IO_U_PLAT_NR; j++)
677a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe			dst->io_u_plat[i][j] = le32_to_cpu(src->io_u_plat[i][j]);
678a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
679a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 3; i++) {
680a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->total_io_u[i]	= le64_to_cpu(src->total_io_u[i]);
68193eee04aef9ed39070ce2e69bd1f661a95b1d50aJens Axboe		dst->short_io_u[i]	= le64_to_cpu(src->short_io_u[i]);
682a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
683a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
684a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->total_submit	= le64_to_cpu(src->total_submit);
685a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->total_complete	= le64_to_cpu(src->total_complete);
686a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
687a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 2; i++) {
688a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_bytes[i]	= le64_to_cpu(src->io_bytes[i]);
689a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->runtime[i]		= le64_to_cpu(src->runtime[i]);
690a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
691a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
692a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->total_run_time	= le64_to_cpu(src->total_run_time);
693a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->continue_on_error	= le16_to_cpu(src->continue_on_error);
694a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->total_err_count	= le64_to_cpu(src->total_err_count);
695ddcc0b69aa4ed04c8681f447a1a6274bb8837a14Jens Axboe	dst->first_error	= le32_to_cpu(src->first_error);
696ddcc0b69aa4ed04c8681f447a1a6274bb8837a14Jens Axboe	dst->kb_base		= le32_to_cpu(src->kb_base);
697a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
698a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
699a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboestatic void convert_gs(struct group_run_stats *dst, struct group_run_stats *src)
700a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
701a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	int i;
702a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
703a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	for (i = 0; i < 2; i++) {
704a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->max_run[i]		= le64_to_cpu(src->max_run[i]);
705a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->min_run[i]		= le64_to_cpu(src->min_run[i]);
706a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->max_bw[i]		= le64_to_cpu(src->max_bw[i]);
707a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->min_bw[i]		= le64_to_cpu(src->min_bw[i]);
708a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->io_kb[i]		= le64_to_cpu(src->io_kb[i]);
709a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe		dst->agg[i]		= le64_to_cpu(src->agg[i]);
710a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	}
711a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
712a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->kb_base	= le32_to_cpu(src->kb_base);
713a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	dst->groupid	= le32_to_cpu(src->groupid);
714a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
715a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
71689e5fad91bc33f1687cca6b1bf5aa3084c424650Jens Axboestatic void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd)
717a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
718a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload;
719a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
720a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	show_thread_status(&p->ts, &p->rs);
72137f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe
72237f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	if (sum_stat_clients == 1)
72337f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe		return;
72437f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe
72537f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	sum_thread_stats(&client_ts, &p->ts, sum_stat_nr);
72637f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	sum_group_stats(&client_gs, &p->rs);
72737f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe
72837f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	client_ts.members++;
7292f122b135b7319ff8dd04dadf31ff28b301051a3Jens Axboe	client_ts.thread_number = p->ts.thread_number;
73037f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	client_ts.groupid = p->ts.groupid;
73137f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe
73237f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	if (++sum_stat_nr == sum_stat_clients) {
73337f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe		strcpy(client_ts.name, "All clients");
73437f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe		show_thread_status(&client_ts, &client_gs);
73537f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	}
736a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
737a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
73889e5fad91bc33f1687cca6b1bf5aa3084c424650Jens Axboestatic void handle_gs(struct fio_client *client, struct fio_net_cmd *cmd)
739a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe{
740a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	struct group_run_stats *gs = (struct group_run_stats *) cmd->payload;
741a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
742a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe	show_group_stats(gs);
743a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe}
744a64e88dad0c0e4a510ae8ab54cde1a20b99c59d1Jens Axboe
7453bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboestatic void handle_text(struct fio_client *client, struct fio_net_cmd *cmd)
7463bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe{
7473bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	struct cmd_text_pdu *pdu = (struct cmd_text_pdu *) cmd->payload;
7483bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	const char *buf = (const char *) pdu->buf;
7493bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	const char *name;
7503bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	int fio_unused ret;
7513bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
7523bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	name = client->name ? client->name : client->hostname;
7533bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
7543bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	if (!client->skip_newline)
7553bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		fprintf(f_out, "<%s> ", name);
7563bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	ret = fwrite(buf, pdu->buf_len, 1, f_out);
7573bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	fflush(f_out);
7583bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	client->skip_newline = strchr(buf, '\n') == NULL;
7593bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe}
7603bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
761d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboestatic void convert_agg(struct disk_util_agg *agg)
762d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe{
763d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	int i;
764d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
765d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	for (i = 0; i < 2; i++) {
766d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		agg->ios[i]	= le32_to_cpu(agg->ios[i]);
767d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		agg->merges[i]	= le32_to_cpu(agg->merges[i]);
768d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		agg->sectors[i]	= le64_to_cpu(agg->sectors[i]);
769d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		agg->ticks[i]	= le32_to_cpu(agg->ticks[i]);
770d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	}
771d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
772d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	agg->io_ticks		= le32_to_cpu(agg->io_ticks);
773d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	agg->time_in_queue	= le32_to_cpu(agg->time_in_queue);
774d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	agg->slavecount		= le32_to_cpu(agg->slavecount);
775823ba54bfc91f18fdd847e6efc41b422529bc4f8Anton Blanchard	agg->max_util.u.f	= fio_uint64_to_double(__le64_to_cpu(agg->max_util.u.i));
776d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe}
777d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
778d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboestatic void convert_dus(struct disk_util_stat *dus)
779d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe{
780d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	int i;
781d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
782d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	for (i = 0; i < 2; i++) {
783d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		dus->ios[i]	= le32_to_cpu(dus->ios[i]);
784d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		dus->merges[i]	= le32_to_cpu(dus->merges[i]);
785d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		dus->sectors[i]	= le64_to_cpu(dus->sectors[i]);
786d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		dus->ticks[i]	= le32_to_cpu(dus->ticks[i]);
787d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	}
788d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
789d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	dus->io_ticks		= le32_to_cpu(dus->io_ticks);
790d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	dus->time_in_queue	= le32_to_cpu(dus->time_in_queue);
791d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	dus->msec		= le64_to_cpu(dus->msec);
792d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe}
793d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
794d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboestatic void handle_du(struct fio_client *client, struct fio_net_cmd *cmd)
795d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe{
796d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	struct cmd_du_pdu *du = (struct cmd_du_pdu *) cmd->payload;
797d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
798d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	if (!client->disk_stats_shown) {
799d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		client->disk_stats_shown = 1;
800d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		log_info("\nDisk stats (read/write):\n");
801d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe	}
802d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
803f2f788dd732d97c2c3a5f5dd93223a7bfafcc410Jens Axboe	print_disk_util(&du->dus, &du->agg, terse_output);
804d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe}
805d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe
8063bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboestatic void convert_jobs_eta(struct jobs_eta *je)
807cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe{
808cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	int i;
809cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
810cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->nr_running		= le32_to_cpu(je->nr_running);
811cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->nr_ramp		= le32_to_cpu(je->nr_ramp);
812cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->nr_pending		= le32_to_cpu(je->nr_pending);
813cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->files_open		= le32_to_cpu(je->files_open);
814cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
815cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	for (i = 0; i < 2; i++) {
8163e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe		je->m_rate[i]		= le32_to_cpu(je->m_rate[i]);
8173e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe		je->t_rate[i]		= le32_to_cpu(je->t_rate[i]);
8183e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe		je->m_iops[i]		= le32_to_cpu(je->m_iops[i]);
8193e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe		je->t_iops[i]		= le32_to_cpu(je->t_iops[i]);
820cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe		je->rate[i]	= le32_to_cpu(je->rate[i]);
821cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe		je->iops[i]	= le32_to_cpu(je->iops[i]);
822cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	}
823cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
824b51eedb75e3f1a9db33fa488ff7d9cc0a956b8eeJens Axboe	je->elapsed_sec		= le64_to_cpu(je->elapsed_sec);
825cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe	je->eta_sec		= le64_to_cpu(je->eta_sec);
8268c621fb2aa4b99c8a8b6b62435d713ab39b52c62Jens Axboe	je->nr_threads		= le32_to_cpu(je->nr_threads);
82748fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe}
82848fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe
8293e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboevoid fio_client_sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je)
83048fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe{
83148fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	int i;
83248fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe
83348fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	dst->nr_running		+= je->nr_running;
83448fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	dst->nr_ramp		+= je->nr_ramp;
83548fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	dst->nr_pending		+= je->nr_pending;
83648fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	dst->files_open		+= je->files_open;
83748fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe
83848fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	for (i = 0; i < 2; i++) {
8393e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe		dst->m_rate[i]	+= je->m_rate[i];
8403e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe		dst->t_rate[i]	+= je->t_rate[i];
8413e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe		dst->m_iops[i]	+= je->m_iops[i];
8423e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe		dst->t_iops[i]	+= je->t_iops[i];
84348fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe		dst->rate[i]	+= je->rate[i];
84448fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe		dst->iops[i]	+= je->iops[i];
84548fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	}
84648fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe
84748fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	dst->elapsed_sec	+= je->elapsed_sec;
84848fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe
84948fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	if (je->eta_sec > dst->eta_sec)
85048fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe		dst->eta_sec = je->eta_sec;
8518c621fb2aa4b99c8a8b6b62435d713ab39b52c62Jens Axboe
8528c621fb2aa4b99c8a8b6b62435d713ab39b52c62Jens Axboe	dst->nr_threads		+= je->nr_threads;
8538c621fb2aa4b99c8a8b6b62435d713ab39b52c62Jens Axboe	/* we need to handle je->run_str too ... */
85448fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe}
85548fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe
856a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboevoid fio_client_dec_jobs_eta(struct client_eta *eta, client_eta_op eta_fn)
85782c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe{
85882c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe	if (!--eta->pending) {
859a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe		eta_fn(&eta->eta);
86082c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe		free(eta);
86182c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe	}
86282c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe}
86382c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe
86489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboestatic void remove_reply_cmd(struct fio_client *client, struct fio_net_cmd *cmd)
86589c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe{
86689c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	struct fio_net_int_cmd *icmd = NULL;
86789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	struct flist_head *entry;
86889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
86989c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	flist_for_each(entry, &client->cmd_list) {
87089c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		icmd = flist_entry(entry, struct fio_net_int_cmd, list);
87189c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
872df380934e53c645b4b7cdec882b512b4d20ebc14Jens Axboe		if (cmd->tag == (uintptr_t) icmd)
87389c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe			break;
87489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
87589c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		icmd = NULL;
87689c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	}
87789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
87889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	if (!icmd) {
87989c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		log_err("fio: client: unable to find matching tag\n");
88089c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		return;
88189c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	}
88289c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
88389c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	flist_del(&icmd->list);
88489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	cmd->tag = icmd->saved_tag;
88589c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	free(icmd);
88689c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe}
88789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
88882c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboestatic void handle_eta(struct fio_client *client, struct fio_net_cmd *cmd)
88948fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe{
89048fbb46e7c9a2721b3b23898ab9ec79727ab4e9bJens Axboe	struct jobs_eta *je = (struct jobs_eta *) cmd->payload;
891df380934e53c645b4b7cdec882b512b4d20ebc14Jens Axboe	struct client_eta *eta = (struct client_eta *) (uintptr_t) cmd->tag;
892af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
893af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	dprint(FD_NET, "client: got eta tag %p, %d\n", eta, eta->pending);
894cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
895f77d2676c36ec30cfb765b90505bdda7208c9796Jens Axboe	assert(client->eta_in_flight == eta);
896f77d2676c36ec30cfb765b90505bdda7208c9796Jens Axboe
897f77d2676c36ec30cfb765b90505bdda7208c9796Jens Axboe	client->eta_in_flight = NULL;
89882c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe	flist_del_init(&client->eta_list);
89982c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe
9002f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	if (client->ops->jobs_eta)
9012f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe		client->ops->jobs_eta(client, je);
9022f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
9033e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe	fio_client_sum_jobs_eta(&eta->eta, je);
904a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe	fio_client_dec_jobs_eta(eta, client->ops->eta);
905cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe}
906cf451d1ede3bbbd2fed3619eb43def054d5b5a5aJens Axboe
907b5296ddb3f34610e4bd90272bf5035a41691d00fJens Axboestatic void handle_probe(struct fio_client *client, struct fio_net_cmd *cmd)
9082e03b4b2a072b79946b0ee651dff38273868473aJens Axboe{
9092e03b4b2a072b79946b0ee651dff38273868473aJens Axboe	struct cmd_probe_pdu *probe = (struct cmd_probe_pdu *) cmd->payload;
910d2333358fb3729de6681ed5cc3ec45cd86b5cfb8Jens Axboe	const char *os, *arch;
911d2333358fb3729de6681ed5cc3ec45cd86b5cfb8Jens Axboe	char bit[16];
9122e03b4b2a072b79946b0ee651dff38273868473aJens Axboe
913cca84643cc10cd72b0b453ff92ccb8643ba51493Jens Axboe	os = fio_get_os_string(probe->os);
914cca84643cc10cd72b0b453ff92ccb8643ba51493Jens Axboe	if (!os)
915cca84643cc10cd72b0b453ff92ccb8643ba51493Jens Axboe		os = "unknown";
916cca84643cc10cd72b0b453ff92ccb8643ba51493Jens Axboe
917cca84643cc10cd72b0b453ff92ccb8643ba51493Jens Axboe	arch = fio_get_arch_string(probe->arch);
918cca84643cc10cd72b0b453ff92ccb8643ba51493Jens Axboe	if (!arch)
919cca84643cc10cd72b0b453ff92ccb8643ba51493Jens Axboe		os = "unknown";
920cca84643cc10cd72b0b453ff92ccb8643ba51493Jens Axboe
921d2333358fb3729de6681ed5cc3ec45cd86b5cfb8Jens Axboe	sprintf(bit, "%d-bit", probe->bpp * 8);
92238fdef226f1a1fa053ab53005abbc184143bff65Jens Axboe
92338fdef226f1a1fa053ab53005abbc184143bff65Jens Axboe	log_info("hostname=%s, be=%u, %s, os=%s, arch=%s, fio=%u.%u.%u\n",
92438fdef226f1a1fa053ab53005abbc184143bff65Jens Axboe		probe->hostname, probe->bigendian, bit, os, arch,
92538fdef226f1a1fa053ab53005abbc184143bff65Jens Axboe		probe->fio_major, probe->fio_minor, probe->fio_patch);
926b5296ddb3f34610e4bd90272bf5035a41691d00fJens Axboe
927b5296ddb3f34610e4bd90272bf5035a41691d00fJens Axboe	if (!client->name)
928b5296ddb3f34610e4bd90272bf5035a41691d00fJens Axboe		client->name = strdup((char *) probe->hostname);
9292e03b4b2a072b79946b0ee651dff38273868473aJens Axboe}
9302e03b4b2a072b79946b0ee651dff38273868473aJens Axboe
93111e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboestatic void handle_start(struct fio_client *client, struct fio_net_cmd *cmd)
93211e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe{
93311e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe	struct cmd_start_pdu *pdu = (struct cmd_start_pdu *) cmd->payload;
93411e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe
93511e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe	client->state = Client_started;
93685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	client->jobs = pdu->jobs;
93711e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe}
93811e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe
93911e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboestatic void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd)
94011e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe{
941498c92c27b475bcc0cb65e529fb02713bc1fb62cJens Axboe	if (client->error)
942498c92c27b475bcc0cb65e529fb02713bc1fb62cJens Axboe		log_info("client <%s>: exited with error %d\n", client->hostname, client->error);
94311e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe}
94411e950bd785d9f03b7d35a8ee4b4704256217504Jens Axboe
9456b79c80c14766df7b0507c4ec679507a315ad61aJens Axboestatic void convert_stop(struct fio_net_cmd *cmd)
9466b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe{
9476b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe	struct cmd_end_pdu *pdu = (struct cmd_end_pdu *) cmd->payload;
9486b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe
9496b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe	pdu->error = le32_to_cpu(pdu->error);
9506b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe}
9516b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe
952084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboestatic void convert_text(struct fio_net_cmd *cmd)
953084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe{
954084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe	struct cmd_text_pdu *pdu = (struct cmd_text_pdu *) cmd->payload;
955084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe
956084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe	pdu->level	= le32_to_cpu(pdu->level);
957084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe	pdu->buf_len	= le32_to_cpu(pdu->buf_len);
958084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe	pdu->log_sec	= le64_to_cpu(pdu->log_sec);
959084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe	pdu->log_usec	= le64_to_cpu(pdu->log_usec);
960084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe}
961084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe
9621b42725f06f8906b9b99381da3490484f59df28aJens Axboe/*
9631b42725f06f8906b9b99381da3490484f59df28aJens Axboe * This has been compressed on the server side, since it can be big.
9641b42725f06f8906b9b99381da3490484f59df28aJens Axboe * Uncompress here.
9651b42725f06f8906b9b99381da3490484f59df28aJens Axboe */
9661b42725f06f8906b9b99381da3490484f59df28aJens Axboestatic struct cmd_iolog_pdu *convert_iolog(struct fio_net_cmd *cmd)
9671b42725f06f8906b9b99381da3490484f59df28aJens Axboe{
9681b42725f06f8906b9b99381da3490484f59df28aJens Axboe	struct cmd_iolog_pdu *pdu = (struct cmd_iolog_pdu *) cmd->payload;
9691b42725f06f8906b9b99381da3490484f59df28aJens Axboe	struct cmd_iolog_pdu *ret;
9701b42725f06f8906b9b99381da3490484f59df28aJens Axboe	uint32_t nr_samples;
9711b42725f06f8906b9b99381da3490484f59df28aJens Axboe	unsigned long total;
9721b42725f06f8906b9b99381da3490484f59df28aJens Axboe	z_stream stream;
9731b42725f06f8906b9b99381da3490484f59df28aJens Axboe	void *p;
974f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	int i;
9751b42725f06f8906b9b99381da3490484f59df28aJens Axboe
9761b42725f06f8906b9b99381da3490484f59df28aJens Axboe	stream.zalloc = Z_NULL;
9771b42725f06f8906b9b99381da3490484f59df28aJens Axboe	stream.zfree = Z_NULL;
9781b42725f06f8906b9b99381da3490484f59df28aJens Axboe	stream.opaque = Z_NULL;
9791b42725f06f8906b9b99381da3490484f59df28aJens Axboe	stream.avail_in = 0;
9801b42725f06f8906b9b99381da3490484f59df28aJens Axboe	stream.next_in = Z_NULL;
9811b42725f06f8906b9b99381da3490484f59df28aJens Axboe
9821b42725f06f8906b9b99381da3490484f59df28aJens Axboe	if (inflateInit(&stream) != Z_OK)
9831b42725f06f8906b9b99381da3490484f59df28aJens Axboe		return NULL;
9841b42725f06f8906b9b99381da3490484f59df28aJens Axboe
9851b42725f06f8906b9b99381da3490484f59df28aJens Axboe	/*
986f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	 * Get header first, it's not compressed
9871b42725f06f8906b9b99381da3490484f59df28aJens Axboe	 */
9881b42725f06f8906b9b99381da3490484f59df28aJens Axboe	nr_samples = le32_to_cpu(pdu->nr_samples);
9891b42725f06f8906b9b99381da3490484f59df28aJens Axboe
990f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	total = nr_samples * sizeof(struct io_sample);
991f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	ret = malloc(total + sizeof(*pdu));
9922f122b135b7319ff8dd04dadf31ff28b301051a3Jens Axboe	ret->thread_number = le32_to_cpu(pdu->thread_number);
9931b42725f06f8906b9b99381da3490484f59df28aJens Axboe	ret->nr_samples = nr_samples;
994f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	ret->log_type = le32_to_cpu(pdu->log_type);
995f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	strcpy((char *) ret->name, (char *) pdu->name);
996f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe
997f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	p = (void *) ret + sizeof(*pdu);
9981b42725f06f8906b9b99381da3490484f59df28aJens Axboe
999f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	stream.avail_in = cmd->pdu_len - sizeof(*pdu);
1000f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	stream.next_in = (void *) pdu + sizeof(*pdu);
10011b42725f06f8906b9b99381da3490484f59df28aJens Axboe	while (stream.avail_in) {
10021b42725f06f8906b9b99381da3490484f59df28aJens Axboe		unsigned int this_chunk = 65536;
10031b42725f06f8906b9b99381da3490484f59df28aJens Axboe		unsigned int this_len;
10041b42725f06f8906b9b99381da3490484f59df28aJens Axboe		int err;
10051b42725f06f8906b9b99381da3490484f59df28aJens Axboe
10061b42725f06f8906b9b99381da3490484f59df28aJens Axboe		if (this_chunk > total)
10071b42725f06f8906b9b99381da3490484f59df28aJens Axboe			this_chunk = total;
10081b42725f06f8906b9b99381da3490484f59df28aJens Axboe
10091b42725f06f8906b9b99381da3490484f59df28aJens Axboe		stream.avail_out = this_chunk;
10101b42725f06f8906b9b99381da3490484f59df28aJens Axboe		stream.next_out = p;
10111b42725f06f8906b9b99381da3490484f59df28aJens Axboe		err = inflate(&stream, Z_NO_FLUSH);
10123c547fe0547c924ca5174d9aa36720ddb441480aJens Axboe		/* may be Z_OK, or Z_STREAM_END */
10133c547fe0547c924ca5174d9aa36720ddb441480aJens Axboe		if (err < 0) {
10141b42725f06f8906b9b99381da3490484f59df28aJens Axboe			log_err("fio: inflate error %d\n", err);
1015f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe			free(ret);
1016f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe			ret = NULL;
10171b42725f06f8906b9b99381da3490484f59df28aJens Axboe			goto out;
10181b42725f06f8906b9b99381da3490484f59df28aJens Axboe		}
10191b42725f06f8906b9b99381da3490484f59df28aJens Axboe
10201b42725f06f8906b9b99381da3490484f59df28aJens Axboe		this_len = this_chunk - stream.avail_out;
10211b42725f06f8906b9b99381da3490484f59df28aJens Axboe		p += this_len;
10221b42725f06f8906b9b99381da3490484f59df28aJens Axboe		total -= this_len;
10231b42725f06f8906b9b99381da3490484f59df28aJens Axboe	}
10241b42725f06f8906b9b99381da3490484f59df28aJens Axboe
1025f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	for (i = 0; i < ret->nr_samples; i++) {
1026f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe		struct io_sample *s = &ret->samples[i];
1027f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe
1028f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe		s->time	= le64_to_cpu(s->time);
1029f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe		s->val	= le64_to_cpu(s->val);
1030f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe		s->ddir	= le32_to_cpu(s->ddir);
1031f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe		s->bs	= le32_to_cpu(s->bs);
1032f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe	}
1033f5ed765adadc5dca61efb5fc103fa5cd0310bcecJens Axboe
10341b42725f06f8906b9b99381da3490484f59df28aJens Axboeout:
10351b42725f06f8906b9b99381da3490484f59df28aJens Axboe	inflateEnd(&stream);
10361b42725f06f8906b9b99381da3490484f59df28aJens Axboe	return ret;
10371b42725f06f8906b9b99381da3490484f59df28aJens Axboe}
10381b42725f06f8906b9b99381da3490484f59df28aJens Axboe
1039a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboeint fio_handle_client(struct fio_client *client)
104037db14feece08eb6e43de87c404180650ed5aa6fJens Axboe{
1041a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe	struct client_ops *ops = client->ops;
104237db14feece08eb6e43de87c404180650ed5aa6fJens Axboe	struct fio_net_cmd *cmd;
104337db14feece08eb6e43de87c404180650ed5aa6fJens Axboe
104460efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe	dprint(FD_NET, "client: handle %s\n", client->hostname);
104560efd14e3b5b5a2adb9f7c9ecfb9bfba38f76ce9Jens Axboe
1046e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	cmd = fio_net_recv_cmd(client->fd);
1047e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	if (!cmd)
1048e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		return 0;
1049c2c9458515bda1f77e25f95122ef6ec8d8cc3ec7Jens Axboe
1050b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe	dprint(FD_NET, "client: got cmd op %s from %s (pdu=%u)\n",
1051b9d2f30a214ebd274340f888739be250838d63c2Jens Axboe		fio_server_op(cmd->opcode), client->hostname, cmd->pdu_len);
105246c48f1f9b8ce94132c13638e4c83c13e1d392daJens Axboe
1053e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	switch (cmd->opcode) {
1054e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_QUIT:
10553ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe		if (ops->quit)
105635c0ba7ff55bbd438cdc171945c61d501a4e693eJens Axboe			ops->quit(client, cmd);
1057e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		remove_client(client);
1058e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1059e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
1060084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe	case FIO_NET_CMD_TEXT:
1061084d1c6f817eacaaefa1de4f0637ef6c1405d74bJens Axboe		convert_text(cmd);
106235c0ba7ff55bbd438cdc171945c61d501a4e693eJens Axboe		ops->text(client, cmd);
1063e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1064e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
10653bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	case FIO_NET_CMD_DU: {
10663bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		struct cmd_du_pdu *du = (struct cmd_du_pdu *) cmd->payload;
10673bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
10683bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		convert_dus(&du->dus);
10693bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		convert_agg(&du->agg);
10703bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
1071dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameron		ops->disk_util(client, cmd);
1072d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		free(cmd);
1073d09a64a01a6c807596e9286c93f6c6f30fd2ea26Jens Axboe		break;
10743bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		}
10753bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	case FIO_NET_CMD_TS: {
10763bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload;
10773bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
10783bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		convert_ts(&p->ts, &p->ts);
10793bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		convert_gs(&p->rs, &p->rs);
10803bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
108189e5fad91bc33f1687cca6b1bf5aa3084c424650Jens Axboe		ops->thread_status(client, cmd);
1082e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1083e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
10843bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		}
10853bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	case FIO_NET_CMD_GS: {
10863bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		struct group_run_stats *gs = (struct group_run_stats *) cmd->payload;
10873bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
10883bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		convert_gs(gs, gs);
10893bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
109089e5fad91bc33f1687cca6b1bf5aa3084c424650Jens Axboe		ops->group_stats(client, cmd);
1091e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1092e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
10933bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		}
10943bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe	case FIO_NET_CMD_ETA: {
10953bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		struct jobs_eta *je = (struct jobs_eta *) cmd->payload;
10963bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe
109789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		remove_reply_cmd(client, cmd);
10983bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		convert_jobs_eta(je);
1099a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe		handle_eta(client, cmd);
1100e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1101e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
11023bf236c082e36f222b64edf9ae2bd7637156d0acJens Axboe		}
1103e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	case FIO_NET_CMD_PROBE:
110489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		remove_reply_cmd(client, cmd);
1105dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameron		ops->probe(client, cmd);
1106e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1107e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
11085d7793aa2b1dc1044b1918d829a1bcd4c9a19196Jens Axboe	case FIO_NET_CMD_SERVER_START:
110901be038efc66ea1b49b4471f2ba9dd2d7121cfe7Jens Axboe		client->state = Client_running;
111085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		if (ops->job_start)
111185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe			ops->job_start(client, cmd);
111201be038efc66ea1b49b4471f2ba9dd2d7121cfe7Jens Axboe		free(cmd);
111301be038efc66ea1b49b4471f2ba9dd2d7121cfe7Jens Axboe		break;
111485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	case FIO_NET_CMD_START: {
111585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		struct cmd_start_pdu *pdu = (struct cmd_start_pdu *) cmd->payload;
111685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
111785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		pdu->jobs = le32_to_cpu(pdu->jobs);
111885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		ops->start(client, cmd);
1119e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1120e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
112185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		}
11226b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe	case FIO_NET_CMD_STOP: {
11236b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe		struct cmd_end_pdu *pdu = (struct cmd_end_pdu *) cmd->payload;
11246b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe
11256b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe		convert_stop(cmd);
11266b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe		client->state = Client_stopped;
1127122c772599f1b0a3148a5790775698d3fa92cc10Jens Axboe		client->error = le32_to_cpu(pdu->error);
1128122c772599f1b0a3148a5790775698d3fa92cc10Jens Axboe		client->signal = le32_to_cpu(pdu->signal);
11296b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe		ops->stop(client, cmd);
1130e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1131e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
11326b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe		}
1133807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe	case FIO_NET_CMD_ADD_JOB:
1134807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe		if (ops->add_job)
1135807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe			ops->add_job(client, cmd);
1136807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe		free(cmd);
1137807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe		break;
11381b42725f06f8906b9b99381da3490484f59df28aJens Axboe	case FIO_NET_CMD_IOLOG:
11391b42725f06f8906b9b99381da3490484f59df28aJens Axboe		if (ops->iolog) {
11401b42725f06f8906b9b99381da3490484f59df28aJens Axboe			struct cmd_iolog_pdu *pdu;
11411b42725f06f8906b9b99381da3490484f59df28aJens Axboe
11421b42725f06f8906b9b99381da3490484f59df28aJens Axboe			pdu = convert_iolog(cmd);
11431b42725f06f8906b9b99381da3490484f59df28aJens Axboe			ops->iolog(client, pdu);
11441b42725f06f8906b9b99381da3490484f59df28aJens Axboe		}
11451b42725f06f8906b9b99381da3490484f59df28aJens Axboe		free(cmd);
11461b42725f06f8906b9b99381da3490484f59df28aJens Axboe		break;
1147e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	default:
114889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		log_err("fio: unknown client op: %s\n", fio_server_op(cmd->opcode));
1149e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		free(cmd);
1150e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe		break;
115137db14feece08eb6e43de87c404180650ed5aa6fJens Axboe	}
115237db14feece08eb6e43de87c404180650ed5aa6fJens Axboe
1153e951bdc47d094d43d6f41de95c6af191b8346459Jens Axboe	return 1;
115437db14feece08eb6e43de87c404180650ed5aa6fJens Axboe}
1155b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
1156a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboestatic void request_client_etas(struct client_ops *ops)
1157af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe{
1158af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	struct fio_client *client;
1159af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	struct flist_head *entry;
1160af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	struct client_eta *eta;
116182c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe	int skipped = 0;
1162af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
1163af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	dprint(FD_NET, "client: request eta (%d)\n", nr_clients);
1164af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
1165af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	eta = malloc(sizeof(*eta));
1166af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	memset(&eta->eta, 0, sizeof(eta->eta));
1167af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	eta->pending = nr_clients;
1168af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
1169af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	flist_for_each(entry, &client_list) {
1170af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe		client = flist_entry(entry, struct fio_client, list);
1171af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
117282c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe		if (!flist_empty(&client->eta_list)) {
117382c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe			skipped++;
117482c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe			continue;
117582c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe		}
117601be038efc66ea1b49b4471f2ba9dd2d7121cfe7Jens Axboe		if (client->state != Client_running)
117701be038efc66ea1b49b4471f2ba9dd2d7121cfe7Jens Axboe			continue;
117882c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe
1179f77d2676c36ec30cfb765b90505bdda7208c9796Jens Axboe		assert(!client->eta_in_flight);
118082c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe		flist_add_tail(&client->eta_list, &eta_list);
1181f77d2676c36ec30cfb765b90505bdda7208c9796Jens Axboe		client->eta_in_flight = eta;
1182af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe		fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_SEND_ETA,
1183df380934e53c645b4b7cdec882b512b4d20ebc14Jens Axboe					(uintptr_t) eta, &client->cmd_list);
1184af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	}
1185af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
118682c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe	while (skipped--)
1187a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe		fio_client_dec_jobs_eta(eta, ops->eta);
118882c1ed38d6c90c03beda072ed064a445ecb56acaJens Axboe
1189af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	dprint(FD_NET, "client: requested eta tag %p\n", eta);
1190af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe}
1191af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
119289c1707cb512e562b55b56c268f7fad612be6f04Jens Axboestatic int client_check_cmd_timeout(struct fio_client *client,
119389c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe				    struct timeval *now)
119489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe{
119589c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	struct fio_net_int_cmd *cmd;
119689c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	struct flist_head *entry, *tmp;
119789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	int ret = 0;
119889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
119989c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	flist_for_each_safe(entry, tmp, &client->cmd_list) {
120089c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		cmd = flist_entry(entry, struct fio_net_int_cmd, list);
120189c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
120289c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		if (mtime_since(&cmd->tv, now) < FIO_NET_CLIENT_TIMEOUT)
120389c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe			continue;
120489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
120589c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		log_err("fio: client %s, timeout on cmd %s\n", client->hostname,
120689c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe						fio_server_op(cmd->cmd.opcode));
120789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		flist_del(&cmd->list);
120889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		free(cmd);
120989c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		ret = 1;
121089c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	}
121189c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
121289c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	return flist_empty(&client->cmd_list) && ret;
121389c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe}
121489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
1215a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboestatic int fio_check_clients_timed_out(void)
121689c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe{
121789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	struct fio_client *client;
121889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	struct flist_head *entry, *tmp;
121989c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	struct timeval tv;
122089c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	int ret = 0;
122189c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
122289c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	gettimeofday(&tv, NULL);
122389c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
122489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	flist_for_each_safe(entry, tmp, &client_list) {
122589c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		client = flist_entry(entry, struct fio_client, list);
122689c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
122789c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		if (flist_empty(&client->cmd_list))
122889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe			continue;
122989c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
123089c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		if (!client_check_cmd_timeout(client, &tv))
123189c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe			continue;
123289c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
1233a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe		if (client->ops->timed_out)
1234a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe			client->ops->timed_out(client);
1235ed727a4632fa3195f31758c79e209ca8d524bbc4Jens Axboe		else
1236ed727a4632fa3195f31758c79e209ca8d524bbc4Jens Axboe			log_err("fio: client %s timed out\n", client->hostname);
1237ed727a4632fa3195f31758c79e209ca8d524bbc4Jens Axboe
123889c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		remove_client(client);
123989c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe		ret = 1;
124089c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	}
124189c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
124289c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe	return ret;
124389c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe}
124489c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
1245dd366728eb503e6344215ae6ec153c7ab6eafd9bStephen M. Cameronint fio_handle_clients(struct client_ops *ops)
1246b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe{
1247b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	struct pollfd *pfds;
1248498c92c27b475bcc0cb65e529fb02713bc1fb62cJens Axboe	int i, ret = 0, retval = 0;
1249b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
1250af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe	gettimeofday(&eta_tv, NULL);
1251af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
1252b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	pfds = malloc(nr_clients * sizeof(struct pollfd));
1253b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
125437f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	sum_stat_clients = nr_clients;
125537f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	init_thread_stat(&client_ts);
125637f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe	init_group_run_stat(&client_gs);
125737f0c1ae23ad1716403d3d113c3dfdf41c47e329Jens Axboe
125882a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe	while (!exit_backend && nr_clients) {
1259c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe		struct flist_head *entry, *tmp;
1260c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe		struct fio_client *client;
1261c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe
126282a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe		i = 0;
1263c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe		flist_for_each_safe(entry, tmp, &client_list) {
126482a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe			client = flist_entry(entry, struct fio_client, list);
1265b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
1266a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe			if (!client->sent_job && !client->ops->stay_connected &&
1267c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe			    flist_empty(&client->cmd_list)) {
1268c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe				remove_client(client);
1269c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe				continue;
1270c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe			}
1271c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe
127282a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe			pfds[i].fd = client->fd;
127382a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe			pfds[i].events = POLLIN;
127482a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe			i++;
127582a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe		}
127682a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe
1277c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe		if (!nr_clients)
1278c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe			break;
1279c2cb68696255a8fda93043a1f2219b60af614549Jens Axboe
128082a4be1bcef4228233e61b0b034ad6eb78a7558cJens Axboe		assert(i == nr_clients);
1281b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
12825c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe		do {
1283af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe			struct timeval tv;
1284af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
1285af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe			gettimeofday(&tv, NULL);
12866433ee054a5dc6533066e105baee4ff85197d392Jens Axboe			if (mtime_since(&eta_tv, &tv) >= ops->eta_msec) {
1287a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe				request_client_etas(ops);
1288af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe				memcpy(&eta_tv, &tv, sizeof(tv));
128989c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe
1290a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe				if (fio_check_clients_timed_out())
129189c1707cb512e562b55b56c268f7fad612be6f04Jens Axboe					break;
1292af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe			}
1293af9c9fb34e420fc4d9cf317aa0f3cf6795a5a07fJens Axboe
129480102c86786d7d50ba72366cee03061735b3cbacJens Axboe			ret = poll(pfds, nr_clients, ops->eta_msec);
12955c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe			if (ret < 0) {
12965c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe				if (errno == EINTR)
12975c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe					continue;
12985c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe				log_err("fio: poll clients: %s\n", strerror(errno));
12995c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe				break;
13005c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe			} else if (!ret)
1301b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe				continue;
13025c2857f9f5cb350c9441be3f3e1cd7c9dc18b1c5Jens Axboe		} while (ret <= 0);
1303b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
1304b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe		for (i = 0; i < nr_clients; i++) {
1305b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			if (!(pfds[i].revents & POLLIN))
1306b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe				continue;
1307b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
1308b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			client = find_client_by_fd(pfds[i].fd);
1309b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			if (!client) {
13103c5f57e36712decffa103c8a655b9a693c6d3d13Jens Axboe				log_err("fio: unknown client fd %d\n", pfds[i].fd);
1311b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe				continue;
1312b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe			}
1313a52766160d7f2a937c74d4adee1819ef00467d4bJens Axboe			if (!fio_handle_client(client)) {
131428d3ab07f7c68afe9ad3b07bb9c288f3e94957daJens Axboe				log_info("client: host=%s disconnected\n",
131528d3ab07f7c68afe9ad3b07bb9c288f3e94957daJens Axboe						client->hostname);
131628d3ab07f7c68afe9ad3b07bb9c288f3e94957daJens Axboe				remove_client(client);
1317498c92c27b475bcc0cb65e529fb02713bc1fb62cJens Axboe				retval = 1;
13183899076470e108d9815a322aaa97e662d141b50cJens Axboe			} else if (client->error)
1319498c92c27b475bcc0cb65e529fb02713bc1fb62cJens Axboe				retval = 1;
1320343cb4a98200757bdcb0c5203e9120bb777625a8Jens Axboe			fio_put_client(client);
1321b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe		}
1322b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	}
1323b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe
1324b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe	free(pfds);
1325498c92c27b475bcc0cb65e529fb02713bc1fb62cJens Axboe	return retval;
1326b66570dce15587a37a64685f8ab72c3018771b2bJens Axboe}
1327