xref: /openbsd/usr.sbin/iscsid/poll.c (revision ea99aae6)
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