@@ -54,14 +54,34 @@ static void cache_init(struct cache_head *h, struct cache_detail *detail)
54
54
h -> last_refresh = now ;
55
55
}
56
56
57
+ static struct cache_head * sunrpc_cache_find_rcu (struct cache_detail * detail ,
58
+ struct cache_head * key ,
59
+ int hash )
60
+ {
61
+ struct hlist_head * head = & detail -> hash_table [hash ];
62
+ struct cache_head * tmp ;
63
+
64
+ rcu_read_lock ();
65
+ hlist_for_each_entry_rcu (tmp , head , cache_list ) {
66
+ if (detail -> match (tmp , key )) {
67
+ if (cache_is_expired (detail , tmp ))
68
+ continue ;
69
+ tmp = cache_get_rcu (tmp );
70
+ rcu_read_unlock ();
71
+ return tmp ;
72
+ }
73
+ }
74
+ rcu_read_unlock ();
75
+ return NULL ;
76
+ }
77
+
57
78
static struct cache_head * sunrpc_cache_find (struct cache_detail * detail ,
58
79
struct cache_head * key , int hash )
59
80
{
60
81
struct hlist_head * head = & detail -> hash_table [hash ];
61
82
struct cache_head * tmp ;
62
83
63
84
read_lock (& detail -> hash_lock );
64
-
65
85
hlist_for_each_entry (tmp , head , cache_list ) {
66
86
if (detail -> match (tmp , key )) {
67
87
if (cache_is_expired (detail , tmp ))
@@ -96,10 +116,10 @@ static struct cache_head *sunrpc_cache_add_entry(struct cache_detail *detail,
96
116
write_lock (& detail -> hash_lock );
97
117
98
118
/* check if entry appeared while we slept */
99
- hlist_for_each_entry (tmp , head , cache_list ) {
119
+ hlist_for_each_entry_rcu (tmp , head , cache_list ) {
100
120
if (detail -> match (tmp , key )) {
101
121
if (cache_is_expired (detail , tmp )) {
102
- hlist_del_init (& tmp -> cache_list );
122
+ hlist_del_init_rcu (& tmp -> cache_list );
103
123
detail -> entries -- ;
104
124
freeme = tmp ;
105
125
break ;
@@ -111,7 +131,7 @@ static struct cache_head *sunrpc_cache_add_entry(struct cache_detail *detail,
111
131
}
112
132
}
113
133
114
- hlist_add_head (& new -> cache_list , head );
134
+ hlist_add_head_rcu (& new -> cache_list , head );
115
135
detail -> entries ++ ;
116
136
cache_get (new );
117
137
write_unlock (& detail -> hash_lock );
@@ -121,6 +141,19 @@ static struct cache_head *sunrpc_cache_add_entry(struct cache_detail *detail,
121
141
return new ;
122
142
}
123
143
144
+ struct cache_head * sunrpc_cache_lookup_rcu (struct cache_detail * detail ,
145
+ struct cache_head * key , int hash )
146
+ {
147
+ struct cache_head * ret ;
148
+
149
+ ret = sunrpc_cache_find_rcu (detail , key , hash );
150
+ if (ret )
151
+ return ret ;
152
+ /* Didn't find anything, insert an empty entry */
153
+ return sunrpc_cache_add_entry (detail , key , hash );
154
+ }
155
+ EXPORT_SYMBOL_GPL (sunrpc_cache_lookup_rcu );
156
+
124
157
struct cache_head * sunrpc_cache_lookup (struct cache_detail * detail ,
125
158
struct cache_head * key , int hash )
126
159
{
@@ -134,6 +167,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
134
167
}
135
168
EXPORT_SYMBOL_GPL (sunrpc_cache_lookup );
136
169
170
+
137
171
static void cache_dequeue (struct cache_detail * detail , struct cache_head * ch );
138
172
139
173
static void cache_fresh_locked (struct cache_head * head , time_t expiry ,
@@ -450,7 +484,7 @@ static int cache_clean(void)
450
484
if (!cache_is_expired (current_detail , ch ))
451
485
continue ;
452
486
453
- hlist_del_init (& ch -> cache_list );
487
+ hlist_del_init_rcu (& ch -> cache_list );
454
488
current_detail -> entries -- ;
455
489
rv = 1 ;
456
490
break ;
@@ -521,7 +555,7 @@ void cache_purge(struct cache_detail *detail)
521
555
for (i = 0 ; i < detail -> hash_size ; i ++ ) {
522
556
head = & detail -> hash_table [i ];
523
557
hlist_for_each_entry_safe (ch , tmp , head , cache_list ) {
524
- hlist_del_init (& ch -> cache_list );
558
+ hlist_del_init_rcu (& ch -> cache_list );
525
559
detail -> entries -- ;
526
560
527
561
set_bit (CACHE_CLEANED , & ch -> flags );
@@ -1306,21 +1340,19 @@ EXPORT_SYMBOL_GPL(qword_get);
1306
1340
* get a header, then pass each real item in the cache
1307
1341
*/
1308
1342
1309
- void * cache_seq_start (struct seq_file * m , loff_t * pos )
1310
- __acquires (cd - > hash_lock )
1343
+ static void * __cache_seq_start (struct seq_file * m , loff_t * pos )
1311
1344
{
1312
1345
loff_t n = * pos ;
1313
1346
unsigned int hash , entry ;
1314
1347
struct cache_head * ch ;
1315
1348
struct cache_detail * cd = m -> private ;
1316
1349
1317
- read_lock (& cd -> hash_lock );
1318
1350
if (!n -- )
1319
1351
return SEQ_START_TOKEN ;
1320
1352
hash = n >> 32 ;
1321
1353
entry = n & ((1LL <<32 ) - 1 );
1322
1354
1323
- hlist_for_each_entry (ch , & cd -> hash_table [hash ], cache_list )
1355
+ hlist_for_each_entry_rcu (ch , & cd -> hash_table [hash ], cache_list )
1324
1356
if (!entry -- )
1325
1357
return ch ;
1326
1358
n &= ~((1LL <<32 ) - 1 );
@@ -1332,9 +1364,19 @@ void *cache_seq_start(struct seq_file *m, loff_t *pos)
1332
1364
if (hash >= cd -> hash_size )
1333
1365
return NULL ;
1334
1366
* pos = n + 1 ;
1335
- return hlist_entry_safe (cd -> hash_table [hash ].first ,
1367
+ return hlist_entry_safe (rcu_dereference_raw (
1368
+ hlist_first_rcu (& cd -> hash_table [hash ])),
1336
1369
struct cache_head , cache_list );
1337
1370
}
1371
+
1372
+ void * cache_seq_start (struct seq_file * m , loff_t * pos )
1373
+ __acquires (cd - > hash_lock )
1374
+ {
1375
+ struct cache_detail * cd = m -> private ;
1376
+
1377
+ read_lock (& cd -> hash_lock );
1378
+ return __cache_seq_start (m , pos );
1379
+ }
1338
1380
EXPORT_SYMBOL_GPL (cache_seq_start );
1339
1381
1340
1382
void * cache_seq_next (struct seq_file * m , void * p , loff_t * pos )
@@ -1350,7 +1392,8 @@ void *cache_seq_next(struct seq_file *m, void *p, loff_t *pos)
1350
1392
* pos += 1LL <<32 ;
1351
1393
} else {
1352
1394
++ * pos ;
1353
- return hlist_entry_safe (ch -> cache_list .next ,
1395
+ return hlist_entry_safe (rcu_dereference_raw (
1396
+ hlist_next_rcu (& ch -> cache_list )),
1354
1397
struct cache_head , cache_list );
1355
1398
}
1356
1399
* pos &= ~((1LL <<32 ) - 1 );
@@ -1362,7 +1405,8 @@ void *cache_seq_next(struct seq_file *m, void *p, loff_t *pos)
1362
1405
if (hash >= cd -> hash_size )
1363
1406
return NULL ;
1364
1407
++ * pos ;
1365
- return hlist_entry_safe (cd -> hash_table [hash ].first ,
1408
+ return hlist_entry_safe (rcu_dereference_raw (
1409
+ hlist_first_rcu (& cd -> hash_table [hash ])),
1366
1410
struct cache_head , cache_list );
1367
1411
}
1368
1412
EXPORT_SYMBOL_GPL (cache_seq_next );
@@ -1375,6 +1419,27 @@ void cache_seq_stop(struct seq_file *m, void *p)
1375
1419
}
1376
1420
EXPORT_SYMBOL_GPL (cache_seq_stop );
1377
1421
1422
+ void * cache_seq_start_rcu (struct seq_file * m , loff_t * pos )
1423
+ __acquires (RCU )
1424
+ {
1425
+ rcu_read_lock ();
1426
+ return __cache_seq_start (m , pos );
1427
+ }
1428
+ EXPORT_SYMBOL_GPL (cache_seq_start_rcu );
1429
+
1430
+ void * cache_seq_next_rcu (struct seq_file * file , void * p , loff_t * pos )
1431
+ {
1432
+ return cache_seq_next (file , p , pos );
1433
+ }
1434
+ EXPORT_SYMBOL_GPL (cache_seq_next_rcu );
1435
+
1436
+ void cache_seq_stop_rcu (struct seq_file * m , void * p )
1437
+ __releases (RCU )
1438
+ {
1439
+ rcu_read_unlock ();
1440
+ }
1441
+ EXPORT_SYMBOL_GPL (cache_seq_stop_rcu );
1442
+
1378
1443
static int c_show (struct seq_file * m , void * p )
1379
1444
{
1380
1445
struct cache_head * cp = p ;
@@ -1863,7 +1928,7 @@ void sunrpc_cache_unhash(struct cache_detail *cd, struct cache_head *h)
1863
1928
{
1864
1929
write_lock (& cd -> hash_lock );
1865
1930
if (!hlist_unhashed (& h -> cache_list )){
1866
- hlist_del_init (& h -> cache_list );
1931
+ hlist_del_init_rcu (& h -> cache_list );
1867
1932
cd -> entries -- ;
1868
1933
write_unlock (& cd -> hash_lock );
1869
1934
cache_put (h , cd );
0 commit comments