diff options
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r-- | net/sctp/protocol.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index ab0d538a74ed..1099e99a53c4 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -60,6 +60,8 @@ | |||
60 | #include <net/inet_common.h> | 60 | #include <net/inet_common.h> |
61 | #include <net/inet_ecn.h> | 61 | #include <net/inet_ecn.h> |
62 | 62 | ||
63 | #define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024) | ||
64 | |||
63 | /* Global data structures. */ | 65 | /* Global data structures. */ |
64 | struct sctp_globals sctp_globals __read_mostly; | 66 | struct sctp_globals sctp_globals __read_mostly; |
65 | 67 | ||
@@ -1355,6 +1357,8 @@ static __init int sctp_init(void) | |||
1355 | unsigned long limit; | 1357 | unsigned long limit; |
1356 | int max_share; | 1358 | int max_share; |
1357 | int order; | 1359 | int order; |
1360 | int num_entries; | ||
1361 | int max_entry_order; | ||
1358 | 1362 | ||
1359 | sock_skb_cb_check_size(sizeof(struct sctp_ulpevent)); | 1363 | sock_skb_cb_check_size(sizeof(struct sctp_ulpevent)); |
1360 | 1364 | ||
@@ -1407,14 +1411,24 @@ static __init int sctp_init(void) | |||
1407 | 1411 | ||
1408 | /* Size and allocate the association hash table. | 1412 | /* Size and allocate the association hash table. |
1409 | * The methodology is similar to that of the tcp hash tables. | 1413 | * The methodology is similar to that of the tcp hash tables. |
1414 | * Though not identical. Start by getting a goal size | ||
1410 | */ | 1415 | */ |
1411 | if (totalram_pages >= (128 * 1024)) | 1416 | if (totalram_pages >= (128 * 1024)) |
1412 | goal = totalram_pages >> (22 - PAGE_SHIFT); | 1417 | goal = totalram_pages >> (22 - PAGE_SHIFT); |
1413 | else | 1418 | else |
1414 | goal = totalram_pages >> (24 - PAGE_SHIFT); | 1419 | goal = totalram_pages >> (24 - PAGE_SHIFT); |
1415 | 1420 | ||
1416 | for (order = 0; (1UL << order) < goal; order++) | 1421 | /* Then compute the page order for said goal */ |
1417 | ; | 1422 | order = get_order(goal); |
1423 | |||
1424 | /* Now compute the required page order for the maximum sized table we | ||
1425 | * want to create | ||
1426 | */ | ||
1427 | max_entry_order = get_order(MAX_SCTP_PORT_HASH_ENTRIES * | ||
1428 | sizeof(struct sctp_bind_hashbucket)); | ||
1429 | |||
1430 | /* Limit the page order by that maximum hash table size */ | ||
1431 | order = min(order, max_entry_order); | ||
1418 | 1432 | ||
1419 | /* Allocate and initialize the endpoint hash table. */ | 1433 | /* Allocate and initialize the endpoint hash table. */ |
1420 | sctp_ep_hashsize = 64; | 1434 | sctp_ep_hashsize = 64; |
@@ -1430,20 +1444,35 @@ static __init int sctp_init(void) | |||
1430 | INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain); | 1444 | INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain); |
1431 | } | 1445 | } |
1432 | 1446 | ||
1433 | /* Allocate and initialize the SCTP port hash table. */ | 1447 | /* Allocate and initialize the SCTP port hash table. |
1448 | * Note that order is initalized to start at the max sized | ||
1449 | * table we want to support. If we can't get that many pages | ||
1450 | * reduce the order and try again | ||
1451 | */ | ||
1434 | do { | 1452 | do { |
1435 | sctp_port_hashsize = (1UL << order) * PAGE_SIZE / | ||
1436 | sizeof(struct sctp_bind_hashbucket); | ||
1437 | if ((sctp_port_hashsize > (64 * 1024)) && order > 0) | ||
1438 | continue; | ||
1439 | sctp_port_hashtable = (struct sctp_bind_hashbucket *) | 1453 | sctp_port_hashtable = (struct sctp_bind_hashbucket *) |
1440 | __get_free_pages(GFP_KERNEL | __GFP_NOWARN, order); | 1454 | __get_free_pages(GFP_KERNEL | __GFP_NOWARN, order); |
1441 | } while (!sctp_port_hashtable && --order > 0); | 1455 | } while (!sctp_port_hashtable && --order > 0); |
1456 | |||
1442 | if (!sctp_port_hashtable) { | 1457 | if (!sctp_port_hashtable) { |
1443 | pr_err("Failed bind hash alloc\n"); | 1458 | pr_err("Failed bind hash alloc\n"); |
1444 | status = -ENOMEM; | 1459 | status = -ENOMEM; |
1445 | goto err_bhash_alloc; | 1460 | goto err_bhash_alloc; |
1446 | } | 1461 | } |
1462 | |||
1463 | /* Now compute the number of entries that will fit in the | ||
1464 | * port hash space we allocated | ||
1465 | */ | ||
1466 | num_entries = (1UL << order) * PAGE_SIZE / | ||
1467 | sizeof(struct sctp_bind_hashbucket); | ||
1468 | |||
1469 | /* And finish by rounding it down to the nearest power of two | ||
1470 | * this wastes some memory of course, but its needed because | ||
1471 | * the hash function operates based on the assumption that | ||
1472 | * that the number of entries is a power of two | ||
1473 | */ | ||
1474 | sctp_port_hashsize = rounddown_pow_of_two(num_entries); | ||
1475 | |||
1447 | for (i = 0; i < sctp_port_hashsize; i++) { | 1476 | for (i = 0; i < sctp_port_hashsize; i++) { |
1448 | spin_lock_init(&sctp_port_hashtable[i].lock); | 1477 | spin_lock_init(&sctp_port_hashtable[i].lock); |
1449 | INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); | 1478 | INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); |
@@ -1452,7 +1481,8 @@ static __init int sctp_init(void) | |||
1452 | if (sctp_transport_hashtable_init()) | 1481 | if (sctp_transport_hashtable_init()) |
1453 | goto err_thash_alloc; | 1482 | goto err_thash_alloc; |
1454 | 1483 | ||
1455 | pr_info("Hash tables configured (bind %d)\n", sctp_port_hashsize); | 1484 | pr_info("Hash tables configured (bind %d/%d)\n", sctp_port_hashsize, |
1485 | num_entries); | ||
1456 | 1486 | ||
1457 | sctp_sysctl_register(); | 1487 | sctp_sysctl_register(); |
1458 | 1488 | ||