Extensibility(9)
β¨ Extensibility β¨
okay bestie, welcome to the Kernel API Manual page for Extensibility(9) β this one is lowkey a story about trying to be flexible and getting humbled by userspace π. let's get into it.
Originally, the plan was to allow backward- and forward-compatible changes by just adding fields at the end of the structure. Those new fields wouldn't be reported on older kernels on read, and older kernels wouldn't write them on write, with the kernel reporting the size it did accept as the result. β¨
That would've let userspace detect on read and write which kernel structure version it was dealing with. And if it was just recompiled, it would've gotten the new fields β obviously not accessed them, but things should've continued to work. in theory π
Unfortunately, while actually exercising this mechanism to add the hard block reasons field, they found userspace (notably systemd) doing all kinds of fun things not in line with this scheme:
- treat the (expected) short writes as an error;
- ask to read
sizeof(struct rfkill_event)but then compare the actual return value toRFKILL_EVENT_SIZE_V1and treat any mismatch as an error.
As a consequence, just recompiling with a new struct version caused things to no longer work correctly on old and new kernels. not iconic π
Hence, they've rolled back struct rfkill_event to the original version and added struct rfkill_event_ext. This effectively reverts to the old behaviour for all userspace, unless it explicitly opts in to the rules outlined here by using the new struct rfkill_event_ext. π
Additionally, some other userspace (bluez, g-s-d) was reading with a large size but as streaming reads rather than message-based, or with too strict checks for the returned size. So eventually, they completely reverted this, and extended messages need to be opted in to by using an ioctl:
ioctl(fd, RFKILL_IOCTL_MAX_SIZE, sizeof(struct rfkill_event_ext));
Userspace using struct rfkill_event_ext and the ioctl must adhere to the following rules:
- accept short writes, optionally using them to detect that it's running on an older kernel;
- accept short reads, knowing that this means it's running on an older kernel;
- treat reads that are as long as requested as acceptable, not checking against
RFKILL_EVENT_SIZE_V1or such.
π SEE ALSO π
Kernel file ./include/uapi/linux/rfkill.h: enum rfkill_type(9), enum rfkill_operation(9), enum rfkill_hard_block_reasons(9), struct rfkill_event(9), struct rfkill_event_ext(9).
big kiss from the Kernel API Manual besties β source/version is ./include/uapi/linux, dated October 2026, and this page is Extensibility(9) π
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms