In order to handle reading an in-flight response while in the middle
of sending a second command, we'll need a way to jump back into the
middle of a command being sent. This is easier if the state that sets
wbuf/wlen is distinct from the state that reads into wbuf and alters
wlen, and also easier if we don't move the command to the in-flight
queue until after the writes finish (since the previous patch was
careful to queue new pending commands to the end of the list, the head
of the list is always the current command needing to be sent).
---
generator/generator | 14 ++++++++++
generator/states-issue-command.c | 45 ++++++++++++++++++++------------
2 files changed, 42 insertions(+), 17 deletions(-)
diff --git a/generator/generator b/generator/generator
index a1523e1..f8d59a0 100755
--- a/generator/generator
+++ b/generator/generator
@@ -638,12 +638,26 @@ and issue_command_state_machine = [
external_events = [ NotifyWrite, "" ];
};
+ State {
+ default_state with
+ name = "PREPARE_WRITE_PAYLOAD";
+ comment = "Prepare the write payload to send to the remote server";
+ external_events = [];
+ };
+
State {
default_state with
name = "SEND_WRITE_PAYLOAD";
comment = "Sending the write payload to the remote server";
external_events = [ NotifyWrite, "" ];
};
+
+State {
+ default_state with
+ name = "FINISH";
+ comment = "Finish issuing a command";
+ external_events = [];
+ };
]
(* Receiving a reply from the server. *)
diff --git a/generator/states-issue-command.c b/generator/states-issue-command.c
index a57f40f..e24ea34 100644
--- a/generator/states-issue-command.c
+++ b/generator/states-issue-command.c
@@ -24,9 +24,6 @@
assert (conn->cmds_to_issue != NULL);
cmd = conn->cmds_to_issue;
- conn->cmds_to_issue = cmd->next;
- cmd->next = conn->cmds_in_flight;
- conn->cmds_in_flight = cmd;
conn->sbuf.request.magic = htobe32 (NBD_REQUEST_MAGIC);
conn->sbuf.request.flags = htobe16 (cmd->flags);
@@ -40,29 +37,43 @@
return 0;
ISSUE_COMMAND.SEND_REQUEST:
- struct command_in_flight *cmd;
-
switch (send_from_wbuf (conn)) {
case -1: SET_NEXT_STATE (%.DEAD); return -1;
- case 0:
- assert (conn->cmds_in_flight != NULL);
- cmd = conn->cmds_in_flight;
- assert (cmd->handle == be64toh (conn->sbuf.request.handle));
- if (cmd->type == NBD_CMD_WRITE) {
- conn->wbuf = cmd->data;
- conn->wlen = cmd->count;
- SET_NEXT_STATE (%SEND_WRITE_PAYLOAD);
- }
- else
- SET_NEXT_STATE (%.READY);
+ case 0: SET_NEXT_STATE (%PREPARE_WRITE_PAYLOAD);
}
return 0;
+ ISSUE_COMMAND.PREPARE_WRITE_PAYLOAD:
+ struct command_in_flight *cmd;
+
+ assert (conn->cmds_to_issue != NULL);
+ cmd = conn->cmds_to_issue;
+ assert (cmd->handle == be64toh (conn->sbuf.request.handle));
+ if (cmd->type == NBD_CMD_WRITE) {
+ conn->wbuf = cmd->data;
+ conn->wlen = cmd->count;
+ SET_NEXT_STATE (%SEND_WRITE_PAYLOAD);
+ }
+ else
+ SET_NEXT_STATE (%FINISH);
+ return 0;
+
ISSUE_COMMAND.SEND_WRITE_PAYLOAD:
switch (send_from_wbuf (conn)) {
case -1: SET_NEXT_STATE (%.DEAD); return -1;
- case 0: SET_NEXT_STATE (%.READY);
+ case 0: SET_NEXT_STATE (%FINISH);
}
return 0;
+ ISSUE_COMMAND.FINISH:
+ struct command_in_flight *cmd;
+
+ assert (conn->cmds_to_issue != NULL);
+ cmd = conn->cmds_to_issue;
+ conn->cmds_to_issue = cmd->next;
+ cmd->next = conn->cmds_in_flight;
+ conn->cmds_in_flight = cmd;
+ SET_NEXT_STATE (%.READY);
+ return 0;
+
} /* END STATE MACHINE */
--
2.20.1