diff options
-rw-r--r-- | net/tipc/config.c | 83 |
1 files changed, 38 insertions, 45 deletions
diff --git a/net/tipc/config.c b/net/tipc/config.c index 48b5de2dbe60..41c8447276f9 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
@@ -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, |