cong.c (552c69b36ebd966186573b9c7a286b390935cce1) | cong.c (eee2fa6ab3225192d6d894c54a6fb02ac9efdff6) |
---|---|
1/* | 1/* |
2 * Copyright (c) 2007 Oracle. All rights reserved. | 2 * Copyright (c) 2007, 2017 Oracle and/or its affiliates. All rights reserved. |
3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or --- 85 unchanged lines hidden (view full) --- 96 * 97 * It's sadly ordered under the socket callback lock and the connection lock. 98 * Receive paths can mark ports congested from interrupt context so the 99 * lock masks interrupts. 100 */ 101static DEFINE_SPINLOCK(rds_cong_lock); 102static struct rb_root rds_cong_tree = RB_ROOT; 103 | 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or --- 85 unchanged lines hidden (view full) --- 96 * 97 * It's sadly ordered under the socket callback lock and the connection lock. 98 * Receive paths can mark ports congested from interrupt context so the 99 * lock masks interrupts. 100 */ 101static DEFINE_SPINLOCK(rds_cong_lock); 102static struct rb_root rds_cong_tree = RB_ROOT; 103 |
104static struct rds_cong_map *rds_cong_tree_walk(__be32 addr, | 104static struct rds_cong_map *rds_cong_tree_walk(const struct in6_addr *addr, |
105 struct rds_cong_map *insert) 106{ 107 struct rb_node **p = &rds_cong_tree.rb_node; 108 struct rb_node *parent = NULL; 109 struct rds_cong_map *map; 110 111 while (*p) { | 105 struct rds_cong_map *insert) 106{ 107 struct rb_node **p = &rds_cong_tree.rb_node; 108 struct rb_node *parent = NULL; 109 struct rds_cong_map *map; 110 111 while (*p) { |
112 int diff; 113 |
|
112 parent = *p; 113 map = rb_entry(parent, struct rds_cong_map, m_rb_node); 114 | 114 parent = *p; 115 map = rb_entry(parent, struct rds_cong_map, m_rb_node); 116 |
115 if (addr < map->m_addr) | 117 diff = rds_addr_cmp(addr, &map->m_addr); 118 if (diff < 0) |
116 p = &(*p)->rb_left; | 119 p = &(*p)->rb_left; |
117 else if (addr > map->m_addr) | 120 else if (diff > 0) |
118 p = &(*p)->rb_right; 119 else 120 return map; 121 } 122 123 if (insert) { 124 rb_link_node(&insert->m_rb_node, parent, p); 125 rb_insert_color(&insert->m_rb_node, &rds_cong_tree); 126 } 127 return NULL; 128} 129 130/* 131 * There is only ever one bitmap for any address. Connections try and allocate 132 * these bitmaps in the process getting pointers to them. The bitmaps are only 133 * ever freed as the module is removed after all connections have been freed. 134 */ | 121 p = &(*p)->rb_right; 122 else 123 return map; 124 } 125 126 if (insert) { 127 rb_link_node(&insert->m_rb_node, parent, p); 128 rb_insert_color(&insert->m_rb_node, &rds_cong_tree); 129 } 130 return NULL; 131} 132 133/* 134 * There is only ever one bitmap for any address. Connections try and allocate 135 * these bitmaps in the process getting pointers to them. The bitmaps are only 136 * ever freed as the module is removed after all connections have been freed. 137 */ |
135static struct rds_cong_map *rds_cong_from_addr(__be32 addr) | 138static struct rds_cong_map *rds_cong_from_addr(const struct in6_addr *addr) |
136{ 137 struct rds_cong_map *map; 138 struct rds_cong_map *ret = NULL; 139 unsigned long zp; 140 unsigned long i; 141 unsigned long flags; 142 143 map = kzalloc(sizeof(struct rds_cong_map), GFP_KERNEL); 144 if (!map) 145 return NULL; 146 | 139{ 140 struct rds_cong_map *map; 141 struct rds_cong_map *ret = NULL; 142 unsigned long zp; 143 unsigned long i; 144 unsigned long flags; 145 146 map = kzalloc(sizeof(struct rds_cong_map), GFP_KERNEL); 147 if (!map) 148 return NULL; 149 |
147 map->m_addr = addr; | 150 map->m_addr = *addr; |
148 init_waitqueue_head(&map->m_waitq); 149 INIT_LIST_HEAD(&map->m_conn_list); 150 151 for (i = 0; i < RDS_CONG_MAP_PAGES; i++) { 152 zp = get_zeroed_page(GFP_KERNEL); 153 if (zp == 0) 154 goto out; 155 map->m_page_addrs[i] = zp; --- 10 unchanged lines hidden (view full) --- 166 167out: 168 if (map) { 169 for (i = 0; i < RDS_CONG_MAP_PAGES && map->m_page_addrs[i]; i++) 170 free_page(map->m_page_addrs[i]); 171 kfree(map); 172 } 173 | 151 init_waitqueue_head(&map->m_waitq); 152 INIT_LIST_HEAD(&map->m_conn_list); 153 154 for (i = 0; i < RDS_CONG_MAP_PAGES; i++) { 155 zp = get_zeroed_page(GFP_KERNEL); 156 if (zp == 0) 157 goto out; 158 map->m_page_addrs[i] = zp; --- 10 unchanged lines hidden (view full) --- 169 170out: 171 if (map) { 172 for (i = 0; i < RDS_CONG_MAP_PAGES && map->m_page_addrs[i]; i++) 173 free_page(map->m_page_addrs[i]); 174 kfree(map); 175 } 176 |
174 rdsdebug("map %p for addr %x\n", ret, be32_to_cpu(addr)); | 177 rdsdebug("map %p for addr %pI6c\n", ret, addr); |
175 176 return ret; 177} 178 179/* 180 * Put the conn on its local map's list. This is called when the conn is 181 * really added to the hash. It's nested under the rds_conn_lock, sadly. 182 */ --- 14 unchanged lines hidden (view full) --- 197 rdsdebug("removing conn %p from map %p\n", conn, conn->c_lcong); 198 spin_lock_irqsave(&rds_cong_lock, flags); 199 list_del_init(&conn->c_map_item); 200 spin_unlock_irqrestore(&rds_cong_lock, flags); 201} 202 203int rds_cong_get_maps(struct rds_connection *conn) 204{ | 178 179 return ret; 180} 181 182/* 183 * Put the conn on its local map's list. This is called when the conn is 184 * really added to the hash. It's nested under the rds_conn_lock, sadly. 185 */ --- 14 unchanged lines hidden (view full) --- 200 rdsdebug("removing conn %p from map %p\n", conn, conn->c_lcong); 201 spin_lock_irqsave(&rds_cong_lock, flags); 202 list_del_init(&conn->c_map_item); 203 spin_unlock_irqrestore(&rds_cong_lock, flags); 204} 205 206int rds_cong_get_maps(struct rds_connection *conn) 207{ |
205 conn->c_lcong = rds_cong_from_addr(conn->c_laddr); 206 conn->c_fcong = rds_cong_from_addr(conn->c_faddr); | 208 conn->c_lcong = rds_cong_from_addr(&conn->c_laddr); 209 conn->c_fcong = rds_cong_from_addr(&conn->c_faddr); |
207 208 if (!(conn->c_lcong && conn->c_fcong)) 209 return -ENOMEM; 210 211 return 0; 212} 213 214void rds_cong_queue_updates(struct rds_cong_map *map) --- 133 unchanged lines hidden (view full) --- 348 struct rds_cong_map *map; 349 350 write_lock_irqsave(&rds_cong_monitor_lock, flags); 351 list_del_init(&rs->rs_cong_list); 352 write_unlock_irqrestore(&rds_cong_monitor_lock, flags); 353 354 /* update congestion map for now-closed port */ 355 spin_lock_irqsave(&rds_cong_lock, flags); | 210 211 if (!(conn->c_lcong && conn->c_fcong)) 212 return -ENOMEM; 213 214 return 0; 215} 216 217void rds_cong_queue_updates(struct rds_cong_map *map) --- 133 unchanged lines hidden (view full) --- 351 struct rds_cong_map *map; 352 353 write_lock_irqsave(&rds_cong_monitor_lock, flags); 354 list_del_init(&rs->rs_cong_list); 355 write_unlock_irqrestore(&rds_cong_monitor_lock, flags); 356 357 /* update congestion map for now-closed port */ 358 spin_lock_irqsave(&rds_cong_lock, flags); |
356 map = rds_cong_tree_walk(rs->rs_bound_addr, NULL); | 359 map = rds_cong_tree_walk(&rs->rs_bound_addr, NULL); |
357 spin_unlock_irqrestore(&rds_cong_lock, flags); 358 359 if (map && rds_cong_test_bit(map, rs->rs_bound_port)) { 360 rds_cong_clear_bit(map, rs->rs_bound_port); 361 rds_cong_queue_updates(map); 362 } 363} 364 --- 61 unchanged lines hidden --- | 360 spin_unlock_irqrestore(&rds_cong_lock, flags); 361 362 if (map && rds_cong_test_bit(map, rs->rs_bound_port)) { 363 rds_cong_clear_bit(map, rs->rs_bound_port); 364 rds_cong_queue_updates(map); 365 } 366} 367 --- 61 unchanged lines hidden --- |