On Tue, 2024-02-27 at 16:12 -0800, Kui-Feng Lee wrote: [...] > It only has to scan once with an additional flag. > The value of the autoload of a prog should be > true if its autoload_user_set is false and autocreate of any one of > struct_ops maps pointing to the prog is true. > > Let's say the flag is autoload_autocreate. > In bpf_map__init_kern_struct_ops(), it has to check > prog->autoload_user_set, and do prog->autoload |= map->autocreate if > prog->autoload_user_set is false and autoload_autocreate is true. Do > prog->autoload = map->autocreate if autoload_autocreate is false I think > it is enough, right? > > if (!prog->autoload_user_set) { > if (!prog->autoload_autocreate) > prog->autoload = map->autocreate; > else > prog->autoload |= map->autocreate; > prog->autoload_autocreate = true; > } Since the full thing is moved to load phase I was hoping to make do w/o changes to struct bpf_program. To have it more contained. E.g. the code below apperas to work (needs more testing): --- 8< ------------------------------------- static int bpf_object__adjust_struct_ops_autoload(struct bpf_object *obj) { struct bpf_program *prog; struct bpf_map *map; int i, j, k, vlen; struct { __u8 autoload:1; /* only change autoload for programs that are * referenced from some struct_ops maps */ __u8 used:1; } *refs; refs = calloc(obj->nr_programs, sizeof(refs[0])); if (!refs) return -ENOMEM; for (i = 0; i < obj->nr_maps; i++) { map = &obj->maps[i]; if (!bpf_map__is_struct_ops(map)) continue; vlen = btf_vlen(map->st_ops->type); for (j = 0; j < vlen; ++j) { prog = map->st_ops->progs[j]; if (!prog) continue; k = prog - obj->programs; refs[k].used = true; refs[k].autoload |= map->autocreate; } } for (i = 0; i < obj->nr_programs; ++i) { prog = &obj->programs[i]; if (prog->autoload_user_set || !refs[i].used) continue; prog->autoload = refs[i].autoload; } free(refs); return 0; } ------------------------------------- >8 ---