diff mbox series

[bpf-next,1/3] libbpf: introduce more granular state for bpf_object

Message ID 20250228175255.254009-2-mykyta.yatsenko5@gmail.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series Introduce bpf_object__prepare | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / GCC BPF
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / GCC BPF
bpf/vmtest-bpf-next-VM_Test-12 success Logs for aarch64-gcc / veristat-meta
bpf/vmtest-bpf-next-VM_Test-11 success Logs for aarch64-gcc / veristat-kernel
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-15 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-19 success Logs for s390x-gcc / veristat-kernel
bpf/vmtest-bpf-next-VM_Test-21 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for s390x-gcc / veristat-meta
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-gcc / veristat-meta / x86_64-gcc veristat_meta
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-gcc / veristat-kernel / x86_64-gcc veristat_kernel
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-17 / veristat-kernel
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-17 / veristat-meta
bpf/vmtest-bpf-next-VM_Test-44 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-43 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-45 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-50 success Logs for x86_64-llvm-18 / veristat-kernel
bpf/vmtest-bpf-next-VM_Test-49 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-51 success Logs for x86_64-llvm-18 / veristat-meta
bpf/vmtest-bpf-next-VM_Test-8 success Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / GCC BPF / GCC BPF
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / GCC BPF / GCC BPF
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / GCC BPF / GCC BPF
bpf/vmtest-bpf-next-VM_Test-46 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-47 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-48 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/build_tools success Errors and warnings before: 26 (+1) this patch: 26 (+1)
netdev/cc_maintainers warning 8 maintainers not CCed: song@kernel.org kpsingh@kernel.org john.fastabend@gmail.com jolsa@kernel.org yonghong.song@linux.dev haoluo@google.com sdf@fomichev.me martin.lau@linux.dev
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 178 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Mykyta Yatsenko Feb. 28, 2025, 5:52 p.m. UTC
From: Mykyta Yatsenko <yatsenko@meta.com>

Add struct bpf_object_state, substitute bpf_object member loaded by
state. State could be OBJ_OPEN - indicates that bpf_object was just
created, OBJ_PREPARED - prepare step will be introduced in the next
patch, OBJ_LOADED - indicates that bpf_object is loaded, similar to
loaded=true currently.

Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
---
 tools/lib/bpf/libbpf.c | 47 +++++++++++++++++++++++-------------------
 1 file changed, 26 insertions(+), 21 deletions(-)

Comments

