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); }