From ada57bb70e23fbb5ee52dd456b33c8cdd41885ff Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sun, 19 Sep 2010 09:35:03 -0700 Subject: [PATCH] Rx: avoid lock churn in rxi_ReceiveAckPacket rxi_ReceiveAckPacket can acquire and drop the conn_data_lock several times and acquires and drops the peer_lock unnecessarily. This patchset adds a variable to track whether the conn_data_lock is held in order to avoid the need to drop it and reacquire it based upon conditional operations. It also relocates the peer->maxPacketSize computations in order to consolidate the work performed under the peer_lock. Change-Id: I0bc9e42e8ef198a04315f9f2df529073ce9dfd03 Reviewed-on: http://gerrit.openafs.org/2781 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear (cherry picked from commit c59ce29602086f795d5fbaef6a5f88fae9dd2dea) Reviewed-on: http://gerrit.openafs.org/2806 --- src/rx/rx.c | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/rx/rx.c b/src/rx/rx.c index 8ab02391f..923d9b8fc 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -3831,6 +3831,7 @@ rxi_ReceiveAckPacket(struct rx_call *call, struct rx_packet *np, int newAckCount = 0; int maxDgramPackets = 0; /* Set if peer supports AFS 3.5 jumbo datagrams */ int pktsize = 0; /* Set if we need to update the peer mtu */ + int conn_data_locked = 0; if (rx_stats_active) rx_MutexIncrement(rx_stats.ackPacketsRead, rx_stats_mutex); @@ -3860,42 +3861,28 @@ rxi_ReceiveAckPacket(struct rx_call *call, struct rx_packet *np, if (conn->lastPacketSizeSeq) { MUTEX_ENTER(&conn->conn_data_lock); + conn_data_locked = 1; if ((first > conn->lastPacketSizeSeq) && (conn->lastPacketSize)) { pktsize = conn->lastPacketSize; conn->lastPacketSize = conn->lastPacketSizeSeq = 0; } - MUTEX_EXIT(&conn->conn_data_lock); } if ((ap->reason == RX_ACK_PING_RESPONSE) && (conn->lastPingSizeSer)) { - MUTEX_ENTER(&conn->conn_data_lock); + if (!conn_data_locked) { + MUTEX_ENTER(&conn->conn_data_lock); + conn_data_locked = 1; + } if ((conn->lastPingSizeSer == serial) && (conn->lastPingSize)) { /* process mtu ping ack */ pktsize = conn->lastPingSize; conn->lastPingSizeSer = conn->lastPingSize = 0; } - MUTEX_EXIT(&conn->conn_data_lock); } - if (pktsize) { - MUTEX_ENTER(&peer->peer_lock); - /* - * Start somewhere. Can't assume we can send what we can receive, - * but we are clearly receiving. - */ - if (!peer->maxPacketSize) - peer->maxPacketSize = RX_MIN_PACKET_SIZE+RX_IPUDP_SIZE; - - if (pktsize > peer->maxPacketSize) { - peer->maxPacketSize = pktsize; - if ((pktsize-RX_IPUDP_SIZE > peer->ifMTU)) { - peer->ifMTU=pktsize-RX_IPUDP_SIZE; - peer->natMTU = rxi_AdjustIfMTU(peer->ifMTU); - rxi_ScheduleGrowMTUEvent(call, 1); - } - } - MUTEX_EXIT(&peer->peer_lock); + if (conn_data_locked) { + MUTEX_EXIT(&conn->conn_data_lock); + conn_data_locked = 0; } - #ifdef RXDEBUG #ifdef AFS_NT40_ENV if (rxdebug_active) { @@ -3936,11 +3923,29 @@ rxi_ReceiveAckPacket(struct rx_call *call, struct rx_packet *np, #endif /* AFS_NT40_ENV */ #endif + MUTEX_ENTER(&peer->peer_lock); + if (pktsize) { + /* + * Start somewhere. Can't assume we can send what we can receive, + * but we are clearly receiving. + */ + if (!peer->maxPacketSize) + peer->maxPacketSize = RX_MIN_PACKET_SIZE+RX_IPUDP_SIZE; + + if (pktsize > peer->maxPacketSize) { + peer->maxPacketSize = pktsize; + if ((pktsize-RX_IPUDP_SIZE > peer->ifMTU)) { + peer->ifMTU=pktsize-RX_IPUDP_SIZE; + peer->natMTU = rxi_AdjustIfMTU(peer->ifMTU); + rxi_ScheduleGrowMTUEvent(call, 1); + } + } + } + /* Update the outgoing packet skew value to the latest value of * the peer's incoming packet skew value. The ack packet, of * course, could arrive out of order, but that won't affect things * much */ - MUTEX_ENTER(&peer->peer_lock); peer->outPacketSkew = skew; /* Check for packets that no longer need to be transmitted, and -- 2.39.5