};
struct sk_out {
- unsigned int refs;
+ unsigned int refs; /* frees sk_out when it drops to zero.
+ * protected by below ->lock */
- int sk;
- struct fio_mutex *lock;
- struct flist_head list;
- struct fio_mutex *wait;
+ int sk; /* socket fd to talk to client */
+ struct fio_mutex *lock; /* protects ref and below list */
+ struct flist_head list; /* list of pending transmit work */
+ struct fio_mutex *wait; /* wake backend when items added to list */
};
static char *fio_server_arg;
pthread_setspecific(sk_out_key, NULL);
}
+static void __fio_init_net_cmd(struct fio_net_cmd *cmd, uint16_t opcode,
+ uint32_t pdu_len, uint64_t tag)
+{
+ memset(cmd, 0, sizeof(*cmd));
+
+ cmd->version = __cpu_to_le16(FIO_SERVER_VER);
+ cmd->opcode = cpu_to_le16(opcode);
+ cmd->tag = cpu_to_le64(tag);
+ cmd->pdu_len = cpu_to_le32(pdu_len);
+}
+
+
+static void fio_init_net_cmd(struct fio_net_cmd *cmd, uint16_t opcode,
+ const void *pdu, uint32_t pdu_len, uint64_t tag)
+{
+ __fio_init_net_cmd(cmd, opcode, pdu_len, tag);
+
+ if (pdu)
+ memcpy(&cmd->payload, pdu, pdu_len);
+}
+
const char *fio_server_op(unsigned int op)
{
static char buf[32];
return 1;
}
-int fio_send_data(int sk, const void *p, unsigned int len)
+static int fio_send_data(int sk, const void *p, unsigned int len)
{
struct iovec iov = { .iov_base = (void *) p, .iov_len = len };
return fio_sendv_data(sk, &iov, 1);
}
-int fio_recv_data(int sk, void *p, unsigned int len)
+static int fio_recv_data(int sk, void *p, unsigned int len)
{
do {
int ret = recv(sk, p, len, MSG_WAITALL);
free(reply);
}
-void fio_net_cmd_crc_pdu(struct fio_net_cmd *cmd, const void *pdu)
+static void fio_net_cmd_crc_pdu(struct fio_net_cmd *cmd, const void *pdu)
{
uint32_t pdu_len;
cmd->pdu_crc16 = __cpu_to_le16(fio_crc16(pdu, pdu_len));
}
-void fio_net_cmd_crc(struct fio_net_cmd *cmd)
+static void fio_net_cmd_crc(struct fio_net_cmd *cmd)
{
fio_net_cmd_crc_pdu(cmd, cmd->payload);
}
return ret;
}
-struct sk_entry *fio_net_prep_cmd(uint16_t opcode, void *buf, off_t size,
- uint64_t *tagptr, int flags)
+static struct sk_entry *fio_net_prep_cmd(uint16_t opcode, void *buf, off_t size,
+ uint64_t *tagptr, int flags)
{
struct sk_entry *entry;
handle_xmits(sk_out);
close(sk_out->sk);
+ sk_out->sk = -1;
__sk_out_drop(sk_out);
_exit(ret);
}
/* get the address on this host bound by the input socket,
* whether it is ipv6 or ipv4 */
-int get_my_addr_str(int sk)
+static int get_my_addr_str(int sk)
{
struct sockaddr_in6 myaddr6 = { 0, };
struct sockaddr_in myaddr4 = { 0, };
return 0;
}
-static int accept_loop(struct sk_out *sk_out, int listen_sk)
+static int accept_loop(int listen_sk)
{
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
fio_set_fd_nonblocking(listen_sk, "server");
while (!exit_backend) {
+ struct sk_out *sk_out;
const char *from;
char buf[64];
pid_t pid;
continue;
}
- /* exits */
- get_my_addr_str(sk); /* if error, it's already logged, non-fatal */
+ /* if error, it's already logged, non-fatal */
+ get_my_addr_str(sk);
+
+ /*
+ * Assign sk_out here, it'll be dropped in handle_connection()
+ * since that function calls _exit() when done
+ */
sk_out_assign(sk_out);
handle_connection(sk_out);
}
fio_net_queue_cmd(FIO_NET_CMD_GS, &gs, sizeof(gs), NULL, SK_F_COPY);
}
+void fio_server_send_job_options(struct flist_head *opt_list,
+ unsigned int groupid)
+{
+ struct cmd_job_option pdu;
+ struct flist_head *entry;
+
+ if (flist_empty(opt_list))
+ return;
+
+ flist_for_each(entry, opt_list) {
+ struct print_option *p;
+ size_t len;
+
+ p = flist_entry(entry, struct print_option, list);
+ memset(&pdu, 0, sizeof(pdu));
+
+ if (groupid == -1U) {
+ pdu.global = __cpu_to_le16(1);
+ pdu.groupid = 0;
+ } else {
+ pdu.global = 0;
+ pdu.groupid = cpu_to_le32(groupid);
+ }
+ len = strlen(p->name);
+ if (len >= sizeof(pdu.name)) {
+ len = sizeof(pdu.name) - 1;
+ pdu.truncated = __cpu_to_le16(1);
+ }
+ memcpy(pdu.name, p->name, len);
+ if (p->value) {
+ len = strlen(p->value);
+ if (len >= sizeof(pdu.value)) {
+ len = sizeof(pdu.value) - 1;
+ pdu.truncated = __cpu_to_le16(1);
+ }
+ memcpy(pdu.value, p->value, len);
+ }
+ fio_net_queue_cmd(FIO_NET_CMD_JOB_OPT, &pdu, sizeof(pdu), NULL, SK_F_COPY);
+ }
+}
+
static void convert_agg(struct disk_util_agg *dst, struct disk_util_agg *src)
{
int i;
log_info("fio: server listening on %s\n", bind_str);
- if (listen(sk, 0) < 0) {
+ if (listen(sk, 4) < 0) {
log_err("fio: listen: %s\n", strerror(errno));
close(sk);
return -1;
static int fio_server(void)
{
- struct sk_out *sk_out;
int sk, ret;
+ if (pthread_key_create(&sk_out_key, NULL)) {
+ log_err("fio: can't create sk_out backend key\n");
+ return -1;
+ }
+
+ pthread_setspecific(sk_out_key, NULL);
+
dprint(FD_NET, "starting server\n");
if (fio_handle_server_arg())
set_sig_handlers();
- if (pthread_key_create(&sk_out_key, NULL))
- log_err("fio: can't create sk_out backend key\n");
-
- ret = accept_loop(sk_out, sk);
+ ret = accept_loop(sk);
close(sk);