tipc: Add missing locks in broadcast link statistics accumulation
authorAllan Stephens <allan.stephens@windriver.com>
Wed, 26 Oct 2011 20:13:35 +0000 (16:13 -0400)
committerPaul Gortmaker <paul.gortmaker@windriver.com>
Mon, 6 Feb 2012 21:59:18 +0000 (16:59 -0500)
Ensures that all attempts to update broadcast link statistics are done
only while holding the lock that protects the link's main data structures,
to prevent interference by simultaneous updates caused by messages
arriving on other interfaces.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
net/tipc/bcast.c

index 035b350be5c6240f0451e0c88fe7b121c15febfc..facc216c6a92e771d1957cf9732fecffce0cb38d 100644 (file)
@@ -520,6 +520,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
 
        if (likely(seqno == next_in)) {
 receive:
+               spin_lock_bh(&bc_lock);
                bcl->stats.recv_info++;
                node->bclink.last_in++;
                bclink_set_gap(node);
@@ -527,7 +528,9 @@ receive:
                        bclink_send_ack(node);
                        bcl->stats.sent_acks++;
                }
+
                if (likely(msg_isdata(msg))) {
+                       spin_unlock_bh(&bc_lock);
                        tipc_node_unlock(node);
                        if (likely(msg_mcast(msg)))
                                tipc_port_recv_mcast(buf, NULL);
@@ -536,6 +539,7 @@ receive:
                } else if (msg_user(msg) == MSG_BUNDLER) {
                        bcl->stats.recv_bundles++;
                        bcl->stats.recv_bundled += msg_msgcnt(msg);
+                       spin_unlock_bh(&bc_lock);
                        tipc_node_unlock(node);
                        tipc_link_recv_bundle(buf);
                } else if (msg_user(msg) == MSG_FRAGMENTER) {
@@ -543,12 +547,15 @@ receive:
                        if (tipc_link_recv_fragment(&node->bclink.defragm,
                                                    &buf, &msg))
                                bcl->stats.recv_fragmented++;
+                       spin_unlock_bh(&bc_lock);
                        tipc_node_unlock(node);
                        tipc_net_route_msg(buf);
                } else if (msg_user(msg) == NAME_DISTRIBUTOR) {
+                       spin_unlock_bh(&bc_lock);
                        tipc_node_unlock(node);
                        tipc_named_recv(buf);
                } else {
+                       spin_unlock_bh(&bc_lock);
                        tipc_node_unlock(node);
                        buf_discard(buf);
                }
@@ -601,11 +608,15 @@ receive:
        } else
                deferred = 0;
 
+       spin_lock_bh(&bc_lock);
+
        if (deferred)
                bcl->stats.deferred_recv++;
        else
                bcl->stats.duplicates++;
 
+       spin_unlock_bh(&bc_lock);
+
 unlock:
        tipc_node_unlock(node);
 exit: