Analytics & Cookies

We use self-hosted Matomo analytics. By default we measure anonymously with no cookies. Enable cookies to give us a clearer picture and help us improve your experience. You can change this anytime.

Engineering · Linux Driver

A kernel driver that tests and ships itself

Code that sits in the write path of a production disk is only as trustworthy as the machinery that proves it before it reaches you. Every commit to the ShadowCradle Linux snapshot driver is linted, compiled against four distribution families and two architectures, booted on eleven kernel versions inside throwaway VMs, run through 151 correctness assertions, and packaged for five distribution formats — without a human deciding which kernels to cover or whether it was good enough to ship.

All of it is public. The pipeline definition, the test harness, the kernel matrix and the results are in the same GPL-licensed repository as the driver itself, so none of what follows has to be taken on trust.

151
Correctness assertions
across five automated suites
11
Kernel versions booted
5.12 through 7.2-rc
4
Distribution families built
Debian, Ubuntu, RHEL, Arch
0
Manual release steps
tag in, packages out

Six stages, from commit to signed release

Each stage exists because a specific class of bug escaped an earlier one. They run in order, and a red stage stops everything downstream — a package is never built from a commit whose tests did not pass.

1
Lint
Every shell script and every Python tool in the repository is checked before a compiler is even installed. Cheap, and it catches the class of mistake that otherwise fails forty minutes into a kernel build.
2
Build
The module is compiled against every kernel-headers package shipped by Debian 12, Debian 13, Ubuntu 24.04 and Rocky 9, plus an arm64 cross-compile. This is what catches kernel API drift on the day it lands.
3
Kernels
Prebuilt mainline kernels are fetched and the driver is compiled against each one — including whatever series upstream released this week, discovered at run time rather than read from a list.
4
Test
A real kernel is booted in QEMU, the module is loaded, and the full correctness suite runs against a disposable disk. The module is never loaded into the host, so a driver bug panics a throwaway VM and nothing else.
5
Package
.deb, .rpm, an Arch recipe, a tarball and a self-extracting installer are all built from the same commit that passed the tests, in the distribution containers they target.
6
Publish and release
Packages are uploaded to the registry and the published URLs are attached to the tag. Nobody uploads a build from a laptop, because there is no step in which that would be possible.
The pipeline, end to end
Fully automated. No human picks the kernels, runs the suites, or decides whether it shipped.
How the driver is testedThe pipeline asks the upstream kernel archive which versions currently exist, downloads each one, builds the driver against it in a container, boots it in a virtual machine, and runs the correctness, crash, filesystem and fault-injection suites. Release artifacts are published only if every stage passes.Kernel archiveasked, not hard-codedBuild matrixevery live seriesBoot in a VMone per kernelCorrectness and crash suitesFilesystem and fault injectionMemory and lock validationartifacts are published only when every stage passesnew releases pickedup automatically

What happens when a new kernel ships

This is the question that decides whether a block driver is a liability. The Linux block layer changes between releases, and a driver hooked into it breaks quietly when it does. Our answer is that nobody has to notice: a scheduled pipeline asks upstream what exists, fetches it, builds it and boots it, and turns red on its own if the new kernel broke us.

The kernel list maintains itself
A scheduled pipeline asks the upstream archive which series exist today and tests the newest release of each, plus the newest release candidate. A hand-maintained list stays green while the kernel your servers actually run quietly falls out of it.
Green cannot mean "never booted"
The QEMU suites use hardware acceleration where the runner provides it and emulate where it does not, scaling every timeout to match. Which accelerator ran the tests is recorded per kernel in the results artifact, so a matrix cannot be green by having skipped the hard part.
A skip is a failure
Every matrix job runs with skip-is-failure set. A kernel that could not be fetched, or whose pinned compiler was missing, turns the pipeline red instead of leaving a quiet hole where coverage is assumed to be.
Reproducible by construction
Kernel builds happen in containers carrying five GCC versions, because mainline trees pin the exact compiler that built them. Nobody is asked to install a compiler zoo on a workstation to reproduce a CI result.
Every distribution, one source tree
Debian, Ubuntu and RHEL-family kernels build from identical source with no per-distribution patches, and DKMS rebuilds the module automatically when the host kernel is upgraded.
Interfaces are detected, not guessed
The build compiles small probes against the target kernel and asks it directly which block-layer interfaces exist. Version-number checks break on enterprise distributions whose numbers do not describe their contents; probes do not.
The versions pinned on purpose
The matrix is not an arbitrary spread. Each entry is a branch point where the block layer moved underneath us: 5.12 is the oldest kernel supported at all, 5.15 and 5.16 sit either side of a change in how the submit path takes its queue reference, 6.1 is the branch most enterprise distributions track, 6.6 changed how block devices are opened by path, and 6.12 is the current long-term branch. Alongside them, latest and latest-rc track whatever upstream released since the last run.

Five suites, in increasing realism

A backup product that loses data quietly is worse than no backup product, so the suites are built around the quiet failures specifically: not "did it work", but "what did it do when the power went out halfway through".

Functional
79 assertions
Minimal initramfs, test binary as PID 1
Raw block correctness across six device classes: virtio, loop, device-mapper, md RAID1, zram and nbd.
Crash consistency
28 assertions
Two boots per scenario, same disk
Survival of a power cut mid-copy and mid-teardown — and that a persisted change list correctly does not survive one.
Filesystem crash
18 assertions
Same, with e2fsprogs and xfsprogs staged in
A power cut with a journaling ext4 or XFS filesystem mounted on the protected device.
Fault injection
18 assertions
A debug kernel, one failure armed at a time
Every error path driven deliberately, proving a failing store costs the backup and never the server.
Filesystem level
8 assertions
A full Debian VM over SSH
mkfs, mount, fsck and fio against the snapshot device, the way an operator would use it.
And on top of the suites
A run under the kernel address sanitiser, undefined-behaviour sanitiser and lock validator.
A byte-for-byte comparison against dattobd, the closest existing driver, on the same disk.
Runnable examples in shell and Python, executed against a real driver rather than pasted as snippets.
Performance sweeps that report throughput against chunk size, so a regression is a number and not an impression.

Deployment is a build artifact, not a procedure

Every format below is produced by the same pipeline run, from the same commit that passed the tests, inside the distribution container it targets. Tagging a release attaches the published URLs to the tag; there is no step in which somebody uploads a build from a laptop.

.deb
Debian, Ubuntu
.rpm
RHEL, Rocky, Alma
PKGBUILD
Arch
tarball
Anything else
self-extracting installer
Air-gapped hosts
DKMS module
Automatic rebuild on kernel upgrade

On a managed ShadowCradle appliance none of this is your problem — the agent carries the driver and DKMS rebuilds it when the host kernel is upgraded. The artifacts exist so that you can install, inspect and reproduce it independently of us if you ever want to.

Check Our Work

The pipeline definition, the test harness and the kernel matrix are public. Read them, run them, and tell us what we missed.

No credit card required · Cancel anytime · 60-day free trial