summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorAnders Persson <Anders.Persson@Sun.COM>2009-05-04 12:55:57 -0700
committerAnders Persson <Anders.Persson@Sun.COM>2009-05-04 12:55:57 -0700
commitf3124163ff308d38b77c6099323e42484176988e (patch)
tree6c291b6a58c0183a39e88467b15e8f3bdc27eb92 /usr/src
parentb277c5a6ff3dbd12b9ecf0adcf3320d5f6dc1175 (diff)
downloadillumos-joyent-f3124163ff308d38b77c6099323e42484176988e.tar.gz
6831864 tcp loopback is not flow controlled when fusion is used
6834277 random streams options can be set with garbage 6836584 squeue_synch_enter() and squeue_synch_exit() are lint-unfriendly
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/inet/squeue.c17
-rw-r--r--usr/src/uts/common/inet/tcp.h2
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c190
-rw-r--r--usr/src/uts/common/inet/tcp/tcp_fusion.c53
-rw-r--r--usr/src/uts/common/inet/tcp_impl.h1
-rw-r--r--usr/src/uts/common/sys/squeue.h7
6 files changed, 125 insertions, 145 deletions
diff --git a/usr/src/uts/common/inet/squeue.c b/usr/src/uts/common/inet/squeue.c
index 396068a2d9..8d2d83d966 100644
--- a/usr/src/uts/common/inet/squeue.c
+++ b/usr/src/uts/common/inet/squeue.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1273,12 +1273,9 @@ squeue_wakeup_conn(void *arg, mblk_t *mp, void *arg2)
mutex_exit(&sqp->sq_lock);
}
-/* ARGSUSED */
int
-squeue_synch_enter(squeue_t *sqp, void *arg, uint8_t tag)
+squeue_synch_enter(squeue_t *sqp, conn_t *connp, mblk_t *use_mp)
{
- conn_t *connp = (conn_t *)arg;
-
mutex_enter(&sqp->sq_lock);
if (sqp->sq_first == NULL && !(sqp->sq_state & SQS_PROC)) {
/*
@@ -1304,7 +1301,7 @@ squeue_synch_enter(squeue_t *sqp, void *arg, uint8_t tag)
} else {
mblk_t *mp;
- mp = allocb(0, BPRI_MED);
+ mp = (use_mp == NULL) ? allocb(0, BPRI_MED) : use_mp;
if (mp == NULL) {
mutex_exit(&sqp->sq_lock);
return (ENOMEM);
@@ -1329,18 +1326,16 @@ squeue_synch_enter(squeue_t *sqp, void *arg, uint8_t tag)
cv_wait(&connp->conn_sq_cv, &sqp->sq_lock);
mutex_exit(&sqp->sq_lock);
- freeb(mp);
+ if (use_mp == NULL)
+ freeb(mp);
return (0);
}
}
-/* ARGSUSED */
void
-squeue_synch_exit(squeue_t *sqp, void *arg)
+squeue_synch_exit(squeue_t *sqp, conn_t *connp)
{
- conn_t *connp = (conn_t *)arg;
-
mutex_enter(&sqp->sq_lock);
if (sqp->sq_run == curthread) {
ASSERT(sqp->sq_state & SQS_PROC);
diff --git a/usr/src/uts/common/inet/tcp.h b/usr/src/uts/common/inet/tcp.h
index 079823420c..1d10a8cbfa 100644
--- a/usr/src/uts/common/inet/tcp.h
+++ b/usr/src/uts/common/inet/tcp.h
@@ -668,7 +668,7 @@ extern void tcp_conn_request(void *arg, mblk_t *mp, void *arg2);
extern void tcp_conn_request_unbound(void *arg, mblk_t *mp, void *arg2);
extern void tcp_input(void *arg, mblk_t *mp, void *arg2);
extern void tcp_rput_data(void *arg, mblk_t *mp, void *arg2);
-extern void *tcp_get_conn(void *arg, tcp_stack_t *, boolean_t);
+extern void *tcp_get_conn(void *arg, tcp_stack_t *);
extern void tcp_time_wait_collector(void *arg);
extern mblk_t *tcp_snmp_get(queue_t *, mblk_t *);
extern int tcp_snmp_set(queue_t *, int, int, uchar_t *, int len);
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index 352b920f55..78471b606a 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -4834,8 +4834,7 @@ tcp_conn_create_v4(conn_t *lconnp, conn_t *connp, ipha_t *ipha,
* in case of error mpp is freed.
*/
conn_t *
-tcp_get_ipsec_conn(tcp_t *tcp, squeue_t *sqp, mblk_t **mpp,
- boolean_t is_streams)
+tcp_get_ipsec_conn(tcp_t *tcp, squeue_t *sqp, mblk_t **mpp)
{
conn_t *connp = tcp->tcp_connp;
conn_t *econnp;
@@ -4845,7 +4844,7 @@ tcp_get_ipsec_conn(tcp_t *tcp, squeue_t *sqp, mblk_t **mpp,
boolean_t mctl_present = B_FALSE;
uint_t ipvers;
- econnp = tcp_get_conn(sqp, tcp->tcp_tcps, is_streams);
+ econnp = tcp_get_conn(sqp, tcp->tcp_tcps);
if (econnp == NULL) {
freemsg(first_mp);
return (NULL);
@@ -4982,7 +4981,7 @@ tcp_get_ipsec_conn(tcp_t *tcp, squeue_t *sqp, mblk_t **mpp,
* there for too long.
*/
void *
-tcp_get_conn(void *arg, tcp_stack_t *tcps, boolean_t is_streams)
+tcp_get_conn(void *arg, tcp_stack_t *tcps)
{
tcp_t *tcp = NULL;
conn_t *connp = NULL;
@@ -4998,19 +4997,6 @@ tcp_get_conn(void *arg, tcp_stack_t *tcps, boolean_t is_streams)
tcp = tcp_time_wait->tcp_free_list;
ASSERT((tcp != NULL) ^ (tcp_time_wait->tcp_free_list_cnt == 0));
if (tcp != NULL) {
- if (is_streams && tcp->tcp_rsrv_mp == NULL) {
- /*
- * Pre-allocate the tcp_rsrv_mp if neccessary.
- * This mblk will not be freed until this conn_t/tcp_t
- * is freed at ipcl_conn_destroy().
- */
- if ((tcp->tcp_rsrv_mp = allocb(0, BPRI_HI)) == NULL) {
- mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
- return (NULL);
- }
- mutex_init(&tcp->tcp_rsrv_mp_lock,
- NULL, MUTEX_DEFAULT, NULL);
- }
tcp_time_wait->tcp_free_list = tcp->tcp_time_wait_next;
tcp_time_wait->tcp_free_list_cnt--;
mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
@@ -5020,7 +5006,7 @@ tcp_get_conn(void *arg, tcp_stack_t *tcps, boolean_t is_streams)
ASSERT(tcp->tcp_tcps == NULL);
ASSERT(connp->conn_netstack == NULL);
- ASSERT(!is_streams || tcp->tcp_rsrv_mp != NULL);
+ ASSERT(tcp->tcp_rsrv_mp != NULL);
ns = tcps->tcps_netstack;
netstack_hold(ns);
connp->conn_netstack = ns;
@@ -5030,22 +5016,17 @@ tcp_get_conn(void *arg, tcp_stack_t *tcps, boolean_t is_streams)
return ((void *)connp);
}
mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
- if (is_streams) {
- /*
- * Pre-allocate the tcp_rsrv_mp if neccessary.
- * This mblk will not be freed until this conn_t/tcp_t
- * is freed at ipcl_conn_destroy().
- */
- tcp_rsrv_mp = allocb(0, BPRI_HI);
- if (tcp_rsrv_mp == NULL)
- return (NULL);
- }
+ /*
+ * Pre-allocate the tcp_rsrv_mp. This mblk will not be freed until
+ * this conn_t/tcp_t is freed at ipcl_conn_destroy().
+ */
+ tcp_rsrv_mp = allocb(0, BPRI_HI);
+ if (tcp_rsrv_mp == NULL)
+ return (NULL);
+
if ((connp = ipcl_conn_create(IPCL_TCPCONN, KM_NOSLEEP,
tcps->tcps_netstack)) == NULL) {
- if (is_streams) {
- ASSERT(tcp_rsrv_mp != NULL);
- freeb(tcp_rsrv_mp);
- }
+ freeb(tcp_rsrv_mp);
return (NULL);
}
@@ -5313,8 +5294,7 @@ tcp_conn_request(void *arg, mblk_t *mp, void *arg2)
new_sqp = (squeue_t *)DB_CKSUMSTART(mp);
DB_CKSUMSTART(mp) = 0;
mp->b_datap->db_struioflag &= ~STRUIO_EAGER;
- econnp = (conn_t *)tcp_get_conn(arg2, tcps,
- !IPCL_IS_NONSTR(connp));
+ econnp = (conn_t *)tcp_get_conn(arg2, tcps);
if (econnp == NULL)
goto error2;
ASSERT(econnp->conn_netstack == connp->conn_netstack);
@@ -5324,8 +5304,7 @@ tcp_conn_request(void *arg, mblk_t *mp, void *arg2)
/*
* mp is updated in tcp_get_ipsec_conn().
*/
- econnp = tcp_get_ipsec_conn(tcp, arg2, &mp,
- !IPCL_IS_NONSTR(connp));
+ econnp = tcp_get_ipsec_conn(tcp, arg2, &mp);
if (econnp == NULL) {
/*
* mp freed by tcp_get_ipsec_conn.
@@ -9163,7 +9142,7 @@ tcp_create_common(queue_t *q, cred_t *credp, boolean_t isv6,
}
sqp = IP_SQUEUE_GET((uint_t)gethrtime());
- connp = (conn_t *)tcp_get_conn(sqp, tcps, q != NULL ? B_TRUE : B_FALSE);
+ connp = (conn_t *)tcp_get_conn(sqp, tcps);
/*
* Both tcp_get_conn and netstack_find_by_cred incremented refcnt,
* so we drop it by one.
@@ -9797,7 +9776,7 @@ tcp_getsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
optvalp_buf = kmem_alloc(max_optbuf_len, KM_SLEEP);
- error = squeue_synch_enter(sqp, connp, 0);
+ error = squeue_synch_enter(sqp, connp, NULL);
if (error == ENOMEM) {
return (ENOMEM);
}
@@ -10725,7 +10704,7 @@ tcp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
}
}
- error = squeue_synch_enter(sqp, connp, 0);
+ error = squeue_synch_enter(sqp, connp, NULL);
if (error == ENOMEM) {
return (ENOMEM);
}
@@ -15479,7 +15458,6 @@ tcp_rsrv_input(void *arg, mblk_t *mp, void *arg2)
conn_t *connp = (conn_t *)arg;
tcp_t *tcp = connp->conn_tcp;
queue_t *q = tcp->tcp_rq;
- uint_t thwin;
tcp_stack_t *tcps = tcp->tcp_tcps;
ASSERT(!IPCL_IS_NONSTR(connp));
@@ -15494,52 +15472,14 @@ tcp_rsrv_input(void *arg, mblk_t *mp, void *arg2)
}
if (tcp->tcp_fused) {
- tcp_t *peer_tcp = tcp->tcp_loopback_peer;
-
- ASSERT(tcp->tcp_fused);
- ASSERT(peer_tcp != NULL && peer_tcp->tcp_fused);
- ASSERT(peer_tcp->tcp_loopback_peer == tcp);
- ASSERT(!TCP_IS_DETACHED(tcp));
- ASSERT(tcp->tcp_connp->conn_sqp ==
- peer_tcp->tcp_connp->conn_sqp);
-
- /*
- * Normally we would not get backenabled in synchronous
- * streams mode, but in case this happens, we need to plug
- * synchronous streams during our drain to prevent a race
- * with tcp_fuse_rrw() or tcp_fuse_rinfop().
- */
- TCP_FUSE_SYNCSTR_PLUG_DRAIN(tcp);
- if (tcp->tcp_rcv_list != NULL)
- (void) tcp_rcv_drain(tcp);
-
- if (peer_tcp > tcp) {
- mutex_enter(&peer_tcp->tcp_non_sq_lock);
- mutex_enter(&tcp->tcp_non_sq_lock);
- } else {
- mutex_enter(&tcp->tcp_non_sq_lock);
- mutex_enter(&peer_tcp->tcp_non_sq_lock);
- }
-
- if (peer_tcp->tcp_flow_stopped &&
- (TCP_UNSENT_BYTES(peer_tcp) <=
- peer_tcp->tcp_xmit_lowater)) {
- tcp_clrqfull(peer_tcp);
- }
- mutex_exit(&peer_tcp->tcp_non_sq_lock);
- mutex_exit(&tcp->tcp_non_sq_lock);
-
- TCP_FUSE_SYNCSTR_UNPLUG_DRAIN(tcp);
- TCP_STAT(tcps, tcp_fusion_backenabled);
+ tcp_fuse_backenable(tcp);
return;
}
if (canputnext(q)) {
/* Not flow-controlled, open rwnd */
tcp->tcp_rwnd = q->q_hiwat;
- thwin = ((uint_t)BE16_TO_U16(tcp->tcp_tcph->th_win))
- << tcp->tcp_rcv_ws;
- thwin -= tcp->tcp_rnxt - tcp->tcp_rack;
+
/*
* Send back a window update immediately if TCP is above
* ESTABLISHED state and the increase of the rcv window
@@ -15547,11 +15487,10 @@ tcp_rsrv_input(void *arg, mblk_t *mp, void *arg2)
* control is lifted.
*/
if (tcp->tcp_state >= TCPS_ESTABLISHED &&
- (q->q_hiwat - thwin >= tcp->tcp_mss)) {
+ tcp_rwnd_reopen(tcp) == TH_ACK_NEEDED) {
tcp_xmit_ctl(NULL, tcp,
(tcp->tcp_swnd == 0) ? tcp->tcp_suna :
tcp->tcp_snxt, tcp->tcp_rnxt, TH_ACK);
- BUMP_MIB(&tcps->tcps_mib, tcpOutWinUpdate);
}
}
}
@@ -17272,8 +17211,7 @@ tcp_accept_finish(void *arg, mblk_t *mp, void *arg2)
DB_TYPE(stropt_mp) = M_SETOPTS;
stropt = (struct stroptions *)stropt_mp->b_rptr;
stropt_mp->b_wptr += sizeof (struct stroptions);
- stropt = (struct stroptions *)stropt_mp->b_rptr;
- stropt->so_flags |= SO_HIWAT | SO_WROFF | SO_MAXBLK;
+ stropt->so_flags = SO_HIWAT | SO_WROFF | SO_MAXBLK;
stropt->so_hiwat = sopp_rxhiwat;
stropt->so_wroff = sopp_wroff;
stropt->so_maxblk = sopp_maxblk;
@@ -26142,7 +26080,7 @@ tcp_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa,
ASSERT(sqp != NULL);
ASSERT(connp->conn_upper_handle != NULL);
- error = squeue_synch_enter(sqp, connp, 0);
+ error = squeue_synch_enter(sqp, connp, NULL);
if (error != 0) {
/* failed to enter */
return (ENOSR);
@@ -26315,7 +26253,7 @@ tcp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa,
return (error);
}
- error = squeue_synch_enter(sqp, connp, 0);
+ error = squeue_synch_enter(sqp, connp, NULL);
if (error != 0) {
/* failed to enter */
return (ENOSR);
@@ -26656,8 +26594,7 @@ tcp_fallback_noneager(tcp_t *tcp, mblk_t *stropt_mp, queue_t *q,
DB_TYPE(stropt_mp) = M_SETOPTS;
stropt = (struct stroptions *)stropt_mp->b_rptr;
stropt_mp->b_wptr += sizeof (struct stroptions);
- stropt = (struct stroptions *)stropt_mp->b_rptr;
- stropt->so_flags |= SO_HIWAT | SO_WROFF | SO_MAXBLK;
+ stropt->so_flags = SO_HIWAT | SO_WROFF | SO_MAXBLK;
stropt->so_wroff = tcp->tcp_hdr_len + (tcp->tcp_loopback ? 0 :
tcp->tcp_tcps->tcps_wroff_xtra);
@@ -26752,7 +26689,6 @@ tcp_fallback(sock_lower_handle_t proto_handle, queue_t *q,
mblk_t *stropt_mp;
mblk_t *ordrel_mp;
mblk_t *fused_sigurp_mp;
- mblk_t *tcp_rsrv_mp;
tcp = connp->conn_tcp;
@@ -26771,22 +26707,14 @@ tcp_fallback(sock_lower_handle_t proto_handle, queue_t *q,
fused_sigurp_mp = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL);
/*
- * Pre-allocate the tcp_rsrv_mp mblk.
- * It is possible that this conn was previously used for a streams
- * socket and already has tcp_rsrv_mp
- */
- tcp_rsrv_mp = allocb_wait(0, BPRI_HI, STR_NOSIG, NULL);
-
- /*
* Enter the squeue so that no new packets can come in
*/
- error = squeue_synch_enter(connp->conn_sqp, connp, 0);
+ error = squeue_synch_enter(connp->conn_sqp, connp, NULL);
if (error != 0) {
/* failed to enter, free all the pre-allocated messages. */
freeb(stropt_mp);
freeb(ordrel_mp);
freeb(fused_sigurp_mp);
- freeb(tcp_rsrv_mp);
/*
* We cannot process the eager, so at least send out a
* RST so the peer can reconnect.
@@ -26812,14 +26740,6 @@ tcp_fallback(sock_lower_handle_t proto_handle, queue_t *q,
freeb(fused_sigurp_mp);
}
- if (tcp->tcp_rsrv_mp == NULL) {
- tcp->tcp_rsrv_mp = tcp_rsrv_mp;
- } else {
- /*
- * reusing a conn that was previously used for streams socket
- */
- freeb(tcp_rsrv_mp);
- }
if (tcp->tcp_listener != NULL) {
/* The eager will deal with opts when accept() is called */
freeb(stropt_mp);
@@ -26919,7 +26839,7 @@ tcp_listen(sock_lower_handle_t proto_handle, int backlog, cred_t *cr)
/* All Solaris components should pass a cred for this operation. */
ASSERT(cr != NULL);
- error = squeue_synch_enter(sqp, connp, 0);
+ error = squeue_synch_enter(sqp, connp, NULL);
if (error != 0) {
/* failed to enter */
return (ENOBUFS);
@@ -27050,30 +26970,46 @@ tcp_clr_flowctrl(sock_lower_handle_t proto_handle)
{
conn_t *connp = (conn_t *)proto_handle;
tcp_t *tcp = connp->conn_tcp;
- tcp_stack_t *tcps = tcp->tcp_tcps;
- uint_t thwin;
+ mblk_t *mp;
+ int error;
ASSERT(connp->conn_upper_handle != NULL);
- (void) squeue_synch_enter(connp->conn_sqp, connp, 0);
-
- /* Flow control condition has been removed. */
- tcp->tcp_rwnd = tcp->tcp_recv_hiwater;
- thwin = ((uint_t)BE16_TO_U16(tcp->tcp_tcph->th_win))
- << tcp->tcp_rcv_ws;
- thwin -= tcp->tcp_rnxt - tcp->tcp_rack;
/*
- * Send back a window update immediately if TCP is above
- * ESTABLISHED state and the increase of the rcv window
- * that the other side knows is at least 1 MSS after flow
- * control is lifted.
- */
- if (tcp->tcp_state >= TCPS_ESTABLISHED &&
- (tcp->tcp_recv_hiwater - thwin >= tcp->tcp_mss)) {
- tcp_xmit_ctl(NULL, tcp,
- (tcp->tcp_swnd == 0) ? tcp->tcp_suna :
- tcp->tcp_snxt, tcp->tcp_rnxt, TH_ACK);
- BUMP_MIB(&tcps->tcps_mib, tcpOutWinUpdate);
+ * If tcp->tcp_rsrv_mp == NULL, it means that tcp_clr_flowctrl()
+ * is currently running.
+ */
+ mutex_enter(&tcp->tcp_rsrv_mp_lock);
+ if ((mp = tcp->tcp_rsrv_mp) == NULL) {
+ mutex_exit(&tcp->tcp_rsrv_mp_lock);
+ return;
+ }
+ tcp->tcp_rsrv_mp = NULL;
+ mutex_exit(&tcp->tcp_rsrv_mp_lock);
+
+ error = squeue_synch_enter(connp->conn_sqp, connp, mp);
+ ASSERT(error == 0);
+
+ mutex_enter(&tcp->tcp_rsrv_mp_lock);
+ tcp->tcp_rsrv_mp = mp;
+ mutex_exit(&tcp->tcp_rsrv_mp_lock);
+
+ if (tcp->tcp_fused) {
+ tcp_fuse_backenable(tcp);
+ } else {
+ tcp->tcp_rwnd = tcp->tcp_recv_hiwater;
+ /*
+ * Send back a window update immediately if TCP is above
+ * ESTABLISHED state and the increase of the rcv window
+ * that the other side knows is at least 1 MSS after flow
+ * control is lifted.
+ */
+ if (tcp->tcp_state >= TCPS_ESTABLISHED &&
+ tcp_rwnd_reopen(tcp) == TH_ACK_NEEDED) {
+ tcp_xmit_ctl(NULL, tcp,
+ (tcp->tcp_swnd == 0) ? tcp->tcp_suna :
+ tcp->tcp_snxt, tcp->tcp_rnxt, TH_ACK);
+ }
}
squeue_synch_exit(connp->conn_sqp, connp);
diff --git a/usr/src/uts/common/inet/tcp/tcp_fusion.c b/usr/src/uts/common/inet/tcp/tcp_fusion.c
index a3a35e3bca..4e4802c063 100644
--- a/usr/src/uts/common/inet/tcp/tcp_fusion.c
+++ b/usr/src/uts/common/inet/tcp/tcp_fusion.c
@@ -797,10 +797,12 @@ tcp_fuse_output(tcp_t *tcp, mblk_t *mp, uint32_t send_size)
(peer_tcp->tcp_connp->conn_upper_handle, 0);
tcp->tcp_valid_bits &= ~TCP_URG_VALID;
}
- (*peer_tcp->tcp_connp->conn_upcalls->su_recv)(
+ if ((*peer_tcp->tcp_connp->conn_upcalls->su_recv)(
peer_tcp->tcp_connp->conn_upper_handle, mp, recv_size,
- flags, &error, &push);
- ASSERT(error != EOPNOTSUPP);
+ flags, &error, &push) < 0) {
+ ASSERT(error != EOPNOTSUPP);
+ peer_data_queued = B_TRUE;
+ }
} else {
if (IPCL_IS_NONSTR(peer_tcp->tcp_connp) &&
(tcp->tcp_valid_bits & TCP_URG_VALID) &&
@@ -1568,3 +1570,48 @@ tcp_fuse_maxpsz_set(tcp_t *tcp)
}
return (maxpsz);
}
+
+/*
+ * Called to release flow control.
+ */
+void
+tcp_fuse_backenable(tcp_t *tcp)
+{
+ tcp_t *peer_tcp = tcp->tcp_loopback_peer;
+
+ ASSERT(tcp->tcp_fused);
+ ASSERT(peer_tcp != NULL && peer_tcp->tcp_fused);
+ ASSERT(peer_tcp->tcp_loopback_peer == tcp);
+ ASSERT(!TCP_IS_DETACHED(tcp));
+ ASSERT(tcp->tcp_connp->conn_sqp ==
+ peer_tcp->tcp_connp->conn_sqp);
+
+ /*
+ * Normally we would not get backenabled in synchronous
+ * streams mode, but in case this happens, we need to plug
+ * synchronous streams during our drain to prevent a race
+ * with tcp_fuse_rrw() or tcp_fuse_rinfop().
+ */
+ TCP_FUSE_SYNCSTR_PLUG_DRAIN(tcp);
+ if (tcp->tcp_rcv_list != NULL)
+ (void) tcp_fuse_rcv_drain(tcp->tcp_rq, tcp, NULL);
+
+ if (peer_tcp > tcp) {
+ mutex_enter(&peer_tcp->tcp_non_sq_lock);
+ mutex_enter(&tcp->tcp_non_sq_lock);
+ } else {
+ mutex_enter(&tcp->tcp_non_sq_lock);
+ mutex_enter(&peer_tcp->tcp_non_sq_lock);
+ }
+
+ if (peer_tcp->tcp_flow_stopped &&
+ (TCP_UNSENT_BYTES(peer_tcp) <=
+ peer_tcp->tcp_xmit_lowater)) {
+ tcp_clrqfull(peer_tcp);
+ }
+ mutex_exit(&peer_tcp->tcp_non_sq_lock);
+ mutex_exit(&tcp->tcp_non_sq_lock);
+
+ TCP_FUSE_SYNCSTR_UNPLUG_DRAIN(tcp);
+ TCP_STAT(tcp->tcp_tcps, tcp_fusion_backenabled);
+}
diff --git a/usr/src/uts/common/inet/tcp_impl.h b/usr/src/uts/common/inet/tcp_impl.h
index ac986bc52c..b4c31f3ddd 100644
--- a/usr/src/uts/common/inet/tcp_impl.h
+++ b/usr/src/uts/common/inet/tcp_impl.h
@@ -265,6 +265,7 @@ extern int tcp_fuse_rrw(queue_t *, struiod_t *);
extern int tcp_fuse_rinfop(queue_t *, infod_t *);
extern size_t tcp_fuse_set_rcv_hiwat(tcp_t *, size_t);
extern int tcp_fuse_maxpsz_set(tcp_t *);
+extern void tcp_fuse_backenable(tcp_t *tcp);
/*
* Object to represent database of options to search passed to
diff --git a/usr/src/uts/common/sys/squeue.h b/usr/src/uts/common/sys/squeue.h
index e14ded203a..a2d808f647 100644
--- a/usr/src/uts/common/sys/squeue.h
+++ b/usr/src/uts/common/sys/squeue.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -85,8 +85,9 @@ extern void squeue_enter(squeue_t *, mblk_t *, mblk_t *,
uint32_t, int, uint8_t);
extern uintptr_t *squeue_getprivate(squeue_t *, sqprivate_t);
-extern int squeue_synch_enter(squeue_t *, void *, uint8_t);
-extern void squeue_synch_exit(squeue_t *, void *);
+struct conn_s;
+extern int squeue_synch_enter(squeue_t *, struct conn_s *, mblk_t *);
+extern void squeue_synch_exit(squeue_t *, struct conn_s *);
#ifdef __cplusplus
}