[TIPC]: Disallow config operations that aren't supported in certain modes.
authorAllan Stephens <allan.stephens@windriver.com>
Mon, 26 Jun 2006 06:51:08 +0000 (23:51 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 26 Jun 2006 06:51:08 +0000 (23:51 -0700)
This change provides user-friendly feedback when TIPC is unable to perform
certain configuration operations that don't work properly in certain modes.
(In particular, any reconfiguration request that would temporarily take TIPC
from network mode to standalone mode, or from standalone mode to not running
mode, is disallowed.)

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Per Liden <per.liden@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/config.c

index 48b5de2..41c8447 100644 (file)
@@ -291,13 +291,22 @@ static struct sk_buff *cfg_set_own_addr(void)
        if (!tipc_addr_node_valid(addr))
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
                                                   " (node address)");
-       if (tipc_own_addr)
+       if (tipc_mode == TIPC_NET_MODE)
                return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
                                                   " (cannot change node address once assigned)");
+       tipc_own_addr = addr;
+
+       /* 
+        * Must release all spinlocks before calling start_net() because
+        * Linux version of TIPC calls eth_media_start() which calls
+        * register_netdevice_notifier() which may block!
+        *
+        * Temporarily releasing the lock should be harmless for non-Linux TIPC,
+        * but Linux version of eth_media_start() should really be reworked
+        * so that it can be called with spinlocks held.
+        */
 
        spin_unlock_bh(&config_lock);
-       tipc_core_stop_net();
-       tipc_own_addr = addr;
        tipc_core_start_net();
        spin_lock_bh(&config_lock);
        return tipc_cfg_reply_none();
@@ -350,50 +359,21 @@ static struct sk_buff *cfg_set_max_subscriptions(void)
 
 static struct sk_buff *cfg_set_max_ports(void)
 {
-       int orig_mode;
        u32 value;
 
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
        value = *(u32 *)TLV_DATA(req_tlv_area);
        value = ntohl(value);
+       if (value == tipc_max_ports)
+               return tipc_cfg_reply_none();
        if (value != delimit(value, 127, 65535))
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
                                                   " (max ports must be 127-65535)");
-
-       if (value == tipc_max_ports)
-               return tipc_cfg_reply_none();
-
-       if (atomic_read(&tipc_user_count) > 2)
+       if (tipc_mode != TIPC_NOT_RUNNING)
                return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-                                                  " (cannot change max ports while TIPC users exist)");
-
-       spin_unlock_bh(&config_lock);
-       orig_mode = tipc_get_mode();
-       if (orig_mode == TIPC_NET_MODE)
-               tipc_core_stop_net();
-       tipc_core_stop();
+                       " (cannot change max ports while TIPC is active)");
        tipc_max_ports = value;
-       tipc_core_start();
-       if (orig_mode == TIPC_NET_MODE)
-               tipc_core_start_net();
-       spin_lock_bh(&config_lock);
-       return tipc_cfg_reply_none();
-}
-
-static struct sk_buff *set_net_max(int value, int *parameter)
-{
-       int orig_mode;
-
-       if (value != *parameter) {
-               orig_mode = tipc_get_mode();
-               if (orig_mode == TIPC_NET_MODE)
-                       tipc_core_stop_net();
-               *parameter = value;
-               if (orig_mode == TIPC_NET_MODE)
-                       tipc_core_start_net();
-       }
-
        return tipc_cfg_reply_none();
 }
 
@@ -405,10 +385,16 @@ static struct sk_buff *cfg_set_max_zones(void)
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
        value = *(u32 *)TLV_DATA(req_tlv_area);
        value = ntohl(value);
+       if (value == tipc_max_zones)
+               return tipc_cfg_reply_none();
        if (value != delimit(value, 1, 255))
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
                                                   " (max zones must be 1-255)");
-       return set_net_max(value, &tipc_max_zones);
+       if (tipc_mode == TIPC_NET_MODE)
+               return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+                       " (cannot change max zones once TIPC has joined a network)");
+       tipc_max_zones = value;
+       return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_clusters(void)
@@ -419,8 +405,8 @@ static struct sk_buff *cfg_set_max_clusters(void)
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
        value = *(u32 *)TLV_DATA(req_tlv_area);
        value = ntohl(value);
-       if (value != 1)
-               return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+       if (value != delimit(value, 1, 1))
+               return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
                                                   " (max clusters fixed at 1)");
        return tipc_cfg_reply_none();
 }
@@ -433,10 +419,16 @@ static struct sk_buff *cfg_set_max_nodes(void)
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
        value = *(u32 *)TLV_DATA(req_tlv_area);
        value = ntohl(value);
+       if (value == tipc_max_nodes)
+               return tipc_cfg_reply_none();
        if (value != delimit(value, 8, 2047))
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
                                                   " (max nodes must be 8-2047)");
-       return set_net_max(value, &tipc_max_nodes);
+       if (tipc_mode == TIPC_NET_MODE)
+               return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+                       " (cannot change max nodes once TIPC has joined a network)");
+       tipc_max_nodes = value;
+       return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_slaves(void)
@@ -461,15 +453,16 @@ static struct sk_buff *cfg_set_netid(void)
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
        value = *(u32 *)TLV_DATA(req_tlv_area);
        value = ntohl(value);
+       if (value == tipc_net_id)
+               return tipc_cfg_reply_none();
        if (value != delimit(value, 1, 9999))
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
                                                   " (network id must be 1-9999)");
-
-       if (tipc_own_addr)
+       if (tipc_mode == TIPC_NET_MODE)
                return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-                                                  " (cannot change network id once part of network)");
-       
-       return set_net_max(value, &tipc_net_id);
+                       " (cannot change network id once TIPC has joined a network)");
+       tipc_net_id = value;
+       return tipc_cfg_reply_none();
 }
 
 struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,