bpf: pass bpf_struct_ops_link to callbacks in bpf_struct_ops.
authorKui-Feng Lee <thinker.li@gmail.com>
Thu, 30 May 2024 06:59:39 +0000 (23:59 -0700)
committerMartin KaFai Lau <martin.lau@kernel.org>
Thu, 30 May 2024 22:34:13 +0000 (15:34 -0700)
Pass an additional pointer of bpf_struct_ops_link to callback function reg,
unreg, and update provided by subsystems defined in bpf_struct_ops. A
bpf_struct_ops_map can be registered for multiple links. Passing a pointer
of bpf_struct_ops_link helps subsystems to distinguish them.

This pointer will be used in the later patches to let the subsystem
initiate a detachment on a link that was registered to it previously.

Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
Link: https://lore.kernel.org/r/20240530065946.979330-2-thinker.li@gmail.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
include/linux/bpf.h
kernel/bpf/bpf_struct_ops.c
net/bpf/bpf_dummy_struct_ops.c
net/ipv4/bpf_tcp_ca.c
tools/testing/selftests/bpf/bpf_test_no_cfi/bpf_test_no_cfi.c
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c

index 5e694a3..19f8836 100644 (file)
@@ -1730,9 +1730,9 @@ struct bpf_struct_ops {
        int (*init_member)(const struct btf_type *t,
                           const struct btf_member *member,
                           void *kdata, const void *udata);
-       int (*reg)(void *kdata);
-       void (*unreg)(void *kdata);
-       int (*update)(void *kdata, void *old_kdata);
+       int (*reg)(void *kdata, struct bpf_link *link);
+       void (*unreg)(void *kdata, struct bpf_link *link);
+       int (*update)(void *kdata, void *old_kdata, struct bpf_link *link);
        int (*validate)(void *kdata);
        void *cfi_stubs;
        struct module *owner;
index 86c7884..1542dde 100644 (file)
@@ -757,7 +757,7 @@ static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,
                goto unlock;
        }
 
-       err = st_ops->reg(kdata);
+       err = st_ops->reg(kdata, NULL);
        if (likely(!err)) {
                /* This refcnt increment on the map here after
                 * 'st_ops->reg()' is secure since the state of the
@@ -805,7 +805,7 @@ static long bpf_struct_ops_map_delete_elem(struct bpf_map *map, void *key)
                             BPF_STRUCT_OPS_STATE_TOBEFREE);
        switch (prev_state) {
        case BPF_STRUCT_OPS_STATE_INUSE:
-               st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data);
+               st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data, NULL);
                bpf_map_put(map);
                return 0;
        case BPF_STRUCT_OPS_STATE_TOBEFREE:
@@ -1060,7 +1060,7 @@ static void bpf_struct_ops_map_link_dealloc(struct bpf_link *link)
                /* st_link->map can be NULL if
                 * bpf_struct_ops_link_create() fails to register.
                 */
-               st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data);
+               st_map->st_ops_desc->st_ops->unreg(&st_map->kvalue.data, link);
                bpf_map_put(&st_map->map);
        }
        kfree(st_link);
@@ -1125,7 +1125,7 @@ static int bpf_struct_ops_map_link_update(struct bpf_link *link, struct bpf_map
                goto err_out;
        }
 
-       err = st_map->st_ops_desc->st_ops->update(st_map->kvalue.data, old_st_map->kvalue.data);
+       err = st_map->st_ops_desc->st_ops->update(st_map->kvalue.data, old_st_map->kvalue.data, link);
        if (err)
                goto err_out;
 
@@ -1176,7 +1176,7 @@ int bpf_struct_ops_link_create(union bpf_attr *attr)
        if (err)
                goto err_out;
 
-       err = st_map->st_ops_desc->st_ops->reg(st_map->kvalue.data);
+       err = st_map->st_ops_desc->st_ops->reg(st_map->kvalue.data, &link->link);
        if (err) {
                bpf_link_cleanup(&link_primer);
                link = NULL;
index 891cdf6..3ea52b0 100644 (file)
@@ -272,12 +272,12 @@ static int bpf_dummy_init_member(const struct btf_type *t,
        return -EOPNOTSUPP;
 }
 
-static int bpf_dummy_reg(void *kdata)
+static int bpf_dummy_reg(void *kdata, struct bpf_link *link)
 {
        return -EOPNOTSUPP;
 }
 
-static void bpf_dummy_unreg(void *kdata)
+static void bpf_dummy_unreg(void *kdata, struct bpf_link *link)
 {
 }
 
index 1822775..3f88d09 100644 (file)
@@ -260,17 +260,17 @@ static int bpf_tcp_ca_check_member(const struct btf_type *t,
        return 0;
 }
 
-static int bpf_tcp_ca_reg(void *kdata)
+static int bpf_tcp_ca_reg(void *kdata, struct bpf_link *link)
 {
        return tcp_register_congestion_control(kdata);
 }
 
-static void bpf_tcp_ca_unreg(void *kdata)
+static void bpf_tcp_ca_unreg(void *kdata, struct bpf_link *link)
 {
        tcp_unregister_congestion_control(kdata);
 }
 
-static int bpf_tcp_ca_update(void *kdata, void *old_kdata)
+static int bpf_tcp_ca_update(void *kdata, void *old_kdata, struct bpf_link *link)
 {
        return tcp_update_congestion_control(kdata, old_kdata);
 }
index b1dd889..948eb39 100644 (file)
@@ -22,12 +22,12 @@ static int dummy_init_member(const struct btf_type *t,
        return 0;
 }
 
-static int dummy_reg(void *kdata)
+static int dummy_reg(void *kdata, struct bpf_link *link)
 {
        return 0;
 }
 
-static void dummy_unreg(void *kdata)
+static void dummy_unreg(void *kdata, struct bpf_link *link)
 {
 }
 
index 2a18bd3..0a09732 100644 (file)
@@ -820,7 +820,7 @@ static const struct bpf_verifier_ops bpf_testmod_verifier_ops = {
        .is_valid_access = bpf_testmod_ops_is_valid_access,
 };
 
-static int bpf_dummy_reg(void *kdata)
+static int bpf_dummy_reg(void *kdata, struct bpf_link *link)
 {
        struct bpf_testmod_ops *ops = kdata;
 
@@ -835,7 +835,7 @@ static int bpf_dummy_reg(void *kdata)
        return 0;
 }
 
-static void bpf_dummy_unreg(void *kdata)
+static void bpf_dummy_unreg(void *kdata, struct bpf_link *link)
 {
 }
 
@@ -871,7 +871,7 @@ struct bpf_struct_ops bpf_bpf_testmod_ops = {
        .owner = THIS_MODULE,
 };
 
-static int bpf_dummy_reg2(void *kdata)
+static int bpf_dummy_reg2(void *kdata, struct bpf_link *link)
 {
        struct bpf_testmod_ops2 *ops = kdata;