Add a helper to iterate bpf_prog_arrays, which are a hybrid between and array and a linked list. Hide this behind a for each macro. Signed-off-by: Lorenz Bauer <lmb@xxxxxxxxxxxxxx> --- include/linux/bpf.h | 11 +++++------ include/linux/filter.h | 4 +--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index cccaef1088ea..875f6bc4bf1d 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1070,6 +1070,9 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array, /* BPF program asks to set CN on the packet. */ #define BPF_RET_SET_CN (1 << 0) +#define for_each_bpf_prog(_array, _item, _prog) \ + for ((_item) = &(_array)->items[0]; ((_prog) = READ_ONCE((_item)->prog)); (_item)++) + #define BPF_PROG_RUN_ARRAY_FLAGS(array, ctx, func, ret_flags) \ ({ \ struct bpf_prog_array_item *_item; \ @@ -1080,13 +1083,11 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array, migrate_disable(); \ rcu_read_lock(); \ _array = rcu_dereference(array); \ - _item = &_array->items[0]; \ - while ((_prog = READ_ONCE(_item->prog))) { \ + for_each_bpf_prog(_array, _item, _prog) { \ bpf_cgroup_storage_set(_item->cgroup_storage); \ func_ret = func(_prog, ctx); \ _ret &= (func_ret & 1); \ *(ret_flags) |= (func_ret >> 1); \ - _item++; \ } \ rcu_read_unlock(); \ migrate_enable(); \ @@ -1104,11 +1105,9 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array, _array = rcu_dereference(array); \ if (unlikely(check_non_null && !_array))\ goto _out; \ - _item = &_array->items[0]; \ - while ((_prog = READ_ONCE(_item->prog))) { \ + for_each_bpf_prog(_array, _item, _prog) { \ bpf_cgroup_storage_set(_item->cgroup_storage); \ _ret &= func(_prog, ctx); \ - _item++; \ } \ _out: \ rcu_read_unlock(); \ diff --git a/include/linux/filter.h b/include/linux/filter.h index 3b00fc906ccd..9ed20ff29d9a 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -1376,8 +1376,7 @@ extern struct static_key_false bpf_sk_lookup_enabled; u32 _ret; \ \ migrate_disable(); \ - _item = &(array)->items[0]; \ - while ((_prog = READ_ONCE(_item->prog))) { \ + for_each_bpf_prog(array, _item, _prog) { \ /* restore most recent selection */ \ _ctx->selected_sk = _selected_sk; \ _ctx->no_reuseport = _no_reuseport; \ @@ -1390,7 +1389,6 @@ extern struct static_key_false bpf_sk_lookup_enabled; } else if (_ret == SK_DROP && _all_pass) { \ _all_pass = false; \ } \ - _item++; \ } \ _ctx->selected_sk = _selected_sk; \ _ctx->no_reuseport = _no_reuseport; \ -- 2.27.0