tipc: convert bearer_list to RCU list
authorYing Xue <ying.xue@windriver.com>
Mon, 21 Apr 2014 02:55:45 +0000 (10:55 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 23 Apr 2014 01:17:52 +0000 (21:17 -0400)
Convert bearer_list to RCU list. It's protected by RTNL lock on
update side, and RCU read lock is applied to read side.

Signed-off-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Tested-by: Erik Hugne <erik.hugne@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/bcast.c
net/tipc/bearer.c
net/tipc/bearer.h

index 95ab5ef92920fddf34c02478973b98ebbe96ba59..223a19929024e9c3c154ed28174b01cfa6b866a8 100644 (file)
@@ -659,6 +659,7 @@ void tipc_bcbearer_sort(void)
 {
        struct tipc_bcbearer_pair *bp_temp = bcbearer->bpairs_temp;
        struct tipc_bcbearer_pair *bp_curr;
+       struct tipc_bearer *b;
        int b_index;
        int pri;
 
@@ -667,8 +668,9 @@ void tipc_bcbearer_sort(void)
        /* Group bearers by priority (can assume max of two per priority) */
        memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));
 
+       rcu_read_lock();
        for (b_index = 0; b_index < MAX_BEARERS; b_index++) {
-               struct tipc_bearer *b = bearer_list[b_index];
+               b = rcu_dereference_rtnl(bearer_list[b_index]);
                if (!b || !b->nodes.count)
                        continue;
 
@@ -677,6 +679,7 @@ void tipc_bcbearer_sort(void)
                else
                        bp_temp[b->priority].secondary = b;
        }
+       rcu_read_unlock();
 
        /* Create array of bearer pairs for broadcasting */
        bp_curr = bcbearer->bpairs;
@@ -784,7 +787,7 @@ void tipc_bclink_init(void)
        bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
        tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
        bcl->b_ptr = &bcbearer->bearer;
-       bearer_list[BCBEARER] = &bcbearer->bearer;
+       rcu_assign_pointer(bearer_list[MAX_BEARERS], &bcbearer->bearer);
        bcl->state = WORKING_WORKING;
        strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME);
 }
@@ -795,7 +798,7 @@ void tipc_bclink_stop(void)
        tipc_link_purge_queues(bcl);
        spin_unlock_bh(&bc_lock);
 
-       bearer_list[BCBEARER] = NULL;
+       RCU_INIT_POINTER(bearer_list[BCBEARER], NULL);
        memset(bclink, 0, sizeof(*bclink));
        memset(bcbearer, 0, sizeof(*bcbearer));
 }
index dfb4c7fe4865eea0c90db5a819709a7059d7ba6e..65b17639e43d39a44c96508fb4687942c24964e2 100644 (file)
@@ -49,7 +49,7 @@ static struct tipc_media * const media_info_array[] = {
        NULL
 };
 
-struct tipc_bearer *bearer_list[MAX_BEARERS + 1];
+struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1];
 
 static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
 
@@ -178,7 +178,7 @@ struct tipc_bearer *tipc_bearer_find(const char *name)
        u32 i;
 
        for (i = 0; i < MAX_BEARERS; i++) {
-               b_ptr = bearer_list[i];
+               b_ptr = rtnl_dereference(bearer_list[i]);
                if (b_ptr && (!strcmp(b_ptr->name, name)))
                        return b_ptr;
        }
@@ -201,7 +201,7 @@ struct sk_buff *tipc_bearer_get_names(void)
        read_lock_bh(&tipc_net_lock);
        for (i = 0; media_info_array[i] != NULL; i++) {
                for (j = 0; j < MAX_BEARERS; j++) {
-                       b = bearer_list[j];
+                       b = rtnl_dereference(bearer_list[j]);
                        if (!b)
                                continue;
                        if (b->media == media_info_array[i]) {
@@ -287,7 +287,7 @@ restart:
        bearer_id = MAX_BEARERS;
        with_this_prio = 1;
        for (i = MAX_BEARERS; i-- != 0; ) {
-               b_ptr = bearer_list[i];
+               b_ptr = rtnl_dereference(bearer_list[i]);
                if (!b_ptr) {
                        bearer_id = i;
                        continue;
@@ -344,7 +344,7 @@ restart:
                goto exit;
        }
 
-       bearer_list[bearer_id] = b_ptr;
+       rcu_assign_pointer(bearer_list[bearer_id], b_ptr);
 
        pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
                name,
@@ -385,12 +385,12 @@ static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
                tipc_disc_delete(b_ptr->link_req);
 
        for (i = 0; i < MAX_BEARERS; i++) {
-               if (b_ptr == bearer_list[i]) {
-                       bearer_list[i] = NULL;
+               if (b_ptr == rtnl_dereference(bearer_list[i])) {
+                       RCU_INIT_POINTER(bearer_list[i], NULL);
                        break;
                }
        }
-       kfree(b_ptr);
+       kfree_rcu(b_ptr, rcu);
 }
 
 int tipc_disable_bearer(const char *name)
@@ -628,7 +628,7 @@ void tipc_bearer_stop(void)
        u32 i;
 
        for (i = 0; i < MAX_BEARERS; i++) {
-               b_ptr = bearer_list[i];
+               b_ptr = rtnl_dereference(bearer_list[i]);
                if (b_ptr) {
                        bearer_disable(b_ptr, true);
                        bearer_list[i] = NULL;
index ba48145e871dd8dcd357a193b61e9234e5ad7f0d..b67b7ea4cc3644cf7255d55b2e670cdc77e1056b 100644 (file)
@@ -113,6 +113,7 @@ struct tipc_media {
  * @name: bearer name (format = media:interface)
  * @media: ptr to media structure associated with bearer
  * @bcast_addr: media address used in broadcasting
+ * @rcu: rcu struct for tipc_bearer
  * @priority: default link priority for bearer
  * @window: default window size for bearer
  * @tolerance: default link tolerance for bearer
@@ -133,6 +134,7 @@ struct tipc_bearer {
        char name[TIPC_MAX_BEARER_NAME];
        struct tipc_media *media;
        struct tipc_media_addr bcast_addr;
+       struct rcu_head rcu;
        u32 priority;
        u32 window;
        u32 tolerance;
@@ -150,7 +152,7 @@ struct tipc_bearer_names {
 
 struct tipc_link;
 
-extern struct tipc_bearer *bearer_list[];
+extern struct tipc_bearer __rcu *bearer_list[];
 
 /*
  * TIPC routines available to supported media types