Andrii Nakryiko Feb. 28, 2025, 10:20 p.m. UTC | #1
On Fri, Feb 28, 2025 at 9:53 AM Mykyta Yatsenko
<mykyta.yatsenko5@gmail.com> wrote:
>
> From: Mykyta Yatsenko <yatsenko@meta.com>
>
> Add struct bpf_object_state, substitute bpf_object member loaded by
> state. State could be OBJ_OPEN - indicates that bpf_object was just
> created, OBJ_PREPARED - prepare step will be introduced in the next
> patch, OBJ_LOADED - indicates that bpf_object is loaded, similar to
> loaded=true currently.
>
> Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
> ---
>  tools/lib/bpf/libbpf.c | 47 +++++++++++++++++++++++-------------------
>  1 file changed, 26 insertions(+), 21 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 899e98225f3b..9ced1ce2334c 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -670,11 +670,18 @@ struct elf_state {
>
>  struct usdt_manager;
>
> +enum bpf_object_state {
> +       OBJ_OPEN,
> +       OBJ_PREPARED,
> +       OBJ_LOADED,
> +};
> +
>  struct bpf_object {
>         char name[BPF_OBJ_NAME_LEN];
>         char license[64];
>         __u32 kern_version;
>
> +       enum bpf_object_state state;
>         struct bpf_program *programs;
>         size_t nr_programs;
>         struct bpf_map *maps;
> @@ -686,7 +693,6 @@ struct bpf_object {
>         int nr_extern;
>         int kconfig_map_idx;
>
> -       bool loaded;
>         bool has_subcalls;
>         bool has_rodata;
>
> @@ -1511,7 +1517,7 @@ static struct bpf_object *bpf_object__new(const char *path,
>         obj->kconfig_map_idx = -1;
>
>         obj->kern_version = get_kernel_version();
> -       obj->loaded = false;
> +       obj->state  = OBJ_OPEN;
>
>         return obj;
>  }
> @@ -4852,7 +4858,7 @@ bool bpf_map__autocreate(const struct bpf_map *map)
>
>  int bpf_map__set_autocreate(struct bpf_map *map, bool autocreate)
>  {
> -       if (map->obj->loaded)
> +       if (map->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EBUSY);
>
>         map->autocreate = autocreate;
> @@ -4946,7 +4952,7 @@ struct bpf_map *bpf_map__inner_map(struct bpf_map *map)
>
>  int bpf_map__set_max_entries(struct bpf_map *map, __u32 max_entries)
>  {
> -       if (map->obj->loaded)
> +       if (map->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EBUSY);
>
>         map->def.max_entries = max_entries;
> @@ -5193,7 +5199,7 @@ static void bpf_map__destroy(struct bpf_map *map);
>
>  static bool map_is_created(const struct bpf_map *map)
>  {
> -       return map->obj->loaded || map->reused;
> +       return map->obj->state >= OBJ_LOADED || map->reused;
>  }
>
>  static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, bool is_inner)
> @@ -8550,7 +8556,7 @@ static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch
>         if (!obj)
>                 return libbpf_err(-EINVAL);
>
> -       if (obj->loaded) {
> +       if (obj->state >= OBJ_LOADED) {
>                 pr_warn("object '%s': load can't be attempted twice\n", obj->name);
>                 return libbpf_err(-EINVAL);
>         }
> @@ -8602,8 +8608,7 @@ static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch
>         btf__free(obj->btf_vmlinux);
>         obj->btf_vmlinux = NULL;
>
> -       obj->loaded = true; /* doesn't matter if successfully or not */
> -
> +       obj->state = OBJ_LOADED;/* doesn't matter if successfully or not */
>         if (err)
>                 goto out;
>
> @@ -8866,7 +8871,7 @@ int bpf_object__pin_maps(struct bpf_object *obj, const char *path)
>         if (!obj)
>                 return libbpf_err(-ENOENT);
>
> -       if (!obj->loaded) {
> +       if (obj->state < OBJ_LOADED) {

this one seems ok in OBJ_PREPARED as well, all the maps will be
created by that time

>                 pr_warn("object not yet loaded; load it first\n");
>                 return libbpf_err(-ENOENT);
>         }
> @@ -8945,7 +8950,7 @@ int bpf_object__pin_programs(struct bpf_object *obj, const char *path)
>         if (!obj)
>                 return libbpf_err(-ENOENT);
>
> -       if (!obj->loaded) {
> +       if (obj->state < OBJ_LOADED) {
>                 pr_warn("object not yet loaded; load it first\n");
>                 return libbpf_err(-ENOENT);
>         }
> @@ -9132,7 +9137,7 @@ int bpf_object__btf_fd(const struct bpf_object *obj)
>
>  int bpf_object__set_kversion(struct bpf_object *obj, __u32 kern_version)
>  {
> -       if (obj->loaded)
> +       if (obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EINVAL);
>
>         obj->kern_version = kern_version;
> @@ -9229,7 +9234,7 @@ bool bpf_program__autoload(const struct bpf_program *prog)
>
>  int bpf_program__set_autoload(struct bpf_program *prog, bool autoload)
>  {
> -       if (prog->obj->loaded)
> +       if (prog->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EINVAL);
>
>         prog->autoload = autoload;
> @@ -9261,7 +9266,7 @@ int bpf_program__set_insns(struct bpf_program *prog,
>  {
>         struct bpf_insn *insns;
>
> -       if (prog->obj->loaded)
> +       if (prog->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EBUSY);
>
>         insns = libbpf_reallocarray(prog->insns, new_insn_cnt, sizeof(*insns));
> @@ -9304,7 +9309,7 @@ static int last_custom_sec_def_handler_id;
>
>  int bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type)
>  {
> -       if (prog->obj->loaded)
> +       if (prog->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EBUSY);
>
>         /* if type is not changed, do nothing */
> @@ -9335,7 +9340,7 @@ enum bpf_attach_type bpf_program__expected_attach_type(const struct bpf_program
>  int bpf_program__set_expected_attach_type(struct bpf_program *prog,
>                                            enum bpf_attach_type type)
>  {
> -       if (prog->obj->loaded)
> +       if (prog->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EBUSY);
>
>         prog->expected_attach_type = type;
> @@ -9349,7 +9354,7 @@ __u32 bpf_program__flags(const struct bpf_program *prog)
>
>  int bpf_program__set_flags(struct bpf_program *prog, __u32 flags)
>  {
> -       if (prog->obj->loaded)
> +       if (prog->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EBUSY);
>
>         prog->prog_flags = flags;
> @@ -9363,7 +9368,7 @@ __u32 bpf_program__log_level(const struct bpf_program *prog)
>
>  int bpf_program__set_log_level(struct bpf_program *prog, __u32 log_level)
>  {
> -       if (prog->obj->loaded)
> +       if (prog->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EBUSY);
>
>         prog->log_level = log_level;
> @@ -9382,7 +9387,7 @@ int bpf_program__set_log_buf(struct bpf_program *prog, char *log_buf, size_t log
>                 return libbpf_err(-EINVAL);
>         if (prog->log_size > UINT_MAX)
>                 return libbpf_err(-EINVAL);
> -       if (prog->obj->loaded)
> +       if (prog->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EBUSY);
>
>         prog->log_buf = log_buf;
> @@ -10299,7 +10304,7 @@ static int map_btf_datasec_resize(struct bpf_map *map, __u32 size)
>
>  int bpf_map__set_value_size(struct bpf_map *map, __u32 size)
>  {
> -       if (map->obj->loaded || map->reused)
> +       if (map->obj->state >= OBJ_LOADED || map->reused)

OBJ_PREPARED, maps can't be changed after that step

>                 return libbpf_err(-EBUSY);
>
>         if (map->mmaped) {
> @@ -10345,7 +10350,7 @@ int bpf_map__set_initial_value(struct bpf_map *map,
>  {
>         size_t actual_sz;
>
> -       if (map->obj->loaded || map->reused)
> +       if (map->obj->state >= OBJ_LOADED || map->reused)

ditto, I think we have to ban it after OBJ_PREPARED


>                 return libbpf_err(-EBUSY);
>
>         if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG)
> @@ -13666,7 +13671,7 @@ int bpf_program__set_attach_target(struct bpf_program *prog,
>         if (!prog || attach_prog_fd < 0)
>                 return libbpf_err(-EINVAL);
>
> -       if (prog->obj->loaded)
> +       if (prog->obj->state >= OBJ_LOADED)
>                 return libbpf_err(-EINVAL);
>
>         if (attach_prog_fd && !attach_func_name) {
> --
> 2.48.1
>
Andrii Nakryiko Feb. 28, 2025, 10:35 p.m. UTC | #2
On Fri, Feb 28, 2025 at 9:53 AM Mykyta Yatsenko
<mykyta.yatsenko5@gmail.com> wrote:
>
> From: Mykyta Yatsenko <yatsenko@meta.com>
>
> Add struct bpf_object_state, substitute bpf_object member loaded by
> state. State could be OBJ_OPEN - indicates that bpf_object was just
> created, OBJ_PREPARED - prepare step will be introduced in the next
> patch, OBJ_LOADED - indicates that bpf_object is loaded, similar to
> loaded=true currently.
>

This is a bit too low-level and explains "what" at a very mechanistic
level, but not really higher-level "what" and "why". Try to make it a
bit more useful for future readers. E.g., something along the lines
that "we are going to split load step into preparation and loading, to
allow more flexibility when working with bpf_object, and this patch
adds a finer-grained object state enum instead of previous boolean
loaded flag".

> Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
> ---
>  tools/lib/bpf/libbpf.c | 47 +++++++++++++++++++++++-------------------
>  1 file changed, 26 insertions(+), 21 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 899e98225f3b..9ced1ce2334c 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -670,11 +670,18 @@ struct elf_state {
>
>  struct usdt_manager;
>

[...]
diff mbox series

Patch

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 899e98225f3b..9ced1ce2334c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -670,11 +670,18 @@  struct elf_state {
 
 struct usdt_manager;
 
+enum bpf_object_state {
+	OBJ_OPEN,
+	OBJ_PREPARED,
+	OBJ_LOADED,
+};
+
 struct bpf_object {
 	char name[BPF_OBJ_NAME_LEN];
 	char license[64];
 	__u32 kern_version;
 
+	enum bpf_object_state state;
 	struct bpf_program *programs;
 	size_t nr_programs;
 	struct bpf_map *maps;
@@ -686,7 +693,6 @@  struct bpf_object {
 	int nr_extern;
 	int kconfig_map_idx;
 
-	bool loaded;
 	bool has_subcalls;
 	bool has_rodata;
 
@@ -1511,7 +1517,7 @@  static struct bpf_object *bpf_object__new(const char *path,
 	obj->kconfig_map_idx = -1;
 
 	obj->kern_version = get_kernel_version();
-	obj->loaded = false;
+	obj->state  = OBJ_OPEN;
 
 	return obj;
 }
@@ -4852,7 +4858,7 @@  bool bpf_map__autocreate(const struct bpf_map *map)
 
 int bpf_map__set_autocreate(struct bpf_map *map, bool autocreate)
 {
-	if (map->obj->loaded)
+	if (map->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EBUSY);
 
 	map->autocreate = autocreate;
@@ -4946,7 +4952,7 @@  struct bpf_map *bpf_map__inner_map(struct bpf_map *map)
 
 int bpf_map__set_max_entries(struct bpf_map *map, __u32 max_entries)
 {
-	if (map->obj->loaded)
+	if (map->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EBUSY);
 
 	map->def.max_entries = max_entries;
@@ -5193,7 +5199,7 @@  static void bpf_map__destroy(struct bpf_map *map);
 
 static bool map_is_created(const struct bpf_map *map)
 {
-	return map->obj->loaded || map->reused;
+	return map->obj->state >= OBJ_LOADED || map->reused;
 }
 
 static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, bool is_inner)
@@ -8550,7 +8556,7 @@  static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch
 	if (!obj)
 		return libbpf_err(-EINVAL);
 
-	if (obj->loaded) {
+	if (obj->state >= OBJ_LOADED) {
 		pr_warn("object '%s': load can't be attempted twice\n", obj->name);
 		return libbpf_err(-EINVAL);
 	}
@@ -8602,8 +8608,7 @@  static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch
 	btf__free(obj->btf_vmlinux);
 	obj->btf_vmlinux = NULL;
 
-	obj->loaded = true; /* doesn't matter if successfully or not */
-
+	obj->state = OBJ_LOADED;/* doesn't matter if successfully or not */
 	if (err)
 		goto out;
 
@@ -8866,7 +8871,7 @@  int bpf_object__pin_maps(struct bpf_object *obj, const char *path)
 	if (!obj)
 		return libbpf_err(-ENOENT);
 
-	if (!obj->loaded) {
+	if (obj->state < OBJ_LOADED) {
 		pr_warn("object not yet loaded; load it first\n");
 		return libbpf_err(-ENOENT);
 	}
@@ -8945,7 +8950,7 @@  int bpf_object__pin_programs(struct bpf_object *obj, const char *path)
 	if (!obj)
 		return libbpf_err(-ENOENT);
 
-	if (!obj->loaded) {
+	if (obj->state < OBJ_LOADED) {
 		pr_warn("object not yet loaded; load it first\n");
 		return libbpf_err(-ENOENT);
 	}
@@ -9132,7 +9137,7 @@  int bpf_object__btf_fd(const struct bpf_object *obj)
 
 int bpf_object__set_kversion(struct bpf_object *obj, __u32 kern_version)
 {
-	if (obj->loaded)
+	if (obj->state >= OBJ_LOADED)
 		return libbpf_err(-EINVAL);
 
 	obj->kern_version = kern_version;
@@ -9229,7 +9234,7 @@  bool bpf_program__autoload(const struct bpf_program *prog)
 
 int bpf_program__set_autoload(struct bpf_program *prog, bool autoload)
 {
-	if (prog->obj->loaded)
+	if (prog->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EINVAL);
 
 	prog->autoload = autoload;
@@ -9261,7 +9266,7 @@  int bpf_program__set_insns(struct bpf_program *prog,
 {
 	struct bpf_insn *insns;
 
-	if (prog->obj->loaded)
+	if (prog->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EBUSY);
 
 	insns = libbpf_reallocarray(prog->insns, new_insn_cnt, sizeof(*insns));
@@ -9304,7 +9309,7 @@  static int last_custom_sec_def_handler_id;
 
 int bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type)
 {
-	if (prog->obj->loaded)
+	if (prog->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EBUSY);
 
 	/* if type is not changed, do nothing */
@@ -9335,7 +9340,7 @@  enum bpf_attach_type bpf_program__expected_attach_type(const struct bpf_program
 int bpf_program__set_expected_attach_type(struct bpf_program *prog,
 					   enum bpf_attach_type type)
 {
-	if (prog->obj->loaded)
+	if (prog->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EBUSY);
 
 	prog->expected_attach_type = type;
@@ -9349,7 +9354,7 @@  __u32 bpf_program__flags(const struct bpf_program *prog)
 
 int bpf_program__set_flags(struct bpf_program *prog, __u32 flags)
 {
-	if (prog->obj->loaded)
+	if (prog->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EBUSY);
 
 	prog->prog_flags = flags;
@@ -9363,7 +9368,7 @@  __u32 bpf_program__log_level(const struct bpf_program *prog)
 
 int bpf_program__set_log_level(struct bpf_program *prog, __u32 log_level)
 {
-	if (prog->obj->loaded)
+	if (prog->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EBUSY);
 
 	prog->log_level = log_level;
@@ -9382,7 +9387,7 @@  int bpf_program__set_log_buf(struct bpf_program *prog, char *log_buf, size_t log
 		return libbpf_err(-EINVAL);
 	if (prog->log_size > UINT_MAX)
 		return libbpf_err(-EINVAL);
-	if (prog->obj->loaded)
+	if (prog->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EBUSY);
 
 	prog->log_buf = log_buf;
@@ -10299,7 +10304,7 @@  static int map_btf_datasec_resize(struct bpf_map *map, __u32 size)
 
 int bpf_map__set_value_size(struct bpf_map *map, __u32 size)
 {
-	if (map->obj->loaded || map->reused)
+	if (map->obj->state >= OBJ_LOADED || map->reused)
 		return libbpf_err(-EBUSY);
 
 	if (map->mmaped) {
@@ -10345,7 +10350,7 @@  int bpf_map__set_initial_value(struct bpf_map *map,
 {
 	size_t actual_sz;
 
-	if (map->obj->loaded || map->reused)
+	if (map->obj->state >= OBJ_LOADED || map->reused)
 		return libbpf_err(-EBUSY);
 
 	if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG)
@@ -13666,7 +13671,7 @@  int bpf_program__set_attach_target(struct bpf_program *prog,
 	if (!prog || attach_prog_fd < 0)
 		return libbpf_err(-EINVAL);
 
-	if (prog->obj->loaded)
+	if (prog->obj->state >= OBJ_LOADED)
 		return libbpf_err(-EINVAL);
 
 	if (attach_prog_fd && !attach_func_name) {