Blob Blame History Raw
From a744d91046865416a50ea27f143ef0f02fcaf1c6 Mon Sep 17 00:00:00 2001
From: Chris Leech <cleech@redhat.com>
Date: Wed, 17 Feb 2021 12:22:17 -0800
Subject: [PATCH] libopeniscsiusr: skip over removed sessions

When looping over all sessions with iscsi_sessions_get, it's possible to
race against sessions being destroyed and have the sysfs attribute files
be removed before they're read. Let's not treat this as an error, and
simply drop the session that failed to read from the list. I think it
makes sense to treat session that disapear while they're being read as
if they were already gone when the sessions directory was first scanned.

Apparently having iscsiadm exit with an error when trying to get a list
of sessions is a problem for OpenStack deployments.

Signed-off-by: Chris Leech <cleech@redhat.com>
---
 libopeniscsiusr/session.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/libopeniscsiusr/session.c b/libopeniscsiusr/session.c
index f122fe3..4a724c8 100644
--- a/libopeniscsiusr/session.c
+++ b/libopeniscsiusr/session.c
@@ -246,6 +246,7 @@ int iscsi_sessions_get(struct iscsi_context *ctx,
 {
 	int rc = LIBISCSI_OK;
 	uint32_t i = 0;
+	uint32_t j = 0;
 	uint32_t *sids = NULL;
 
 	assert(ctx != NULL);
@@ -264,9 +265,22 @@ int iscsi_sessions_get(struct iscsi_context *ctx,
 
 	for (i = 0; i < *session_count; ++i) {
 		_debug(ctx, "sid %" PRIu32, sids[i]);
-		_good(iscsi_session_get(ctx, sids[i], &((*sessions)[i])),
-		      rc, out);
+		rc = iscsi_session_get(ctx, sids[i], &((*sessions)[j]));
+		if (rc == LIBISCSI_OK) {
+			/* if session info was successfully read from sysfs, advance the sessions pointer */
+			j++;
+		} else {
+			/* if not, just ignore the issue and keep trying with the next session ID,
+			 * there's always going to be an inherent race against session removal when collecting
+			 * attribute data from sysfs
+			 */
+			_debug(ctx, "Problem reading session %" PRIu32 ", skipping.", sids[i]);
+			rc = LIBISCSI_OK;
+		}
 	}
+	/* reset session count and sessions array length to what we were able to read from sysfs */
+	*session_count = j;
+	*sessions = reallocarray(*sessions, *session_count, sizeof(struct iscsi_session *));
 
 out:
 	free(sids);
-- 
2.26.2