Skip to content

Conversation

@opsiff
Copy link
Member

@opsiff opsiff commented Sep 15, 2025

mainline inclusion
from mainline-v6.7-rc1
category: feature

Current code charges modmem for regular trampoline, but not for struct_ops trampoline. Add bpf_jit_[charge|uncharge]_modmem() to struct_ops so the trampoline is charged in both cases.

Link: https://lore.kernel.org/r/[email protected]

(cherry picked from commit 5c04433)

Summary by Sourcery

Account for module memory usage in BPF struct_ops JIT trampolines by adding modmem charge and uncharge calls during allocation and free

New Features:

  • Charge modmem when allocating struct_ops JIT trampolines

Enhancements:

  • Uncharge modmem when freeing struct_ops JIT trampolines

mainline inclusion
from mainline-v6.7-rc1
category: feature

Current code charges modmem for regular trampoline, but not for struct_ops
trampoline. Add bpf_jit_[charge|uncharge]_modmem() to struct_ops so the
trampoline is charged in both cases.

Signed-off-by: Song Liu <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Martin KaFai Lau <[email protected]>
(cherry picked from commit 5c04433)
Signed-off-by: Wentao Guan <[email protected]>
@sourcery-ai
Copy link

sourcery-ai bot commented Sep 15, 2025

Reviewer's Guide

Introduce modmem charging and uncharging for struct_ops trampolines to match regular trampolines, updating allocation and free paths with proper error handling.

Sequence diagram for struct_ops trampoline allocation and modmem charging

sequenceDiagram
participant Caller
participant "bpf_struct_ops_map_alloc()"
participant "bpf_jit_charge_modmem()"
participant "bpf_jit_alloc_exec()"
participant "bpf_jit_uncharge_modmem()"
participant "__bpf_struct_ops_map_free()"
Caller->>"bpf_struct_ops_map_alloc()": Request struct_ops map allocation
"bpf_struct_ops_map_alloc()"->>"bpf_jit_charge_modmem()": Charge modmem for trampoline
alt Charge fails
    "bpf_struct_ops_map_alloc()"->>"__bpf_struct_ops_map_free()": Free resources
    "bpf_struct_ops_map_alloc()"-->>Caller: Return error
else Charge succeeds
    "bpf_struct_ops_map_alloc()"->>"bpf_jit_alloc_exec()": Allocate trampoline image
    alt Allocation fails
        "bpf_struct_ops_map_alloc()"->>"bpf_jit_uncharge_modmem()": Uncharge modmem
        "bpf_struct_ops_map_alloc()"->>"__bpf_struct_ops_map_free()": Free resources
        "bpf_struct_ops_map_alloc()"-->>Caller: Return error
    else Allocation succeeds
        "bpf_struct_ops_map_alloc()"-->>Caller: Return map
    end
end
Loading

Sequence diagram for struct_ops trampoline free and modmem uncharging

sequenceDiagram
participant Caller
participant "__bpf_struct_ops_map_free()"
participant "bpf_jit_free_exec()"
participant "bpf_jit_uncharge_modmem()"
Caller->>"__bpf_struct_ops_map_free()": Free struct_ops map
alt st_map->image exists
    "__bpf_struct_ops_map_free()"->>"bpf_jit_free_exec()": Free trampoline image
    "__bpf_struct_ops_map_free()"->>"bpf_jit_uncharge_modmem()": Uncharge modmem
end
"__bpf_struct_ops_map_free()"-->>Caller: Done
Loading

File-Level Changes

Change Details Files
Integrate modmem charge/uncharge around struct_ops JIT image
  • Call bpf_jit_charge_modmem(PAGE_SIZE) before allocating the JIT image
  • Invoke bpf_jit_uncharge_modmem(PAGE_SIZE) when freeing the image if present
  • Uncharge modmem on allocation failures before cleanup
kernel/bpf/bpf_struct_ops.c
Refactor struct_ops map allocation and error handling
  • Add ret variable to capture charge result
  • Reorder and consolidate st_map->image allocation logic
  • Remove duplicate image allocation at end
  • Adjust null checks to only verify uvalue and links
kernel/bpf/bpf_struct_ops.c

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from opsiff. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@opsiff opsiff changed the title [Deepin-Kernel-SIG] [linux 6.6-y] [Deepin] bpf: Charge modmem for struct_ops trampoline [Deepin-Kernel-SIG] [linux 6.6-y] [Upstream] bpf: Charge modmem for struct_ops trampoline Sep 15, 2025
@deepin-ci-robot
Copy link

