1 /*
2 * Copyright (c) 2021 Dr Ashton Fagg <ashton@fagg.id.au>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <sys/types.h>
18 #include <sys/queue.h>
19 #include <sys/socket.h>
20 #include <sys/uio.h>
21
22 #include <event.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "iscsid.h"
29 #include "log.h"
30
31 void
poll_session(struct session_poll * p,struct session * s)32 poll_session(struct session_poll *p, struct session *s)
33 {
34 if (!s)
35 fatal("poll_session failed: invalid session");
36
37 ++p->session_count;
38
39 /*
40 * If SESS_RUNNING, the session has either been brought up
41 * successfully, or has failed.
42 */
43 if (s->state & SESS_RUNNING) {
44 struct connection *c;
45 int is_logged_in = 0;
46 int is_failed = 0;
47 int is_waiting = 0;
48
49 ++p->session_running_count;
50
51 /* Next, check what state the connections are in. */
52 TAILQ_FOREACH(c, &s->connections, entry) {
53 if (c->state & CONN_LOGGED_IN)
54 ++is_logged_in;
55 else if (c->state & CONN_FAILED)
56 ++is_failed;
57 else if (c->state & CONN_NEVER_LOGGED_IN)
58 ++is_waiting;
59
60 }
61
62 /*
63 * Potentially, we have multiple connections for each session.
64 * Handle this by saying that a single connection logging
65 * in takes precedent over a failed connection. Only say
66 * the session login has failed if none of the connections
67 * have logged in and nothing is in flight.
68 */
69
70 if (is_logged_in)
71 ++p->conn_logged_in_count;
72 if (is_failed)
73 ++p->conn_failed_count;
74 if (is_waiting)
75 ++p->conn_waiting_count;
76
77 /* Sessions in SESS_INIT need to be waited on. */
78 } else if (s->state & SESS_INIT)
79 ++p->session_init_count;
80 else
81 fatal("poll_session: unknown state.");
82 }
83
84 /*
85 * Set session_poll sess_conn_status based on the number of sessions
86 * versus number of logged in or failed sessions. If the numbers are
87 * equal iscsictl can stop polling since all sessions reached a stable state.
88 */
89 void
poll_finalize(struct session_poll * p)90 poll_finalize(struct session_poll *p)
91 {
92 p->sess_conn_status = (p->session_count == p->conn_logged_in_count +
93 p->conn_failed_count);
94 }
95