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 [email protected]
To unsubscribe from this group, send email to
[email protected]
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);
}