--max-jobs Maximum number of threads/processes to support
--server=args Start backend server. See Client/Server section.
--client=host Connect to specified backend.
+ --remote-config=file Tell fio server to load this local file
--idle-prof=option Report cpu idleness on a system or percpu basis
(option=system,percpu) or run unit work
calibration only (option=calibrate).
fio --client=<server1> <job file(s)> --client=<server2> <job file(s)>
+If the job file is located on the fio server, then you can tell the server
+to load a local file as well. This is done by using --remote-config:
+
+fio --client=server --remote-config /path/to/file.fio
+
+Then the fio serer will open this local (to the server) job file instead
+of being passed one from the client.
+
Platforms
---------
free(client->argv);
if (client->name)
free(client->name);
- while (client->nr_ini_file)
- free(client->ini_file[--client->nr_ini_file]);
- if (client->ini_file)
- free(client->ini_file);
+ while (client->nr_files) {
+ struct client_file *cf = &client->files[--client->nr_files];
+
+ free(cf->file);
+ }
+ if (client->files)
+ free(client->files);
if (!client->did_stat)
sum_stat_clients -= client->nr_stat;
return NULL;
}
-void fio_client_add_ini_file(void *cookie, const char *ini_file)
+int fio_client_add_ini_file(void *cookie, const char *ini_file, int remote)
{
struct fio_client *client = cookie;
+ struct client_file *cf;
size_t new_size;
+ void *new_files;
dprint(FD_NET, "client <%s>: add ini %s\n", client->hostname, ini_file);
- new_size = (client->nr_ini_file + 1) * sizeof(char *);
- client->ini_file = realloc(client->ini_file, new_size);
- client->ini_file[client->nr_ini_file] = strdup(ini_file);
- client->nr_ini_file++;
+ new_size = (client->nr_files + 1) * sizeof(struct client_file);
+ new_files = realloc(client->files, new_size);
+ if (!new_files)
+ return 1;
+
+ client->files = new_files;
+ cf = &client->files[client->nr_files];
+ cf->file = strdup(ini_file);
+ cf->remote = remote;
+ client->nr_files++;
+ return 0;
}
int fio_client_add(struct client_ops *ops, const char *hostname, void **cookie)
return flist_empty(&client_list);
}
+static int __fio_client_send_remote_ini(struct fio_client *client,
+ const char *filename)
+{
+ struct cmd_load_file_pdu *pdu;
+ size_t p_size;
+ int ret;
+
+ dprint(FD_NET, "send remote ini %s to %s\n", filename, client->hostname);
+
+ p_size = sizeof(*pdu) + strlen(filename);
+ pdu = malloc(p_size);
+ pdu->name_len = strlen(filename);
+ strcpy((char *) pdu->file, filename);
+ pdu->client_type = cpu_to_le16((uint16_t) client->type);
+
+ client->sent_job = 1;
+ ret = fio_net_send_cmd(client->fd, FIO_NET_CMD_LOAD_FILE, pdu, p_size,NULL, NULL);
+ free(pdu);
+ return ret;
+}
+
/*
* Send file contents to server backend. We could use sendfile(), but to remain
* more portable lets just read/write the darn thing.
*/
-static int __fio_client_send_ini(struct fio_client *client, const char *filename)
+static int __fio_client_send_local_ini(struct fio_client *client,
+ const char *filename)
{
struct cmd_job_pdu *pdu;
size_t p_size;
return ret;
}
-int fio_client_send_ini(struct fio_client *client, const char *filename)
+int fio_client_send_ini(struct fio_client *client, const char *filename,
+ int remote)
{
int ret;
- ret = __fio_client_send_ini(client, filename);
+ if (!remote)
+ ret = __fio_client_send_local_ini(client, filename);
+ else
+ ret = __fio_client_send_remote_ini(client, filename);
+
if (!ret)
client->sent_job = 1;
return ret;
}
+static int fio_client_send_cf(struct fio_client *client,
+ struct client_file *cf)
+{
+ return fio_client_send_ini(client, cf->file, cf->remote);
+}
+
int fio_clients_send_ini(const char *filename)
{
struct fio_client *client;
flist_for_each_safe(entry, tmp, &client_list) {
client = flist_entry(entry, struct fio_client, list);
- if (client->nr_ini_file) {
+ if (client->nr_files) {
int i;
- for (i = 0; i < client->nr_ini_file; i++) {
- const char *ini = client->ini_file[i];
+ for (i = 0; i < client->nr_files; i++) {
+ struct client_file *cf;
- if (fio_client_send_ini(client, ini)) {
+ cf = &client->files[i];
+
+ if (fio_client_send_cf(client, cf)) {
remove_client(client);
break;
}
}
- } else if (!filename || fio_client_send_ini(client, filename))
+ }
+ if (client->sent_job)
+ continue;
+ if (!filename || fio_client_send_ini(client, filename, 0))
remove_client(client);
}
Client_exited = 5,
};
+struct client_file {
+ char *file;
+ int remote;
+};
+
struct fio_client {
struct flist_head list;
struct flist_head hash_list;
struct client_ops *ops;
void *client_data;
- char **ini_file;
- unsigned int nr_ini_file;
+ struct client_file *files;
+ unsigned int nr_files;
};
struct cmd_iolog_pdu;
extern int fio_clients_connect(void);
extern int fio_start_client(struct fio_client *);
extern int fio_start_all_clients(void);
-extern int fio_client_send_ini(struct fio_client *, const char *);
extern int fio_clients_send_ini(const char *);
+extern int fio_client_send_ini(struct fio_client *, const char *, int);
extern int fio_handle_clients(struct client_ops *);
extern int fio_client_add(struct client_ops *, const char *, void **);
extern struct fio_client *fio_client_add_explicit(struct client_ops *, const char *, int, int);
extern void fio_client_add_cmd_option(void *, const char *);
-extern void fio_client_add_ini_file(void *, const char *);
+extern int fio_client_add_ini_file(void *, const char *, int);
extern int fio_client_terminate(struct fio_client *);
extern void fio_clients_terminate(void);
extern struct fio_client *fio_get_client(struct fio_client *);
You can connect to multiple clients as well, to do that you could run:
fio \-\-client=server2 \-\-client=server2 <job file(s)>
+
+If the job file is located on the fio server, then you can tell the server
+to load a local file as well. This is done by using \-\-remote-config:
+
+fio \-\-client=server \-\-remote-config /path/to/file.fio
+
+Then the fio serer will open this local (to the server) job file instead
+of being passed one from the client.
.SH AUTHORS
.B fio
free(gco);
}
- ret = fio_client_send_ini(gc->client, ge->job_file);
+ ret = fio_client_send_ini(gc->client, ge->job_file, 0);
if (!ret)
return 0;
.has_arg = required_argument,
.val = 'C',
},
+ {
+ .name = (char *) "remote-config",
+ .has_arg = required_argument,
+ .val = 'R',
+ },
{
.name = (char *) "cpuclock-test",
.has_arg = no_argument,
f = fopen(file, "r");
if (!f) {
- perror("fopen job file");
+ int __err = errno;
+
+ log_err("fio: unable to open '%s' job file\n", file);
+ td_verror(td, __err, "job file open");
return 1;
}
}
printf(" --server=args\t\tStart a backend fio server\n");
printf(" --daemonize=pidfile\tBackground fio server, write pid to file\n");
printf(" --client=hostname\tTalk to remote backend fio server at hostname\n");
+ printf(" --remote-config=file\tTell fio server to load this local job file\n");
printf(" --idle-prof=option\tReport cpu idleness on a system or percpu basis\n"
"\t\t\t(option=system,percpu) or run unit work\n"
"\t\t\tcalibration only (option=calibrate)\n");
!strncmp(argv[optind], "-", 1))
break;
- fio_client_add_ini_file(cur_client, argv[optind]);
+ if (fio_client_add_ini_file(cur_client, argv[optind], 0))
+ break;
optind++;
}
break;
+ case 'R':
+ did_arg = 1;
+ if (fio_client_add_ini_file(cur_client, optarg, 1)) {
+ do_exit++;
+ exit_val = 1;
+ }
+ break;
case 'T':
did_arg = 1;
do_exit++;
"ADD_JOB",
"CMD_RUN",
"CMD_IOLOG",
+ "CMD_UPDATE_JOB",
+ "CMD_LOAD_FILE",
};
const char *fio_server_op(unsigned int op)
fio_server_check_fork_items(conn_list);
}
+static int handle_load_file_cmd(struct fio_net_cmd *cmd)
+{
+ struct cmd_load_file_pdu *pdu = (struct cmd_load_file_pdu *) cmd->payload;
+ void *file_name = pdu->file;
+ struct cmd_start_pdu spdu;
+
+ dprint(FD_NET, "server: loading local file %s\n", (char *) file_name);
+
+ pdu->name_len = le16_to_cpu(pdu->name_len);
+ pdu->client_type = le16_to_cpu(pdu->client_type);
+
+ if (parse_jobs_ini(file_name, 0, 0, pdu->client_type)) {
+ fio_net_send_quit(server_fd);
+ return -1;
+ }
+
+ spdu.jobs = cpu_to_le32(thread_number);
+ spdu.stat_outputs = cpu_to_le32(stat_number);
+ fio_net_send_cmd(server_fd, FIO_NET_CMD_START, &spdu, sizeof(spdu), NULL, NULL);
+ return 0;
+}
+
static int handle_run_cmd(struct flist_head *job_list, struct fio_net_cmd *cmd)
{
pid_t pid;
case FIO_NET_CMD_EXIT:
exit_backend = 1;
return -1;
+ case FIO_NET_CMD_LOAD_FILE:
+ ret = handle_load_file_cmd(cmd);
+ break;
case FIO_NET_CMD_JOB:
ret = handle_job_cmd(cmd);
break;
};
enum {
- FIO_SERVER_VER = 36,
+ FIO_SERVER_VER = 37,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_SERVER_MAX_CMD_MB = 2048,
FIO_NET_CMD_RUN = 16,
FIO_NET_CMD_IOLOG = 17,
FIO_NET_CMD_UPDATE_JOB = 18,
- FIO_NET_CMD_NR = 19,
+ FIO_NET_CMD_LOAD_FILE = 19,
+ FIO_NET_CMD_NR = 20,
FIO_NET_CMD_F_MORE = 1UL << 0,
FIO_PROBE_FLAG_ZLIB = 1UL << 0,
};
+struct cmd_load_file_pdu {
+ uint16_t name_len;
+ uint16_t client_type;
+ uint8_t file[];
+};
+
struct cmd_ts_pdu {
struct thread_stat ts;
struct group_run_stats rs;
extern void fio_server_send_du(void);
extern void fio_server_idle_loop(void);
-extern int fio_clients_connect(void);
-extern int fio_clients_send_ini(const char *);
-extern void fio_client_add_cmd_option(void *, const char *);
-extern void fio_client_add_ini_file(void *, const char *);
-
extern int fio_recv_data(int sk, void *p, unsigned int len);
extern int fio_send_data(int sk, const void *p, unsigned int len);
extern void fio_net_cmd_crc(struct fio_net_cmd *);