All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maurizio Lombardi <mlombard@redhat.com>
To: martin.petersen@oracle.com
Cc: michael.christie@oracle.com, target-devel@vger.kernel.org
Subject: [PATCH] target: iscsi: use GFP_NOIO with loopback connections
Date: Mon, 27 Feb 2023 08:57:35 +0100	[thread overview]
Message-ID: <20230227075735.8695-1-mlombard@redhat.com> (raw)

When an iscsi initiator is connected to a target running on the
same machine, the system may trigger a deadlock when working
under memory pressure.
This may happen, for example, when the iscsi rx thread tries to
allocate memory and a memory reclaim is performed, the rx thread may
therefore end up waiting for the initiator to complete I/O operations,
causing a deadlock.

Fix the issue by using memalloc_noio_*() to enable implicit GFP_NOIO
in the vulnerable code paths, when the connection is in loopback.

Suggested-by: David Jeffery <djeffery@redhat.com>
Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
---
 drivers/target/iscsi/iscsi_target.c       | 19 ++++++++++++++++---
 drivers/target/iscsi/iscsi_target_login.c |  8 ++++++++
 include/target/iscsi/iscsi_target_core.h  |  1 +
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index baf4da7bb3b4..4d997a049bf7 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3918,9 +3918,9 @@ static int iscsit_handle_response_queue(struct iscsit_conn *conn)
 
 int iscsi_target_tx_thread(void *arg)
 {
-	int ret = 0;
+	int ret = 0, flags;
 	struct iscsit_conn *conn = arg;
-	bool conn_freed = false;
+	bool conn_freed = false, loopback;
 
 	/*
 	 * Allow ourselves to be interrupted by SIGINT so that a
@@ -3928,6 +3928,10 @@ int iscsi_target_tx_thread(void *arg)
 	 */
 	allow_signal(SIGINT);
 
+	loopback = conn->loopback;
+	if (loopback)
+		flags = memalloc_noio_save();
+
 	while (!kthread_should_stop()) {
 		/*
 		 * Ensure that both TX and RX per connection kthreads
@@ -3966,6 +3970,9 @@ int iscsi_target_tx_thread(void *arg)
 	if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
 		iscsit_take_action_for_connection_exit(conn, &conn_freed);
 out:
+	if (loopback)
+		memalloc_noio_restore(flags);
+
 	if (!conn_freed) {
 		while (!kthread_should_stop()) {
 			msleep(100);
@@ -4166,7 +4173,7 @@ static void iscsit_get_rx_pdu(struct iscsit_conn *conn)
 
 int iscsi_target_rx_thread(void *arg)
 {
-	int rc;
+	int rc, flags;
 	struct iscsit_conn *conn = arg;
 	bool conn_freed = false;
 
@@ -4186,8 +4193,14 @@ int iscsi_target_rx_thread(void *arg)
 	if (!conn->conn_transport->iscsit_get_rx_pdu)
 		return 0;
 
+	if (conn->loopback)
+		flags = memalloc_noio_save();
+
 	conn->conn_transport->iscsit_get_rx_pdu(conn);
 
+	if (conn->loopback)
+		memalloc_noio_restore(flags);
+
 	if (!signal_pending(current))
 		atomic_set(&conn->transport_failed, 1);
 	iscsit_take_action_for_connection_exit(conn, &conn_freed);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 27e448c2d066..bbda125f6526 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -17,6 +17,7 @@
 #include <linux/tcp.h>        /* TCP_NODELAY */
 #include <net/ip.h>
 #include <net/ipv6.h>         /* ipv6_addr_v4mapped() */
+#include <net/sock.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
@@ -1246,6 +1247,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
 	struct iscsi_portal_group *tpg = NULL;
 	struct iscsi_login_req *pdu;
 	struct iscsi_tpg_np *tpg_np;
+	struct dst_entry *dst;
 	bool new_sess = false;
 
 	flush_signals(current);
@@ -1289,6 +1291,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
 		iscsit_free_conn(conn);
 		return 1;
 	}
+
+	dst = sk_dst_get(conn->sock->sk);
+	if (dst && dst->dev && dst->dev->flags & IFF_LOOPBACK)
+		conn->loopback = true;
+	dst_release(dst);
+
 	/*
 	 * Perform the remaining iSCSI connection initialization items..
 	 */
diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h
index 94d06ddfd80a..aa8d4026e32e 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -538,6 +538,7 @@ struct iscsit_conn {
 	struct sockaddr_storage local_sockaddr;
 	int			conn_usage_count;
 	int			conn_waiting_on_uc;
+	bool			loopback;
 	atomic_t		check_immediate_queue;
 	atomic_t		conn_logout_remove;
 	atomic_t		connection_exit;
-- 
2.31.1


             reply	other threads:[~2023-02-27  7:58 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-27  7:57 Maurizio Lombardi [this message]
2023-03-22 13:59 ` [PATCH] target: iscsi: use GFP_NOIO with loopback connections Maurizio Lombardi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230227075735.8695-1-mlombard@redhat.com \
    --to=mlombard@redhat.com \
    --cc=martin.petersen@oracle.com \
    --cc=michael.christie@oracle.com \
    --cc=target-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.