adopt (breaking) changes from linux kernel v6.15, v6.19 and v7.0 - #110
tiararodney wants to merge 19 commits into
Conversation
kernel ver. >=7.0 changed the signature of __cond_acquires [1] and introduced a return value token, so a Clang checker is now able to differentiate between held and unheld locks. Context analysis wasn't documented, prior to v7.0. on `homa_rpc.h::homa_rpc_try_lock()`, the correct choice would probably be to use a `nonzero` token, however since these are annotations that don't expand to anything outside of Clang's static analysis, I think it's safe to just use `nonnull` as a truthy value? The macros' docstring make that assumption as well [2]... What might be a bit problematic regarding readability is that the inline `__COND_ACQUIRES` in `homa_rpc.h` is dependent on the include order of the headers throughout. Not a real issue though, since `homa_impl.h is always included before `homa_rpc.h` throughout and it was like that with the raw `__cond_acquires` before anyway. [1] https://www.kernel.org/doc/html/v7.0/dev-tools/context-analysis.html#c.__cond_acquires [2] https://github.com/torvalds/linux/blob/v7.0/include/linux/compiler-context-analysis.h#L288-L291
This comment was marked as outdated.
This comment was marked as outdated.
this is a drive-by commit and should probably be handled via a separate PR... explicitly pinning to C11 and ms-extensions, as to mirror what kbuild does, since newer versions of GCC use C23 by default.
46292f2 to
d40d78d
Compare
sockaddr is deprecated since v6.19 [1] and replaced by sockaddr_unsized, which is now unbounded against addr_len, removing the prior 14-bytes cap. It's interchangeable throughout Homa though, since there is no dependency on `sizeof(struct sockaddr)`.. [1] https://github.com/torvalds/linux/blob/v6.19/include/linux/socket.h#L35
qdisk_from_priv was removed in v7.0 [1], however it's just a tiny helper [2] anyway, so we can simply redefine it. [1] torvalds/linux@1145739 [2] https://github.com/torvalds/linux/blob/v6.18/include/net/pkt_sched.h#L28-L31
c7680f0 to
c3f72da
Compare
starting with kernel v6.15, the task_struct was moved into pcpu_hot [1][2],
hence the conflicting named address spaces (generic vs __seg_gs), when
DECLARE_PER_CPU_CACHE_HOT [3] is expanded.
The unit tests model per-CPU variables as plain arrays (see the DECLARE_PER_CPU
/ per_cpu / this_cpu_ptr overrides in `mock.h`), so the test build must not see
x86's segment-based ("named address space") per-CPU addressing. On kernels built
with CONFIG_CC_HAS_NAMED_AS, per-CPU symbols become __seg_gs-qualified [4]. That
qualifier is applicable through __typeof__ in the kselftest EXPECT_* macros onto
auto variables ("__seg_gs specified for auto variable") and conflicts with the
mock's plain declarations.
[1] https://lore.kernel.org/all/20250303165246.2175811-1-brgerst@gmail.com/
[2] torvalds/linux@a1e4cc0
[3] https://github.com/torvalds/linux/commits/v6.15/arch/x86/include/asm/current.h
[4] https://github.com/torvalds/linux/blob/v6.15/arch/x86/include/asm/current.h#L16
c3f72da to
134218d
Compare
Inline these two small helpers, heavily used in TCP and FQ packet scheduler, and in many other places. This reduces kernel text size, and brings a 1.5% improvement on a network TCP stress test. This is a very small function, inlining it saves cpu cycles by reducing register pressure and removing call/ret overhead. It also reduces vmlinux text size by 744 bytes on a typical x86_64 build. (cherry picked from commit c2d2dad24503d7e2eb7cba354fcc73f95fa78d7a of torvalds/linux.git) [ vendored test/rbtree.c: drop only the out-of-line rb_first(). Its EXPORT_SYMBOL() was already stripped on import, and the inline now comes from the kernel's <linux/rbtree.h>.. ]
This is a very small function, inlining it saves cpu cycles in TCP by reducing register pressure and removing call/ret overhead. It also reduces vmlinux text size by 122 bytes on a typical x86_64 build. (cherry picked from commit 94984bfed58ca129f7e259ce09973ed0b3f540a8 of torvalds/linux.git) [ vendored test/rbtree.c: drop only the out-of-line rb_last(). Its EXPORT_SYMBOL() was already stripped on import, and the inline now comes from the kernel's <linux/rbtree.h>.]
linux 6.19 inlined rb_first() and rb_last() into <linux/rbtree.h> [1][2], removing the out-of-line definitions mirrored by the previous two commits. on kernels < 6.19 the header still only declares them extern, so the vendored test/rbtree.c must keep the out-of-line copies. restoring them under a LINUX_VERSION_CODE guard so the harness builds on both... [1] torvalds/linux@c2d2dad [2] torvalds/linux@94984bf
2438eba to
b348a71
Compare
linux 6.18 added an alignment parameter to the k[v]malloc family [1]: the
rhashtable bucket-table allocation moved from kvmalloc_node_noprof(size,
flags, node) to kvmalloc_node_align_noprof(size, align, flags, node), and
on >= 6.18 the old kvmalloc_node_noprof is a 4-arg macro that no longer
expands for the 3-arg call ("implicit declaration of kvmalloc_node_noprof").
The vendored test/rhashtable.c was imported from ~v6.15, so guard the
bucket-table allocation: use the align form (align = 1) on >= 6.18 and the
original 3-arg form on older kernels.
[1] torvalds/linux@2cd8231
linux 6.19 removed the streaming xxh32 API from `linux/xxhash.h`. struct xxh32_state and xxh32_reset()/copy_state() are gone [1], only `xxh32()`, which Homa uses via xxh32_hash() in homa_peer.c, remains. The vendored test/xxhash.c still defines the out-of-line xxh32_copy_state() and xxh32_reset(), which reference the now-removed struct xxh32_state. [1] torvalds/linux@a0b8c6a
f815e40 to
ddfabfe
Compare
In linux 6.18 the last parameter of __icmp_send()' was changed from `const struct ip_options *` to `const struct inet_skb_parm *` [1]. The mock definition conflicted with the new prototype. [1] torvalds/linux@0d3c4a4
linux 6.18 removed the get_time member from struct hrtimer_clock_base kernel now reads clock time via hrtimer_cb_get_time()) [1]. The mock's `hrtimer_init()`/`hrtimer_setup()` assigned `clock_base.get_time`, and the backing `hrtimer_get_time()` stub is unused once those assignments go away. [1] torvalds/linux@cdea7cd
linux 6.18 added an alignment parameter to `__kvmalloc_node_noprof()` [1]. the mock's definition used the old prototype and no longer matched. The mock ignores the alignment. [1] torvalds/linux@2cd8231
linux 6.19 introduced struct sockaddr_unsized (linux/socket.h) and switched inet_dgram_connect()'s address argument to it [1] [1] torvalds/linux@449f68f
Linux 6.19 switched ip4_datagram_connect() address argument to the new struct sockaddr_unsized (linux/socket.h). [1] torvalds/linux@449f68f
linux 6.19 switched ip6_datagram_connect() address argument to the new struct sockaddr_unsized (linux/socket.h) [1]. [1] torvalds/linux@449f68f
linux 6.19 turned __mutex_init() into a static inline in linux/mutex.h (non-DEBUG, non-PREEMPT_RT config). it was an extern before... [1] torvalds/linux@51d7a05
linux 7.0 made csum_ipv6_magic() a static inline in the x86 asm/checksum_64.h [1], it was out-of-line before so the harness supplied its own stub. The mock's definition then conflicted with the inline. [1] torvalds/linux@529676c
linux/preempt.h only declares preempt_count_add()/preempt_count_sub() as extern functions under CONFIG_DEBUG_PREEMPT or CONFIG_TRACE_PREEMPT_TOGGLE, otherwise it defines them as macros around the arch __preempt_count_add() inline. The mock defined them unconditionally, which redefined that inline on a kernel built without those options.
|
Alright, after having ignored the test harness (pardon...), both the module and test harness now compile against 7.0.0-34-generic on Ubuntu with GCC15 and (hopefully) only linker issues are remaining. All the required changes have luckily been pretty mechanical so far. I've restructured the commits, since I figured this PR is probably a bad idea scope-wise anyway (way too broad)... Instead, I focused on it serving as a reference for creating new PRs according to the kernel version compatibility breakpoints? Up until now, 4 version breakpoints for 6.15, 6.18, 6.19, and 7.0 surfaced and some expectations towards the build environment required patching. The commits are verbosely labeled and all changes in linux are annotated with commit references. Two changes, required patching vendored sources, which I cherry-picked of the linux sources and retained the provenance. |
johnousterhout
left a comment
There was a problem hiding this comment.
Thanks for these patches. Most look good to me and I will start applying them, but I have a few questions.
| WARNS := -Wall -Wundef -Wno-trigraphs -Wno-sign-compare -Wuninitialized \ | ||
| -Wno-strict-aliasing -Wunused-but-set-variable -Werror | ||
| CFLAGS := $(WARNS) -Wstrict-prototypes -MD -no-pie -g $(CINCLUDES) $(DEFS) \ | ||
| CFLAGS := -std=gnu11 -fms-extensions $(WARNS) -Wstrict-prototypes -MD -no-pie -g $(CINCLUDES) $(DEFS) \ |
There was a problem hiding this comment.
Can you say a bit more about why -fms-extensions is needed? I don't see this flag when I do normal kbuilds of Homa.
|
|
||
| #include <linux/ethtool.h> | ||
|
|
||
| #ifndef qdisc_from_priv |
There was a problem hiding this comment.
I think I'm going to redefine this with a Homa-specific name, in order to eliminate any dependency on Linux version.
| __rb_insert(node, root, augment_rotate); | ||
| } | ||
|
|
||
| /* Linux 6.19 inlined rb_first()/rb_last() into <linux/rbtree.h> as static |
There was a problem hiding this comment.
Rather than trying to patch the sources to rbtree.c, rhashtable.c, and xxhash.c so that they compile across multiple versions, I wonder if it might be simpler just to keep different versions of these files and then select the appropriate version in the Makefile (this is basically what I have been doing so far: when I upgrade to new Linux versions, I grab new versions of those files from the kernel sources)? Thoughts on the tradeoffs between these approaches?
| $(KERN_INCLUDES) \ | ||
| -include $(KDIR)/include/linux/kconfig.h | ||
| -include $(KDIR)/include/linux/kconfig.h \ | ||
| -include seg_compat.h |
There was a problem hiding this comment.
Can you say a bit more about why this file is needed? I saw the commit log entry, but I'm confused because my normal build version is 6.17 and I'm not seeing any problems (and CONFIG_CC_HAS_NAMED_AS is defined for me).
As suggested in #107:
TODO:
some remaining errors in the test harness regardingNote: removing the gates entirely made the renaming of__seg_gs, and I'm thinking about ditching commit d40d78d altogether and just remove the x86 specific gates (works, but feels hacked), so that__seg_gsisn't auto-selected at all. But I don't yet understand how this would affect other architectures...current_taskredundant. Only seems applicable for x86.unit tests haven't adopted the changes from 917d6c3 yet.Note: applied onto same commit.changes tocherry-picked changes from lib/rbtree.c and applied kernel version guardlinux/rbtree.hin v7.0 break some test casesvendored-libs like xxhash.c break... I'm not sure if patching is the strategy.build and test against vanilla kernel (I've used Ubuntu so far)Note: I'm using a tiny test bench, so I can continuously test against vanilla kernelsYou can use the following script to reproduce the build, and tests against the vanilla kernel 7.0.14 (unit + smoke test, loading the module in a QEMU guest), which I patched against.