From: Wenchao Hao <73930449+wenchao-hao@users.noreply.github.com>
Date: Thu, 5 Jan 2023 07:46:05 +0800
Subject: iscsid: clear scanning thread's PR_SET_IO_FLUSHER flag (#382)
Git-commit: 138a5306fc9238d0becf3cc8a5d90ca0b9d71f72
References: bsc#1235606

commit 72949ef (iscsid: set PR_SET_IO_FLUSHER) set the iscsid's
PR_SET_IO_FLUSHER flag to avoid deadlock. While we do not need
to set this flag when scanning host.

If this flag is set for scanning thread, we may lost devices
reported by target because of memory allocation failure.

Signed-off-by: Wenchao Hao <haowenchao@huawei.com>

Signed-off-by: Wenchao Hao <haowenchao@huawei.com>

---
 usr/iscsi_sysfs.c |    7 +++++++
 usr/iscsi_util.c  |   27 +++++++++++++++++++++++++++
 usr/iscsi_util.h  |    1 +
 usr/iscsid.c      |   15 ++-------------
 4 files changed, 37 insertions(+), 13 deletions(-)

--- open-iscsi-2.1.7-suse.orig/usr/iscsi_sysfs.c
+++ open-iscsi-2.1.7-suse/usr/iscsi_sysfs.c
@@ -40,6 +40,7 @@
 #include "host.h"
 #include "iscsi_err.h"
 #include "flashnode.h"
+#include "iscsi_util.h"
 
 /*
  * TODO: remove the _DIR defines and search for subsys dirs like
@@ -1994,6 +1995,12 @@ pid_t iscsi_sysfs_scan_host(int hostno,
 		/* child */
 		log_debug(4, "scanning host%d", hostno);
 
+		/*
+		 * The return value of init_thread_io_flusher would not
+		 * affect the scan flow, so just ignore it.
+		 */
+		set_thread_io_flusher(0);
+
 		snprintf(id, sizeof(id), ISCSI_HOST_ID, hostno);
 		sysfs_set_param(id, SCSI_HOST_SUBSYS, "scan", write_buf,
 				strlen(write_buf));
--- open-iscsi-2.1.7-suse.orig/usr/iscsi_util.c
+++ open-iscsi-2.1.7-suse/usr/iscsi_util.c
@@ -30,6 +30,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/resource.h>
+#include <sys/prctl.h>
 
 #include "sysdeps.h"
 #include "log.h"
@@ -38,6 +39,10 @@
 #include "session_info.h"
 #include "iscsi_util.h"
 
+#ifndef PR_SET_IO_FLUSHER
+#define PR_SET_IO_FLUSHER 57
+#endif
+
 int setup_abstract_addr(struct sockaddr_un *addr, char *unix_sock_name)
 {
 	memset(addr, 0, sizeof(*addr));
@@ -385,3 +390,25 @@ int iscsi_match_target(void *data, struc
 				     info->persistent_port, NULL,
 				     MATCH_ANY_SID);
 }
+
+/*
+ * set thread's PR_SET_IO_FLUSHER flag
+ *
+ * val: 1 to set to set thread's PR_SET_IO_FLUSHER flag
+ *      0 to clear thread's PR_SET_IO_FLUSHER flag
+ *
+ * return: return 0 on success, else error number is returned
+ */
+int set_thread_io_flusher(int val)
+{
+	if (prctl(PR_SET_IO_FLUSHER, val, 0, 0, 0) == 0)
+		return 0;
+
+	/*
+	 * prctl would return EINVAL if the kernel do not support PR_SET_IO_FLUSHER
+	 * so donot print error log if errorno is EINVAL to avoid unnecessary errorlog
+	 */
+	if (errno != EINVAL)
+		log_error("prctl could not %s thread's PR_SET_IO_FLUSHER flag due to error %s\n", val ? "set" : "clear", strerror(errno));
+	return errno;
+}
--- open-iscsi-2.1.7-suse.orig/usr/iscsi_util.h
+++ open-iscsi-2.1.7-suse/usr/iscsi_util.h
@@ -20,6 +20,7 @@ extern int __iscsi_match_session(struct
 				 char *address, int port,
 				 struct iface_rec *iface,
 				 unsigned sid);
+extern int set_thread_io_flusher(int val);
 
 #define MATCH_ANY_SID 0
 
--- open-iscsi-2.1.7-suse.orig/usr/iscsid.c
+++ open-iscsi-2.1.7-suse/usr/iscsid.c
@@ -34,7 +34,6 @@
 #include <sys/wait.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/prctl.h>
 #ifndef	NO_SYSTEMD
 #include <systemd/sd-daemon.h>
 #endif
@@ -57,10 +56,6 @@
 #include "iscsid_req.h"
 #include "iscsi_err.h"
 
-#ifndef PR_SET_IO_FLUSHER
-#define PR_SET_IO_FLUSHER 57
-#endif
-
 /* global config info */
 struct iscsi_daemon_config daemon_config;
 struct iscsi_daemon_config *dconfig = &daemon_config;
@@ -624,14 +619,8 @@ int main(int argc, char *argv[])
 		exit(ISCSI_ERR);
 	}
 
-	if (prctl(PR_SET_IO_FLUSHER, 1, 0, 0, 0) == -1) {
-		if (errno == EINVAL) {
-			log_info("prctl could not mark iscsid with the PR_SET_IO_FLUSHER flag, because the feature is not supported in this kernel. Will proceed, but iscsid may hang during session level recovery if memory is low.\n");
-		} else {
-			log_error("prctl could not mark iscsid with the PR_SET_IO_FLUSHER flag due to error %s\n",
-				  strerror(errno));
-		}
-	}
+	if (set_thread_io_flusher(1) == EINVAL)
+		log_info("prctl could not mark iscsid with the PR_SET_IO_FLUSHER flag, because the feature is not supported in this kernel. Will proceed, but iscsid may hang during session level recovery if memory is low.\n");
 
 	set_state_to_ready();
 	event_loop(ipc, control_fd, mgmt_ipc_fd);
