34
34
35
35
#define xfrm_state_deref_prot (table , net ) \
36
36
rcu_dereference_protected((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock))
37
+ #define xfrm_state_deref_check (table , net ) \
38
+ rcu_dereference_check((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock))
37
39
38
40
static void xfrm_state_gc_task (struct work_struct * work );
39
41
@@ -62,6 +64,8 @@ static inline unsigned int xfrm_dst_hash(struct net *net,
62
64
u32 reqid ,
63
65
unsigned short family )
64
66
{
67
+ lockdep_assert_held (& net -> xfrm .xfrm_state_lock );
68
+
65
69
return __xfrm_dst_hash (daddr , saddr , reqid , family , net -> xfrm .state_hmask );
66
70
}
67
71
@@ -70,18 +74,24 @@ static inline unsigned int xfrm_src_hash(struct net *net,
70
74
const xfrm_address_t * saddr ,
71
75
unsigned short family )
72
76
{
77
+ lockdep_assert_held (& net -> xfrm .xfrm_state_lock );
78
+
73
79
return __xfrm_src_hash (daddr , saddr , family , net -> xfrm .state_hmask );
74
80
}
75
81
76
82
static inline unsigned int
77
83
xfrm_spi_hash (struct net * net , const xfrm_address_t * daddr ,
78
84
__be32 spi , u8 proto , unsigned short family )
79
85
{
86
+ lockdep_assert_held (& net -> xfrm .xfrm_state_lock );
87
+
80
88
return __xfrm_spi_hash (daddr , spi , proto , family , net -> xfrm .state_hmask );
81
89
}
82
90
83
91
static unsigned int xfrm_seq_hash (struct net * net , u32 seq )
84
92
{
93
+ lockdep_assert_held (& net -> xfrm .xfrm_state_lock );
94
+
85
95
return __xfrm_seq_hash (seq , net -> xfrm .state_hmask );
86
96
}
87
97
@@ -1108,16 +1118,38 @@ xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl,
1108
1118
x -> props .family = tmpl -> encap_family ;
1109
1119
}
1110
1120
1111
- static struct xfrm_state * __xfrm_state_lookup_all (struct net * net , u32 mark ,
1121
+ struct xfrm_hash_state_ptrs {
1122
+ const struct hlist_head * bydst ;
1123
+ const struct hlist_head * bysrc ;
1124
+ const struct hlist_head * byspi ;
1125
+ unsigned int hmask ;
1126
+ };
1127
+
1128
+ static void xfrm_hash_ptrs_get (const struct net * net , struct xfrm_hash_state_ptrs * ptrs )
1129
+ {
1130
+ unsigned int sequence ;
1131
+
1132
+ do {
1133
+ sequence = read_seqcount_begin (& net -> xfrm .xfrm_state_hash_generation );
1134
+
1135
+ ptrs -> bydst = xfrm_state_deref_check (net -> xfrm .state_bydst , net );
1136
+ ptrs -> bysrc = xfrm_state_deref_check (net -> xfrm .state_bysrc , net );
1137
+ ptrs -> byspi = xfrm_state_deref_check (net -> xfrm .state_byspi , net );
1138
+ ptrs -> hmask = net -> xfrm .state_hmask ;
1139
+ } while (read_seqcount_retry (& net -> xfrm .xfrm_state_hash_generation , sequence ));
1140
+ }
1141
+
1142
+ static struct xfrm_state * __xfrm_state_lookup_all (const struct xfrm_hash_state_ptrs * state_ptrs ,
1143
+ u32 mark ,
1112
1144
const xfrm_address_t * daddr ,
1113
1145
__be32 spi , u8 proto ,
1114
1146
unsigned short family ,
1115
1147
struct xfrm_dev_offload * xdo )
1116
1148
{
1117
- unsigned int h = xfrm_spi_hash ( net , daddr , spi , proto , family );
1149
+ unsigned int h = __xfrm_spi_hash ( daddr , spi , proto , family , state_ptrs -> hmask );
1118
1150
struct xfrm_state * x ;
1119
1151
1120
- hlist_for_each_entry_rcu (x , net -> xfrm . state_byspi + h , byspi ) {
1152
+ hlist_for_each_entry_rcu (x , state_ptrs -> byspi + h , byspi ) {
1121
1153
#ifdef CONFIG_XFRM_OFFLOAD
1122
1154
if (xdo -> type == XFRM_DEV_OFFLOAD_PACKET ) {
1123
1155
if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1151,15 +1183,16 @@ static struct xfrm_state *__xfrm_state_lookup_all(struct net *net, u32 mark,
1151
1183
return NULL ;
1152
1184
}
1153
1185
1154
- static struct xfrm_state * __xfrm_state_lookup (struct net * net , u32 mark ,
1186
+ static struct xfrm_state * __xfrm_state_lookup (const struct xfrm_hash_state_ptrs * state_ptrs ,
1187
+ u32 mark ,
1155
1188
const xfrm_address_t * daddr ,
1156
1189
__be32 spi , u8 proto ,
1157
1190
unsigned short family )
1158
1191
{
1159
- unsigned int h = xfrm_spi_hash ( net , daddr , spi , proto , family );
1192
+ unsigned int h = __xfrm_spi_hash ( daddr , spi , proto , family , state_ptrs -> hmask );
1160
1193
struct xfrm_state * x ;
1161
1194
1162
- hlist_for_each_entry_rcu (x , net -> xfrm . state_byspi + h , byspi ) {
1195
+ hlist_for_each_entry_rcu (x , state_ptrs -> byspi + h , byspi ) {
1163
1196
if (x -> props .family != family ||
1164
1197
x -> id .spi != spi ||
1165
1198
x -> id .proto != proto ||
@@ -1181,11 +1214,11 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
1181
1214
__be32 spi , u8 proto ,
1182
1215
unsigned short family )
1183
1216
{
1217
+ struct xfrm_hash_state_ptrs state_ptrs ;
1184
1218
struct hlist_head * state_cache_input ;
1185
1219
struct xfrm_state * x = NULL ;
1186
- int cpu = get_cpu ();
1187
1220
1188
- state_cache_input = per_cpu_ptr (net -> xfrm .state_cache_input , cpu );
1221
+ state_cache_input = raw_cpu_ptr (net -> xfrm .state_cache_input );
1189
1222
1190
1223
rcu_read_lock ();
1191
1224
hlist_for_each_entry_rcu (x , state_cache_input , state_cache_input ) {
@@ -1202,7 +1235,9 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
1202
1235
goto out ;
1203
1236
}
1204
1237
1205
- x = __xfrm_state_lookup (net , mark , daddr , spi , proto , family );
1238
+ xfrm_hash_ptrs_get (net , & state_ptrs );
1239
+
1240
+ x = __xfrm_state_lookup (& state_ptrs , mark , daddr , spi , proto , family );
1206
1241
1207
1242
if (x && x -> km .state == XFRM_STATE_VALID ) {
1208
1243
spin_lock_bh (& net -> xfrm .xfrm_state_lock );
@@ -1217,20 +1252,20 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
1217
1252
1218
1253
out :
1219
1254
rcu_read_unlock ();
1220
- put_cpu ();
1221
1255
return x ;
1222
1256
}
1223
1257
EXPORT_SYMBOL (xfrm_input_state_lookup );
1224
1258
1225
- static struct xfrm_state * __xfrm_state_lookup_byaddr (struct net * net , u32 mark ,
1259
+ static struct xfrm_state * __xfrm_state_lookup_byaddr (const struct xfrm_hash_state_ptrs * state_ptrs ,
1260
+ u32 mark ,
1226
1261
const xfrm_address_t * daddr ,
1227
1262
const xfrm_address_t * saddr ,
1228
1263
u8 proto , unsigned short family )
1229
1264
{
1230
- unsigned int h = xfrm_src_hash ( net , daddr , saddr , family );
1265
+ unsigned int h = __xfrm_src_hash ( daddr , saddr , family , state_ptrs -> hmask );
1231
1266
struct xfrm_state * x ;
1232
1267
1233
- hlist_for_each_entry_rcu (x , net -> xfrm . state_bysrc + h , bysrc ) {
1268
+ hlist_for_each_entry_rcu (x , state_ptrs -> bysrc + h , bysrc ) {
1234
1269
if (x -> props .family != family ||
1235
1270
x -> id .proto != proto ||
1236
1271
!xfrm_addr_equal (& x -> id .daddr , daddr , family ) ||
@@ -1250,14 +1285,17 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1250
1285
static inline struct xfrm_state *
1251
1286
__xfrm_state_locate (struct xfrm_state * x , int use_spi , int family )
1252
1287
{
1288
+ struct xfrm_hash_state_ptrs state_ptrs ;
1253
1289
struct net * net = xs_net (x );
1254
1290
u32 mark = x -> mark .v & x -> mark .m ;
1255
1291
1292
+ xfrm_hash_ptrs_get (net , & state_ptrs );
1293
+
1256
1294
if (use_spi )
1257
- return __xfrm_state_lookup (net , mark , & x -> id .daddr ,
1295
+ return __xfrm_state_lookup (& state_ptrs , mark , & x -> id .daddr ,
1258
1296
x -> id .spi , x -> id .proto , family );
1259
1297
else
1260
- return __xfrm_state_lookup_byaddr (net , mark ,
1298
+ return __xfrm_state_lookup_byaddr (& state_ptrs , mark ,
1261
1299
& x -> id .daddr ,
1262
1300
& x -> props .saddr ,
1263
1301
x -> id .proto , family );
@@ -1331,6 +1369,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
1331
1369
unsigned short family , u32 if_id )
1332
1370
{
1333
1371
static xfrm_address_t saddr_wildcard = { };
1372
+ struct xfrm_hash_state_ptrs state_ptrs ;
1334
1373
struct net * net = xp_net (pol );
1335
1374
unsigned int h , h_wildcard ;
1336
1375
struct xfrm_state * x , * x0 , * to_put ;
@@ -1395,8 +1434,10 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
1395
1434
else if (acquire_in_progress ) /* XXX: acquire_in_progress should not happen */
1396
1435
WARN_ON (1 );
1397
1436
1398
- h = xfrm_dst_hash (net , daddr , saddr , tmpl -> reqid , encap_family );
1399
- hlist_for_each_entry_rcu (x , net -> xfrm .state_bydst + h , bydst ) {
1437
+ xfrm_hash_ptrs_get (net , & state_ptrs );
1438
+
1439
+ h = __xfrm_dst_hash (daddr , saddr , tmpl -> reqid , encap_family , state_ptrs .hmask );
1440
+ hlist_for_each_entry_rcu (x , state_ptrs .bydst + h , bydst ) {
1400
1441
#ifdef CONFIG_XFRM_OFFLOAD
1401
1442
if (pol -> xdo .type == XFRM_DEV_OFFLOAD_PACKET ) {
1402
1443
if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1429,8 +1470,9 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
1429
1470
if (best || acquire_in_progress )
1430
1471
goto found ;
1431
1472
1432
- h_wildcard = xfrm_dst_hash (net , daddr , & saddr_wildcard , tmpl -> reqid , encap_family );
1433
- hlist_for_each_entry_rcu (x , net -> xfrm .state_bydst + h_wildcard , bydst ) {
1473
+ h_wildcard = __xfrm_dst_hash (daddr , & saddr_wildcard , tmpl -> reqid ,
1474
+ encap_family , state_ptrs .hmask );
1475
+ hlist_for_each_entry_rcu (x , state_ptrs .bydst + h_wildcard , bydst ) {
1434
1476
#ifdef CONFIG_XFRM_OFFLOAD
1435
1477
if (pol -> xdo .type == XFRM_DEV_OFFLOAD_PACKET ) {
1436
1478
if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1468,7 +1510,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
1468
1510
1469
1511
if (!x && !error && !acquire_in_progress ) {
1470
1512
if (tmpl -> id .spi &&
1471
- (x0 = __xfrm_state_lookup_all (net , mark , daddr ,
1513
+ (x0 = __xfrm_state_lookup_all (& state_ptrs , mark , daddr ,
1472
1514
tmpl -> id .spi , tmpl -> id .proto ,
1473
1515
encap_family ,
1474
1516
& pol -> xdo )) != NULL ) {
@@ -2253,10 +2295,13 @@ struct xfrm_state *
2253
2295
xfrm_state_lookup (struct net * net , u32 mark , const xfrm_address_t * daddr , __be32 spi ,
2254
2296
u8 proto , unsigned short family )
2255
2297
{
2298
+ struct xfrm_hash_state_ptrs state_ptrs ;
2256
2299
struct xfrm_state * x ;
2257
2300
2258
2301
rcu_read_lock ();
2259
- x = __xfrm_state_lookup (net , mark , daddr , spi , proto , family );
2302
+ xfrm_hash_ptrs_get (net , & state_ptrs );
2303
+
2304
+ x = __xfrm_state_lookup (& state_ptrs , mark , daddr , spi , proto , family );
2260
2305
rcu_read_unlock ();
2261
2306
return x ;
2262
2307
}
@@ -2267,10 +2312,14 @@ xfrm_state_lookup_byaddr(struct net *net, u32 mark,
2267
2312
const xfrm_address_t * daddr , const xfrm_address_t * saddr ,
2268
2313
u8 proto , unsigned short family )
2269
2314
{
2315
+ struct xfrm_hash_state_ptrs state_ptrs ;
2270
2316
struct xfrm_state * x ;
2271
2317
2272
2318
spin_lock_bh (& net -> xfrm .xfrm_state_lock );
2273
- x = __xfrm_state_lookup_byaddr (net , mark , daddr , saddr , proto , family );
2319
+
2320
+ xfrm_hash_ptrs_get (net , & state_ptrs );
2321
+
2322
+ x = __xfrm_state_lookup_byaddr (& state_ptrs , mark , daddr , saddr , proto , family );
2274
2323
spin_unlock_bh (& net -> xfrm .xfrm_state_lock );
2275
2324
return x ;
2276
2325
}
0 commit comments