};
struct sk_entry {
- struct flist_head list;
- int opcode;
+ struct flist_head list; /* link on sk_out->list */
+ int flags; /* SK_F_* */
+ int opcode; /* Actual command fields */
void *buf;
off_t size;
uint64_t *tagptr;
- int flags;
- struct flist_head next;
+ struct flist_head next; /* Other sk_entry's, if linked command */
};
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, sk_out);
}
-static void __sk_out_drop(struct sk_out *sk_out)
+static void sk_out_free(struct sk_out *sk_out)
{
fio_mutex_remove(sk_out->lock);
fio_mutex_remove(sk_out->wait);
sfree(sk_out);
}
-void sk_out_drop(void)
+static int __sk_out_drop(struct sk_out *sk_out)
{
- struct sk_out *sk_out = pthread_getspecific(sk_out_key);
-
if (sk_out) {
int refs;
refs = --sk_out->refs;
sk_unlock(sk_out);
- if (!refs)
- __sk_out_drop(sk_out);
+ if (!refs) {
+ sk_out_free(sk_out);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+void sk_out_drop(void)
+{
+ struct sk_out *sk_out;
+ sk_out = pthread_getspecific(sk_out_key);
+ if (!__sk_out_drop(sk_out))
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)
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, };
dprint(FD_NET, "server: connect from %s\n", from);
+ sk_out = smalloc(sizeof(*sk_out));
sk_out->sk = sk;
+ INIT_FLIST_HEAD(&sk_out->list);
+ sk_out->lock = fio_mutex_init(FIO_MUTEX_UNLOCKED);
+ sk_out->wait = fio_mutex_init(FIO_MUTEX_LOCKED);
pid = fork();
if (pid) {
close(sk);
fio_server_add_conn_pid(&conn_list, pid);
- pthread_setspecific(sk_out_key, sk_out);
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);
}
if (pthread_key_create(&sk_out_key, NULL))
log_err("fio: can't create sk_out backend key\n");
- sk_out = smalloc(sizeof(*sk_out));
- INIT_FLIST_HEAD(&sk_out->list);
- sk_out->lock = fio_mutex_init(FIO_MUTEX_UNLOCKED);
- sk_out->wait = fio_mutex_init(FIO_MUTEX_LOCKED);
-
- sk_out_assign(sk_out);
-
ret = accept_loop(sk_out, sk);
close(sk);
if (bind_sock)
free(bind_sock);
- sk_out_drop();
-
return ret;
}