summaryrefslogtreecommitdiffstats
path: root/sys/dev/iscsi
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2014-05-07 07:53:24 +0000
committertrasz <trasz@FreeBSD.org>2014-05-07 07:53:24 +0000
commit16f70f6ffb70707608e5d6000a8ecba858baacda (patch)
tree03898de1f899cbff45717b89156bf1f0ae801b41 /sys/dev/iscsi
parenta3b0c7e4a8cfbe4b4a4cf24848a4f5e97b7ac6de (diff)
downloadFreeBSD-src-16f70f6ffb70707608e5d6000a8ecba858baacda.zip
FreeBSD-src-16f70f6ffb70707608e5d6000a8ecba858baacda.tar.gz
MFC r264348 by mav@:
Improve use of socket buffer upcalls. Use soreadable()/sowriteable() in socket upcalls to avoid extra wakeups until we have enough data to read or space to write. Increase partial receive len from 1K to 128K to not wake up on every received packet. This significantly reduces locks congestion and CPU usage and improves throughput for large I/Os on NICs without TSO and LRO. MFC r264552 by mav@: Close the race in older code, that caused connection stuck after r264348. Sponsored by: iXsystems, Inc.
Diffstat (limited to 'sys/dev/iscsi')
-rw-r--r--sys/dev/iscsi/icl.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/sys/dev/iscsi/icl.c b/sys/dev/iscsi/icl.c
index 9fa6951..b40dc68 100644
--- a/sys/dev/iscsi/icl.c
+++ b/sys/dev/iscsi/icl.c
@@ -45,6 +45,7 @@
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/module.h>
+#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
@@ -67,7 +68,7 @@ static int coalesce = 1;
TUNABLE_INT("kern.icl.coalesce", &coalesce);
SYSCTL_INT(_kern_icl, OID_AUTO, coalesce, CTLFLAG_RWTUN,
&coalesce, 1, "Try to coalesce PDUs before sending");
-static int partial_receive_len = 1 * 1024; /* XXX: More? */
+static int partial_receive_len = 128 * 1024;
TUNABLE_INT("kern.icl.partial_receive_len", &partial_receive_len);
SYSCTL_INT(_kern_icl, OID_AUTO, partial_receive_len, CTLFLAG_RWTUN,
&partial_receive_len, 1 * 1024, "Minimum read size for partially received "
@@ -750,12 +751,19 @@ icl_receive_thread(void *arg)
break;
}
+ /*
+ * Set the low watermark, to be checked by
+ * soreadable() in icl_soupcall_receive()
+ * to avoid unneccessary wakeups until there
+ * is enough data received to read the PDU.
+ */
SOCKBUF_LOCK(&so->so_rcv);
available = so->so_rcv.sb_cc;
if (available < ic->ic_receive_len) {
so->so_rcv.sb_lowat = ic->ic_receive_len;
cv_wait(&ic->ic_receive_cv, &so->so_rcv.sb_mtx);
- }
+ } else
+ so->so_rcv.sb_lowat = so->so_rcv.sb_hiwat + 1;
SOCKBUF_UNLOCK(&so->so_rcv);
icl_conn_receive_pdus(ic, available);
@@ -772,6 +780,9 @@ icl_soupcall_receive(struct socket *so, void *arg, int waitflag)
{
struct icl_conn *ic;
+ if (!soreadable(so))
+ return (SU_OK);
+
ic = arg;
cv_signal(&ic->ic_receive_cv);
return (SU_OK);
@@ -854,10 +865,10 @@ icl_conn_send_pdus(struct icl_conn *ic, struct icl_pdu_stailq *queue)
available = sbspace(&so->so_snd);
/*
- * Notify the socket layer that it doesn't need to call
- * send socket upcall for the time being.
+ * Notify the socket upcall that we don't need wakeups
+ * for the time being.
*/
- so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
+ so->so_snd.sb_lowat = so->so_snd.sb_hiwat + 1;
SOCKBUF_UNLOCK(&so->so_snd);
while (!STAILQ_EMPTY(queue)) {
@@ -866,21 +877,26 @@ icl_conn_send_pdus(struct icl_conn *ic, struct icl_pdu_stailq *queue)
request = STAILQ_FIRST(queue);
size = icl_pdu_size(request);
if (available < size) {
-#if 1
- ICL_DEBUG("no space to send; "
- "have %zd, need %zd",
- available, size);
-#endif
/*
- * Set the low watermark on the socket,
+ * Set the low watermark, to be checked by
+ * sowritable() in icl_soupcall_send()
* to avoid unneccessary wakeups until there
* is enough space for the PDU to fit.
*/
SOCKBUF_LOCK(&so->so_snd);
- so->so_snd.sb_lowat = size;
+ available = sbspace(&so->so_snd);
+ if (available < size) {
+#if 1
+ ICL_DEBUG("no space to send; "
+ "have %zd, need %zd",
+ available, size);
+#endif
+ so->so_snd.sb_lowat = size;
+ SOCKBUF_UNLOCK(&so->so_snd);
+ return;
+ }
SOCKBUF_UNLOCK(&so->so_snd);
- return;
}
STAILQ_REMOVE_HEAD(queue, ip_next);
error = icl_pdu_finalize(request);
@@ -1016,6 +1032,9 @@ icl_soupcall_send(struct socket *so, void *arg, int waitflag)
{
struct icl_conn *ic;
+ if (!sowriteable(so))
+ return (SU_OK);
+
ic = arg;
ICL_CONN_LOCK(ic);
OpenPOWER on IntegriCloud