deepin pr auto review

这段代码是关于BPF (Berkeley Packet Filter) struct_ops实现的部分修改,主要涉及到内存分配和释放的改进。我来对这段代码进行审查:

1. 语法逻辑

代码语法正确,逻辑流程清晰。主要改进是将内存分配和释放的操作进行了更细致的处理,特别是对image相关的内存管理增加了更多的错误处理。

2. 代码质量

代码质量有所提升,主要表现在:

  • 增加了对image分配失败时的处理
  • 添加了bpf_jit_charge_modmembpf_jit_uncharge_modmem的配对调用
  • 改进了错误处理路径,确保资源正确释放

3. 代码性能

性能方面没有明显变化,因为主要是对错误处理路径的改进,不会影响正常执行路径的性能。

4. 代码安全

安全性的改进较为显著:

  • 增加了内存分配失败时的资源释放
  • 确保image分配和释放的配对操作
  • 添加了对image为NULL的检查,避免空指针解引用

改进建议:

  1. __bpf_struct_ops_map_free函数中,对image的检查可以更早进行,避免不必要的其他资源释放操作:
static void __bpf_struct_ops_map_free(struct bpf_map *map)
{
    struct bpf_struct_ops_map *st_map = container_of(map, struct bpf_struct_ops_map, map);
    
    if (st_map->image) {
        bpf_jit_free_exec(st_map->image);
        bpf_jit_uncharge_modmem(PAGE_SIZE);
    }
    if (st_map->links)
        bpf_struct_ops_map_put_progs(st_map);
    bpf_map_area_free(st_map->links);
    bpf_map_area_free(st_map->uvalue);
    bpf_map_area_free(st_map);
}
  1. bpf_struct_ops_map_alloc函数中,可以考虑将内存分配操作集中处理,便于错误处理:
static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr)
{
    struct bpf_struct_ops_map *st_map;
    const struct btf_type *t, *vt;
    struct bpf_map *map;
    int ret;

    st_ops = bpf_struct_ops_find_value(attr->btf_vmlinux_value_type_id);
    if (!st_ops)
        return ERR_PTR(-ENOENT);

    t = st_ops->type;
    vt = btf_type_by_id(st_ops->btf, st_ops->value_type_id);
    if (!t || !vt)
        return ERR_PTR(-EINVAL);

    st_map = bpf_map_area_alloc(sizeof(*st_map), NUMA_NO_NODE);
    if (!st_map)
        return ERR_PTR(-ENOMEM);

    st_map->st_ops = st_ops;
    map = &st_map->map;

    ret = bpf_jit_charge_modmem(PAGE_SIZE);
    if (ret) {
        bpf_map_area_free(st_map);
        return ERR_PTR(ret);
    }

    st_map->image = bpf_jit_alloc_exec(PAGE_SIZE);
    if (!st_map->image) {
        bpf_jit_uncharge_modmem(PAGE_SIZE);
        bpf_map_area_free(st_map);
        return ERR_PTR(-ENOMEM);
    }

    st_map->uvalue = bpf_map_area_alloc(vt->size, NUMA_NO_NODE);
    st_map->links = bpf_map_area_alloc(btf_type_vlen(t) * sizeof(struct bpf_links *), NUMA_NO_NODE);
    
    if (!st_map->uvalue || !st_map->links) {
        __bpf_struct_ops_map_free(map);
        return ERR_PTR(-ENOMEM);
    }

    return map;
}

这些改进可以使代码更加健壮,错误处理更加完善,同时保持代码的可读性和可维护性。

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dongert dongert requested a review from Copilot October 27, 2025 06:07
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR backports a kernel patch from mainline v6.7-rc1 that adds proper module memory accounting for BPF struct_ops trampolines. Currently, modmem is charged for regular trampolines but not for struct_ops trampolines, creating an accounting inconsistency.

Key changes:

  • Adds bpf_jit_charge_modmem() call during struct_ops map allocation to account for trampoline memory
  • Adds bpf_jit_uncharge_modmem() call during map cleanup to properly release the memory charge

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

st_map->image = bpf_jit_alloc_exec(PAGE_SIZE);
if (!st_map->image) {
/* __bpf_struct_ops_map_free() uses st_map->image as flag
* for "charged or not". In this case, we need to unchange
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'unchange' to 'uncharge'.

Suggested change
* for "charged or not". In this case, we need to unchange
* for "charged or not". In this case, we need to uncharge

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants