summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/tcp/tcp_fusion.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/inet/tcp/tcp_fusion.c')
-rw-r--r--usr/src/uts/common/inet/tcp/tcp_fusion.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/usr/src/uts/common/inet/tcp/tcp_fusion.c b/usr/src/uts/common/inet/tcp/tcp_fusion.c
index c22868be52..2503a13e29 100644
--- a/usr/src/uts/common/inet/tcp/tcp_fusion.c
+++ b/usr/src/uts/common/inet/tcp/tcp_fusion.c
@@ -948,12 +948,26 @@ plugged:
mutex_exit(&tcp->tcp_non_sq_lock);
mutex_enter(&peer_tcp->tcp_non_sq_lock);
mutex_enter(&tcp->tcp_non_sq_lock);
- CONN_DEC_REF(peer_tcp->tcp_connp);
- /* This might have changed in the interim */
+ /*
+ * This might have changed in the interim
+ * Once read-side tcp_non_sq_lock is dropped above
+ * anything can happen, we need to check all
+ * known conditions again once we reaquire
+ * read-side tcp_non_sq_lock.
+ */
if (tcp->tcp_fuse_syncstr_plugged) {
mutex_exit(&peer_tcp->tcp_non_sq_lock);
+ CONN_DEC_REF(peer_tcp->tcp_connp);
goto plugged;
}
+ if (!tcp->tcp_direct_sockfs || tcp->tcp_fuse_syncstr_stopped) {
+ mutex_exit(&tcp->tcp_non_sq_lock);
+ mutex_exit(&peer_tcp->tcp_non_sq_lock);
+ CONN_DEC_REF(peer_tcp->tcp_connp);
+ TCP_STAT(tcps, tcp_fusion_rrw_busy);
+ return (EBUSY);
+ }
+ CONN_DEC_REF(peer_tcp->tcp_connp);
} else {
mutex_enter(&peer_tcp->tcp_non_sq_lock);
}