bpf: offload: free prog->aux->offload when device disappears
All bpf offload operations should now be under bpf_devs_lock, it's safe to free and clear the entire offload structure, not only the netdev pointer. __bpf_prog_offload_destroy() will no longer be called multiple times. Suggested-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
cae1927c0b
commit
ce3b9db4db
|
@ -70,12 +70,14 @@ err_free:
|
|||
static int __bpf_offload_ndo(struct bpf_prog *prog, enum bpf_netdev_command cmd,
|
||||
struct netdev_bpf *data)
|
||||
{
|
||||
struct net_device *netdev = prog->aux->offload->netdev;
|
||||
struct bpf_dev_offload *offload = prog->aux->offload;
|
||||
struct net_device *netdev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (!netdev)
|
||||
if (!offload)
|
||||
return -ENODEV;
|
||||
netdev = offload->netdev;
|
||||
if (!netdev->netdev_ops->ndo_bpf)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
@ -111,7 +113,7 @@ int bpf_prog_offload_verify_insn(struct bpf_verifier_env *env,
|
|||
|
||||
down_read(&bpf_devs_lock);
|
||||
offload = env->prog->aux->offload;
|
||||
if (offload->netdev)
|
||||
if (offload)
|
||||
ret = offload->dev_ops->insn_hook(env, insn_idx, prev_insn_idx);
|
||||
up_read(&bpf_devs_lock);
|
||||
|
||||
|
@ -123,31 +125,24 @@ static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
|
|||
struct bpf_dev_offload *offload = prog->aux->offload;
|
||||
struct netdev_bpf data = {};
|
||||
|
||||
/* Caution - if netdev is destroyed before the program, this function
|
||||
* will be called twice.
|
||||
*/
|
||||
|
||||
data.offload.prog = prog;
|
||||
|
||||
if (offload->dev_state)
|
||||
WARN_ON(__bpf_offload_ndo(prog, BPF_OFFLOAD_DESTROY, &data));
|
||||
|
||||
offload->dev_state = false;
|
||||
list_del_init(&offload->offloads);
|
||||
offload->netdev = NULL;
|
||||
kfree(offload);
|
||||
prog->aux->offload = NULL;
|
||||
}
|
||||
|
||||
void bpf_prog_offload_destroy(struct bpf_prog *prog)
|
||||
{
|
||||
struct bpf_dev_offload *offload = prog->aux->offload;
|
||||
|
||||
rtnl_lock();
|
||||
down_write(&bpf_devs_lock);
|
||||
__bpf_prog_offload_destroy(prog);
|
||||
if (prog->aux->offload)
|
||||
__bpf_prog_offload_destroy(prog);
|
||||
up_write(&bpf_devs_lock);
|
||||
rtnl_unlock();
|
||||
|
||||
kfree(offload);
|
||||
}
|
||||
|
||||
static int bpf_prog_offload_translate(struct bpf_prog *prog)
|
||||
|
|
Loading…
Reference in New Issue