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 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 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