Packaging kernel modules for Fedora Extras

Introduction

Kernel modules are a special case in rpm packaging and need careful handling. There are a lot of ways to package kernel modules -- to avoid confusion for the users and reviewers as well as to make it easier for RPM depsolvers to support kernel-modules the Fedora Extras Steering Commitee (FESCo) worked out below standard for packaging kernel-modules in Fedora. This standard hopefully solves many pitfalls earlier standards in other repos had.

The most important rule for packages with kernel modules: There are always at least two SRPMS -- one builds a userland package of the source, the other builds packages with *only* the kernel-module(s) in it.

Note: The kernel-module packaging standard is quite new -- there still might be some issues that need finetuning, so be prepared for a little more maintain work. This document also still needs a bit love.

Note: Fedora Extras has some special polices for packaging and reviewing kernel-module packages for Extras. They can be found in the Extras/Policy/KernelModules . Be sure to read them, too -- this document only describes the technical issues around packaging modules.

userland package

The binary packages build from the userland SRPM contains tools, documentation, license, udev configuration etc. There always has to exist such a package -- even if the packaged software only builds kernel-modules it has at least some docs and a license file that need to be packaged in the userland package.

The packager is free to split the userland-package further into those with a the general userland parts, that works fine without the kernel-modules (docs, general tools, devel-files), and one with the kernel-module related parts (udev rules for example).

The userland packages follow the usual Packaging Guidelines. Two additional rules MUST be followed for packages with parts related to the kernel-module(s):

1. The package must tie itself to the kernel-module using something like 'Requires: %{name}-kmod >= %{version}'

1. The package must provide %{name}-kmod-common using something like 'Provides: %{name}- kmod-common = %{version}' or the name of the package must be %{name}-kmod-common

kernel-module package

Of course all general rules that apply to rpm packaging in Fedora Extras apply for kernel module packages, too. Especially those around the licensing -- there are a lot of kernel-modules out there that can't be included in Fedora Extras due to licensing issues.

Besides the normal rules there are several additional rules -- instead of writing all those down FESCo created a specfile template and a script (used by the specfile) that handles most things automatically. Both are described in detail below.

All kernel module packages should use the template (see below) as a base. Reviewers of kernel modules should diff the proposed kernel module packages against the template. Only the names and the way the modules itself are build should differ. There shouldn't be other differences without a good reason.

Script

The bash script that is used by kernel-module-packages is named kmodtool. It is planed to be added to the redhat-rpm-config package and to be available to with the macro %{kmodtool}. In the testing phase the script is part of the packages. The current up2date version can be found here .

The script is no real magic -- if you understand a bit of bash scripting you should be able to see how it works. The most important part is the function get_rpmtemplate and this part of it:

All kernel modules need to have the prefix kmod (that's a bit shorter
than kernel-module)

Provides: kernel-modules = 2.6.21-1.1776_FC7

With the explicit Provides depsolvers such as yum can know that it's working with a kernel module. You also easily can get the kver the module was build for with this.

Provides: foo-kmod = 1.5

The userland-package that depends on a package that provides that to make sure that yum and other depsolvers install a proper kernel-module if you install a userland package that requires a kernel-module.

Requires: kernel-i686 = 2.6.21-1.1776_FC7

A kernel module without the kernel it was built for is useless. Don't use /boot/vmlinuz-*, it's not portable.

Requires: foo = 1.5

Kernel modules without the userland part is useless in most cases. There are rare packages when kernel modules don't need a part in userland, but we require it anyway -- at least the license and the docs needs to be placed somewhere in any case and a userland package is the right place for them.

BuildRequires: kernel-devel-i686 = 2.6.21-1.1776_FC7

Needed for building kernel-modules

%defattr(644,root,root,755)

Kernel modules shall not be executable -- but they need to be after %install to allow /usr/lib/rpm/find-debuginfo.sh to strip them.

/lib/modules/2.6.21-1.1776_FC7/extra/foo/

Separate location -- don't mess up with the rest of the kernel. "extra" was picked because of upstream kernel documentation. Only kernel modules in that dir are allowed -- nothing else, because otherwise they might conflict between different versions!

kernel module specfile

An example kernel module specfile for "foo" might looks like this (download File:Obsolete KernelModules kmod-template.spec ; note that the first part of the page needs adjustments for the different releases -- see the end of this page for up2date examples):

