Mike Christie wrote:
> On 07/31/2009 04:03 AM, Hannes Reinecke wrote:
>> Mike Christie wrote:
>>> tcp_sendpages/tcp_sendmsg can wait sndtmo seconds
>>> if a connection goes bad. This then delays session
>>> recovery, because that code must wait for the xmit
>>> thread to flush. OTOH, if we did not wait at all
>>> we are less efficient in the lock management
>>> because we must reacquire the session lock every
>>> time the network layer returns ENOBUFS and runs
>>> iscsi_tcp's write_space callout.
>>>
>>> This tries to balance the two by reducing the
>>> wait to 3 seconds from 15. If we have waited 3 secs
>>> to send a pdu then perf is already taking a hit so
>>> grabbing the session lock again is not going to make a
>>> difference. And waiting up to 3 secs for the xmit thread
>>> to flush and suspend is not that long (at least a lot better
>>> than 15).
>>>
>> :-)
>>
>> Cool. I'm running with 1 sec here, but the principle is
>> the same. Especially for a multipathed setup you really
>> want this.
>>
>> Oh, what about making this setting dependend on the
>> transport class timeout?
>> Worst case sendpages/sendmsg will take up to 3 seconds
>> now before it even will return an error.
>> So having a transport class timeout lower than that
>> is pointless as we have no means of terminating
>> a call being stuck in sendpages/sendmsg and the
>> transport class will always terminate the command.
>>
>> So we should either limit the transport class timeout
>> to not being able to be set lower than 3 seconds or
>> make this timeout set by the transport class timeout.
>>
> 
> Good point! Let me backout my patch, and do some more digging on why I 
> cannot just do
> 
> signal(xmit thread)
> 
> to wake it from sendpage/sendmsg right away.
> 
> If I cannot get that to work, then I will send a patch to implement what 
> you describe.

I got the signal stuff working. I am attaching the patch here. I put it 
in my iscsi branch, because it is built over some other patches I sent 
Erez in his logout takes ~50 secs thread.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index a8e5089..b508468 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -304,7 +304,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
 		 * is getting stopped. libiscsi will know so propogate err
 		 * for it to do the right thing.
 		 */
-		if (rc == -EAGAIN)
+		if (rc == -EAGAIN || rc == -EINTR || rc == -ENODATA)
 			return rc;
 		else if (rc < 0) {
 			rc = ISCSI_ERR_XMIT_FAILED;
@@ -508,6 +508,24 @@ static int iscsi_sw_tcp_pdu_alloc(struct iscsi_task *task, uint8_t opcode)
 	return 0;
 }
 
+static void __iscsi_sw_tcp_prep_xmit_wq(struct work_struct *work)
+{
+	struct iscsi_sw_tcp_conn *tcp_sw_conn =
+			container_of(work, struct iscsi_sw_tcp_conn, prep_work);
+
+	allow_signal(SIGUSR1);
+	set_user_nice(current, -20);
+	tcp_sw_conn->xmit_task = current;
+}
+
+static void iscsi_sw_tcp_prep_xmit_wq(struct iscsi_host *ihost,
+				     struct iscsi_sw_tcp_conn *tcp_sw_conn)
+{
+	INIT_WORK(&tcp_sw_conn->prep_work, __iscsi_sw_tcp_prep_xmit_wq);
+	queue_work(ihost->workq, &tcp_sw_conn->prep_work);
+	flush_workqueue(ihost->workq);
+}
+
 static struct iscsi_cls_conn *
 iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,
 			 uint32_t conn_idx)
@@ -538,6 +556,8 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,
 		goto free_tx_tfm;
 	tcp_conn->rx_hash = &tcp_sw_conn->rx_hash;
 
+	iscsi_sw_tcp_prep_xmit_wq(shost_priv(conn->session->host),
+				  tcp_sw_conn);
 	return cls_conn;
 
 free_tx_tfm:
@@ -606,6 +626,10 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
 	write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
 
+	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+	if (tcp_sw_conn->xmit_task)
+		send_sig(SIGUSR1, tcp_sw_conn->xmit_task, 0);
+
 	iscsi_conn_stop(cls_conn, flag);
 	iscsi_sw_tcp_release_conn(conn);
 }
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index ca6b7bc..cec3d4c 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -36,8 +36,9 @@ struct iscsi_sw_tcp_send {
 };
 
 struct iscsi_sw_tcp_conn {
-	struct iscsi_conn	*iscsi_conn;
 	struct socket		*sock;
+	struct task_struct	*xmit_task;
+	struct work_struct	prep_work;
 
 	struct iscsi_sw_tcp_send out;
 	/* old values for socket callbacks */
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index a7ee4bb..ef08f10 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1436,6 +1436,9 @@ static void iscsi_xmitworker(struct work_struct *work)
 	 * serialize Xmit worker on a per-connection basis.
 	 */
 	do {
+		if (signal_pending(current))
+			flush_signals(current);
+
 		rc = iscsi_data_xmit(conn);
 	} while (rc >= 0 || rc == -EAGAIN);
 }

Reply via email to