@@ -1070,8 +1070,8 @@ int btf__dedup(struct btf *btf, struct btf_ext *btf_ext,
1070
1070
return err ;
1071
1071
}
1072
1072
1073
- #define BTF_DEDUP_TABLE_SIZE_LOG 14
1074
- #define BTF_DEDUP_TABLE_MOD ((1 << BTF_DEDUP_TABLE_SIZE_LOG) - 1)
1073
+ #define BTF_DEDUP_TABLE_DEFAULT_SIZE (1 << 14)
1074
+ #define BTF_DEDUP_TABLE_MAX_SIZE_LOG 31
1075
1075
#define BTF_UNPROCESSED_ID ((__u32)-1)
1076
1076
#define BTF_IN_PROGRESS_ID ((__u32)-2)
1077
1077
@@ -1128,18 +1128,21 @@ static inline __u32 hash_combine(__u32 h, __u32 value)
1128
1128
#undef GOLDEN_RATIO_PRIME
1129
1129
}
1130
1130
1131
- #define for_each_hash_node (table , hash , node ) \
1132
- for (node = table[hash & BTF_DEDUP_TABLE_MOD]; node; node = node->next)
1131
+ #define for_each_dedup_cand (d , hash , node ) \
1132
+ for (node = d->dedup_table[hash & (d->opts.dedup_table_size - 1)]; \
1133
+ node; \
1134
+ node = node->next)
1133
1135
1134
1136
static int btf_dedup_table_add (struct btf_dedup * d , __u32 hash , __u32 type_id )
1135
1137
{
1136
1138
struct btf_dedup_node * node = malloc (sizeof (struct btf_dedup_node ));
1139
+ int bucket = hash & (d -> opts .dedup_table_size - 1 );
1137
1140
1138
1141
if (!node )
1139
1142
return - ENOMEM ;
1140
1143
node -> type_id = type_id ;
1141
- node -> next = d -> dedup_table [hash & BTF_DEDUP_TABLE_MOD ];
1142
- d -> dedup_table [hash & BTF_DEDUP_TABLE_MOD ] = node ;
1144
+ node -> next = d -> dedup_table [bucket ];
1145
+ d -> dedup_table [bucket ] = node ;
1143
1146
return 0 ;
1144
1147
}
1145
1148
@@ -1177,7 +1180,7 @@ static void btf_dedup_table_free(struct btf_dedup *d)
1177
1180
if (!d -> dedup_table )
1178
1181
return ;
1179
1182
1180
- for (i = 0 ; i < ( 1 << BTF_DEDUP_TABLE_SIZE_LOG ) ; i ++ ) {
1183
+ for (i = 0 ; i < d -> opts . dedup_table_size ; i ++ ) {
1181
1184
while (d -> dedup_table [i ]) {
1182
1185
tmp = d -> dedup_table [i ];
1183
1186
d -> dedup_table [i ] = tmp -> next ;
@@ -1212,19 +1215,37 @@ static void btf_dedup_free(struct btf_dedup *d)
1212
1215
free (d );
1213
1216
}
1214
1217
1218
+ /* Find closest power of two >= to size, capped at 2^max_size_log */
1219
+ static __u32 roundup_pow2_max (__u32 size , int max_size_log )
1220
+ {
1221
+ int i ;
1222
+
1223
+ for (i = 0 ; i < max_size_log && (1U << i ) < size ; i ++ )
1224
+ ;
1225
+ return 1U << i ;
1226
+ }
1227
+
1228
+
1215
1229
static struct btf_dedup * btf_dedup_new (struct btf * btf , struct btf_ext * btf_ext ,
1216
1230
const struct btf_dedup_opts * opts )
1217
1231
{
1218
1232
struct btf_dedup * d = calloc (1 , sizeof (struct btf_dedup ));
1219
1233
int i , err = 0 ;
1234
+ __u32 sz ;
1220
1235
1221
1236
if (!d )
1222
1237
return ERR_PTR (- ENOMEM );
1223
1238
1239
+ d -> opts .dont_resolve_fwds = opts && opts -> dont_resolve_fwds ;
1240
+ sz = opts && opts -> dedup_table_size ? opts -> dedup_table_size
1241
+ : BTF_DEDUP_TABLE_DEFAULT_SIZE ;
1242
+ sz = roundup_pow2_max (sz , BTF_DEDUP_TABLE_MAX_SIZE_LOG );
1243
+ d -> opts .dedup_table_size = sz ;
1244
+
1224
1245
d -> btf = btf ;
1225
1246
d -> btf_ext = btf_ext ;
1226
1247
1227
- d -> dedup_table = calloc (1 << BTF_DEDUP_TABLE_SIZE_LOG ,
1248
+ d -> dedup_table = calloc (d -> opts . dedup_table_size ,
1228
1249
sizeof (struct btf_dedup_node * ));
1229
1250
if (!d -> dedup_table ) {
1230
1251
err = - ENOMEM ;
@@ -1249,8 +1270,6 @@ static struct btf_dedup *btf_dedup_new(struct btf *btf, struct btf_ext *btf_ext,
1249
1270
for (i = 0 ; i <= btf -> nr_types ; i ++ )
1250
1271
d -> hypot_map [i ] = BTF_UNPROCESSED_ID ;
1251
1272
1252
- d -> opts .dont_resolve_fwds = opts && opts -> dont_resolve_fwds ;
1253
-
1254
1273
done :
1255
1274
if (err ) {
1256
1275
btf_dedup_free (d );
@@ -1644,7 +1663,7 @@ static __u32 btf_hash_struct(struct btf_type *t)
1644
1663
* IDs. This check is performed during type graph equivalence check and
1645
1664
* referenced types equivalence is checked separately.
1646
1665
*/
1647
- static bool btf_equal_struct (struct btf_type * t1 , struct btf_type * t2 )
1666
+ static bool btf_shallow_equal_struct (struct btf_type * t1 , struct btf_type * t2 )
1648
1667
{
1649
1668
struct btf_member * m1 , * m2 ;
1650
1669
__u16 vlen ;
@@ -1824,7 +1843,7 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
1824
1843
1825
1844
case BTF_KIND_INT :
1826
1845
h = btf_hash_int (t );
1827
- for_each_hash_node ( d -> dedup_table , h , cand_node ) {
1846
+ for_each_dedup_cand ( d , h , cand_node ) {
1828
1847
cand = d -> btf -> types [cand_node -> type_id ];
1829
1848
if (btf_equal_int (t , cand )) {
1830
1849
new_id = cand_node -> type_id ;
@@ -1835,7 +1854,7 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
1835
1854
1836
1855
case BTF_KIND_ENUM :
1837
1856
h = btf_hash_enum (t );
1838
- for_each_hash_node ( d -> dedup_table , h , cand_node ) {
1857
+ for_each_dedup_cand ( d , h , cand_node ) {
1839
1858
cand = d -> btf -> types [cand_node -> type_id ];
1840
1859
if (btf_equal_enum (t , cand )) {
1841
1860
new_id = cand_node -> type_id ;
@@ -1846,7 +1865,7 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
1846
1865
1847
1866
case BTF_KIND_FWD :
1848
1867
h = btf_hash_common (t );
1849
- for_each_hash_node ( d -> dedup_table , h , cand_node ) {
1868
+ for_each_dedup_cand ( d , h , cand_node ) {
1850
1869
cand = d -> btf -> types [cand_node -> type_id ];
1851
1870
if (btf_equal_common (t , cand )) {
1852
1871
new_id = cand_node -> type_id ;
@@ -2105,7 +2124,7 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
2105
2124
struct btf_member * cand_m , * canon_m ;
2106
2125
__u16 vlen ;
2107
2126
2108
- if (!btf_equal_struct (cand_type , canon_type ))
2127
+ if (!btf_shallow_equal_struct (cand_type , canon_type ))
2109
2128
return 0 ;
2110
2129
vlen = BTF_INFO_VLEN (cand_type -> info );
2111
2130
cand_m = (struct btf_member * )(cand_type + 1 );
@@ -2246,7 +2265,7 @@ static void btf_dedup_merge_hypot_map(struct btf_dedup *d)
2246
2265
static int btf_dedup_struct_type (struct btf_dedup * d , __u32 type_id )
2247
2266
{
2248
2267
struct btf_dedup_node * cand_node ;
2249
- struct btf_type * t ;
2268
+ struct btf_type * cand_type , * t ;
2250
2269
/* if we don't find equivalent type, then we are canonical */
2251
2270
__u32 new_id = type_id ;
2252
2271
__u16 kind ;
@@ -2263,9 +2282,23 @@ static int btf_dedup_struct_type(struct btf_dedup *d, __u32 type_id)
2263
2282
return 0 ;
2264
2283
2265
2284
h = btf_hash_struct (t );
2266
- for_each_hash_node ( d -> dedup_table , h , cand_node ) {
2285
+ for_each_dedup_cand ( d , h , cand_node ) {
2267
2286
int eq ;
2268
2287
2288
+ /*
2289
+ * Even though btf_dedup_is_equiv() checks for
2290
+ * btf_shallow_equal_struct() internally when checking two
2291
+ * structs (unions) for equivalence, we need to guard here
2292
+ * from picking matching FWD type as a dedup candidate.
2293
+ * This can happen due to hash collision. In such case just
2294
+ * relying on btf_dedup_is_equiv() would lead to potentially
2295
+ * creating a loop (FWD -> STRUCT and STRUCT -> FWD), because
2296
+ * FWD and compatible STRUCT/UNION are considered equivalent.
2297
+ */
2298
+ cand_type = d -> btf -> types [cand_node -> type_id ];
2299
+ if (!btf_shallow_equal_struct (t , cand_type ))
2300
+ continue ;
2301
+
2269
2302
btf_dedup_clear_hypot_map (d );
2270
2303
eq = btf_dedup_is_equiv (d , type_id , cand_node -> type_id );
2271
2304
if (eq < 0 )
@@ -2350,7 +2383,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
2350
2383
t -> type = ref_type_id ;
2351
2384
2352
2385
h = btf_hash_common (t );
2353
- for_each_hash_node ( d -> dedup_table , h , cand_node ) {
2386
+ for_each_dedup_cand ( d , h , cand_node ) {
2354
2387
cand = d -> btf -> types [cand_node -> type_id ];
2355
2388
if (btf_equal_common (t , cand )) {
2356
2389
new_id = cand_node -> type_id ;
@@ -2373,7 +2406,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
2373
2406
info -> index_type = ref_type_id ;
2374
2407
2375
2408
h = btf_hash_array (t );
2376
- for_each_hash_node ( d -> dedup_table , h , cand_node ) {
2409
+ for_each_dedup_cand ( d , h , cand_node ) {
2377
2410
cand = d -> btf -> types [cand_node -> type_id ];
2378
2411
if (btf_equal_array (t , cand )) {
2379
2412
new_id = cand_node -> type_id ;
@@ -2404,7 +2437,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
2404
2437
}
2405
2438
2406
2439
h = btf_hash_fnproto (t );
2407
- for_each_hash_node ( d -> dedup_table , h , cand_node ) {
2440
+ for_each_dedup_cand ( d , h , cand_node ) {
2408
2441
cand = d -> btf -> types [cand_node -> type_id ];
2409
2442
if (btf_equal_fnproto (t , cand )) {
2410
2443
new_id = cand_node -> type_id ;
0 commit comments