|
From: Ying X. <yin...@wi...> - 2013-09-30 08:39:09
|
As tipc_bearers will be protected by RCU lock, tipc_bearers is
defined as static array where the data of tipc_bearer struct is
located in each array element. But since static array has not seen
with RCU, tipc_bearers should be redefined to a pointer array where
a pointer pointed to dynamically allocated instance of tipc_bearer
struct is located in each array element, allowing the pointer
array to be protected with RCU.
Signed-off-by: Ying Xue <yin...@wi...>
---
net/tipc/bcast.c | 6 +++---
net/tipc/bearer.c | 53 ++++++++++++++++++++++++++++++++++++++---------------
net/tipc/bearer.h | 2 +-
3 files changed, 42 insertions(+), 19 deletions(-)
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index c78f30c..0378fda 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -660,6 +660,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;
@@ -669,9 +670,8 @@ void tipc_bcbearer_sort(void)
memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));
for (b_index = 0; b_index < MAX_BEARERS; b_index++) {
- struct tipc_bearer *b = &tipc_bearers[b_index];
-
- if (!b->active || !b->nodes.count)
+ b = bearer_list[b_index];
+ if (!b || !b->active || !b->nodes.count)
continue;
if (!bp_temp[b->priority].primary)
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 5dd587b..5b32254 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -42,10 +42,9 @@
#define MAX_ADDR_STR 60
static struct tipc_media *media_list[MAX_MEDIA];
+struct tipc_bearer *bearer_list[MAX_BEARERS];
static u32 media_count;
-struct tipc_bearer tipc_bearers[MAX_BEARERS];
-
static void bearer_disable(struct tipc_bearer *b_ptr);
/**
@@ -228,8 +227,9 @@ struct tipc_bearer *tipc_bearer_find(const char *name)
struct tipc_bearer *b_ptr;
u32 i;
- for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
- if (b_ptr->active && (!strcmp(b_ptr->name, name)))
+ for (i = 0; i < MAX_BEARERS; i++) {
+ b_ptr = bearer_list[i];
+ if (b_ptr && b_ptr->active && (!strcmp(b_ptr->name, name)))
return b_ptr;
}
return NULL;
@@ -244,8 +244,9 @@ struct tipc_bearer *tipc_bearer_find_interface(const char *if_name)
char *b_if_name;
u32 i;
- for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
- if (!b_ptr->active)
+ for (i = 0; i < MAX_BEARERS; i++) {
+ b_ptr = bearer_list[i];
+ if (!b_ptr || !b_ptr->active)
continue;
b_if_name = strchr(b_ptr->name, ':') + 1;
if (!strcmp(b_if_name, if_name))
@@ -270,7 +271,9 @@ struct sk_buff *tipc_bearer_get_names(void)
read_lock_bh(&tipc_net_lock);
for (i = 0; i < media_count; i++) {
for (j = 0; j < MAX_BEARERS; j++) {
- b_ptr = &tipc_bearers[j];
+ b_ptr = bearer_list[j];
+ if (!b_ptr)
+ continue;
if (b_ptr->active && (b_ptr->media == media_list[i])) {
tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
b_ptr->name,
@@ -354,17 +357,17 @@ restart:
bearer_id = MAX_BEARERS;
with_this_prio = 1;
for (i = MAX_BEARERS; i-- != 0; ) {
- if (!tipc_bearers[i].active) {
+ b_ptr = bearer_list[i];
+ if (!b_ptr || !b_ptr->active) {
bearer_id = i;
continue;
}
- if (!strcmp(name, tipc_bearers[i].name)) {
+ if (!strcmp(name, b_ptr->name)) {
pr_warn("Bearer <%s> rejected, already enabled\n",
name);
goto exit;
}
- if ((tipc_bearers[i].priority == priority) &&
- (++with_this_prio > 2)) {
+ if ((b_ptr->priority == priority) && (++with_this_prio > 2)) {
if (priority-- == 0) {
pr_warn("Bearer <%s> rejected, duplicate priority\n",
name);
@@ -381,7 +384,12 @@ restart:
goto exit;
}
- b_ptr = &tipc_bearers[bearer_id];
+ b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC);
+ if (!b_ptr) {
+ res = -ENOMEM;
+ goto exit;
+ }
+
strcpy(b_ptr->name, name);
atomic_set(&b_ptr->blocked, 0);
smp_mb();
@@ -409,6 +417,9 @@ restart:
name);
goto exit;
}
+
+ bearer_list[bearer_id] = b_ptr;
+
pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
name,
tipc_addr_string_fill(addr_string, disc_domain), priority);
@@ -449,9 +460,17 @@ static void bearer_disable(struct tipc_bearer *b_ptr)
struct tipc_link *l_ptr;
struct tipc_link *temp_l_ptr;
struct tipc_link_req *temp_req;
+ u32 i;
pr_info("Disabling bearer <%s>\n", b_ptr->name);
atomic_add_unless(&b_ptr->blocked, 1, 1);
+ for (i = 0; i < MAX_BEARERS; i++) {
+ if (b_ptr == bearer_list[i]) {
+ bearer_list[i] = NULL;
+ break;
+ }
+ }
+
spin_lock_bh(&b_ptr->lock);
b_ptr->media->disable_media(b_ptr);
list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
@@ -464,7 +483,7 @@ static void bearer_disable(struct tipc_bearer *b_ptr)
if (temp_req)
tipc_disc_delete(temp_req);
- memset(b_ptr, 0, sizeof(struct tipc_bearer));
+ kfree(b_ptr);
}
int tipc_disable_bearer(const char *name)
@@ -487,11 +506,15 @@ int tipc_disable_bearer(const char *name)
void tipc_bearer_stop(void)
{
+ struct tipc_bearer *b_ptr;
u32 i;
for (i = 0; i < MAX_BEARERS; i++) {
- if (tipc_bearers[i].active)
- bearer_disable(&tipc_bearers[i]);
+ b_ptr = bearer_list[i];
+ if (b_ptr && b_ptr->active) {
+ bearer_disable(b_ptr);
+ bearer_list[i] = NULL;
+ }
}
media_count = 0;
}
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 280c23d..757eda9 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -154,7 +154,7 @@ struct tipc_bearer_names {
struct tipc_link;
-extern struct tipc_bearer tipc_bearers[];
+extern struct tipc_bearer *bearer_list[];
/*
* TIPC routines available to supported media types
--
1.7.9.5
|