Skip to content

adopt (breaking) changes from linux kernel v6.15, v6.19 and v7.0 - #110

Draft
tiararodney wants to merge 19 commits into
PlatformLab:mainfrom
tiararodney:linux-v619
Draft

tiararodney wants to merge 19 commits into
PlatformLab:mainfrom
tiararodney:linux-v619

Conversation

@tiararodney

@tiararodney tiararodney commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

As suggested in #107:

$> git log --pretty=tformat:'%s' 22c5317f..HEAD
Build test harness against !defined(CONFIG_DEBUG_PREEMPT)
Build test harness against linux 7.0 kernel asm/checksum_64.h header
Build test harness against linux 6.19 kernel linux/mutex.h header
Build test harness against linux 6.19 kernel net/ipv6.h header
Build test harness against linux 6.19 kernel net/ip.h header
Build test harness against linux 6.19 kernel net/inet_common.h header
Build test harness against linux 6.18 kernel linux/slab.h header
Build test harness against linux 6.18 kernel linux/hrtimer.h header
Build test harness against linux 6.18 kernel net/icmp.h header
Build test harness against linux 6.19 kernel linux/xxhash.h header
Build test harness against linux 6.18 kernel linux/rhashtable.h header
Build test harness against linux 6.19 kernel linux/rbtree.h header
rbtree: inline rb_last()
rbtree: inline rb_first()
Build test harness against percpu cache hot data
Build test harness against kbuild dialect and extensions
Build against linux 7.0 kernel net/pkt_sched.h header
Build against linux 6.19 kernel net/socket.h header
Build against linux 7.0 kernel compiler_types.h header

TODO:

  • some remaining errors in the test harness regarding __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_gs isn't auto-selected at all. But I don't yet understand how this would affect other architectures... Note: removing the gates entirely made the renaming of current_task redundant. Only seems applicable for x86.
  • unit tests haven't adopted the changes from 917d6c3 yet. Note: applied onto same commit.
  • changes to linux/rbtree.h in v7.0 break some test cases cherry-picked changes from lib/rbtree.c and applied kernel version guard
  • vendored-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 kernels
  • linker issues for test harness (it compiles already though)

You 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.

sh -ex << 'EOF'
WORKDIR="$(mktemp -d)"
HOMA_GIT_BRANCH=linux-v619 # branch only exists on my fork, which is accounted for further down
KERNEL_VERSION=7.0.14

finally () {
    cat $WORKDIR/test-report/unit/$KERNEL_VERSION/$HOMA_GIT_BRANCH.log 2>/dev/null \
    || cat /dev/null
    cat $WORKDIR/test-report/smoke/$KERNEL_VERSION/$HOMA_GIT_BRANCH.log 2>/dev/null \
    || cat /dev/null
    rm -r "$WORKDIR"
} 

trap finally EXIT

git clone https://github.com/tiararodney/HomaModuleTestBench.git "$WORKDIR"
cd "$WORKDIR"

git submodule update --init HomaModule.git/
sh ./configure

# need to adjust the submodule to point to my fork...
git -C HomaModule.git/ remote set-url origin https://github.com/tiararodney/HomaModule.git
git -C HomaModule.git/ fetch origin $HOMA_GIT_BRANCH
git -C HomaModule.git/ checkout -B $HOMA_GIT_BRANCH origin/$HOMA_GIT_BRANCH


make -j2 test-report/unit/$KERNEL_VERSION/$HOMA_GIT_BRANCH.log \
         test-report/smoke/$KERNEL_VERSION/$HOMA_GIT_BRANCH.log
EOF

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
@tiararodney

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.
@tiararodney
tiararodney force-pushed the linux-v619 branch 2 times, most recently from 46292f2 to d40d78d Compare October 1, 2026 08:33
@tiararodney tiararodney changed the title adopt (breaking) changes from linux kernel v6.19 and v7.0 adopt (breaking) changes from linux kernel v6.15, v6.19 and v7.0 Oct 1, 2026
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
@tiararodney
tiararodney force-pushed the linux-v619 branch 3 times, most recently from c7680f0 to c3f72da Compare October 2, 2026 05:23
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
edumazet and others added 3 commits October 2, 2026 08:08
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
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
@tiararodney
tiararodney force-pushed the linux-v619 branch 2 times, most recently from f815e40 to ddfabfe Compare October 2, 2026 11:39
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.
@tiararodney

Copy link
Copy Markdown
Contributor Author

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 johnousterhout left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for these patches. Most look good to me and I will start applying them, but I have a few questions.

Comment thread test/Makefile
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) \

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Comment thread homa_qdisc.c

#include <linux/ethtool.h>

#ifndef qdisc_from_priv

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think I'm going to redefine this with a Homa-specific name, in order to eliminate any dependency on Linux version.

Comment thread test/rbtree.c
__rb_insert(node, root, augment_rotate);
}

/* Linux 6.19 inlined rb_first()/rb_last() into <linux/rbtree.h> as static

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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?

Comment thread test/Makefile
$(KERN_INCLUDES) \
-include $(KDIR)/include/linux/kconfig.h
-include $(KDIR)/include/linux/kconfig.h \
-include seg_compat.h

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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).

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