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
@@ -1041,16 +1051,38 @@ xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl,
1041
1051
x -> props .family = tmpl -> encap_family ;
1042
1052
}
1043
1053
1044
- static struct xfrm_state * __xfrm_state_lookup_all (struct net * net , u32 mark ,
1054
+ struct xfrm_hash_state_ptrs {
1055
+ const struct hlist_head * bydst ;
1056
+ const struct hlist_head * bysrc ;
1057
+ const struct hlist_head * byspi ;
1058
+ unsigned int hmask ;
1059
+ };
1060
+
1061
+ static void xfrm_hash_ptrs_get (const struct net * net , struct xfrm_hash_state_ptrs * ptrs )
1062
+ {
1063
+ unsigned int sequence ;
1064
+
1065
+ do {
1066
+ sequence = read_seqcount_begin (& net -> xfrm .xfrm_state_hash_generation );
1067
+
1068
+ ptrs -> bydst = xfrm_state_deref_check (net -> xfrm .state_bydst , net );
1069
+ ptrs -> bysrc = xfrm_state_deref_check (net -> xfrm .state_bysrc , net );
1070
+ ptrs -> byspi = xfrm_state_deref_check (net -> xfrm .state_byspi , net );
1071
+ ptrs -> hmask = net -> xfrm .state_hmask ;
1072
+ } while (read_seqcount_retry (& net -> xfrm .xfrm_state_hash_generation , sequence ));
1073
+ }
1074
+
1075
+ static struct xfrm_state * __xfrm_state_lookup_all (const struct xfrm_hash_state_ptrs * state_ptrs ,
1076
+ u32 mark ,
1045
1077
const xfrm_address_t * daddr ,
1046
1078
__be32 spi , u8 proto ,
1047
1079
unsigned short family ,
1048
1080
struct xfrm_dev_offload * xdo )
1049
1081
{
1050
- unsigned int h = xfrm_spi_hash ( net , daddr , spi , proto , family );
1082
+ unsigned int h = __xfrm_spi_hash ( daddr , spi , proto , family , state_ptrs -> hmask );
1051
1083
struct xfrm_state * x ;
1052
1084
1053
- hlist_for_each_entry_rcu (x , net -> xfrm . state_byspi + h , byspi ) {
1085
+ hlist_for_each_entry_rcu (x , state_ptrs -> byspi + h , byspi ) {
1054
1086
#ifdef CONFIG_XFRM_OFFLOAD
1055
1087
if (xdo -> type == XFRM_DEV_OFFLOAD_PACKET ) {
1056
1088
if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1084,15 +1116,16 @@ static struct xfrm_state *__xfrm_state_lookup_all(struct net *net, u32 mark,
1084
1116
return NULL ;
1085
1117
}
1086
1118
1087
- static struct xfrm_state * __xfrm_state_lookup (struct net * net , u32 mark ,
1119
+ static struct xfrm_state * __xfrm_state_lookup (const struct xfrm_hash_state_ptrs * state_ptrs ,
1120
+ u32 mark ,
1088
1121
const xfrm_address_t * daddr ,
1089
1122
__be32 spi , u8 proto ,
1090
1123
unsigned short family )
1091
1124
{
1092
- unsigned int h = xfrm_spi_hash ( net , daddr , spi , proto , family );
1125
+ unsigned int h = __xfrm_spi_hash ( daddr , spi , proto , family , state_ptrs -> hmask );
1093
1126
struct xfrm_state * x ;
1094
1127
1095
- hlist_for_each_entry_rcu (x , net -> xfrm . state_byspi + h , byspi ) {
1128
+ hlist_for_each_entry_rcu (x , state_ptrs -> byspi + h , byspi ) {
1096
1129
if (x -> props .family != family ||
1097
1130
x -> id .spi != spi ||
1098
1131
x -> id .proto != proto ||
@@ -1114,6 +1147,7 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
1114
1147
__be32 spi , u8 proto ,
1115
1148
unsigned short family )
1116
1149
{
1150
+ struct xfrm_hash_state_ptrs state_ptrs ;
1117
1151
struct hlist_head * state_cache_input ;
1118
1152
struct xfrm_state * x = NULL ;
1119
1153
int cpu = get_cpu ();
@@ -1135,7 +1169,9 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
1135
1169
goto out ;
1136
1170
}
1137
1171
1138
- x = __xfrm_state_lookup (net , mark , daddr , spi , proto , family );
1172
+ xfrm_hash_ptrs_get (net , & state_ptrs );
1173
+
1174
+ x = __xfrm_state_lookup (& state_ptrs , mark , daddr , spi , proto , family );
1139
1175
1140
1176
if (x && x -> km .state == XFRM_STATE_VALID ) {
1141
1177
spin_lock_bh (& net -> xfrm .xfrm_state_lock );
@@ -1155,15 +1191,16 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
1155
1191
}
1156
1192
EXPORT_SYMBOL (xfrm_input_state_lookup );
1157
1193
1158
- static struct xfrm_state * __xfrm_state_lookup_byaddr (struct net * net , u32 mark ,
1194
+ static struct xfrm_state * __xfrm_state_lookup_byaddr (const struct xfrm_hash_state_ptrs * state_ptrs ,
1195
+ u32 mark ,
1159
1196
const xfrm_address_t * daddr ,
1160
1197
const xfrm_address_t * saddr ,
1161
1198
u8 proto , unsigned short family )
1162
1199
{
1163
- unsigned int h = xfrm_src_hash ( net , daddr , saddr , family );
1200
+ unsigned int h = __xfrm_src_hash ( daddr , saddr , family , state_ptrs -> hmask );
1164
1201
struct xfrm_state * x ;
1165
1202
1166
- hlist_for_each_entry_rcu (x , net -> xfrm . state_bysrc + h , bysrc ) {
1203
+ hlist_for_each_entry_rcu (x , state_ptrs -> bysrc + h , bysrc ) {
1167
1204
if (x -> props .family != family ||
1168
1205
x -> id .proto != proto ||
1169
1206
!xfrm_addr_equal (& x -> id .daddr , daddr , family ) ||
@@ -1183,14 +1220,17 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
1183
1220
static inline struct xfrm_state *
1184
1221
__xfrm_state_locate (struct xfrm_state * x , int use_spi , int family )
1185
1222
{
1223
+ struct xfrm_hash_state_ptrs state_ptrs ;
1186
1224
struct net * net = xs_net (x );
1187
1225
u32 mark = x -> mark .v & x -> mark .m ;
1188
1226
1227
+ xfrm_hash_ptrs_get (net , & state_ptrs );
1228
+
1189
1229
if (use_spi )
1190
- return __xfrm_state_lookup (net , mark , & x -> id .daddr ,
1230
+ return __xfrm_state_lookup (& state_ptrs , mark , & x -> id .daddr ,
1191
1231
x -> id .spi , x -> id .proto , family );
1192
1232
else
1193
- return __xfrm_state_lookup_byaddr (net , mark ,
1233
+ return __xfrm_state_lookup_byaddr (& state_ptrs , mark ,
1194
1234
& x -> id .daddr ,
1195
1235
& x -> props .saddr ,
1196
1236
x -> id .proto , family );
@@ -1264,6 +1304,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
1264
1304
unsigned short family , u32 if_id )
1265
1305
{
1266
1306
static xfrm_address_t saddr_wildcard = { };
1307
+ struct xfrm_hash_state_ptrs state_ptrs ;
1267
1308
struct net * net = xp_net (pol );
1268
1309
unsigned int h , h_wildcard ;
1269
1310
struct xfrm_state * x , * x0 , * to_put ;
@@ -1328,8 +1369,10 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
1328
1369
else if (acquire_in_progress ) /* XXX: acquire_in_progress should not happen */
1329
1370
WARN_ON (1 );
1330
1371
1331
- h = xfrm_dst_hash (net , daddr , saddr , tmpl -> reqid , encap_family );
1332
- hlist_for_each_entry_rcu (x , net -> xfrm .state_bydst + h , bydst ) {
1372
+ xfrm_hash_ptrs_get (net , & state_ptrs );
1373
+
1374
+ h = __xfrm_dst_hash (daddr , saddr , tmpl -> reqid , encap_family , state_ptrs .hmask );
1375
+ hlist_for_each_entry_rcu (x , state_ptrs .bydst + h , bydst ) {
1333
1376
#ifdef CONFIG_XFRM_OFFLOAD
1334
1377
if (pol -> xdo .type == XFRM_DEV_OFFLOAD_PACKET ) {
1335
1378
if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1362,8 +1405,9 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
1362
1405
if (best || acquire_in_progress )
1363
1406
goto found ;
1364
1407
1365
- h_wildcard = xfrm_dst_hash (net , daddr , & saddr_wildcard , tmpl -> reqid , encap_family );
1366
- hlist_for_each_entry_rcu (x , net -> xfrm .state_bydst + h_wildcard , bydst ) {
1408
+ h_wildcard = __xfrm_dst_hash (daddr , & saddr_wildcard , tmpl -> reqid ,
1409
+ encap_family , state_ptrs .hmask );
1410
+ hlist_for_each_entry_rcu (x , state_ptrs .bydst + h_wildcard , bydst ) {
1367
1411
#ifdef CONFIG_XFRM_OFFLOAD
1368
1412
if (pol -> xdo .type == XFRM_DEV_OFFLOAD_PACKET ) {
1369
1413
if (x -> xso .type != XFRM_DEV_OFFLOAD_PACKET )
@@ -1401,7 +1445,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
1401
1445
1402
1446
if (!x && !error && !acquire_in_progress ) {
1403
1447
if (tmpl -> id .spi &&
1404
- (x0 = __xfrm_state_lookup_all (net , mark , daddr ,
1448
+ (x0 = __xfrm_state_lookup_all (& state_ptrs , mark , daddr ,
1405
1449
tmpl -> id .spi , tmpl -> id .proto ,
1406
1450
encap_family ,
1407
1451
& pol -> xdo )) != NULL ) {
@@ -2180,10 +2224,13 @@ struct xfrm_state *
2180
2224
xfrm_state_lookup (struct net * net , u32 mark , const xfrm_address_t * daddr , __be32 spi ,
2181
2225
u8 proto , unsigned short family )
2182
2226
{
2227
+ struct xfrm_hash_state_ptrs state_ptrs ;
2183
2228
struct xfrm_state * x ;
2184
2229
2185
2230
rcu_read_lock ();
2186
- x = __xfrm_state_lookup (net , mark , daddr , spi , proto , family );
2231
+ xfrm_hash_ptrs_get (net , & state_ptrs );
2232
+
2233
+ x = __xfrm_state_lookup (& state_ptrs , mark , daddr , spi , proto , family );
2187
2234
rcu_read_unlock ();
2188
2235
return x ;
2189
2236
}
@@ -2194,10 +2241,14 @@ xfrm_state_lookup_byaddr(struct net *net, u32 mark,
2194
2241
const xfrm_address_t * daddr , const xfrm_address_t * saddr ,
2195
2242
u8 proto , unsigned short family )
2196
2243
{
2244
+ struct xfrm_hash_state_ptrs state_ptrs ;
2197
2245
struct xfrm_state * x ;
2198
2246
2199
2247
spin_lock_bh (& net -> xfrm .xfrm_state_lock );
2200
- x = __xfrm_state_lookup_byaddr (net , mark , daddr , saddr , proto , family );
2248
+
2249
+ xfrm_hash_ptrs_get (net , & state_ptrs );
2250
+
2251
+ x = __xfrm_state_lookup_byaddr (& state_ptrs , mark , daddr , saddr , proto , family );
2201
2252
spin_unlock_bh (& net -> xfrm .xfrm_state_lock );
2202
2253
return x ;
2203
2254
}
0 commit comments