Skip to content

Commit 77620d1

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
bpf: use realloc in bpf_patch_insn_data
Avoid excessive vzalloc/vfree calls when patching instructions in do_misc_fixups(). bpf_patch_insn_data() uses vzalloc to allocate new memory for env->insn_aux_data for each patch as follows: struct bpf_prog *bpf_patch_insn_data(env, ...) { ... new_data = vzalloc(... O(program size) ...); ... adjust_insn_aux_data(env, new_data, ...); ... } void adjust_insn_aux_data(env, new_data, ...) { ... memcpy(new_data, env->insn_aux_data); vfree(env->insn_aux_data); env->insn_aux_data = new_data; ... } The vzalloc/vfree pair is hot in perf report collected for e.g. pyperf180 test case. It can be replaced with a call to vrealloc in order to reduce the number of actual memory allocations. This is a stop-gap solution, as bpf_patch_insn_data is still hot in the profile. More comprehansive solutions had been discussed before e.g. as in [1]. [1] https://lore.kernel.org/bpf/CAEf4BzY_E8MSL4mD0UPuuiDcbJhh9e2xQo2=5w+ppRWWiYSGvQ@mail.gmail.com/ Suggested-by: Alexei Starovoitov <[email protected]> Signed-off-by: Eduard Zingerman <[email protected]> Acked-by: Kumar Kartikeya Dwivedi <[email protected]> Tested-by: Anton Protopopov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent cb070a8 commit 77620d1

File tree

1 file changed

+15
-14
lines changed

1 file changed

+15
-14
lines changed

kernel/bpf/verifier.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20699,35 +20699,32 @@ static void convert_pseudo_ld_imm64(struct bpf_verifier_env *env)
2069920699
* [0, off) and [off, end) to new locations, so the patched range stays zero
2070020700
*/
2070120701
static void adjust_insn_aux_data(struct bpf_verifier_env *env,
20702-
struct bpf_insn_aux_data *new_data,
2070320702
struct bpf_prog *new_prog, u32 off, u32 cnt)
2070420703
{
20705-
struct bpf_insn_aux_data *old_data = env->insn_aux_data;
20704+
struct bpf_insn_aux_data *data = env->insn_aux_data;
2070620705
struct bpf_insn *insn = new_prog->insnsi;
20707-
u32 old_seen = old_data[off].seen;
20706+
u32 old_seen = data[off].seen;
2070820707
u32 prog_len;
2070920708
int i;
2071020709

2071120710
/* aux info at OFF always needs adjustment, no matter fast path
2071220711
* (cnt == 1) is taken or not. There is no guarantee INSN at OFF is the
2071320712
* original insn at old prog.
2071420713
*/
20715-
old_data[off].zext_dst = insn_has_def32(insn + off + cnt - 1);
20714+
data[off].zext_dst = insn_has_def32(insn + off + cnt - 1);
2071620715

2071720716
if (cnt == 1)
2071820717
return;
2071920718
prog_len = new_prog->len;
2072020719

20721-
memcpy(new_data, old_data, sizeof(struct bpf_insn_aux_data) * off);
20722-
memcpy(new_data + off + cnt - 1, old_data + off,
20723-
sizeof(struct bpf_insn_aux_data) * (prog_len - off - cnt + 1));
20720+
memmove(data + off + cnt - 1, data + off,
20721+
sizeof(struct bpf_insn_aux_data) * (prog_len - off - cnt + 1));
20722+
memset(data + off, 0, sizeof(struct bpf_insn_aux_data) * (cnt - 1));
2072420723
for (i = off; i < off + cnt - 1; i++) {
2072520724
/* Expand insni[off]'s seen count to the patched range. */
20726-
new_data[i].seen = old_seen;
20727-
new_data[i].zext_dst = insn_has_def32(insn + i);
20725+
data[i].seen = old_seen;
20726+
data[i].zext_dst = insn_has_def32(insn + i);
2072820727
}
20729-
env->insn_aux_data = new_data;
20730-
vfree(old_data);
2073120728
}
2073220729

2073320730
static void adjust_subprog_starts(struct bpf_verifier_env *env, u32 off, u32 len)
@@ -20765,10 +20762,14 @@ static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 of
2076520762
struct bpf_insn_aux_data *new_data = NULL;
2076620763

2076720764
if (len > 1) {
20768-
new_data = vzalloc(array_size(env->prog->len + len - 1,
20769-
sizeof(struct bpf_insn_aux_data)));
20765+
new_data = vrealloc(env->insn_aux_data,
20766+
array_size(env->prog->len + len - 1,
20767+
sizeof(struct bpf_insn_aux_data)),
20768+
GFP_KERNEL_ACCOUNT | __GFP_ZERO);
2077020769
if (!new_data)
2077120770
return NULL;
20771+
20772+
env->insn_aux_data = new_data;
2077220773
}
2077320774

2077420775
new_prog = bpf_patch_insn_single(env->prog, off, patch, len);
@@ -20780,7 +20781,7 @@ static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 of
2078020781
vfree(new_data);
2078120782
return NULL;
2078220783
}
20783-
adjust_insn_aux_data(env, new_data, new_prog, off, len);
20784+
adjust_insn_aux_data(env, new_prog, off, len);
2078420785
adjust_subprog_starts(env, off, len);
2078520786
adjust_poke_descs(new_prog, off, len);
2078620787
return new_prog;

0 commit comments

Comments
 (0)