When using GCC on x86-64 to compile an usdt prog with -O1 or higher
optimization, the compiler will generate SIB addressing mode for global
array and PC-relative addressing mode for global variable,
e.g. "1@-96(%rbp,%rax,8)" and "-1@4+t1(%rip)".
The current USDT implementation in libbpf cannot parse these two formats,
causing `bpf_program__attach_usdt()` to fail with -ENOENT
(unrecognized register).
This patch series adds support for SIB addressing mode in USDT probes.
The main changes include:
- add correct handling logic for SIB-addressed arguments in
`parse_usdt_arg`.
- add an usdt_o2 test case to cover SIB addressing mode.
Testing shows that the SIB probe correctly generates 8@(%rcx,%rax,8)
argument spec and passes all validation checks.
The modification history of this patch series:
Change since v1:
- refactor the code to make it more readable
- modify the commit message to explain why and how
Change since v2:
- fix the `scale` uninitialized error
Change since v3:
- force -O2 optimization for usdt.test.o to generate SIB addressing usdt
and pass all test cases.
Change since v4:
- split the patch into two parts, one for the fix and the other for the
test
Change since v5:
- Only enable optimization for x86 architecture to generate SIB addressing
usdt argument spec.
Change since v6:
- Add an usdt_o2 test case to cover SIB addressing mode.
- Reinstate the usdt.c test case.
Change since v7:
- Refactor modifications to __bpf_usdt_arg_spec to avoid increasing its size,
achieving better compatibility
- Fix some minor code style issues
- Refactor the usdt_o2 test case, removing semaphore and adding GCC attribute
to force -O2 optimization
Jiawei Zhao (2):
libbpf: fix USDT SIB argument handling causing unrecognized register
error
selftests/bpf: Add an usdt_o2 test case in selftests to cover SIB
handling logic
tools/lib/bpf/usdt.bpf.h | 55 ++++++++++++++-
tools/lib/bpf/usdt.c | 61 ++++++++++++++--
tools/testing/selftests/bpf/Makefile | 1 +
.../selftests/bpf/prog_tests/usdt_o2.c | 69 +++++++++++++++++++
.../selftests/bpf/progs/test_usdt_o2.c | 37 ++++++++++
5 files changed, 216 insertions(+), 7 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/usdt_o2.c
create mode 100644 tools/testing/selftests/bpf/progs/test_usdt_o2.c
--
2.43.0
When using GCC on x86-64 to compile an usdt prog with -O1 or higher
optimization, the compiler will generate SIB addressing mode for global
array and PC-relative addressing mode for global variable,
e.g. "1@-96(%rbp,%rax,8)" and "-1@4+t1(%rip)".
The current USDT implementation in libbpf cannot parse these two formats,
causing `bpf_program__attach_usdt()` to fail with -ENOENT
(unrecognized register).
This patch series adds support for SIB addressing mode in USDT probes.
The main changes include:
- add correct handling logic for SIB-addressed arguments in
`parse_usdt_arg`.
- add an usdt_o2 test case to cover SIB addressing mode.
Testing shows that the SIB probe correctly generates 8@(%rcx,%rax,8)
argument spec and passes all validation checks.
The modification history of this patch series:
Change since v1:
- refactor the code to make it more readable
- modify the commit message to explain why and how
Change since v2:
- fix the `scale` uninitialized error
Change since v3:
- force -O2 optimization for usdt.test.o to generate SIB addressing usdt
and pass all test cases.
Change since v4:
- split the patch into two parts, one for the fix and the other for the
test
Change since v5:
- Only enable optimization for x86 architecture to generate SIB addressing
usdt argument spec.
Change since v6:
- Add an usdt_o2 test case to cover SIB addressing mode.
- Reinstate the usdt.c test case.
Change since v7:
- Refactor modifications to __bpf_usdt_arg_spec to avoid increasing its size,
achieving better compatibility
- Fix some minor code style issues
- Refactor the usdt_o2 test case, removing semaphore and adding GCC attribute
to force -O2 optimization
Change since v8:
- Refactor the usdt_o2 test case, using assembly to force SIB addressing mode.
Jiawei Zhao (3):
libbpf: fix USDT SIB argument handling causing unrecognized register
error
selftests/bpf: Add an usdt_o2 test case in selftests to cover SIB
handling logic
selftests/bpf: make usdt_o2 reliably generate SIB USDT arg spec
tools/lib/bpf/usdt.bpf.h | 54 +++++++++++++-
tools/lib/bpf/usdt.c | 61 ++++++++++++++--
tools/testing/selftests/bpf/Makefile | 1 +
.../selftests/bpf/prog_tests/usdt_o2.c | 73 +++++++++++++++++++
.../selftests/bpf/progs/test_usdt_o2.c | 37 ++++++++++
5 files changed, 219 insertions(+), 7 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/usdt_o2.c
create mode 100644 tools/testing/selftests/bpf/progs/test_usdt_o2.c
--
2.43.0
When using GCC on x86-64 to compile an usdt prog with -O1 or higher
optimization, the compiler will generate SIB addressing mode for global
array and PC-relative addressing mode for global variable,
e.g. "1@-96(%rbp,%rax,8)" and "-1@4+t1(%rip)".
The current USDT implementation in libbpf cannot parse these two formats,
causing `bpf_program__attach_usdt()` to fail with -ENOENT
(unrecognized register).
This patch series adds support for SIB addressing mode in USDT probes.
The main changes include:
- add correct handling logic for SIB-addressed arguments in
`parse_usdt_arg`.
- add an usdt_o2 test case to cover SIB addressing mode.
Testing shows that the SIB probe correctly generates 8@(%rcx,%rax,8)
argument spec and passes all validation checks.
The modification history of this patch series:
Change since v1:
- refactor the code to make it more readable
- modify the commit message to explain why and how
Change since v2:
- fix the `scale` uninitialized error
Change since v3:
- force -O2 optimization for usdt.test.o to generate SIB addressing usdt
and pass all test cases.
Change since v4:
- split the patch into two parts, one for the fix and the other for the
test
Change since v5:
- Only enable optimization for x86 architecture to generate SIB addressing
usdt argument spec.
Change since v6:
- Add an usdt_o2 test case to cover SIB addressing mode.
- Reinstate the usdt.c test case.
Change since v7:
- Refactor modifications to __bpf_usdt_arg_spec to avoid increasing its size,
achieving better compatibility
- Fix some minor code style issues
- Refactor the usdt_o2 test case, removing semaphore and adding GCC attribute
to force -O2 optimization
Change since v8:
- Refactor the usdt_o2 test case, using assembly to force SIB addressing mode.
Jiawei Zhao (3):
libbpf: fix USDT SIB argument handling causing unrecognized register
error
selftests/bpf: Add an usdt_o2 test case in selftests to cover SIB
handling logic
selftests/bpf: make usdt_o2 reliably generate SIB USDT arg spec
tools/lib/bpf/usdt.bpf.h | 54 +-
tools/lib/bpf/usdt.c | 61 +-
tools/testing/selftests/bpf/Makefile | 1 +
.../selftests/bpf/prog_tests/usdt_o2.c | 73 +
.../selftests/bpf/progs/test_usdt_o2.c | 37 +
tools/testing/selftests/bpf/record.log | 22207 ++++++++++++++++
6 files changed, 22426 insertions(+), 7 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/usdt_o2.c
create mode 100644 tools/testing/selftests/bpf/progs/test_usdt_o2.c
create mode 100644 tools/testing/selftests/bpf/record.log
--
2.43.0
Named resources attached to a KUnit test must be unique. Currently, the
check for existing named resources in kunit_add_named_resource() is
performed without a lock. While KUnit is largely single-threaded, a
race condition could theoretically lead to multiple resources with the
same name being added.
To prevent this, the uniqueness check logic has been moved into the locked
portion of the __kunit_add_resource() function. This ensures that the
check and resource addition are atomic, preventing duplicate named
resources.
Signed-off-by: Marie Zhussupova <marievic(a)google.com>
---
This patch raises a fundamental question about KUnit's concurrency model.
What are the thread-safety guarantees that KUnit should provide? Should
these guarantees be formally defined before we introduce changes like
this one?
It would be great to have everyone's thoughts on this, as it could have
implications on how we have handle concurrency in KUnit going forward.
---
include/kunit/resource.h | 84 ++++++++++++++++++++++++++++++----------
lib/kunit/resource.c | 12 +++++-
2 files changed, 74 insertions(+), 22 deletions(-)
diff --git a/include/kunit/resource.h b/include/kunit/resource.h
index 4ad69a2642a5..7b33f332769c 100644
--- a/include/kunit/resource.h
+++ b/include/kunit/resource.h
@@ -148,12 +148,14 @@ static inline void kunit_put_resource(struct kunit_resource *res)
* If an init function is supplied, @data is passed to it instead.
* @free: a user-supplied function to free the resource (if needed).
* @res: The resource.
+ * @name: name of the resource if there is one.
* @data: value to pass to init function or set in resource data field.
*/
int __kunit_add_resource(struct kunit *test,
kunit_resource_init_t init,
kunit_resource_free_t free,
struct kunit_resource *res,
+ const char *name,
void *data);
/**
@@ -173,7 +175,7 @@ static inline int kunit_add_resource(struct kunit *test,
void *data)
{
res->should_kfree = false;
- return __kunit_add_resource(test, init, free, res, data);
+ return __kunit_add_resource(test, init, free, res, NULL, data);
}
static inline struct kunit_resource *
@@ -195,21 +197,14 @@ static inline int kunit_add_named_resource(struct kunit *test,
const char *name,
void *data)
{
- struct kunit_resource *existing;
if (!name)
return -EINVAL;
- existing = kunit_find_named_resource(test, name);
- if (existing) {
- kunit_put_resource(existing);
- return -EEXIST;
- }
-
res->name = name;
res->should_kfree = false;
- return __kunit_add_resource(test, init, free, res, data);
+ return __kunit_add_resource(test, init, free, res, name, data);
}
/**
@@ -249,7 +244,7 @@ kunit_alloc_and_get_resource(struct kunit *test,
res->should_kfree = true;
- ret = __kunit_add_resource(test, init, free, res, context);
+ ret = __kunit_add_resource(test, init, free, res, NULL, context);
if (!ret) {
/*
* bump refcount for get; kunit_resource_put() should be called
@@ -290,7 +285,7 @@ static inline void *kunit_alloc_resource(struct kunit *test,
return NULL;
res->should_kfree = true;
- if (!__kunit_add_resource(test, init, free, res, context))
+ if (!__kunit_add_resource(test, init, free, res, NULL, context))
return res->data;
return NULL;
@@ -314,29 +309,54 @@ static inline bool kunit_resource_name_match(struct kunit *test,
}
/**
- * kunit_find_resource() - Find a resource using match function/data.
+ * kunit_find_resource_unlocked() - Find a resource using match function/data
+ * without locking.
* @test: Test case to which the resource belongs.
- * @match: match function to be applied to resources/match data.
- * @match_data: data to be used in matching.
+ * @match: Match function to be applied to resources/match data.
+ * @match_data: Data to be used in matching.
+ *
+ * Finds a resource in @test->resources using @match, but does not acquire
+ * the test's lock.
+ *
+ * Note: This function is for specialized use only as it is **NOT thread-safe**
+ * regarding the test's resource list and test reference count. Callers must prevent
+ * potential race conditions, typically by providing external locking. The thread-safe
+ * alternative, kunit_find_resource(), should be used in most situations.
*/
static inline struct kunit_resource *
-kunit_find_resource(struct kunit *test,
- kunit_resource_match_t match,
- void *match_data)
+kunit_find_resource_unlocked(struct kunit *test,
+ kunit_resource_match_t match,
+ void *match_data)
{
struct kunit_resource *res, *found = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&test->lock, flags);
list_for_each_entry_reverse(res, &test->resources, node) {
- if (match(test, res, (void *)match_data)) {
+ if (match(test, res, match_data)) {
found = res;
kunit_get_resource(found);
break;
}
}
+ return found;
+}
+
+/**
+ * kunit_find_resource() - Find a resource using match function/data.
+ * @test: Test case to which the resource belongs.
+ * @match: match function to be applied to resources/match data.
+ * @match_data: data to be used in matching.
+ */
+static inline struct kunit_resource *
+kunit_find_resource(struct kunit *test,
+ kunit_resource_match_t match,
+ void *match_data)
+{
+ struct kunit_resource *found = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&test->lock, flags);
+ found = kunit_find_resource_unlocked(test, match, match_data);
spin_unlock_irqrestore(&test->lock, flags);
return found;
@@ -355,6 +375,28 @@ kunit_find_named_resource(struct kunit *test,
(void *)name);
}
+/**
+ * kunit_find_named_resource_unlocked() - Find a resource using match name
+ * without locking.
+ * @test: Test case to which the resource belongs.
+ * @name: Match name.
+ *
+ * Finds a resource in @test->resources using its name, but does not acquire
+ * the test's resource lock.
+ *
+ * Note: This function is for specialized use only as it is **NOT thread-safe**
+ * regarding the test's resource list and test reference count. Callers must prevent
+ * potential race conditions, typically by providing external locking. The thread-safe
+ * alternative, kunit_find_named_resource(), should be used in most situations.
+ */
+static inline struct kunit_resource *
+kunit_find_named_resource_unlocked(struct kunit *test,
+ const char *name)
+{
+ return kunit_find_resource_unlocked(test, kunit_resource_name_match,
+ (void *)name);
+}
+
/**
* kunit_destroy_resource() - Find a kunit_resource and destroy it.
* @test: Test case to which the resource belongs.
diff --git a/lib/kunit/resource.c b/lib/kunit/resource.c
index f0209252b179..dae708f81f97 100644
--- a/lib/kunit/resource.c
+++ b/lib/kunit/resource.c
@@ -20,10 +20,12 @@ int __kunit_add_resource(struct kunit *test,
kunit_resource_init_t init,
kunit_resource_free_t free,
struct kunit_resource *res,
+ const char *name,
void *data)
{
int ret = 0;
unsigned long flags;
+ struct kunit_resource *existing;
res->free = free;
kref_init(&res->refcount);
@@ -37,6 +39,14 @@ int __kunit_add_resource(struct kunit *test,
}
spin_lock_irqsave(&test->lock, flags);
+ if (name) {
+ existing = kunit_find_named_resource_unlocked(test, name);
+ if (existing) {
+ kunit_put_resource(existing);
+ spin_unlock_irqrestore(&test->lock, flags);
+ return -EEXIST;
+ }
+ }
list_add_tail(&res->node, &test->resources);
/* refcount for list is established by kref_init() */
spin_unlock_irqrestore(&test->lock, flags);
@@ -107,7 +117,7 @@ int kunit_add_action(struct kunit *test, void (*action)(void *), void *ctx)
action_ctx->res.should_kfree = true;
/* As init is NULL, this cannot fail. */
- __kunit_add_resource(test, NULL, __kunit_action_free, &action_ctx->res, action_ctx);
+ __kunit_add_resource(test, NULL, __kunit_action_free, &action_ctx->res, NULL, action_ctx);
return 0;
}
--
2.51.0.rc0.215.g125493bb4a-goog
This patch fixes unstable LACP negotiation when bonding is configured in
passive mode (`lacp_active=off`).
Previously, the actor would stop sending LACPDUs after initial negotiation
succeeded, leading to the partner timing out and restarting the negotiation
cycle. This resulted in continuous LACP state flapping.
The fix ensures the passive actor starts sending periodic LACPDUs after
receiving the first LACPDU from the partner, in accordance with IEEE
802.1AX-2020 section 6.4.1.
v2:
a) Split the patch in to 2 parts. One for lacp_active setting.
One for passive mode negotiation flapping issue. (Nikolay Aleksandrov)
b) Update fixes tags and some comments (Nikolay Aleksandrov)
c) Update selftest to pass on normal kernel (Jakub Kicinski)
Hangbin Liu (3):
bonding: update LACP activity flag after setting lacp_active
bonding: send LACPDUs periodically in passive mode after receiving
partner's LACPDU
selftests: bonding: add test for passive LACP mode
drivers/net/bonding/bond_3ad.c | 67 +++++++++----
drivers/net/bonding/bond_options.c | 1 +
include/net/bond_3ad.h | 1 +
.../selftests/drivers/net/bonding/Makefile | 3 +-
.../drivers/net/bonding/bond_passive_lacp.sh | 95 +++++++++++++++++++
5 files changed, 148 insertions(+), 19 deletions(-)
create mode 100755 tools/testing/selftests/drivers/net/bonding/bond_passive_lacp.sh
--
2.46.0
This is series 2b/5 of the migration to `core::ffi::CStr`[0].
20250704-core-cstr-prepare-v1-0-a91524037783(a)gmail.com.
This series depends on the prior series[0] and is intended to go through
the rust tree to reduce the number of release cycles required to
complete the work.
Subsystem maintainers: I would appreciate your `Acked-by`s so that this
can be taken through Miguel's tree (where the other series must go).
[0] https://lore.kernel.org/all/20250704-core-cstr-prepare-v1-0-a91524037783@gm…
Signed-off-by: Tamir Duberstein <tamird(a)gmail.com>
---
Changes in v3:
- Add a patch to deal with new code in acpi.
- Drop incorrectly applied Acked-by tags from Danilo.
- Link to v2: https://lore.kernel.org/r/20250719-core-cstr-fanout-1-v2-0-e1cb53f6d233@gma…
Changes in v2:
- Update patch title (was nova-core, now drm/panic).
- Link to v1: https://lore.kernel.org/r/20250709-core-cstr-fanout-1-v1-0-fd793b3e58a2@gma…
---
Tamir Duberstein (11):
drm/panic: use `core::ffi::CStr` method names
rust: auxiliary: use `core::ffi::CStr` method names
rust: configfs: use `core::ffi::CStr` method names
rust: cpufreq: use `core::ffi::CStr` method names
rust: drm: use `core::ffi::CStr` method names
rust: firmware: use `core::ffi::CStr` method names
rust: kunit: use `core::ffi::CStr` method names
rust: miscdevice: use `core::ffi::CStr` method names
rust: net: use `core::ffi::CStr` method names
rust: of: use `core::ffi::CStr` method names
rust: acpi: use `core::ffi::CStr` method names
drivers/gpu/drm/drm_panic_qr.rs | 2 +-
rust/kernel/acpi.rs | 7 ++-----
rust/kernel/auxiliary.rs | 4 ++--
rust/kernel/configfs.rs | 4 ++--
rust/kernel/cpufreq.rs | 2 +-
rust/kernel/drm/device.rs | 4 ++--
rust/kernel/firmware.rs | 2 +-
rust/kernel/kunit.rs | 6 +++---
rust/kernel/miscdevice.rs | 2 +-
rust/kernel/net/phy.rs | 2 +-
rust/kernel/of.rs | 2 +-
samples/rust/rust_configfs.rs | 2 +-
12 files changed, 18 insertions(+), 21 deletions(-)
---
base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
change-id: 20250709-core-cstr-fanout-1-f20611832272
Best regards,
--
Tamir Duberstein <tamird(a)gmail.com>