Now that I have made my own serial port for the ODROID-XU, creating something omitted from this development board, I’m ready to try to compile my own kernel again. At least I should be able to debug any error messages this time.
I did everything in the previous posting, but this time built a uImage properly:
LOADADDR=40008000 make uImage dtbs
sudo cp arch/arm/boot/uImage /boot/uboot/uImage-3.11-rc7
sudo cp uInitrd /boot/uboot/uInitrd-3.11-rc7
sudo cp arch/arm/boot/dts/exynos5410-odroidxu.dtb /boot/uboot/
We end up with (where the bold files are the ones I have built):
$ ll /boot/uboot/
-rwxr-xr-x 1 root root 5510 Sep 27 08:14 boot.ini
-rwxr-xr-x 1 root root 28603 Dec 7 16:34 exynos5410-odroidxu.dtb
-rwxr-xr-x 1 root root 293168 Sep 27 08:14 u-boot.bin
-rwxr-xr-x 1 root root 2113488 Dec 7 16:33 uImage-3.11-rc7
-rwxr-xr-x 1 root root 6518598 Sep 27 08:14 uInitrd
-rwxr-xr-x 1 root root 8104359 Dec 7 16:36 uInitrd-3.11-rc7
-rwxr-xr-x 1 root root 6518598 Nov 8 17:36 uInitrd-official3.4.5
-rwxr-xr-x 1 root root 5127832 Sep 27 08:13 zImage
-rwxr-xr-x 1 root root 5127832 Nov 8 17:36 zImage-official3.4.5
I boot this by interrupting u-boot and typing the load commands by hand. (Note that /boot/uboot is a FAT partition).
set bootargs console=ttySAC2,115200n8 loglevel=9 earlyprintk root=UUID=ad455a75-609c-4b3c-956b-bcef3ebc4603 ro
fatload mmc 0 43000000 uimage-3.11-rc7
fatload mmc 0 46000000 uinitrd-3.11-rc7
fatload mmc 0 49000000 exynos5410-odroidxu.dtb
bootm 43000000 46000000 49000000
This boots the kernel, but fails trying to find the root filesystem:
[ 9.680000] mmc1: error -110 whilst initialising SD card
[ 9.700000] mmc_host mmc1: Bus speed (slot 0) = 100000000Hz (slot req 300000Hz, actual 299401HZ div = 167)
[ 11.730000] mmc1: error -110 whilst initialising SD card
[ 11.750000] mmc_host mmc1: Bus speed (slot 0) = 100000000Hz (slot req 200000Hz, actual 200000HZ div = 250)
[ 13.790000] mmc1: error -110 whilst initialising SD card
[ 13.810000] mmc_host mmc1: Bus speed (slot 0) = 100000000Hz (slot req 196079Hz, actual 196078HZ div = 255)
[ 15.850000] mmc1: error -110 whilst initialising SD card
[ 17.680000] systemd: No control group support available, not creating root group.
[ 17.710000] systemd: Expecting device dev-disk-by\x2duuid-ad455a75\x2d609c\x2d4b3c\x2d956b\x2dbcef3ebc4603.device...
[ 17.720000] systemd: Starting -.slice.
Expecting device dev-disk-by\x2du[ 17.730000] systemd: Caught , dumped core as pid 1144.
[ 17.730000] systemd: Freezing execution.
Update #2: See the comments section.
Update: It’s because the 3.11 kernel doesn’t support the MMC card. I’ll try later using an external USB drive.
For more half-baked ideas, see the ideas tag.
The Linux kernel:
5 MB of highly optimized code that runs the world’s computers. You can copy it around and boot it on different hardware.
No wait, that’s all wrong. I’m forgetting about the modules. There are another 2832 files in
/lib/modules/3.11.9-200.fc19.x86_64 and without them this kernel will hardly function.
It’s nice to be able to copy the kernel around — to compile it on fast x86-64 and run it on slow ARM, or to run the host kernel in a VM, but all those module files make everyone’s lives a lot more complex.
So my half-baked idea is this:
Combine all the modules into a single file, let’s call it
/boot/modules-3.11.9-200.fc19.x86_64. This file might start off as an ext4 filesystem which can be loopback-mounted on /lib/modules. Eventually I’d hope that the module tools could load modules from the file directly.
Now you can happily cross-compile and copy just two kernel files from x86 to ARM or into your VMs, and that’s a lot less hassle.
[Edit: Thanks to adrianmonk for correcting my math]
It’s surprisingly hard to find a definitive answer to the question of what happens with Linux block device names when you get past drive 26 (ie. counting from one, the first disk is
/dev/sda and the 26th disk is
/dev/sdz, what comes next?) I need to find out because libguestfs is currently limited to 25 disks, and this really needs to be fixed.
Anyhow, looking at the code we can see that it depends on which driver is in use.
For virtio-blk (
/dev/vd*) the answer is:
| Drive # —
Beyond 18278 drives the virtio-blk code would fail, but that’s not currently an issue.
For SATA and SCSI drives under a modern Linux kernel, the same as above applies except that the code to derive names works properly beyond
sdzzz up to (in theory)
sd followed by 29
z‘s! [Edit: or maybe not?]
As you can see virtio and SCSI/SATA don’t use common code to name disks. In fact there are also many other block devices in the kernel, all using their own naming scheme. Most of these use numbers instead of letters: eg:
/dev/mmcblk0 and so on.
If disks are partitioned, then the partitions are named by adding the partition number on the end (counting from
1). But if the drive name already ends with a number then a letter
p is added between the drive name and the partition number, thus:
LVM2 snapshots are fully read/write. You can write to either the snapshot or the original volume and the write won’t be seen by the other. In the snapshot volume what is stored is an “exception list”, basically a big hash table(?) recording which blocks are different from the original volume.
Now I was curious how this works, because obviously writes to the original volume must also cause an exception to be added to the snapshot volume. How does the snapshot module see these writes? Does it hook into the original device in some way? It turns out, no.
It’s all handled at higher levels (by the lvcreate command in fact) which inserts a device mapper layer above the original device. This special layer (called a “snapshot-origin”) grabs the write request and passes it to the snapshot code where it causes an exception to be added to the snapshot (or snapshots because several snapshots might have been created against a single origin). [Refer to origin_map and __origin_write in dm-snap.c].
You can see the extra layer added by lvcreate -s by examining the device mapper tables directly. For example, before creating a snapshot:
# dmsetup table | grep F13
vg_pin-F13x64: 0 20971520 linear 253:0 257687936
and after creating a snapshot of that LV (notice the “real” LV has been renamed):
# lvcreate -s -n F13x64snap -L 1G /dev/vg_pin/F13x64
# dmsetup table | grep F13
vg_pin-F13x64snap: 0 20971520 snapshot 253:38 253:39 P 8
vg_pin-F13x64snap-cow: 0 2097152 linear 253:0 605815168
vg_pin-F13x64: 0 20971520 snapshot-origin 253:38
vg_pin-F13x64-real: 0 20971520 linear 253:0 257687936
Resolving the device references into a simpler diagram:
F13x64 (253:4) F13x64snap (253:37)
| | |
| +---------------+ |
v v v
F13x64-real (253:38) F13x64snap-cow (253:39)
F13x64snap-cow at the bottom right is the actual storage used for the snapshot exception list. It is just a plain linear mapping of some blocks from the underlying block device. F13x64snap is the virtual device. When read, the read consults the exception list in the snapshot cow, and if not there, consults the real device. Writes to F13x64snap go to the exception list. Finally, writes to the virtual origin device F13x64 go to the snapshot cow (or snapshot cows plural). There is no explicit connection here — in fact it goes via a hash table stored in kernel memory.
The following pair of commands will hang your Fedora 13/14/15 system solid. Be warned.
$ truncate -s 16G bigfile
$ libtool --mode=execute /bin/ls bigfile
- core_pattern obeys the current chroot, which effectively makes it useless as a way to collect cores centrally if your system has any chrooted processes.
- core_pattern explicitly prevents you from dumping to non-regular files. In a virtual environment it’d be very useful to coredump to a block device.
The Fedora build system Koji runs on RHEL 5
Xen and builds everything on top of that using mock. This can lead to some rather difficult to debug problems where your package builds and tests OK for you on your local Rawhide machine, but fails in Koji. The reason it can fail in Koji is because it is running on the RHEL 5 Linux kernel (2.6.18). Your program, or any program you depend on during the build, might make assumptions about system calls that work for a Rawhide kernel, but fail for a RHEL 5 kernel.
Reproducing these bugs is difficult. Hopefully this posting should be a good start.
Koji is doing roughly the equivalent of this command (on a RHEL 5 host):
mock -r fedora-rawhide-x86_64 --rebuild your.src.rpm
That command doesn’t work straightaway. There are some things you have to install and upgrade first before that works:
- Install RHEL 5 (or use CentOS or another no-cost alternative).
- Install EPEL.
- Install or update yum, python-hashlib, mock.
- Use /usr/sbin/vigr to add yourself to the “mock” group.
- The version of RPM from RHEL 5 is too old to understand the new xz-based compression format used by Rawhide RPMs. You have to build the Fedora 12 RPM (NB: Fedora 13 RPM definitely doesn’t work because it requires Python 2.6).
The Fedora 12 specfile is a starting point, but it won’t work directly. There are some small changes you have to make, and a single patch to the source code, but hopefully those will be obvious. Update: Here for a short time is a scratch build of the Fedora 12 RPM made to work on RHEL 5.4. Once you’ve built the new rpm RPM (!), install it.
At this point you can use the mock command above to test-build SRPMs using the unusual RHEL 5 kernel / Rawhide userspace combination.