So how does it work? let's go through important parts to describe them:

Source10: kmodtool

%define kmodtool sh %{SOURCE10}

Include kmodtool and Source10 and define a variable for it

%{!?kversion: %define kversion 2.6.21-1.2111_FC7}

The kernel-version for which the module will be build needs to be hardcoded for now. Hint: this can he overridden with "--define kversion foo" on the rpmbuild command line.

%define kmod_name foo

The name of the belonging userland package/the original name of the
software. It is used in several places, therefore we define a macro
for it.

%define kverrel %(%{kmodtool} verrel %{?kver} 2>/dev/null)

Define kverrel for the "kernel version release" (for example 2.6.21-1.1776_FC7 for kernel 2.6.21-1.1776_FC7smp). The kmodtool takes care here for stipping off "smp", "xen-guest" or other known variants from the sting %{?kver}. That is normally defined by the buildsys or the user to specify the kernel to build for. Kmodtool will use the string from $(uname -r) if kver is not defined.

The kernel variants for which the module will be build need to be hardcoded for now. Define a variable kvariants with all the know kernel-variants for the current arch. Hint: this can he overridden with "--define kvariant foo bar" on the rpmbuild comand line.

Name: %{kmod_name}-kmod

This is only the name for the SRPM -- the kernel module package itself is named the other way around, e.g. "Name: kmod-{kmod_name}" (see the rpm macro). This might be a bit confusing in the beginning, but solves some problems nicely.

Version: 1.5

This needs to be the same as in the userland package.

Release: 3.%(echo %{kver} | tr - _ )

This results in 3.2.6.21_1.1776_FC7 (e.g. the whole src.rpm is named something like "foo-kmod-1.5-3.2.6.21_1.1776_FC7").

The kver needs to be in the release to get proper debuginfo packages later. With this scheme we of course get a SRPM for each kernel we build the modules for. Therefore it might be better to create a stripped down tarball of the original source (e.g. remove the userland parts) to avoid wasting a lot of disk space. This is one of the drawbacks in this scheme, but it works.

ExclusiveArch: i586 i686 x86_64 ppc

This one is important for the buildsys. i386 should never be in the list because there is no i386 kernel in Fedora -- the buildsys would not find the BuildRequire and fail at that point. If a kernel module is only of interest for some of those archs of course feel free to list only those.

Well, as the comment already says, the magic from kmodtool is buried here -- kmodtool is called with all relevant parameters and will output the part we showed in above example trough the function get_rpmtemplate. One or multiple such parts will get inserted depending on how many variants are passed to kmodtool it (in case the spec file is for example called with '--define "kvariants up smp"')

Mini-FAQ

What's the best way to test if the spec file works fine

Build the kmod with rpmbuild and in mock for a kernel with a different version than the one that are running currently, e.g., if you running 2.6.21-1.2122_FC7 try to build for 2.6.21-1.2111_FC7.

Will there be further enhancements for the kernel module proposal?

Probably yes. We probably didn't consider every possible scenario out there. But the general scheme/direction probably will stay.

Will other repos use the same scheme?

You have to ask those repos. One popular 3rd party repo that enhances Core and Extras uses it currently.

Does it work with yum?

Not perfectly (yet). We need a plugin for yum that will handles some special cases for kernel module packages. It is available in Extras currently, but not perfect yet.

Does it work in the Extras Buildsys?

Not perfectly (yet). We need a plugin or enhancement that will search for the latest kernel version and then will pass this to the rpmbuild command with "--define 'kversion foo'". There are no concrete plans
who works on that ATM. Are you interested to help?

Will this proposal be used for the GFS stuff in Fedora Core, too?

That's the plan.

Is it possible to compile against self compiled kernels?

Yes, if self compiled means "packaged in a manner compatible with FC kernels". Otherwise: no. Well, it's _possible_, but not supported nor documented. Just create a FC compatible kernel package of your
custom kernel, and compile the module packages for it by passing --define 'variant foo' to rpmbuild.

This standard is stupid.

Maybe. Post a better one. (No offense, more a FYI: We invested a lot of time in this standard and had to make a lot of compromises to make everyone happy -- doing bigger changes just "because I like my scheme better" probably won't help. But technical advantages that are documented and already tested in real life might convince us).