Meta

I was in the process of setting up to record a screencast of how to use dynpk, when I discovered that my dynpk fu no longer ran on the RHEL machine I was using. Running my program resulted in this friendly output:

FATAL: kernel too old

Turns out this is a message brought to us by glibc. glibc has a configure option ‘–enable-kernel’. The argument to this option is a Linux version, e.g. 2.6.18. This tells glibc the minimum Linux version that the resulting built stuff has to support. Apparently telling it the name of a more recent kernel version can improve performance because it doesn’t have to include as much compatibility cruft.

The current Fedora 14 glibc is built with this argument set to 2.6.32. Running a statically linked binary generated on F14 on a RHEL 5 machine running 2.6.18 is thus no longer possible without some additional work. What additional work is that? Rebuilding the C library with the ‘–enable-kernel’ option set to something compatible with the target system. glibc will still present the same API to the programs we want to run, but includes the additional fudge for old kernel version compatibility. We don’t have to rebuild all of our programs, just shoehorn our own glibc into the bundle dynpk makes.

“Rebuild the C library from source, you’re crazy.” I hear you say whilst backing away slowly. It’s not a massive deal. All I have to do is:

And some time later, out spring some RPMs. You’ll find the ones I’m using for F14 on RHEL5 here (don’t install them!).

I’ve modified dynpk so that it can take uninstalled RPM files and install them into the bundle (it’s a rather naive install, but it does the job right now). It can also take some glibc RPMs to build its own wrapper against. Here’s how: The build process is modified slightly:

Fedora 14 came out yesterday. Amongst various run-of-the-mill updates, a couple of things stand out in it for me. The newer gdb and gcc combination allow for a much improved debugging experience that rarely involves one cursing at the words “value optimised out”. I happen to know this as good as it says on the tin because I resorted to using an alpha of F14 in qemu to attack a particularly gristly situation I got myself into about a month back. systemd also looks quite interesting, and I think it’s possible to switch over to that in F14.

So I waited patiently for Fedora 14 to appear in preupgrade, which downloads all the updates, reboots and installs them without the need for a CD, DVD, USB key, or data-laden Armadillo. It downloaded everything and I rebooted into the updater to be presented with a prompt asking me to insert a driver disk. Not only did it not tell me what driver it was looking for, it also wouldn’t let me proceed with the upgrade without this “driver disk”.

Now I knew that it didn’t genuinely require some kind of magic driver to continue. My machine contains no exotic hardware, and has been running a plain-old Fedora kernel since its inception. I decided to delve somewhat deeper.

With the help of the Anaconda wiki pages, I quickly worked out how to replace the Anaconda instance that preupgrade was running with one that I’d massaged myself. I got Anaconda to run gdbserver, which I then connected to. Unfortunately 99% of the variables I wanted to look at had been optimised away. I then spent a fair while injecting print statements throughout the bits of relevant code.

Eventually, I discovered the problem. “stage1” of Anaconda, who’s responsibility is to load the more graphical “stage2”, searches through all the block devices in the machine to find disk drives that are worth inspecting. Part of this “worthiness” test involves it inspecting the size of the disk to determine if it’s above some small size that no disks today could be below. This test reads the contents of the ‘size’ file sysfs provides for the device that’s being examined (e.g. /sys/block/sda/size). This file contains a number. This number is the number of 512-byte blocks that the device has. On my machine this file contains “2930277168”.

This bit of Anaconda then used strtol() on this string to convert it to an integer. An important feature of strtol is that it returns a long int. On most 32-bit systems, this is a 32-bit number. It’s signed, so its maximum value is 2147483647. Note that the value from my hard disk, 2930277168, is larger than 2147483647. So strtol returns indicating the value’s out of range. Anaconda’s device listing stuff immediately explodes because of this, and then the (somewhat disturbing) state machine decides that we need a driver disk to solve the problem of us not having a device list.

Solution: A patch to Anaconda to use strtoll instead, which uses long long ints. These are 64-bits, and so there won’t be a problem until disks are measured in zettabytes.

Spent a fair chunk of today sorting out Phil’s hard disk. Mac OS X had impolitely destroyed his partition table for him. I used TestDisk to recover it. There were a couple of issues, which meant that it took a little longer than it was “supposed” to.

It located a couple of adjacent ext3 partitions (Phil’s Fedora and Ubuntu roots) and generated some overlapping numbers for them. I had to manually edit the partition table using sfdisk to get it right. I particularly enjoyed the rollback-like features that sfdisk has (using -O and -I). I had to tell sfdisk to use sector units because it defaults to cylinders.

Then Phil gave me food. Excellent. Technical support for food.

Got a couple of management textbooks out from the library earlier. They’re really boring. Seem to be stating the obvious. Joy.