|
From: Ying X. <yin...@wi...> - 2013-09-30 08:39:04
|
In current TIPC locking policy, tipc_net_lock protects two domains:
'node' and 'bearer' sub-domains. When one link instance is got from
"active_links" array in node sub-domain, tipc_net_lock(read) must be
held. Correspondingly, individual bearers may change status within a
tipc_net_lock(read), and it needs tipc_net_lock(write) to remove/add
any bearers. Obviously, this locking policy makes the two sub-domains
bound together closely.
To simplify the locking policy, we use one fine grained config_muex
lock to proect all resources associated with bearer/media like
media_list, tipc_bearers and media_hlist etc. But, even if the change
is made, tipc_net_lock is not removed from bearer domain until RCU
locks are involved to protect these global lists like media_list,
tipc_bearers and media_hlist in the future.
Additionally both initialised and uninitialised processes of TIPC
module have to be adjusted due to the locking policy change, so
tipc_core_start_net() and tipc_core_stop_net() become obsolete.
Signed-off-by: Ying Xue <yin...@wi...>
---
net/tipc/bearer.c | 4 ++++
net/tipc/config.c | 4 ++--
net/tipc/config.h | 4 ++--
net/tipc/core.c | 37 ++++++-------------------------------
net/tipc/core.h | 1 -
net/tipc/eth_media.c | 5 ++++-
net/tipc/ib_media.c | 5 ++++-
net/tipc/net.c | 3 +++
8 files changed, 25 insertions(+), 38 deletions(-)
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 9f03a93..5dd587b 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -85,6 +85,7 @@ int tipc_register_media(struct tipc_media *m_ptr)
{
int res = -EINVAL;
+ mutex_lock(&config_mutex);
write_lock_bh(&tipc_net_lock);
if ((strlen(m_ptr->name) + 1) > TIPC_MAX_MEDIA_NAME)
@@ -104,6 +105,7 @@ int tipc_register_media(struct tipc_media *m_ptr)
res = 0;
exit:
write_unlock_bh(&tipc_net_lock);
+ mutex_unlock(&config_mutex);
if (res)
pr_warn("Media <%s> registration error\n", m_ptr->name);
return res;
@@ -114,6 +116,7 @@ void tipc_unregister_media(const struct tipc_media *m_ptr)
struct tipc_media *m;
u32 i;
+ mutex_lock(&config_mutex);
write_lock_bh(&tipc_net_lock);
for (i = 0; i < media_count; i++) {
m = media_list[i];
@@ -124,6 +127,7 @@ void tipc_unregister_media(const struct tipc_media *m_ptr)
}
}
write_unlock_bh(&tipc_net_lock);
+ mutex_unlock(&config_mutex);
}
/**
diff --git a/net/tipc/config.c b/net/tipc/config.c
index c301a9a..dc39fc4 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -42,7 +42,7 @@
#define REPLY_TRUNCATED "<truncated>\n"
-static DEFINE_MUTEX(config_mutex);
+DEFINE_MUTEX(config_mutex);
static struct tipc_server cfgsrv;
static const void *req_tlv_area; /* request message TLV area */
@@ -181,7 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void)
if (tipc_own_addr)
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
" (cannot change node address once assigned)");
- tipc_core_start_net(addr);
+ tipc_net_start(addr);
return tipc_cfg_reply_none();
}
diff --git a/net/tipc/config.h b/net/tipc/config.h
index 1f252f3..3c079c2 100644
--- a/net/tipc/config.h
+++ b/net/tipc/config.h
@@ -37,10 +37,10 @@
#ifndef _TIPC_CONFIG_H
#define _TIPC_CONFIG_H
-/* ---------------------------------------------------------------------- */
-
#include "link.h"
+extern struct mutex config_mutex;
+
struct sk_buff *tipc_cfg_reply_alloc(int payload_size);
int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
void *tlv_data, int tlv_data_size);
diff --git a/net/tipc/core.c b/net/tipc/core.c
index fd4eeea..395167d 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -77,41 +77,13 @@ struct sk_buff *tipc_buf_acquire(u32 size)
}
/**
- * tipc_core_stop_net - shut down TIPC networking sub-systems
+ * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode
*/
-static void tipc_core_stop_net(void)
+static void tipc_core_stop(void)
{
tipc_net_stop();
tipc_eth_media_stop();
tipc_ib_media_stop();
-}
-
-/**
- * start_net - start TIPC networking sub-systems
- */
-int tipc_core_start_net(unsigned long addr)
-{
- int res;
-
- tipc_net_start(addr);
- res = tipc_eth_media_start();
- if (res < 0)
- goto err;
- res = tipc_ib_media_start();
- if (res < 0)
- goto err;
- return res;
-
-err:
- tipc_core_stop_net();
- return res;
-}
-
-/**
- * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode
- */
-static void tipc_core_stop(void)
-{
tipc_netlink_stop();
tipc_handler_stop();
tipc_cfg_stop();
@@ -146,6 +118,10 @@ static int tipc_core_start(void)
res = tipc_subscr_start();
if (!res)
res = tipc_cfg_init();
+ if (!res)
+ res = tipc_eth_media_start();
+ if (!res)
+ res = tipc_ib_media_start();
if (res)
tipc_core_stop();
@@ -178,7 +154,6 @@ static int __init tipc_init(void)
static void __exit tipc_exit(void)
{
- tipc_core_stop_net();
tipc_core_stop();
pr_info("Deactivated\n");
}
diff --git a/net/tipc/core.h b/net/tipc/core.h
index bef34ea..5402044 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -90,7 +90,6 @@ extern int tipc_random __read_mostly;
/*
* Routines available to privileged subsystems
*/
-int tipc_core_start_net(unsigned long);
int tipc_handler_start(void);
void tipc_handler_stop(void);
int tipc_netlink_start(void);
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 0480299..2d4458c 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -36,7 +36,7 @@
#include "core.h"
#include "bearer.h"
-#include "net.h"
+#include "config.h"
#define ETH_ADDR_OFFSET 4 /* message header offset of MAC address */
@@ -214,10 +214,12 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
if (!net_eq(dev_net(dev), &init_net))
return NOTIFY_DONE;
+ mutex_lock(&config_mutex);
read_lock_bh(&tipc_net_lock);
eb_ptr = media_get(dev->ifindex);
if (!eb_ptr) {
read_unlock_bh(&tipc_net_lock);
+ mutex_unlock(&config_mutex);
return NOTIFY_DONE; /* bearer had been disabled */
}
@@ -249,6 +251,7 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
break;
}
read_unlock_bh(&tipc_net_lock);
+ mutex_unlock(&config_mutex);
return NOTIFY_OK;
}
diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c
index 916f60e..9decb3d 100644
--- a/net/tipc/ib_media.c
+++ b/net/tipc/ib_media.c
@@ -41,7 +41,7 @@
#include <linux/if_infiniband.h>
#include "core.h"
#include "bearer.h"
-#include "net.h"
+#include "config.h"
/**
* struct ib_media - Infiniband media data structure
@@ -218,10 +218,12 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
if (!net_eq(dev_net(dev), &init_net))
return NOTIFY_DONE;
+ mutex_lock(&config_mutex);
read_lock_bh(&tipc_net_lock);
ib_ptr = media_get(dev->ifindex);
if (!ib_ptr) {
read_unlock_bh(&tipc_net_lock);
+ mutex_unlock(&config_mutex);
return NOTIFY_DONE; /* bearer had been disabled */
}
@@ -253,6 +255,7 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
break;
}
read_unlock_bh(&tipc_net_lock);
+ mutex_unlock(&config_mutex);
return NOTIFY_OK;
}
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 7d305ec..94f4e45 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -195,11 +195,14 @@ void tipc_net_stop(void)
if (!tipc_own_addr)
return;
+
+ mutex_lock(&config_mutex);
write_lock_bh(&tipc_net_lock);
tipc_bearer_stop();
tipc_bclink_stop();
list_for_each_entry_safe(node, t_node, &tipc_node_list, list)
tipc_node_delete(node);
write_unlock_bh(&tipc_net_lock);
+ mutex_unlock(&config_mutex);
pr_info("Left network mode\n");
}
--
1.7.9.5
|