Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nft_set_pipapo: Store real pointer, adjust later.

The struct nft_pipapo_scratch is allocated, then aligned to the required
alignment and difference (in bytes) is then saved in align_off. The
aligned pointer is used later.
While this works, it gets complicated with all the extra checks if
all member before map are larger than the required alignment.

Instead of saving the aligned pointer, just save the returned pointer
and align the map pointer in nft_pipapo_lookup() before using it. The
alignment later on shouldn't be that expensive. With this change, the
align_off can be removed and the pointer can be passed to kfree() as is.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Florian Westphal <fw@strlen.de>

authored by

Sebastian Andrzej Siewior and committed by
Florian Westphal
6aa67d57 84c1da7b

+14 -40
+8 -32
net/netfilter/nft_set_pipapo.c
··· 418 418 const u8 *data, u8 genmask, 419 419 u64 tstamp) 420 420 { 421 + unsigned long *res_map, *fill_map, *map; 421 422 struct nft_pipapo_scratch *scratch; 422 - unsigned long *res_map, *fill_map; 423 423 const struct nft_pipapo_field *f; 424 424 bool map_index; 425 425 int i; ··· 432 432 433 433 map_index = scratch->map_index; 434 434 435 - res_map = scratch->map + (map_index ? m->bsize_max : 0); 436 - fill_map = scratch->map + (map_index ? 0 : m->bsize_max); 435 + map = NFT_PIPAPO_LT_ALIGN(&scratch->__map[0]); 436 + res_map = map + (map_index ? m->bsize_max : 0); 437 + fill_map = map + (map_index ? 0 : m->bsize_max); 437 438 438 439 pipapo_resmap_init(m, res_map); 439 440 ··· 1172 1171 } 1173 1172 1174 1173 /** 1175 - * pipapo_free_scratch() - Free per-CPU map at original (not aligned) address 1174 + * pipapo_free_scratch() - Free per-CPU map at original address 1176 1175 * @m: Matching data 1177 1176 * @cpu: CPU number 1178 1177 */ 1179 1178 static void pipapo_free_scratch(const struct nft_pipapo_match *m, unsigned int cpu) 1180 1179 { 1181 1180 struct nft_pipapo_scratch *s; 1182 - void *mem; 1183 1181 1184 1182 s = *per_cpu_ptr(m->scratch, cpu); 1185 - if (!s) 1186 - return; 1187 1183 1188 - mem = s; 1189 - mem -= s->align_off; 1190 - kvfree(mem); 1184 + kvfree(s); 1191 1185 } 1192 1186 1193 1187 /** ··· 1199 1203 1200 1204 for_each_possible_cpu(i) { 1201 1205 struct nft_pipapo_scratch *scratch; 1202 - #ifdef NFT_PIPAPO_ALIGN 1203 - void *scratch_aligned; 1204 - u32 align_off; 1205 - #endif 1206 - scratch = kvzalloc_node(struct_size(scratch, map, bsize_max * 2) + 1206 + 1207 + scratch = kvzalloc_node(struct_size(scratch, __map, bsize_max * 2) + 1207 1208 NFT_PIPAPO_ALIGN_HEADROOM, 1208 1209 GFP_KERNEL_ACCOUNT, cpu_to_node(i)); 1209 1210 if (!scratch) { ··· 1215 1222 } 1216 1223 1217 1224 pipapo_free_scratch(clone, i); 1218 - 1219 - #ifdef NFT_PIPAPO_ALIGN 1220 - /* Align &scratch->map (not the struct itself): the extra 1221 - * %NFT_PIPAPO_ALIGN_HEADROOM bytes passed to kzalloc_node() 1222 - * above guarantee we can waste up to those bytes in order 1223 - * to align the map field regardless of its offset within 1224 - * the struct. 1225 - */ 1226 - BUILD_BUG_ON(offsetof(struct nft_pipapo_scratch, map) > NFT_PIPAPO_ALIGN_HEADROOM); 1227 - 1228 - scratch_aligned = NFT_PIPAPO_LT_ALIGN(&scratch->map); 1229 - scratch_aligned -= offsetof(struct nft_pipapo_scratch, map); 1230 - align_off = scratch_aligned - (void *)scratch; 1231 - 1232 - scratch = scratch_aligned; 1233 - scratch->align_off = align_off; 1234 - #endif 1235 1225 *per_cpu_ptr(clone->scratch, i) = scratch; 1236 1226 } 1237 1227
+2 -4
net/netfilter/nft_set_pipapo.h
··· 125 125 /** 126 126 * struct nft_pipapo_scratch - percpu data used for lookup and matching 127 127 * @map_index: Current working bitmap index, toggled between field matches 128 - * @align_off: Offset to get the originally allocated address 129 - * @map: store partial matching results during lookup 128 + * @__map: store partial matching results during lookup 130 129 */ 131 130 struct nft_pipapo_scratch { 132 131 u8 map_index; 133 - u32 align_off; 134 - unsigned long map[]; 132 + unsigned long __map[]; 135 133 }; 136 134 137 135 /**
+4 -4
net/netfilter/nft_set_pipapo_avx2.c
··· 1155 1155 { 1156 1156 struct nft_pipapo_scratch *scratch; 1157 1157 const struct nft_pipapo_field *f; 1158 - unsigned long *res, *fill; 1158 + unsigned long *res, *fill, *map; 1159 1159 bool map_index; 1160 1160 int i; 1161 1161 ··· 1164 1164 return NULL; 1165 1165 1166 1166 map_index = scratch->map_index; 1167 - 1168 - res = scratch->map + (map_index ? m->bsize_max : 0); 1169 - fill = scratch->map + (map_index ? 0 : m->bsize_max); 1167 + map = NFT_PIPAPO_LT_ALIGN(&scratch->__map[0]); 1168 + res = map + (map_index ? m->bsize_max : 0); 1169 + fill = map + (map_index ? 0 : m->bsize_max); 1170 1170 1171 1171 pipapo_resmap_init_avx2(m, res); 1172 1172