79
79
* finds that the saved generation number is smaller than the global generation
80
80
* number, it wakes up the process.
81
81
*/
82
+ static atomic_t rds_cong_generation = ATOMIC_INIT (0 );
83
+
84
+ /*
85
+ * Congestion monitoring
86
+ */
87
+
88
+ struct rds_cong_monitor {
89
+ /* global list of monitoring sockets */
90
+ struct list_head rc_monitor ;
91
+ rwlock_t rc_monitor_lock ;
92
+
93
+ /* kworker related */
94
+ spinlock_t rc_notify_lock ;
95
+ u64 rc_notify_portmask ;
96
+ struct work_struct rc_notify_work ;
97
+ bool rc_notify_work_scheduled ;
98
+ };
99
+
100
+ static struct rds_cong_monitor * rds_cong_monitor ;
82
101
83
102
static void rds_cong_notify_worker (struct work_struct * work )
84
103
{
85
104
u64 portmask ;
86
105
bool qwork = false;
87
106
unsigned long flags ;
88
107
struct rds_sock * rs ;
89
- struct rds_cong_monitor * rds_cong_monitor ;
90
-
91
- rds_cong_monitor = container_of (work , struct rds_cong_monitor ,
92
- rc_notify_work );
93
108
94
109
/* take snapshot of portmask for processing */
95
110
spin_lock_bh (& rds_cong_monitor -> rc_notify_lock );
@@ -124,7 +139,7 @@ static void rds_cong_notify_worker(struct work_struct *work)
124
139
queue_work (rds_wq , & rds_cong_monitor -> rc_notify_work );
125
140
}
126
141
127
- static int rds_cong_monitor_init (struct rds_net * rns )
142
+ int rds_cong_monitor_init (void )
128
143
{
129
144
struct rds_cong_monitor * rcm ;
130
145
@@ -137,18 +152,15 @@ static int rds_cong_monitor_init(struct rds_net *rns)
137
152
138
153
spin_lock_init (& rcm -> rc_notify_lock );
139
154
INIT_WORK (& rcm -> rc_notify_work , rds_cong_notify_worker );
140
- rcm -> rc_rns = rns ;
141
- rns -> rns_cong_monitor = rcm ;
155
+ rds_cong_monitor = rcm ;
142
156
143
157
return 0 ;
144
158
}
145
159
146
- static void rds_cong_monitor_free (struct rds_net * rns )
160
+ void rds_cong_monitor_free (void )
147
161
{
148
- struct rds_cong_monitor * rcm = rns -> rns_cong_monitor ;
149
-
150
- cancel_work_sync (& rcm -> rc_notify_work );
151
- kfree (rcm );
162
+ cancel_work_sync (& rds_cong_monitor -> rc_notify_work );
163
+ kfree (rds_cong_monitor );
152
164
}
153
165
154
166
/*
@@ -163,12 +175,13 @@ static void rds_cong_monitor_free(struct rds_net *rns)
163
175
* Receive paths can mark ports congested from interrupt context so the
164
176
* lock masks interrupts.
165
177
*/
178
+ static DEFINE_SPINLOCK (rds_cong_lock );
179
+ static struct rb_root rds_cong_tree = RB_ROOT ;
166
180
167
- static struct rds_cong_map * rds_cong_tree_walk (struct rds_net * rns ,
168
- struct in6_addr * addr ,
181
+ static struct rds_cong_map * rds_cong_tree_walk (struct in6_addr * addr ,
169
182
struct rds_cong_map * insert )
170
183
{
171
- struct rb_node * * p = & rns -> rns_cong_tree .rb_node ;
184
+ struct rb_node * * p = & rds_cong_tree .rb_node ;
172
185
struct rb_node * parent = NULL ;
173
186
struct rds_cong_map * map ;
174
187
@@ -188,7 +201,7 @@ static struct rds_cong_map *rds_cong_tree_walk(struct rds_net *rns,
188
201
189
202
if (insert ) {
190
203
rb_link_node (& insert -> m_rb_node , parent , p );
191
- rb_insert_color (& insert -> m_rb_node , & rns -> rns_cong_tree );
204
+ rb_insert_color (& insert -> m_rb_node , & rds_cong_tree );
192
205
}
193
206
return NULL ;
194
207
}
@@ -198,8 +211,7 @@ static struct rds_cong_map *rds_cong_tree_walk(struct rds_net *rns,
198
211
* these bitmaps in the process getting pointers to them. The bitmaps are only
199
212
* ever freed as the module is removed after all connections have been freed.
200
213
*/
201
- static struct rds_cong_map * rds_cong_from_addr (struct rds_net * rns ,
202
- struct in6_addr * addr )
214
+ static struct rds_cong_map * rds_cong_from_addr (struct in6_addr * addr )
203
215
{
204
216
struct rds_cong_map * map ;
205
217
struct rds_cong_map * ret = NULL ;
@@ -210,7 +222,7 @@ static struct rds_cong_map *rds_cong_from_addr(struct rds_net *rns,
210
222
map = kzalloc (sizeof (struct rds_cong_map ), GFP_KERNEL );
211
223
if (!map )
212
224
return NULL ;
213
- map -> m_rns = rns ;
225
+
214
226
map -> m_addr = * addr ;
215
227
init_waitqueue_head (& map -> m_waitq );
216
228
INIT_LIST_HEAD (& map -> m_conn_list );
@@ -222,9 +234,9 @@ static struct rds_cong_map *rds_cong_from_addr(struct rds_net *rns,
222
234
map -> m_page_addrs [i ] = zp ;
223
235
}
224
236
225
- spin_lock_irqsave (& rns -> rns_cong_lock , flags );
226
- ret = rds_cong_tree_walk (rns , addr , map );
227
- spin_unlock_irqrestore (& rns -> rns_cong_lock , flags );
237
+ spin_lock_irqsave (& rds_cong_lock , flags );
238
+ ret = rds_cong_tree_walk (addr , map );
239
+ spin_unlock_irqrestore (& rds_cong_lock , flags );
228
240
229
241
if (!ret ) {
230
242
ret = map ;
@@ -277,27 +289,27 @@ void rds_cong_add_conn(struct rds_connection *conn)
277
289
unsigned long flags ;
278
290
279
291
rdsdebug ("conn %p now on map %p\n" , conn , conn -> c_lcong );
280
- spin_lock_irqsave (& conn -> c_rns -> rns_cong_lock , flags );
292
+ spin_lock_irqsave (& rds_cong_lock , flags );
281
293
list_add_tail (& conn -> c_map_item , & conn -> c_lcong -> m_conn_list );
282
- spin_unlock_irqrestore (& conn -> c_rns -> rns_cong_lock , flags );
294
+ spin_unlock_irqrestore (& rds_cong_lock , flags );
283
295
}
284
296
285
297
void rds_cong_remove_conn (struct rds_connection * conn )
286
298
{
287
299
unsigned long flags ;
288
300
289
301
rdsdebug ("removing conn %p from map %p\n" , conn , conn -> c_lcong );
290
- spin_lock_irqsave (& conn -> c_rns -> rns_cong_lock , flags );
302
+ spin_lock_irqsave (& rds_cong_lock , flags );
291
303
list_del_init (& conn -> c_map_item );
292
- spin_unlock_irqrestore (& conn -> c_rns -> rns_cong_lock , flags );
304
+ spin_unlock_irqrestore (& rds_cong_lock , flags );
293
305
}
294
306
295
307
int rds_cong_get_maps (struct rds_connection * conn )
296
308
{
297
309
int hash_inx ;
298
310
299
- conn -> c_lcong = rds_cong_from_addr (conn -> c_rns , & conn -> c_laddr );
300
- conn -> c_fcong = rds_cong_from_addr (conn -> c_rns , & conn -> c_faddr );
311
+ conn -> c_lcong = rds_cong_from_addr (& conn -> c_laddr );
312
+ conn -> c_fcong = rds_cong_from_addr (& conn -> c_faddr );
301
313
302
314
if (!(conn -> c_lcong && conn -> c_fcong ))
303
315
return - ENOMEM ;
@@ -317,7 +329,7 @@ void rds_cong_queue_updates(struct rds_cong_map *map)
317
329
struct rds_connection * conn ;
318
330
unsigned long flags ;
319
331
320
- spin_lock_irqsave (& map -> m_rns -> rns_cong_lock , flags );
332
+ spin_lock_irqsave (& rds_cong_lock , flags );
321
333
322
334
list_for_each_entry (conn , & map -> m_conn_list , c_map_item ) {
323
335
if (!test_and_set_bit (RCMQ_BITOFF_CONGU_PENDING ,
@@ -327,21 +339,17 @@ void rds_cong_queue_updates(struct rds_cong_map *map)
327
339
}
328
340
}
329
341
330
- spin_unlock_irqrestore (& map -> m_rns -> rns_cong_lock , flags );
342
+ spin_unlock_irqrestore (& rds_cong_lock , flags );
331
343
}
332
344
333
345
void rds_cong_map_updated (struct rds_cong_map * map , uint64_t portmask )
334
346
{
335
347
bool qwork = false;
336
- struct rds_net * rns ;
337
- struct rds_cong_monitor * rds_cong_monitor ;
338
348
339
349
rdsdebug ("waking map %p for %pI6c\n" ,
340
350
map , & map -> m_addr );
341
- rns = map -> m_rns ;
342
- rds_cong_monitor = rns -> rns_cong_monitor ;
343
351
rds_stats_inc (s_cong_update_received );
344
- atomic_inc (& rns -> rns_cong_generation );
352
+ atomic_inc (& rds_cong_generation );
345
353
if (waitqueue_active (& map -> m_waitq ))
346
354
wake_up (& map -> m_waitq );
347
355
if (waitqueue_active (map -> m_wait_queue_ptr ))
@@ -364,13 +372,13 @@ void rds_cong_map_updated(struct rds_cong_map *map, uint64_t portmask)
364
372
}
365
373
EXPORT_SYMBOL_GPL (rds_cong_map_updated );
366
374
367
- int rds_cong_updated_since (struct rds_sock * rs )
375
+ int rds_cong_updated_since (unsigned long * recent )
368
376
{
369
- unsigned long gen = atomic_read (& rs -> rs_rns -> rns_cong_generation );
377
+ unsigned long gen = atomic_read (& rds_cong_generation );
370
378
371
- if (likely (rs -> rs_cong_track == gen ))
379
+ if (likely (* recent == gen ))
372
380
return 0 ;
373
- rs -> rs_cong_track = gen ;
381
+ * recent = gen ;
374
382
return 1 ;
375
383
}
376
384
@@ -423,8 +431,6 @@ static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port)
423
431
void rds_cong_add_socket (struct rds_sock * rs )
424
432
{
425
433
unsigned long flags ;
426
- struct rds_cong_monitor * rds_cong_monitor =
427
- rs -> rs_rns -> rns_cong_monitor ;
428
434
429
435
write_lock_irqsave (& rds_cong_monitor -> rc_monitor_lock , flags );
430
436
if (list_empty (& rs -> rs_cong_list ))
@@ -436,17 +442,15 @@ void rds_cong_remove_socket(struct rds_sock *rs)
436
442
{
437
443
unsigned long flags ;
438
444
struct rds_cong_map * map ;
439
- struct rds_cong_monitor * rds_cong_monitor =
440
- rs -> rs_rns -> rns_cong_monitor ;
441
445
442
446
write_lock_irqsave (& rds_cong_monitor -> rc_monitor_lock , flags );
443
447
list_del_init (& rs -> rs_cong_list );
444
448
write_unlock_irqrestore (& rds_cong_monitor -> rc_monitor_lock , flags );
445
449
446
450
/* update congestion map for now-closed port */
447
- spin_lock_irqsave (& rs -> rs_rns -> rns_cong_lock , flags );
448
- map = rds_cong_tree_walk (rs -> rs_rns , & rs -> rs_bound_addr , NULL );
449
- spin_unlock_irqrestore (& rs -> rs_rns -> rns_cong_lock , flags );
451
+ spin_lock_irqsave (& rds_cong_lock , flags );
452
+ map = rds_cong_tree_walk (& rs -> rs_bound_addr , NULL );
453
+ spin_unlock_irqrestore (& rds_cong_lock , flags );
450
454
451
455
if (map && rds_cong_test_bit (map , rs -> rs_bound_port )) {
452
456
rds_cong_clear_bit (map , rs -> rs_bound_port );
@@ -479,31 +483,20 @@ int rds_cong_wait(struct rds_cong_map *map, __be16 port, int nonblock,
479
483
!rds_cong_test_bit (map , port ));
480
484
}
481
485
482
- void rds_cong_net_exit ( struct rds_net * rns )
486
+ void rds_cong_exit ( void )
483
487
{
484
488
struct rb_node * node ;
485
489
struct rds_cong_map * map ;
486
490
unsigned long i ;
487
491
488
- while ((node = rb_first (& rns -> rns_cong_tree ))) {
492
+ while ((node = rb_first (& rds_cong_tree ))) {
489
493
map = rb_entry (node , struct rds_cong_map , m_rb_node );
490
494
rdsdebug ("freeing map %p\n" , map );
491
- rb_erase (& map -> m_rb_node , & rns -> rns_cong_tree );
495
+ rb_erase (& map -> m_rb_node , & rds_cong_tree );
492
496
for (i = 0 ; i < RDS_CONG_MAP_PAGES && map -> m_page_addrs [i ]; i ++ )
493
497
free_page (map -> m_page_addrs [i ]);
494
498
kfree (map );
495
499
}
496
- rds_cong_monitor_free (rns );
497
- }
498
-
499
- int rds_cong_net_init (struct rds_net * rns )
500
- {
501
- rns -> rns_cong_generation = ((atomic_t ) { (0 ) });
502
- rds_cong_monitor_init (rns );
503
- spin_lock_init (& rns -> rns_cong_lock );
504
- rns -> rns_cong_tree = RB_ROOT ;
505
-
506
- return 0 ;
507
500
}
508
501
509
502
/*
0 commit comments