diff options
Diffstat (limited to 'net/tipc/config.c')
| -rw-r--r-- | net/tipc/config.c | 87 |
1 files changed, 40 insertions, 47 deletions
diff --git a/net/tipc/config.c b/net/tipc/config.c index 48b5de2dbe60..285e1bc2d880 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
| @@ -63,7 +63,7 @@ struct manager { | |||
| 63 | 63 | ||
| 64 | static struct manager mng = { 0}; | 64 | static struct manager mng = { 0}; |
| 65 | 65 | ||
| 66 | static spinlock_t config_lock = SPIN_LOCK_UNLOCKED; | 66 | static DEFINE_SPINLOCK(config_lock); |
| 67 | 67 | ||
| 68 | static const void *req_tlv_area; /* request message TLV area */ | 68 | static const void *req_tlv_area; /* request message TLV area */ |
| 69 | static int req_tlv_space; /* request message TLV area size */ | 69 | static int req_tlv_space; /* request message TLV area size */ |
| @@ -291,13 +291,22 @@ static struct sk_buff *cfg_set_own_addr(void) | |||
| 291 | if (!tipc_addr_node_valid(addr)) | 291 | if (!tipc_addr_node_valid(addr)) |
| 292 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 292 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
| 293 | " (node address)"); | 293 | " (node address)"); |
| 294 | if (tipc_own_addr) | 294 | if (tipc_mode == TIPC_NET_MODE) |
| 295 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 295 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 296 | " (cannot change node address once assigned)"); | 296 | " (cannot change node address once assigned)"); |
| 297 | tipc_own_addr = addr; | ||
| 298 | |||
| 299 | /* | ||
| 300 | * Must release all spinlocks before calling start_net() because | ||
| 301 | * Linux version of TIPC calls eth_media_start() which calls | ||
| 302 | * register_netdevice_notifier() which may block! | ||
| 303 | * | ||
| 304 | * Temporarily releasing the lock should be harmless for non-Linux TIPC, | ||
| 305 | * but Linux version of eth_media_start() should really be reworked | ||
| 306 | * so that it can be called with spinlocks held. | ||
| 307 | */ | ||
| 297 | 308 | ||
| 298 | spin_unlock_bh(&config_lock); | 309 | spin_unlock_bh(&config_lock); |
| 299 | tipc_core_stop_net(); | ||
| 300 | tipc_own_addr = addr; | ||
| 301 | tipc_core_start_net(); | 310 | tipc_core_start_net(); |
| 302 | spin_lock_bh(&config_lock); | 311 | spin_lock_bh(&config_lock); |
| 303 | return tipc_cfg_reply_none(); | 312 | return tipc_cfg_reply_none(); |
| @@ -350,50 +359,21 @@ static struct sk_buff *cfg_set_max_subscriptions(void) | |||
| 350 | 359 | ||
| 351 | static struct sk_buff *cfg_set_max_ports(void) | 360 | static struct sk_buff *cfg_set_max_ports(void) |
| 352 | { | 361 | { |
| 353 | int orig_mode; | ||
| 354 | u32 value; | 362 | u32 value; |
| 355 | 363 | ||
| 356 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | 364 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
| 357 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 365 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
| 358 | value = *(u32 *)TLV_DATA(req_tlv_area); | 366 | value = *(u32 *)TLV_DATA(req_tlv_area); |
| 359 | value = ntohl(value); | 367 | value = ntohl(value); |
| 368 | if (value == tipc_max_ports) | ||
| 369 | return tipc_cfg_reply_none(); | ||
| 360 | if (value != delimit(value, 127, 65535)) | 370 | if (value != delimit(value, 127, 65535)) |
| 361 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 371 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
| 362 | " (max ports must be 127-65535)"); | 372 | " (max ports must be 127-65535)"); |
| 363 | 373 | if (tipc_mode != TIPC_NOT_RUNNING) | |
| 364 | if (value == tipc_max_ports) | ||
| 365 | return tipc_cfg_reply_none(); | ||
| 366 | |||
| 367 | if (atomic_read(&tipc_user_count) > 2) | ||
| 368 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 374 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 369 | " (cannot change max ports while TIPC users exist)"); | 375 | " (cannot change max ports while TIPC is active)"); |
| 370 | |||
| 371 | spin_unlock_bh(&config_lock); | ||
| 372 | orig_mode = tipc_get_mode(); | ||
| 373 | if (orig_mode == TIPC_NET_MODE) | ||
| 374 | tipc_core_stop_net(); | ||
| 375 | tipc_core_stop(); | ||
| 376 | tipc_max_ports = value; | 376 | tipc_max_ports = value; |
| 377 | tipc_core_start(); | ||
| 378 | if (orig_mode == TIPC_NET_MODE) | ||
| 379 | tipc_core_start_net(); | ||
| 380 | spin_lock_bh(&config_lock); | ||
| 381 | return tipc_cfg_reply_none(); | ||
| 382 | } | ||
| 383 | |||
| 384 | static struct sk_buff *set_net_max(int value, int *parameter) | ||
| 385 | { | ||
| 386 | int orig_mode; | ||
| 387 | |||
| 388 | if (value != *parameter) { | ||
| 389 | orig_mode = tipc_get_mode(); | ||
| 390 | if (orig_mode == TIPC_NET_MODE) | ||
| 391 | tipc_core_stop_net(); | ||
| 392 | *parameter = value; | ||
| 393 | if (orig_mode == TIPC_NET_MODE) | ||
| 394 | tipc_core_start_net(); | ||
| 395 | } | ||
| 396 | |||
| 397 | return tipc_cfg_reply_none(); | 377 | return tipc_cfg_reply_none(); |
| 398 | } | 378 | } |
| 399 | 379 | ||
| @@ -405,10 +385,16 @@ static struct sk_buff *cfg_set_max_zones(void) | |||
| 405 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 385 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
| 406 | value = *(u32 *)TLV_DATA(req_tlv_area); | 386 | value = *(u32 *)TLV_DATA(req_tlv_area); |
| 407 | value = ntohl(value); | 387 | value = ntohl(value); |
| 388 | if (value == tipc_max_zones) | ||
| 389 | return tipc_cfg_reply_none(); | ||
| 408 | if (value != delimit(value, 1, 255)) | 390 | if (value != delimit(value, 1, 255)) |
| 409 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 391 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
| 410 | " (max zones must be 1-255)"); | 392 | " (max zones must be 1-255)"); |
| 411 | return set_net_max(value, &tipc_max_zones); | 393 | if (tipc_mode == TIPC_NET_MODE) |
| 394 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
| 395 | " (cannot change max zones once TIPC has joined a network)"); | ||
| 396 | tipc_max_zones = value; | ||
| 397 | return tipc_cfg_reply_none(); | ||
| 412 | } | 398 | } |
| 413 | 399 | ||
| 414 | static struct sk_buff *cfg_set_max_clusters(void) | 400 | static struct sk_buff *cfg_set_max_clusters(void) |
| @@ -419,8 +405,8 @@ static struct sk_buff *cfg_set_max_clusters(void) | |||
| 419 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 405 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
| 420 | value = *(u32 *)TLV_DATA(req_tlv_area); | 406 | value = *(u32 *)TLV_DATA(req_tlv_area); |
| 421 | value = ntohl(value); | 407 | value = ntohl(value); |
| 422 | if (value != 1) | 408 | if (value != delimit(value, 1, 1)) |
| 423 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 409 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
| 424 | " (max clusters fixed at 1)"); | 410 | " (max clusters fixed at 1)"); |
| 425 | return tipc_cfg_reply_none(); | 411 | return tipc_cfg_reply_none(); |
| 426 | } | 412 | } |
| @@ -433,10 +419,16 @@ static struct sk_buff *cfg_set_max_nodes(void) | |||
| 433 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 419 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
| 434 | value = *(u32 *)TLV_DATA(req_tlv_area); | 420 | value = *(u32 *)TLV_DATA(req_tlv_area); |
| 435 | value = ntohl(value); | 421 | value = ntohl(value); |
| 422 | if (value == tipc_max_nodes) | ||
| 423 | return tipc_cfg_reply_none(); | ||
| 436 | if (value != delimit(value, 8, 2047)) | 424 | if (value != delimit(value, 8, 2047)) |
| 437 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 425 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
| 438 | " (max nodes must be 8-2047)"); | 426 | " (max nodes must be 8-2047)"); |
| 439 | return set_net_max(value, &tipc_max_nodes); | 427 | if (tipc_mode == TIPC_NET_MODE) |
| 428 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
| 429 | " (cannot change max nodes once TIPC has joined a network)"); | ||
| 430 | tipc_max_nodes = value; | ||
| 431 | return tipc_cfg_reply_none(); | ||
| 440 | } | 432 | } |
| 441 | 433 | ||
| 442 | static struct sk_buff *cfg_set_max_slaves(void) | 434 | static struct sk_buff *cfg_set_max_slaves(void) |
| @@ -461,15 +453,16 @@ static struct sk_buff *cfg_set_netid(void) | |||
| 461 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 453 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
| 462 | value = *(u32 *)TLV_DATA(req_tlv_area); | 454 | value = *(u32 *)TLV_DATA(req_tlv_area); |
| 463 | value = ntohl(value); | 455 | value = ntohl(value); |
| 456 | if (value == tipc_net_id) | ||
| 457 | return tipc_cfg_reply_none(); | ||
| 464 | if (value != delimit(value, 1, 9999)) | 458 | if (value != delimit(value, 1, 9999)) |
| 465 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 459 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
| 466 | " (network id must be 1-9999)"); | 460 | " (network id must be 1-9999)"); |
| 467 | 461 | if (tipc_mode == TIPC_NET_MODE) | |
| 468 | if (tipc_own_addr) | ||
| 469 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 462 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 470 | " (cannot change network id once part of network)"); | 463 | " (cannot change network id once TIPC has joined a network)"); |
| 471 | 464 | tipc_net_id = value; | |
| 472 | return set_net_max(value, &tipc_net_id); | 465 | return tipc_cfg_reply_none(); |
| 473 | } | 466 | } |
| 474 | 467 | ||
| 475 | struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, | 468 | struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, |
| @@ -649,7 +642,7 @@ static void cfg_named_msg_event(void *userdata, | |||
| 649 | if ((size < sizeof(*req_hdr)) || | 642 | if ((size < sizeof(*req_hdr)) || |
| 650 | (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || | 643 | (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || |
| 651 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { | 644 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { |
| 652 | warn("discarded invalid configuration message\n"); | 645 | warn("Invalid configuration message discarded\n"); |
| 653 | return; | 646 | return; |
| 654 | } | 647 | } |
| 655 | 648 | ||
