summaryrefslogtreecommitdiff
path: root/usr.sbin/iscsid/poll.c
blob: 1442e2028eb91f5000355d550532eb4e5aba5c6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
 * Copyright (c) 2021 Dr Ashton Fagg <ashton@fagg.id.au>
 *
 * 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/queue.h>
#include <sys/socket.h>
#include <sys/uio.h>

#include <event.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "iscsid.h"
#include "log.h"

void
poll_session(struct session_poll *p, struct session *s)
{
	if (!s)
		fatal("poll_session failed: invalid session");

	++p->session_count;

	/*
	 * If SESS_RUNNING, the session has either been brought up
	 * successfully, or has failed.
	 */
	if (s->state & SESS_RUNNING) {
		struct connection *c;
		int is_logged_in = 0;
		int is_failed = 0;
		int is_waiting = 0;

		++p->session_running_count;

		/* Next, check what state the connections are in. */
		TAILQ_FOREACH(c, &s->connections, entry) {
			if (c->state & CONN_LOGGED_IN)
				++is_logged_in;
			else if (c->state & CONN_FAILED)
				++is_failed;
			else if (c->state & CONN_NEVER_LOGGED_IN)
				++is_waiting;

		}

		/*
		 * Potentially, we have multiple connections for each session.
		 * Handle this by saying that a single connection logging
		 * in takes precedent over a failed connection. Only say
		 * the session login has failed if none of the connections
		 * have logged in and nothing is in flight.
		 */

		if (is_logged_in)
			++p->conn_logged_in_count;
		if (is_failed)
			++p->conn_failed_count;
		if (is_waiting)
			++p->conn_waiting_count;

	/* Sessions in SESS_INIT need to be waited on. */
	} else if (s->state & SESS_INIT)
		++p->session_init_count;
	else
		fatal("poll_session: unknown state.");
}

/*
 * Set session_poll sess_conn_status based on the number of sessions
 * versus number of logged in or failed sessions. If the numbers are
 * equal iscsictl can stop polling since all sessions reached a stable state.
 */
void
poll_finalize(struct session_poll *p)
{
	p->sess_conn_status = (p->session_count == p->conn_logged_in_count +
	    p->conn_failed_count);
}