Problemstellung
Alle meine Rechner haben mindestens zwei Festplatten: eine SSD für / und ~, und eine Magnetplatte für…. naja, Filme, mp3s etc. – aber eben ohne eindeutigen Mountpoint. ~/Downloads und /mnt/data liegt bei mir da drinnen, ~/Desktop hatte ich da mal, weil da auch mal große Datenmengen abgeladen werden, ~ will man da nicht komplett drinnen haben wegen der .$configs. Einfach irgendwie problematisch. Als Lösung bietet sich hier Blockcache an.
Arbeitsweise von Blockcaches
bcache und Konsorten sind ein Block-Layer Cache für Linux. Das heisst es legt sich als zusätzliche Schicht über ein/mehrere bestehendes Blockdevices (z.B. Festplatte) und optimiert an dieser Stelle dann ganz gewaltig.
Ziel ist es, die Vorteile einer SSD Festplatte mit denen einer magnetischen zu kombinieren: Kleine bzw. seek-intensive Lesevorgänge werden auf der SSD gecached, zukünftiges Lesen geht dann entsprechend mit SSD-Geschwindigkeit. Filme, Musik und dergleichen, was vorallem sequenziell gelesen wird, bleibt exklusiv auf der Magnetplatte. Außerdem braucht man sich eben keine Gedanken mehr machen was man wo hin speichert/mounted.
Geht eine SSD kaputt, und das tun sie meiner Erfahrung nach sehr viel regelmäßiger als herkömmliche Festplatten, ist das fast egal, man tauscht sie aus, und hat keinen Totalverlust der Daten and dieser Stelle – eine tote Magnetplatte, sofern sie nicht im RAID läuft, geht natürlich mit totalem Datenverlust einher. Da man aber vernünftige Backups hat, ist das ja auch nicht so schlimm.
Wie oben ja schon verlinkt gibt es diverse Implementierungen von solchen Caches, auf die Schnelle hab ich nur diesen Benchmark gefunden und mich dann kurzerhand für bcache entschieden. Die offizielle Doku findet sich im bcache-kernel.
Der Plan
Mein Laptop läuft noch auf einem uralten Ubuntu, und er hat eh eine SSD und eine Magnetplatte. Ziel ist es also, das frische Ubuntu 12.10 von meinem Desktop auf meinen Laptop zu klonen, und dabei noch einen bcache-Layer einzuziehen. Wenn sich das bewährt, wird der Desktop auch entsprechend konfiguriert. Selbstverständlich soll nach wie vor alles verschlüsselt sein. Als Verschlüsselungssystem kommt bei mir seit langem dm-crypt mit LUKS zum Einsatz, das kommt raus wenn man mit der, inzwischen nicht mehr gepflegten, alternative Installations-CD von Ubuntu die gesamte Festplatte verschlüsselt.
Reihenfolge der Layer
In dem angestrebten Szenario müseen die Daten also durch zwei Layer zusätzlich zu einer normalen Ubuntu-Installation, hierfür gibt es zwei Möglichkeiten:
- Festplatte | Bcache | Crypt | Filesystem
- Festplatte | Crypt | Bcache | Filesystem
Die erstere Version ist sicherlich ein wenig leichter zu implementieren, allerdings sollte der Cryptolayer meines Erachtens nach stets der unterste sein – wer weiss schon was für Metadaten ein auf Performance getrimmter bcache noch auf die Festplatte packt?
Die Umsetzung
- Einen Platz suchen wo man ~9GB Platz frei hat
cd /tmp
- Die vom bcache Team bereitgestellten Kernelquellen ziehen – leider gibts keine individuellen Patches, weswegen noch das ein oder andere Problem wie inkompatible Treiber und so dazu kommt.
git clone http://evilpiepirate.org/git/linux-bcache.git && cd linux-bcache
- Die im aktuellen Kernel verwendeten Einstellungen übernehmen. Die ganzen neuen Optionen hab ich einfach mit „Enter“ im Default belassen. Das geht sicher auch irgendwie eleganter, make-kpkg kümmert sich da ja an sich auch drum…
make oldconfig
- bcache als Modul (oder im Kernel direkt) aktivieren. (Device Drivers —> Multiple devices driver support (RAID and LVM) —> Block device as cache)
make menuconfig
oder einfach das entsprechende Setting direkt im .config setzen
sed -i 's/^CONFIG_BCACHE=.*$/CONFIG_BCACHE=m/' .config
- Den neuen Kernel vorbereiten, das sollte die „version.h“ erstellen
make prepare
- Den neuen Kernel bauen
fakeroot make-kpkg --initrd --append-to-version=-bcache kernel_image kernel_headers
- dabei fallen denn im übergeordneten Verzeichnis zwei .deb Pakete raus – eins mit dem Kernel, eins mit den Kernelheadern. Beide werden sogleich installiert:
sudo dpkg -i /tmp/*bcache*deb deb(Reading database ... 266204 files and directories currently installed.) Preparing to replace linux-headers-3.7.0-bcache+ 3.7.0-bcache+-10.00.Custom (using linux-headers-3.7.0-bcache+_3.7.0-bcache+-10.00.Custom_amd64.deb) ... Unpacking replacement linux-headers-3.7.0-bcache+ ... Selecting previously unselected package linux-image-3.7.0-bcache+. Unpacking linux-image-3.7.0-bcache+ (from linux-image-3.7.0-bcache+_3.7.0-bcache+-10.00.Custom_amd64.deb) ... Done. Setting up linux-headers-3.7.0-bcache+ (3.7.0-bcache+-10.00.Custom) ... Examining /etc/kernel/header_postinst.d. run-parts: executing /etc/kernel/header_postinst.d/dkms 3.7.0-bcache+ /boot/vmlinuz-3.7.0-bcache+ Error! Bad return status for module build on kernel: 3.7.0-bcache+ (x86_64) Consult /var/lib/dkms/fglrx-updates/8.960/build/make.log for more information. Error! Bad return status for module build on kernel: 3.7.0-bcache+ (x86_64) Consult /var/lib/dkms/virtualbox/4.1.12/build/make.log for more information. Setting up linux-image-3.7.0-bcache+ (3.7.0-bcache+-10.00.Custom) ... Running depmod. Examining /etc/kernel/postinst.d. run-parts: executing /etc/kernel/postinst.d/dkms 3.7.0-bcache+ /boot/vmlinuz-3.7.0-bcache+ Error! Bad return status for module build on kernel: 3.7.0-bcache+ (x86_64) Consult /var/lib/dkms/fglrx-updates/8.960/build/make.log for more information. Error! Bad return status for module build on kernel: 3.7.0-bcache+ (x86_64) Consult /var/lib/dkms/virtualbox/4.1.12/build/make.log for more information. run-parts: executing /etc/kernel/postinst.d/initramfs-tools 3.7.0-bcache+ /boot/vmlinuz-3.7.0-bcache+ update-initramfs: Generating /boot/initrd.img-3.7.0-bcache+ W: Possible missing firmware /lib/firmware/rtl_nic/rtl8168g-1.fw for module r8169 W: Possible missing firmware /lib/firmware/rtl_nic/rtl8106e-1.fw for module r8169 run-parts: executing /etc/kernel/postinst.d/pm-utils 3.7.0-bcache+ /boot/vmlinuz-3.7.0-bcache+ run-parts: executing /etc/kernel/postinst.d/update-notifier 3.7.0-bcache+ /boot/vmlinuz-3.7.0-bcache+ run-parts: executing /etc/kernel/postinst.d/zz-update-grub 3.7.0-bcache+ /boot/vmlinuz-3.7.0-bcache+ Generating grub.cfg ... Found background image: .background_cache.png Found linux image: /boot/vmlinuz-3.7.0-bcache+ Found initrd image: /boot/initrd.img-3.7.0-bcache+ Found linux image: /boot/vmlinuz-3.2.0-31-generic Found initrd image: /boot/initrd.img-3.2.0-31-generic Found linux image: /boot/vmlinuz-3.2.0-29-generic Found initrd image: /boot/initrd.img-3.2.0-29-generic Found memtest86+ image: /memtest86+.bin Found Microsoft Windows XP Professional on /dev/sda1 done
Damit gehen aber die Probleme erst richtig los….
Probleme mit dkms
Ich hab bei mir die fglrx-update Pakete installiert, das sind etwas aktuellere Pakete als die einfachen fglrx, aber auch aus dem Standardrepository von Ubuntu. Im Gegensatz zu allen anderen Kerneln, meinte dkms aber bei 3.7-bcache die header von fglrx, also ohne „-update“ verwenden zu müssen. Erst hätt ich dann halt die einfachen fglrx installiert und verwendet, aber nach dem das am Ende auch nicht funktionierte (untrige Patches crashten das System bei der Initialisierung von Xorg) hab ich am Ende die propritären Treiber direkt von AMD installiert:
cd /tmp wget http://www2.ati.com/drivers/beta/amd-driver-installer-catalyst-12.11-beta11-x86.x86_64.zip unzip amd-driver-installer-catalyst-12.11-beta11-x86.x86_64.zip chmod +x amd-driver-installer-catalyst-12.11-beta11-x86.x86_64.run ./amd-driver-installer-catalyst-12.11-beta11-x86.x86_64.run --buildpkg Ubuntu/precise apt-get remove 'fglrx*' dpkg -i fglrx*deb
Jetzt funktionierte dkms immer noch nicht – das lag zum einen daran, dass mir „include/linux/version.h“ der -bcache header fehlten, wohl weil ich den oben beschriebenen „make prepare“ nicht ausgeführt hatte.
# dpkg-reconfigure linux-headers-3.7.0-bcache+ Examining /etc/kernel/header_postinst.d. run-parts: executing /etc/kernel/header_postinst.d/dkms 3.7.0-bcache+ /boot/vmlinuz-3.7.0-bcache+ Error! Bad return status for module build on kernel: 3.7.0-bcache+ (x86_64) Consult /var/lib/dkms/fglrx/8.960/build/make.log for more information. # cat /var/lib/dkms/fglrx/8.960/build/make.log DKMS make.log for fglrx-8.960 for kernel 3.7.0-bcache+ (x86_64) Mon Jan 7 02:36:18 CET 2013 AMD kernel module generator version 2.1 kernel includes at /lib/modules/3.7.0-bcache+/build/include not found or incomplete file: /lib/modules/3.7.0-bcache+/build/include/linux/version.h
Da fehlt ihm wie gesagt jetzt noch die version.h, wobei man sich die notfalls auch selber stricken kann, die Anleitung dazu steht in jeder include/linux/version.h. Naja, hilft nichts, danach schlägt das bauen mit dkms immer noch fehl.
~# cat /var/lib/dkms/fglrx/8.960/build/make.log DKMS make.log for fglrx-8.960 for kernel 3.7.0-bcache+ (x86_64) Mon Jan 7 02:49:18 CET 2013 AMD kernel module generator version 2.1 doing Makefile based build for kernel 2.6.x and higher rm -rf *.c *.h *.o *.ko *.a .??* *.symvers make -C /lib/modules/3.7.0-bcache+/build SUBDIRS=/var/lib/dkms/fglrx/8.960/build/2.6.x modules make[1]: Entering directory `/usr/src/linux-headers-3.7.0-bcache+' CC [M] /var/lib/dkms/fglrx/8.960/build/2.6.x/firegl_public.o /var/lib/dkms/fglrx/8.960/build/2.6.x/firegl_public.c: In function ‘KCL_MEM_VM_MapRegion’: /var/lib/dkms/fglrx/8.960/build/2.6.x/firegl_public.c:3716:39: error: ‘VM_RESERVED’ undeclared (first use in this function) /var/lib/dkms/fglrx/8.960/build/2.6.x/firegl_public.c:3716:39: note: each undeclared identifier is reported only once for each function it appears in make[2]: *** [/var/lib/dkms/fglrx/8.960/build/2.6.x/firegl_public.o] Error 1 make[1]: *** [_module_/var/lib/dkms/fglrx/8.960/build/2.6.x] Error 2 make[1]: Leaving directory `/usr/src/linux-headers-3.7.0-bcache+' make: *** [kmod_build] Error 2 build failed with return value 2
unknown identifier… sieht nicht gut aus für den treiber
Da ist VM_RESERVED nun tatsächlich in linux 3.7 rausgeflogen, es wurde wohl ersetzt durch
VM_DONTEXPAND | VM_DONTDUMP
Debian hat da nen bug dazu, da ist auch ein Patch dabei, den ich einspiele (der hier sieht auch gut aus, vielleicht sogar besser – er räumt mit dem alten identifier gleich komplett auf). Das betrifft nicht nur die Grafiktreiber, sondern auch Virtualbox und mit Sicherheit einige andere propritäre Module.
# patch -p6 /usr/src/fglrx-9.010/firegl_public.c --- fglrx-driver-12.11~beta11.orig/common/lib/modules/fglrx/build_mod/firegl_public.c 2012-12-03 03:03:45.000000000 +0100 +++ fglrx-driver-12.11~beta11/common/lib/modules/fglrx/build_mod/firegl_public.c 2013-01-05 12:32:40.605448455 +0100 @@ -203,6 +203,11 @@ #define VM_SHM 0 #endif +// VM_RESERVED is replaced with VM_DONTEXPAND | VM_DONTDUMP in Linux 3.7+ +#ifndef VM_RESERVED +#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP) +#endif + #ifdef FGL_LINUX253P1_VMA_API // Linux 2.5.3-pre1 and compatibles #define FGL_VMA_API_TYPE struct vm_area_struct * (CTRL-D) patching file /usr/src/fglrx-9.010/firegl_public.c Hunk #1 succeeded at 200.
Und schon funktioniert das ganze:
# dpkg-reconfigure linux-headers-3.7.0-bcache+ Examining /etc/kernel/header_postinst.d. run-parts: executing /etc/kernel/header_postinst.d/dkms 3.7.0-bcache+ /boot/vmlinuz-3.7.0-bcache+
Ein Reboot in den neuen Kernel läd auch endlich den fglrx Treiber ohne das System zu crashen – und weil ich den Betatreiber von AMD genommen hab, werde ich jetzt auch bis in Ewigkeit daran erinnert werden – unten rechts am Bildschirm… [Update: das lässt sich mit einer korrigierten /etc/ati/signature fixen]
Wer immer nen aktuellen Treiber verwendet hätte das sicherlich gewusst, mir ist das jetzt erstmal egal. Kernel und Module sind jedenfalls gebaut, jetzt geht’s um die Tools.
Zunächst die Sourcen aus dem Repository ziehen, eine fehlende Dependencie nachziehen und zu guter Letzt Paketbauen für faule (bei letzterem drauf achten dass die Version eine Zahl, und kein Wort ist.).
git clone http://evilpiepirate.org/git/bcache-tools.git sudo apt-get install uuid-dev sudo checkinstall make install
Damit wären schon mal die Grundlagen geschaffen – ein funktionierendes System mit bcache support – war doch komplizierter als ich erwartet hatte, vorallem wegen der elendigen proprietären Treiber. Das hat aber mit bcache nichts zu tun, sondern eher allgemein mit dem einhergehenden Kernelupdate. Im nächsten Teil wird das ganze noch auf einen Laptop mit bcache’ed+crypted / übertragen.