Commit f8322dfc authored by Ying Xue's avatar Ying Xue Committed by David S. Miller

tipc: convert bearer_list to RCU list

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: default avatarYing Xue <ying.xue@windriver.com>
Reviewed-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Tested-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f97e455a
...@@ -659,6 +659,7 @@ void tipc_bcbearer_sort(void) ...@@ -659,6 +659,7 @@ void tipc_bcbearer_sort(void)
{ {
struct tipc_bcbearer_pair *bp_temp = bcbearer->bpairs_temp; struct tipc_bcbearer_pair *bp_temp = bcbearer->bpairs_temp;
struct tipc_bcbearer_pair *bp_curr; struct tipc_bcbearer_pair *bp_curr;
struct tipc_bearer *b;
int b_index; int b_index;
int pri; int pri;
...@@ -667,8 +668,9 @@ void tipc_bcbearer_sort(void) ...@@ -667,8 +668,9 @@ void tipc_bcbearer_sort(void)
/* Group bearers by priority (can assume max of two per priority) */ /* Group bearers by priority (can assume max of two per priority) */
memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp)); memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));
rcu_read_lock();
for (b_index = 0; b_index < MAX_BEARERS; b_index++) { 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) if (!b || !b->nodes.count)
continue; continue;
...@@ -677,6 +679,7 @@ void tipc_bcbearer_sort(void) ...@@ -677,6 +679,7 @@ void tipc_bcbearer_sort(void)
else else
bp_temp[b->priority].secondary = b; bp_temp[b->priority].secondary = b;
} }
rcu_read_unlock();
/* Create array of bearer pairs for broadcasting */ /* Create array of bearer pairs for broadcasting */
bp_curr = bcbearer->bpairs; bp_curr = bcbearer->bpairs;
...@@ -784,7 +787,7 @@ void tipc_bclink_init(void) ...@@ -784,7 +787,7 @@ void tipc_bclink_init(void)
bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
bcl->b_ptr = &bcbearer->bearer; bcl->b_ptr = &bcbearer->bearer;
bearer_list[BCBEARER] = &bcbearer->bearer; rcu_assign_pointer(bearer_list[MAX_BEARERS], &bcbearer->bearer);
bcl->state = WORKING_WORKING; bcl->state = WORKING_WORKING;
strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME);
} }
...@@ -795,7 +798,7 @@ void tipc_bclink_stop(void) ...@@ -795,7 +798,7 @@ void tipc_bclink_stop(void)
tipc_link_purge_queues(bcl); tipc_link_purge_queues(bcl);
spin_unlock_bh(&bc_lock); spin_unlock_bh(&bc_lock);
bearer_list[BCBEARER] = NULL; RCU_INIT_POINTER(bearer_list[BCBEARER], NULL);
memset(bclink, 0, sizeof(*bclink)); memset(bclink, 0, sizeof(*bclink));
memset(bcbearer, 0, sizeof(*bcbearer)); memset(bcbearer, 0, sizeof(*bcbearer));
} }
......
...@@ -49,7 +49,7 @@ static struct tipc_media * const media_info_array[] = { ...@@ -49,7 +49,7 @@ static struct tipc_media * const media_info_array[] = {
NULL 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); 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) ...@@ -178,7 +178,7 @@ struct tipc_bearer *tipc_bearer_find(const char *name)
u32 i; u32 i;
for (i = 0; i < MAX_BEARERS; 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))) if (b_ptr && (!strcmp(b_ptr->name, name)))
return b_ptr; return b_ptr;
} }
...@@ -201,7 +201,7 @@ struct sk_buff *tipc_bearer_get_names(void) ...@@ -201,7 +201,7 @@ struct sk_buff *tipc_bearer_get_names(void)
read_lock_bh(&tipc_net_lock); read_lock_bh(&tipc_net_lock);
for (i = 0; media_info_array[i] != NULL; i++) { for (i = 0; media_info_array[i] != NULL; i++) {
for (j = 0; j < MAX_BEARERS; j++) { for (j = 0; j < MAX_BEARERS; j++) {
b = bearer_list[j]; b = rtnl_dereference(bearer_list[j]);
if (!b) if (!b)
continue; continue;
if (b->media == media_info_array[i]) { if (b->media == media_info_array[i]) {
...@@ -287,7 +287,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) ...@@ -287,7 +287,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
bearer_id = MAX_BEARERS; bearer_id = MAX_BEARERS;
with_this_prio = 1; with_this_prio = 1;
for (i = MAX_BEARERS; i-- != 0; ) { for (i = MAX_BEARERS; i-- != 0; ) {
b_ptr = bearer_list[i]; b_ptr = rtnl_dereference(bearer_list[i]);
if (!b_ptr) { if (!b_ptr) {
bearer_id = i; bearer_id = i;
continue; continue;
...@@ -344,7 +344,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) ...@@ -344,7 +344,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
goto exit; 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", pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
name, name,
...@@ -385,12 +385,12 @@ static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down) ...@@ -385,12 +385,12 @@ static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
tipc_disc_delete(b_ptr->link_req); tipc_disc_delete(b_ptr->link_req);
for (i = 0; i < MAX_BEARERS; i++) { for (i = 0; i < MAX_BEARERS; i++) {
if (b_ptr == bearer_list[i]) { if (b_ptr == rtnl_dereference(bearer_list[i])) {
bearer_list[i] = NULL; RCU_INIT_POINTER(bearer_list[i], NULL);
break; break;
} }
} }
kfree(b_ptr); kfree_rcu(b_ptr, rcu);
} }
int tipc_disable_bearer(const char *name) int tipc_disable_bearer(const char *name)
...@@ -628,7 +628,7 @@ void tipc_bearer_stop(void) ...@@ -628,7 +628,7 @@ void tipc_bearer_stop(void)
u32 i; u32 i;
for (i = 0; i < MAX_BEARERS; i++) { for (i = 0; i < MAX_BEARERS; i++) {
b_ptr = bearer_list[i]; b_ptr = rtnl_dereference(bearer_list[i]);
if (b_ptr) { if (b_ptr) {
bearer_disable(b_ptr, true); bearer_disable(b_ptr, true);
bearer_list[i] = NULL; bearer_list[i] = NULL;
......
...@@ -113,6 +113,7 @@ struct tipc_media { ...@@ -113,6 +113,7 @@ struct tipc_media {
* @name: bearer name (format = media:interface) * @name: bearer name (format = media:interface)
* @media: ptr to media structure associated with bearer * @media: ptr to media structure associated with bearer
* @bcast_addr: media address used in broadcasting * @bcast_addr: media address used in broadcasting
* @rcu: rcu struct for tipc_bearer
* @priority: default link priority for bearer * @priority: default link priority for bearer
* @window: default window size for bearer * @window: default window size for bearer
* @tolerance: default link tolerance for bearer * @tolerance: default link tolerance for bearer
...@@ -133,6 +134,7 @@ struct tipc_bearer { ...@@ -133,6 +134,7 @@ struct tipc_bearer {
char name[TIPC_MAX_BEARER_NAME]; char name[TIPC_MAX_BEARER_NAME];
struct tipc_media *media; struct tipc_media *media;
struct tipc_media_addr bcast_addr; struct tipc_media_addr bcast_addr;
struct rcu_head rcu;
u32 priority; u32 priority;
u32 window; u32 window;
u32 tolerance; u32 tolerance;
...@@ -150,7 +152,7 @@ struct tipc_bearer_names { ...@@ -150,7 +152,7 @@ struct tipc_bearer_names {
struct tipc_link; struct tipc_link;
extern struct tipc_bearer *bearer_list[]; extern struct tipc_bearer __rcu *bearer_list[];
/* /*
* TIPC routines available to supported media types * TIPC routines available to supported media types
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment