On Mon, Jan 23, 2023 at 2:44 PM Stephen Rothwell <sfr@xxxxxxxxxxxxxxxx> wrote: > > Hi all, > > Today's linux-next merge of the bpf-next tree got a conflict in: > > kernel/bpf/offload.c > > between commit: > > ef01f4e25c17 ("bpf: restore the ebpf program ID for BPF_AUDIT_UNLOAD and PERF_BPF_EVENT_PROG_UNLOAD") > > from Linus' tree and commit: > > 89bbc53a4dbb ("bpf: Reshuffle some parts of bpf/offload.c") > > from the bpf-next tree. > > I fixed it up (see below) and can carry the fix as necessary. This > is now fixed as far as linux-next is concerned, but any non trivial > conflicts should be mentioned to your upstream maintainer when your tree > is submitted for merging. You may also want to consider cooperating > with the maintainer of the conflicting tree to minimise any particularly > complex conflicts. Yeah, that looks like a correct resolution, thank you! Not sure what would've been the correct way to handle it in bpf-next (except waiting for bpf tree to be merged)? > -- > Cheers, > Stephen Rothwell > > diff --cc kernel/bpf/offload.c > index 190d9f9dc987,e87cab2ed710..000000000000 > --- a/kernel/bpf/offload.c > +++ b/kernel/bpf/offload.c > @@@ -75,20 -74,124 +74,121 @@@ bpf_offload_find_netdev(struct net_devi > return rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params); > } > > - int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr) > + static int __bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev, > + struct net_device *netdev) > { > struct bpf_offload_netdev *ondev; > - struct bpf_prog_offload *offload; > int err; > > - if (attr->prog_type != BPF_PROG_TYPE_SCHED_CLS && > - attr->prog_type != BPF_PROG_TYPE_XDP) > - return -EINVAL; > + ondev = kzalloc(sizeof(*ondev), GFP_KERNEL); > + if (!ondev) > + return -ENOMEM; > > - if (attr->prog_flags) > - return -EINVAL; > + ondev->netdev = netdev; > + ondev->offdev = offdev; > + INIT_LIST_HEAD(&ondev->progs); > + INIT_LIST_HEAD(&ondev->maps); > + > + err = rhashtable_insert_fast(&offdevs, &ondev->l, offdevs_params); > + if (err) { > + netdev_warn(netdev, "failed to register for BPF offload\n"); > + goto err_free; > + } > + > + if (offdev) > + list_add(&ondev->offdev_netdevs, &offdev->netdevs); > + return 0; > + > + err_free: > + kfree(ondev); > + return err; > + } > + > + static void __bpf_prog_offload_destroy(struct bpf_prog *prog) > + { > + struct bpf_prog_offload *offload = prog->aux->offload; > + > + if (offload->dev_state) > + offload->offdev->ops->destroy(prog); > + > - /* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */ > - bpf_prog_free_id(prog, true); > - > + list_del_init(&offload->offloads); > + kfree(offload); > + prog->aux->offload = NULL; > + } > + > + static int bpf_map_offload_ndo(struct bpf_offloaded_map *offmap, > + enum bpf_netdev_command cmd) > + { > + struct netdev_bpf data = {}; > + struct net_device *netdev; > + > + ASSERT_RTNL(); > + > + data.command = cmd; > + data.offmap = offmap; > + /* Caller must make sure netdev is valid */ > + netdev = offmap->netdev; > + > + return netdev->netdev_ops->ndo_bpf(netdev, &data); > + } > + > + static void __bpf_map_offload_destroy(struct bpf_offloaded_map *offmap) > + { > + WARN_ON(bpf_map_offload_ndo(offmap, BPF_OFFLOAD_MAP_FREE)); > + /* Make sure BPF_MAP_GET_NEXT_ID can't find this dead map */ > + bpf_map_free_id(&offmap->map, true); > + list_del_init(&offmap->offloads); > + offmap->netdev = NULL; > + } > + > + static void __bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev, > + struct net_device *netdev) > + { > + struct bpf_offload_netdev *ondev, *altdev = NULL; > + struct bpf_offloaded_map *offmap, *mtmp; > + struct bpf_prog_offload *offload, *ptmp; > + > + ASSERT_RTNL(); > + > + ondev = rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params); > + if (WARN_ON(!ondev)) > + return; > + > + WARN_ON(rhashtable_remove_fast(&offdevs, &ondev->l, offdevs_params)); > + > + /* Try to move the objects to another netdev of the device */ > + if (offdev) { > + list_del(&ondev->offdev_netdevs); > + altdev = list_first_entry_or_null(&offdev->netdevs, > + struct bpf_offload_netdev, > + offdev_netdevs); > + } > + > + if (altdev) { > + list_for_each_entry(offload, &ondev->progs, offloads) > + offload->netdev = altdev->netdev; > + list_splice_init(&ondev->progs, &altdev->progs); > + > + list_for_each_entry(offmap, &ondev->maps, offloads) > + offmap->netdev = altdev->netdev; > + list_splice_init(&ondev->maps, &altdev->maps); > + } else { > + list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads) > + __bpf_prog_offload_destroy(offload->prog); > + list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads) > + __bpf_map_offload_destroy(offmap); > + } > + > + WARN_ON(!list_empty(&ondev->progs)); > + WARN_ON(!list_empty(&ondev->maps)); > + kfree(ondev); > + } > + > + static int __bpf_prog_dev_bound_init(struct bpf_prog *prog, struct net_device *netdev) > + { > + struct bpf_offload_netdev *ondev; > + struct bpf_prog_offload *offload; > + int err; > > offload = kzalloc(sizeof(*offload), GFP_USER); > if (!offload)