+/*
+ * Send a command with a separate PDU, not inlined in the command
+ */
+static int fio_send_cmd_ext_pdu(int sk, uint16_t opcode, const void *buf,
+ off_t size, uint64_t tag, uint32_t flags)
+{
+ struct fio_net_cmd cmd;
+ struct iovec iov[2];
+
+ iov[0].iov_base = (void *) &cmd;
+ iov[0].iov_len = sizeof(cmd);
+ iov[1].iov_base = (void *) buf;
+ iov[1].iov_len = size;
+
+ __fio_init_net_cmd(&cmd, opcode, size, tag);
+ cmd.flags = __cpu_to_le32(flags);
+ fio_net_cmd_crc_pdu(&cmd, buf);
+
+ return fio_sendv_data(sk, iov, 2);
+}
+
+static void finish_entry(struct sk_entry *entry)
+{
+ if (entry->flags & SK_F_FREE)
+ free(entry->buf);
+ else if (entry->flags & SK_F_COPY)
+ sfree(entry->buf);
+
+ sfree(entry);
+}
+
+static void send_vec_entry(struct sk_out *sk_out, struct sk_entry *first)
+{
+ uint64_t tag;
+ int flags;
+
+ if (!flist_empty(&first->next))
+ flags = FIO_NET_CMD_F_MORE;
+ else
+ flags = 0;
+
+ if (first->tagptr)
+ tag = *first->tagptr;
+ else
+ tag = 0;
+
+ fio_send_cmd_ext_pdu(sk_out->sk, first->opcode, first->buf, first->size, tag, flags);
+
+ while (!flist_empty(&first->next)) {
+ struct sk_entry *next;
+
+ next = flist_first_entry(&first->next, struct sk_entry, list);
+ flist_del_init(&next->list);
+ if (flist_empty(&first->next))
+ flags = 0;
+
+ if (next->tagptr)
+ tag = *next->tagptr;
+ else
+ tag = 0;
+
+ fio_send_cmd_ext_pdu(sk_out->sk, next->opcode, next->buf, next->size, tag, flags);
+ finish_entry(next);
+ }
+}
+