@@ -251,7 +251,8 @@ bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
251
251
252
252
static int neigh_forced_gc (struct neigh_table * tbl )
253
253
{
254
- int max_clean = atomic_read (& tbl -> gc_entries ) - tbl -> gc_thresh2 ;
254
+ int max_clean = atomic_read (& tbl -> gc_entries ) -
255
+ READ_ONCE (tbl -> gc_thresh2 );
255
256
unsigned long tref = jiffies - 5 * HZ ;
256
257
struct neighbour * n , * tmp ;
257
258
int shrunk = 0 ;
@@ -280,7 +281,7 @@ static int neigh_forced_gc(struct neigh_table *tbl)
280
281
}
281
282
}
282
283
283
- tbl -> last_flush = jiffies ;
284
+ WRITE_ONCE ( tbl -> last_flush , jiffies ) ;
284
285
285
286
write_unlock_bh (& tbl -> lock );
286
287
@@ -464,17 +465,17 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl,
464
465
{
465
466
struct neighbour * n = NULL ;
466
467
unsigned long now = jiffies ;
467
- int entries ;
468
+ int entries , gc_thresh3 ;
468
469
469
470
if (exempt_from_gc )
470
471
goto do_alloc ;
471
472
472
473
entries = atomic_inc_return (& tbl -> gc_entries ) - 1 ;
473
- if ( entries >= tbl -> gc_thresh3 ||
474
- (entries >= tbl -> gc_thresh2 &&
475
- time_after ( now , tbl -> last_flush + 5 * HZ ))) {
476
- if (! neigh_forced_gc (tbl ) &&
477
- entries >= tbl -> gc_thresh3 ) {
474
+ gc_thresh3 = READ_ONCE ( tbl -> gc_thresh3 );
475
+ if (entries >= gc_thresh3 ||
476
+ ( entries >= READ_ONCE ( tbl -> gc_thresh2 ) &&
477
+ time_after ( now , READ_ONCE (tbl -> last_flush ) + 5 * HZ ))) {
478
+ if (! neigh_forced_gc ( tbl ) && entries >= gc_thresh3 ) {
478
479
net_info_ratelimited ("%s: neighbor table overflow!\n" ,
479
480
tbl -> id );
480
481
NEIGH_CACHE_STAT_INC (tbl , table_fulls );
@@ -955,13 +956,14 @@ static void neigh_periodic_work(struct work_struct *work)
955
956
956
957
if (time_after (jiffies , tbl -> last_rand + 300 * HZ )) {
957
958
struct neigh_parms * p ;
958
- tbl -> last_rand = jiffies ;
959
+
960
+ WRITE_ONCE (tbl -> last_rand , jiffies );
959
961
list_for_each_entry (p , & tbl -> parms_list , list )
960
962
p -> reachable_time =
961
963
neigh_rand_reach_time (NEIGH_VAR (p , BASE_REACHABLE_TIME ));
962
964
}
963
965
964
- if (atomic_read (& tbl -> entries ) < tbl -> gc_thresh1 )
966
+ if (atomic_read (& tbl -> entries ) < READ_ONCE ( tbl -> gc_thresh1 ) )
965
967
goto out ;
966
968
967
969
for (i = 0 ; i < (1 << nht -> hash_shift ); i ++ ) {
@@ -2167,23 +2169,24 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
2167
2169
ndtmsg -> ndtm_pad2 = 0 ;
2168
2170
2169
2171
if (nla_put_string (skb , NDTA_NAME , tbl -> id ) ||
2170
- nla_put_msecs (skb , NDTA_GC_INTERVAL , tbl -> gc_interval , NDTA_PAD ) ||
2171
- nla_put_u32 (skb , NDTA_THRESH1 , tbl -> gc_thresh1 ) ||
2172
- nla_put_u32 (skb , NDTA_THRESH2 , tbl -> gc_thresh2 ) ||
2173
- nla_put_u32 (skb , NDTA_THRESH3 , tbl -> gc_thresh3 ))
2172
+ nla_put_msecs (skb , NDTA_GC_INTERVAL , READ_ONCE (tbl -> gc_interval ),
2173
+ NDTA_PAD ) ||
2174
+ nla_put_u32 (skb , NDTA_THRESH1 , READ_ONCE (tbl -> gc_thresh1 )) ||
2175
+ nla_put_u32 (skb , NDTA_THRESH2 , READ_ONCE (tbl -> gc_thresh2 )) ||
2176
+ nla_put_u32 (skb , NDTA_THRESH3 , READ_ONCE (tbl -> gc_thresh3 )))
2174
2177
goto nla_put_failure ;
2175
2178
{
2176
2179
unsigned long now = jiffies ;
2177
- long flush_delta = now - tbl -> last_flush ;
2178
- long rand_delta = now - tbl -> last_rand ;
2180
+ long flush_delta = now - READ_ONCE ( tbl -> last_flush ) ;
2181
+ long rand_delta = now - READ_ONCE ( tbl -> last_rand ) ;
2179
2182
struct neigh_hash_table * nht ;
2180
2183
struct ndt_config ndc = {
2181
2184
.ndtc_key_len = tbl -> key_len ,
2182
2185
.ndtc_entry_size = tbl -> entry_size ,
2183
2186
.ndtc_entries = atomic_read (& tbl -> entries ),
2184
2187
.ndtc_last_flush = jiffies_to_msecs (flush_delta ),
2185
2188
.ndtc_last_rand = jiffies_to_msecs (rand_delta ),
2186
- .ndtc_proxy_qlen = tbl -> proxy_queue .qlen ,
2189
+ .ndtc_proxy_qlen = READ_ONCE ( tbl -> proxy_queue .qlen ) ,
2187
2190
};
2188
2191
2189
2192
rcu_read_lock ();
@@ -2206,17 +2209,17 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
2206
2209
struct neigh_statistics * st ;
2207
2210
2208
2211
st = per_cpu_ptr (tbl -> stats , cpu );
2209
- ndst .ndts_allocs += st -> allocs ;
2210
- ndst .ndts_destroys += st -> destroys ;
2211
- ndst .ndts_hash_grows += st -> hash_grows ;
2212
- ndst .ndts_res_failed += st -> res_failed ;
2213
- ndst .ndts_lookups += st -> lookups ;
2214
- ndst .ndts_hits += st -> hits ;
2215
- ndst .ndts_rcv_probes_mcast += st -> rcv_probes_mcast ;
2216
- ndst .ndts_rcv_probes_ucast += st -> rcv_probes_ucast ;
2217
- ndst .ndts_periodic_gc_runs += st -> periodic_gc_runs ;
2218
- ndst .ndts_forced_gc_runs += st -> forced_gc_runs ;
2219
- ndst .ndts_table_fulls += st -> table_fulls ;
2212
+ ndst .ndts_allocs += READ_ONCE ( st -> allocs ) ;
2213
+ ndst .ndts_destroys += READ_ONCE ( st -> destroys ) ;
2214
+ ndst .ndts_hash_grows += READ_ONCE ( st -> hash_grows ) ;
2215
+ ndst .ndts_res_failed += READ_ONCE ( st -> res_failed ) ;
2216
+ ndst .ndts_lookups += READ_ONCE ( st -> lookups ) ;
2217
+ ndst .ndts_hits += READ_ONCE ( st -> hits ) ;
2218
+ ndst .ndts_rcv_probes_mcast += READ_ONCE ( st -> rcv_probes_mcast ) ;
2219
+ ndst .ndts_rcv_probes_ucast += READ_ONCE ( st -> rcv_probes_ucast ) ;
2220
+ ndst .ndts_periodic_gc_runs += READ_ONCE ( st -> periodic_gc_runs ) ;
2221
+ ndst .ndts_forced_gc_runs += READ_ONCE ( st -> forced_gc_runs ) ;
2222
+ ndst .ndts_table_fulls += READ_ONCE ( st -> table_fulls ) ;
2220
2223
}
2221
2224
2222
2225
if (nla_put_64bit (skb , NDTA_STATS , sizeof (ndst ), & ndst ,
@@ -2445,16 +2448,16 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
2445
2448
goto errout_tbl_lock ;
2446
2449
2447
2450
if (tb [NDTA_THRESH1 ])
2448
- tbl -> gc_thresh1 = nla_get_u32 (tb [NDTA_THRESH1 ]);
2451
+ WRITE_ONCE ( tbl -> gc_thresh1 , nla_get_u32 (tb [NDTA_THRESH1 ]) );
2449
2452
2450
2453
if (tb [NDTA_THRESH2 ])
2451
- tbl -> gc_thresh2 = nla_get_u32 (tb [NDTA_THRESH2 ]);
2454
+ WRITE_ONCE ( tbl -> gc_thresh2 , nla_get_u32 (tb [NDTA_THRESH2 ]) );
2452
2455
2453
2456
if (tb [NDTA_THRESH3 ])
2454
- tbl -> gc_thresh3 = nla_get_u32 (tb [NDTA_THRESH3 ]);
2457
+ WRITE_ONCE ( tbl -> gc_thresh3 , nla_get_u32 (tb [NDTA_THRESH3 ]) );
2455
2458
2456
2459
if (tb [NDTA_GC_INTERVAL ])
2457
- tbl -> gc_interval = nla_get_msecs (tb [NDTA_GC_INTERVAL ]);
2460
+ WRITE_ONCE ( tbl -> gc_interval , nla_get_msecs (tb [NDTA_GC_INTERVAL ]) );
2458
2461
2459
2462
err = 0 ;
2460
2463
0 commit comments