This commit adds a stubbed bpf_prog_put_dev() that is symmetric to bpf_prog_get_type_dev() such that all bpf device attachments are using a *_dev() API. This gives core bpf the ability to do special refcnt handling for device attachments. Signed-off-by: Daniel Xu <dxu@xxxxxxxxx> --- include/linux/bpf.h | 1 + kernel/bpf/devmap.c | 8 ++++---- kernel/bpf/syscall.c | 6 ++++++ net/core/dev.c | 16 ++++++++-------- net/sched/cls_bpf.c | 4 ++-- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index eced6400f778..08269ad8cc45 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -2030,6 +2030,7 @@ void bpf_prog_sub(struct bpf_prog *prog, int i); void bpf_prog_inc(struct bpf_prog *prog); struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog); void bpf_prog_put(struct bpf_prog *prog); +void bpf_prog_put_dev(struct bpf_prog *prog); void bpf_prog_free_id(struct bpf_prog *prog); void bpf_map_free_id(struct bpf_map *map); diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index 4d42f6ed6c11..b5d33a87a560 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -212,7 +212,7 @@ static void dev_map_free(struct bpf_map *map) hlist_for_each_entry_safe(dev, next, head, index_hlist) { hlist_del_rcu(&dev->index_hlist); if (dev->xdp_prog) - bpf_prog_put(dev->xdp_prog); + bpf_prog_put_dev(dev->xdp_prog); dev_put(dev->dev); kfree(dev); } @@ -228,7 +228,7 @@ static void dev_map_free(struct bpf_map *map) continue; if (dev->xdp_prog) - bpf_prog_put(dev->xdp_prog); + bpf_prog_put_dev(dev->xdp_prog); dev_put(dev->dev); kfree(dev); } @@ -800,7 +800,7 @@ static void __dev_map_entry_free(struct rcu_head *rcu) dev = container_of(rcu, struct bpf_dtab_netdev, rcu); if (dev->xdp_prog) - bpf_prog_put(dev->xdp_prog); + bpf_prog_put_dev(dev->xdp_prog); dev_put(dev->dev); kfree(dev); } @@ -884,7 +884,7 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net, return dev; err_put_prog: - bpf_prog_put(prog); + bpf_prog_put_dev(prog); err_put_dev: dev_put(dev->dev); err_out: diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 10666d17b9e3..d8e5530598f3 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2164,6 +2164,12 @@ void bpf_prog_put(struct bpf_prog *prog) } EXPORT_SYMBOL_GPL(bpf_prog_put); +void bpf_prog_put_dev(struct bpf_prog *prog) +{ + bpf_prog_put(prog); +} +EXPORT_SYMBOL_GPL(bpf_prog_put_dev); + static int bpf_prog_release(struct inode *inode, struct file *filp) { struct bpf_prog *prog = filp->private_data; diff --git a/net/core/dev.c b/net/core/dev.c index 17e6281e408c..ed0ece344416 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5676,7 +5676,7 @@ static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp) case XDP_SETUP_PROG: rcu_assign_pointer(dev->xdp_prog, new); if (old) - bpf_prog_put(old); + bpf_prog_put_dev(old); if (old && !new) { static_branch_dec(&generic_xdp_needed_key); @@ -9167,7 +9167,7 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode, err = bpf_op(dev, &xdp); if (err) { if (prog) - bpf_prog_put(prog); + bpf_prog_put_dev(prog); return err; } @@ -9202,7 +9202,7 @@ static void dev_xdp_uninstall(struct net_device *dev) if (link) link->dev = NULL; else - bpf_prog_put(prog); + bpf_prog_put_dev(prog); dev_xdp_set_link(dev, mode, NULL); } @@ -9326,7 +9326,7 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack else dev_xdp_set_prog(dev, mode, new_prog); if (cur_prog) - bpf_prog_put(cur_prog); + bpf_prog_put_dev(cur_prog); return 0; } @@ -9445,7 +9445,7 @@ static int bpf_xdp_link_update(struct bpf_link *link, struct bpf_prog *new_prog, if (old_prog == new_prog) { /* no-op, don't disturb drivers */ - bpf_prog_put(new_prog); + bpf_prog_put_dev(new_prog); goto out_unlock; } @@ -9457,7 +9457,7 @@ static int bpf_xdp_link_update(struct bpf_link *link, struct bpf_prog *new_prog, goto out_unlock; old_prog = xchg(&link->prog, new_prog); - bpf_prog_put(old_prog); + bpf_prog_put_dev(old_prog); out_unlock: rtnl_unlock(); @@ -9568,9 +9568,9 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, err_out: if (err && new_prog) - bpf_prog_put(new_prog); + bpf_prog_put_dev(new_prog); if (old_prog) - bpf_prog_put(old_prog); + bpf_prog_put_dev(old_prog); return err; } diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 382c7a71f81f..20129d73dab4 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -258,7 +258,7 @@ static int cls_bpf_init(struct tcf_proto *tp) static void cls_bpf_free_parms(struct cls_bpf_prog *prog) { if (cls_bpf_is_ebpf(prog)) - bpf_prog_put(prog->filter); + bpf_prog_put_dev(prog->filter); else bpf_prog_destroy(prog->filter); @@ -391,7 +391,7 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog, if (tb[TCA_BPF_NAME]) { name = nla_memdup(tb[TCA_BPF_NAME], GFP_KERNEL); if (!name) { - bpf_prog_put(fp); + bpf_prog_put_dev(fp); return -ENOMEM; } } -- 2.41.0