Re: [PATCH v2 bpf-next 1/4] bpf: Search for kptrs in prog BTF structs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Aug 5, 2024 at 3:25 PM Martin KaFai Lau <martin.lau@xxxxxxxxx> wrote:
>
> On 8/5/24 1:44 PM, Amery Hung wrote:
> >>>>> Maybe we should move the common btf used by kptr and graph_root into
> >>>>> btf_record and let the callers of btf_parse_fields() and
> >>>>> btf_record_free() to decide the life cycle of btf in btf_record.
> >>>> Could you maybe explain if and why moving btf of btf_field_kptr and
> >>>> btf_field_graph_root to btf_record is necessary? I think letting
> >>>> callers of btf_parse_fields() and btf_record_free() decide whether or
> >>>> not to change refcount should be enough. Besides, I personally would
> >>>> like to keep individual btf in btf_field_kptr and
> >>>> btf_field_graph_root, so that later we can have special fields
> >>>> referencing different btf.
> >>>
> >>> Sorry, I didn't express the rough idea clearly enough. I didn't mean to
> >>> move btf of btf_field_kptr and btf_field_graph_root to btf_record,
> >>> because there are other btf-s which are different with the btf which
> >>> creates the struct_meta_tab. What I was trying to suggest is to save one
> >>> btf in btf_record and hope it will simplify the pin and the unpin of btf
> >>> in btf_record:
> >>>
> >>> 1) save the btf which owns the btf_record in btf_record.
> >>> 2) during btf_parse_kptr() or similar, if the used btf is the same as
> >>> the btf in btf_record, there is no need to pin the btf
> >>
> >> I assume the used btf is the one that btf_parse is working on.
> >>
> >>> 3) when freeing the btf_record, if the btf saved in btf_field is the
> >>> same as the btf in btf_record, there is no need to put it
> >>
> >> For btf_field_kptr.btf, is it the same as testing the btf_field_kptr.btf is
> >> btf_is_kernel() or not? How about only does btf_get/put for btf_is_kernel()?
> >>
> >
> > IIUC. It will not be the same. For a map referencing prog btf, I
> > suppose we should still do btf_get().
> >
> > I think the core idea is since a btf_record and the prog btf
> > containing it has the same life time, we don't need to
> > btf_get()/btf_put() in btf_parse_kptr()/btf_record_free() when a
> > btf_field_kptr.btf is referencing itself.
> >
> > However, since btf_parse_kptr() called from btf_parse() and
> > map_check_btf() all use prog btf, we need a way to differentiate the
> > two. Hence Hou suggested saving the owner's btf in btf_record, and
>
> map_check_btf() calls btf_parse_kptr(map->btf).
>
> I am missing how it is different from the
> btf_new_fd()=>btf_parse()=>btf_parse_kptr(new_btf).
>
> akaik, the map->record has no issue now because bpf_map_free_deferred() does
> btf_record_free(map->record) before btf_put(map->btf). In the map->record case,
> does the map->record need to take a refcnt of the btf_field_kptr.btf if the
> btf_field_kptr.btf is pointing back to itself (map->btf) which is not a kernel btf?
>
> > then check if btf_record->btf is the same as the btf_field_kptr.btf in
> > btf_parse_kptr()/btf_record_free().
>
> I suspect it will have the same end result? The btf_field_kptr.btf is only the
> same as the owner's btf when btf_parse_kptr() cannot found the kptr type from a
> kernel's btf (the id == -ENOENT case in btf_parse_kptr).

I added some code to better explain how I think it could work.

I am thinking about adding a struct btf* under struct btf_record, and
then adding an argument in btf_parse_fields:

btf_parse_fields(const struct btf *btf,..., bool btf_is_owner)
{
        ...
        /* Before the for loop that goes through info_arr */
        rec->btf = btf_is_owner ? btf : NULL;
        ...
}

The btf_is_owner indicates whether the btf_record returned by the
function will be part of the btf. So map_check_btf() will set it to
false while btf_parse() will set it to true. Maybe "owner" is what
makes it confusing? (btf_record for a map belongs to bpf_map but not
map->btf. On the other hand, btf_record for a prog btf is part of it.)

Then, in btf_record_free(), we can do:

case BPF_KPTR_XXX:
        ...
        if (rec->btf != rec->fields[i].kptr.btf)
                btf_put(rec->fields[i].kptr.btf);

In btf_parse_kptr(), we also do similar things. We just need to pass
btf_record into it.





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux