Re: [PATCH V2] target: iscsi: use GFP_NOIO with loopback connections

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 3/27/23 5:45 AM, Maurizio Lombardi wrote:
> 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.
> 
> 
> v2: Check the IFF_LOOPBACK flag in the iscsit_accept_np() callback,
>     where the conn->sock pointer is initialized.
> 
> Suggested-by: David Jeffery <djeffery@xxxxxxxxxx>
> Signed-off-by: Maurizio Lombardi <mlombard@xxxxxxxxxx>
> ---
>  drivers/target/iscsi/iscsi_target.c       | 19 ++++++++++++++++---
>  drivers/target/iscsi/iscsi_target_login.c |  7 +++++++
>  include/target/iscsi/iscsi_target_core.h  |  1 +
>  3 files changed, 24 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();

Do you need to do sk_set_memalloc on the socket as well or do we do all
net allocations from the the rx/tx threads? I know there are some net
allocations that are not going to take place from those threads, but
did you not set the socket flags because they are small allocations or
just forgot, or something else?




[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux