Ashton Fagg <[email protected]> writes:
> Attached is my first attempt at a "proper" solution. I haven't tested it
> beyond building as I can't take my machine down for testing right now...
>
> But, I'd appreciate a sanity check that I'm on the right track.
Sorry for the noise. I think my mail client mangled the attachment, so
trying again.
diff --git a/usr.sbin/iscsictl/iscsictl.c b/usr.sbin/iscsictl/iscsictl.c
index 77f9c74abde..5fc326acca6 100644
--- a/usr.sbin/iscsictl/iscsictl.c
+++ b/usr.sbin/iscsictl/iscsictl.c
@@ -40,6 +40,8 @@ struct pdu *ctl_getpdu(char *, size_t);
int ctl_sendpdu(int, struct pdu *);
void show_config(struct ctrlmsghdr *, struct pdu *);
void show_vscsi_stats(struct ctrlmsghdr *, struct pdu *);
+void poll_and_wait(void);
+void register_poll(struct ctrlmsghdr *, struct pdu *);
char cbuf[CONTROL_READ_SIZE];
@@ -48,6 +50,14 @@ struct control {
int fd;
} control;
+struct poll_result {
+ u_int8_t result;
+ int attempts;
+} pr;
+
+#define POLL_DELAY 1
+#define POLL_ATTEMPTS 10
+
__dead void
usage(void)
{
@@ -68,7 +78,7 @@ main (int argc, char* argv[])
char *sockname = ISCSID_CONTROL;
struct session_ctlcfg *s;
struct iscsi_config *cf;
- int ch, val = 0;
+ int ch, poll = 0, val = 0;
/* check flags */
while ((ch = getopt(argc, argv, "f:s:")) != -1) {
@@ -135,6 +145,9 @@ main (int argc, char* argv[])
&cf->initiator, sizeof(cf->initiator)) == -1)
err(1, "control_compose");
}
+
+ /* Reloading, so poll afterwards. */
+ poll = 1;
SIMPLEQ_FOREACH(s, &cf->sessions, entry) {
struct ctrldata cdv[3];
bzero(cdv, sizeof(cdv));
@@ -174,6 +187,12 @@ main (int argc, char* argv[])
run();
+ /* If we've reloaded, we probably should wait in case any new connections
+ need to come up (or fail). */
+ if (poll) {
+ poll_and_wait();
+ }
+
close(control.fd);
return (0);
@@ -229,6 +248,10 @@ run_command(struct pdu *pdu)
case CTRL_INPROGRESS:
printf("command in progress...\n");
break;
+ case CTRL_SESS_POLL:
+ done = 1;
+ register_poll(cmh, pdu);
+ break;
case CTRL_INITIATOR_CONFIG:
case CTRL_SESSION_CONFIG:
show_config(cmh, pdu);
@@ -383,3 +406,43 @@ show_vscsi_stats(struct ctrlmsghdr *cmh, struct pdu *pdu)
vs->cnt_t2i_status[1],
vs->cnt_t2i_status[2]);
}
+
+void
+poll_and_wait(void)
+{
+ pr.result = (u_int8_t) 0;
+ printf("polling...");
+
+ for (pr.attempts = 1; pr.attempts <= POLL_ATTEMPTS; ++pr.attempts) {
+ if (control_compose(NULL, CTRL_SESS_POLL, NULL, 0) == -1)
+ err(1, "control_compose");
+
+ struct pdu *pdu;
+ while ((pdu = TAILQ_FIRST(&control.channel)) != NULL) {
+ run_command(pdu);
+ }
+
+ /* Poll says we are good to go. */
+ if (pr.result != 0) {
+ printf("ok!\n");
+ return;
+ }
+
+ /* Poll says we should wait... */
+ printf("%d, ", pr.attempts);
+ sleep(POLL_DELAY);
+ }
+
+ printf("..,timer exceeded.\n");
+}
+
+void
+register_poll(struct ctrlmsghdr *cmh, struct pdu *pdu)
+{
+ u_int8_t *r = &pr.result;
+
+ if (cmh->len[0] != sizeof(u_int8_t))
+ errx(1, "poll: bad size of response");
+
+ r = pdu_getbuf(pdu, NULL, 1);
+}
diff --git a/usr.sbin/iscsid/Makefile b/usr.sbin/iscsid/Makefile
index 7a62024e68b..bac59d934f8 100644
--- a/usr.sbin/iscsid/Makefile
+++ b/usr.sbin/iscsid/Makefile
@@ -2,7 +2,7 @@
PROG= iscsid
SRCS= connection.c control.c initiator.c iscsid.c log.c logmsg.c pdu.c \
- session.c task.c util.c vscsi.c
+ poll.c session.c task.c util.c vscsi.c
MAN= iscsid.8
diff --git a/usr.sbin/iscsid/iscsid.c b/usr.sbin/iscsid/iscsid.c
index d3526e96363..61f831c3b24 100644
--- a/usr.sbin/iscsid/iscsid.c
+++ b/usr.sbin/iscsid/iscsid.c
@@ -211,6 +211,7 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu)
struct initiator_config *ic;
struct session_config *sc;
struct session *s;
+ struct session_poll *p;
int *valp;
cmh = pdu_getbuf(pdu, NULL, 0);
@@ -304,6 +305,20 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu)
control_compose(ch, CTRL_SUCCESS, NULL, 0);
break;
+ case CTRL_SESS_POLL:
+ p = poll_alloc();
+
+ TAILQ_FOREACH(s, &initiator->sessions, entry) {
+ poll_session(p, s);
+ }
+
+ poll_finalize(p);
+
+ control_compose(ch, CTRL_SESS_POLL,
+ (void *) &(p->status), sizeof(u_int8_t));
+
+ poll_dealloc(p);
+ break;
default:
log_warnx("unknown control message type %d", cmh->type);
control_compose(ch, CTRL_FAILURE, NULL, 0);
diff --git a/usr.sbin/iscsid/iscsid.h b/usr.sbin/iscsid/iscsid.h
index b43fb5dcd99..08d5f251a39 100644
--- a/usr.sbin/iscsid/iscsid.h
+++ b/usr.sbin/iscsid/iscsid.h
@@ -67,7 +67,7 @@ struct ctrldata {
#define CTRL_LOG_VERBOSE 6
#define CTRL_VSCSI_STATS 7
#define CTRL_SHOW_SUM 8
-
+#define CTRL_SESS_POLL 9
TAILQ_HEAD(session_head, session);
TAILQ_HEAD(connection_head, connection);
@@ -251,6 +251,13 @@ struct session {
int action;
};
+struct session_poll {
+ u_int16_t session_count; /* Total number of configured sessions*/
+ u_int16_t init_count; /* Number of sessions in init state */
+ u_int16_t running_count; /* Number of sessions in running state */
+ u_int8_t status; /* Status flag */
+};
+
struct connection {
struct event ev;
struct event wev;
@@ -391,6 +398,12 @@ void vscsi_status(int, int, void *, size_t);
void vscsi_event(unsigned long, u_int, u_int);
struct vscsi_stats *vscsi_stats(void);
+/* Session polling */
+struct session_poll *poll_alloc(void);
+void poll_dealloc(struct session_poll *);
+void poll_session(struct session_poll *, struct session *);
+void poll_finalize(struct session_poll *);
+
/* logmsg.c */
void log_hexdump(void *, size_t);
void log_pdu(struct pdu *, int);
diff --git a/usr.sbin/iscsid/poll.c b/usr.sbin/iscsid/poll.c
new file mode 100644
index 00000000000..d3c79985d71
--- /dev/null
+++ b/usr.sbin/iscsid/poll.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021 Dr Ashton Fagg <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <event.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "iscsid.h"
+#include "log.h"
+
+struct session_poll
+*poll_alloc(void)
+{
+ struct session_poll *p;
+
+ if (!(p = calloc(1, sizeof(*p))))
+ fatal("poll_alloc failed.");
+
+ p->session_count = (u_int16_t) 0;
+ p->init_count = (u_int16_t) 0;
+ p->running_count = (u_int16_t) 0;
+
+ return p;
+}
+
+
+void
+poll_dealloc(struct session_poll *p)
+{
+ free(p);
+}
+
+void
+poll_session(struct session_poll *p, struct session *s)
+{
+ if (!s)
+ fatal("poll_session failed: invalid session");
+
+ ++(p->session_count);
+
+ /* If SESS_RUNNING, this determines the session has either
+ been brought up successfully, or has failed. Either way,
+ we aren't waiting on it. */
+ if (s->state & SESS_RUNNING)
+ ++(p->running_count);
+ /* Otherwise, it is in SESS_INIT. These need to be waited on. */
+ else if (s->state & SESS_RUNNING)
+ ++(p->init_count);
+ else
+ fatal("poll_session: unknown state.");
+}
+
+void
+poll_finalize(struct session_poll *p)
+{
+ /* Perform final book keeping to determine status.
+ *
+ * status will be non-zero if the number of sessions that are
+ * in states other than SESS_INIT is equal to the total number
+ * of configured sessions. This indicates to the poller that
+ * we are not waiting for something to complete. */
+ p->status = (u_int8_t) (p->session_count == p->running_count);
+}