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