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 ---