Surrende Rechner mit rotierenden Plattenstapeln sind out. In den eleganten Tablets und Smartphones des Digital Lifestyle steckt Flashspeicher, der Platz und Energie spart. Dieser Beitrag erklärt die Eigenheiten der Speicherchips und bietet geeignete Linux-Dateisysteme an.
Computer älterer Bauweise mit Festplatten und Lüftern verstecken sich zunehmend in Rechnenzentren, hinter dem Schutz der Cloud. Dort merkt der Anwender nicht, wie viel Wärme sie produzieren und welchen Krach sie machen. Smartphones und Tablets, die neuen Computer, durchdringen dagegen viele Lebensbereiche – schließlich sind sie mobil, leise und energiesparend.
Das verdanken die Geräte Speichertechnologien, die statt auf rotierende Platten auf Chips setzen. Diese Flash- oder Solid-State-Speicher besitzen keine beweglichen Teile und sind damit wesentlich robuster gegen mechanische Belastung. Zudem können sie schneller auf gewünschte Daten zugreifen, weil sich kein Lesekopf bewegen muss. Sie produzieren keinen Lärm und weniger Wärme und machen laute Lüfter überflüssig.
Linux unterstützt eine große Vielfalt an Flashspeichern. Dieser Artikel stellt geeignete Linux-Dateisysteme und -Tools für deren Einsatz vor und erläutert die technischen Hintergründe.
Speicherzwerge
Allerdings besitzt Flashspeicher auch Nachteile. Erstens ist er deutlich kostspieliger als herkömmliche Festplatten: Der Kunde erhält zum gleichen Preis gerade ein Zehntel der Speicherkapazität. Zweitens gelten für das Schreiben auf Solid-State-Speicher technische Beschränkungen. Man kann kein zweites Mal in denselben Block des Mediums schreiben, ohne den gesamten Block zu löschen, der daher auch Erase Block heißt. Aus diesem Grund fällt die Geschwindigkeit beim Schreiben auch meist wesentlich geringer aus als beim Lesen.
Zum Dritten hält ein Flashblock nur eine begrenzte Anzahl solcher Vorgänge aus, bevor er kaputtgeht – zwischen einigen Tausend bis zu einer Million. Hard- und Software müssen daher die Schreibvorgänge und damit den Verschleiß möglichst gut über die Blöcke verteilen, was man als Wear Leveling bezeichnet.
Kleine Warenkunde
NOR-Flash, benannt nach den auf dem Chip eingesetzten Gattern, war der erste verfügbare Flashspeicher. NOR macht es dem Entwickler einfach, da die CPU auf jedes beliebige Byte darauf direkt zugreifen kann. So lassen sich auch Programme direkt von NOR-Flash ausführen. Das kommt etwa bei Bootloadern zum Einsatz, die man dann nicht erst in den Arbeitsspeicher kopieren muss.
Die heute verbreitetste Art Solid-State-Speicher ist NAND-Flash, der mehr Speicherkapazität zu geringerem Preis bietet (Abbildung 1). Sein Nachteil besteht darin, dass er wie ein externes Laufwerk über einen Controller angebunden wird. Die CPU kann keinen Code vom Speichermedium ausführen, ohne ihn zuerst in den RAM zu kopieren. Außerdem kann NAND-Flash bereits ab Werk defekte Blocks (Bad Blocks) enthalten, die geeignete Hard- oder Software im Betrieb umgehen muss.

Abbildung 1: Der große Block in der Mitte des Einplatinen-Computers Beagleboard ist ein OMAP-System von Texas Instruments, auf dem obenauf der NAND-Flash sitzt.
Beim NAND-Flash sind wiederum zwei Typen auf dem Markt. Der eine ahmt ein normales Blockgerät nach. Dazu kommt ein in Hardware umgesetzter Flash Translation Layer zum Einsatz, der sich um das Löschen von Blocks, um Wear Leveling und die Bad Blocks kümmert. Solcher Speicher ist in USB-Sticks, Speicherkarten, EMMC (Embedded Multimedia Cards) und Solid State Drives (SSD) verbaut. Das Betriebssystem hat keine Kontrolle über die Verwaltung der Blöcke auf dem Medium.
Den zweiten Typ NAND-Speicher bezeichnet man als rohen Flash, denn hier darf das Betriebssystem selbst die Blöcke verwalten. Es kann beispielsweise über den Block Erase Count ermitteln, wie oft ein Block schon überschrieben wurde. Für derartigen Speicher gibt es im Linux-Kernel das MTD-Subsystem, das seinen Namen von der Bezeichnung Memory Technology Device ableitet (Abbildung 2). Es bietet eine einheitliche Programmierschnittstelle für vielerlei Arten von rohem Flash.

Abbildung 2: Das MTD-Subsystem des Linux-Kernels enthält zahlreiche Module für den Umgang mit Flashspeicher.
MTD-Partitionen
Roher Zugriff bedeutet, dass kein Dateisystem zum Einsatz kommt. Ein solches System benötigt man zum Speichern mehrerer Dateien, für manche Anwendungen genügt aber bereits eine einzige große Binärdatei. In der Regel kommen auf MTD-Speichern jedoch Partitionen zum Einsatz. So lassen sich Bereiche für bestimmte Zwecke reservieren, beispielsweise für Bootloader oder das Root-Dateisystem.
Einzelne Partitionen kann man auch read-only verwenden, etwa um das Betriebssystem vor Manipulationen zu schützen. Abbildung 3 zeigt ein typisches Partitionierungsschema.
Im Unterschied zu Festplatten ist bei MTD-Speicher die Partitionstabelle nicht auf dem Medium gespeichert – schließlich stellt es wegen möglicher Bad Blocks einen unsicheren Aufbewahrungsort dar. Stattdessen definiert eine Datenstruktur im Linux-Kernel die Partitionen. Abbildung 4 zeigt den betreffenden Ausschnitt aus der Datei »arch/arm/mach-omap2/board-omap3beagle.c« , der die Partitionen des NAND-Flash auf dem Beagleboard festlegt.

Abbildung 4: Die Partitionen des MTD-Speichers auf dem Beagleboard sind im Kernelquelltext vordefiniert.
Praktischerweise lassen sich diese Standardeinstellungen ändern, ohne den Kernel neu zu kompilieren. Dazu ermittelt der Entwickler zunächst den Namen des MTD-Geräts, indem er die Bootmeldungen des Kernels durchsieht. Im Beagleboard-Beispiel macht sich der NAND-Flash wie in Listing 1 bemerkbar. Der Gerätename ist »omap2-nand.0« .
Listing 1
Bootmeldungen
01 omap2-nand driver initializing 02 ONFI flash detected 03 NAND device: Manufacturer ID: 0x2c, Chip ID: 0xba (Micron NAND 256MiB 1,8V 16-bit) 04 Creating 5 MTD partitions on "omap2-nand.0": 05 0x000000000000-0x000000080000 : "X-Loader" 06 0x000000080000-0x000000260000 : "U-Boot" 07 0x000000260000-0x000000280000 : "U-Boot Env" 08 0x000000280000-0x000000680000 : "Kernel" 09 0x000000680000-0x000010000000 : "File System"
Ist der Gerätename bekannt, lässt sich die gewünschte Partitionierung mir Hilfe des Bootparameters »mtdparts« auf der Kernel-Kommandozeile übergeben:
mtdparts=omap2-nand.0:128k(X-Loader)ro,256k(U-Boot)ro,? 128k(Environment),4m(Kernel)ro,32m(RootFS)ro,-(Data)
Diese Angaben definieren folgende sechs Partionen:
- Erste Stufe des Bootloaders (128 KiB, read-only)
- Bootloader U-Boot (256 KiB, read-only)
- U-Boot-Umgebungsvariablen (128 KiB)
- Linux-Kernel (4 MiB, read-only)
- Root-Dateisystem (16 MiB, read-only)
- Daten (restlicher Speicherplatz)
Dabei muss die Partitionsgröße stets einem Vielfachen der Größe eines Erase Block entsprechen. Daher verwenden die Größenangaben auch die binären Präfixe (1 MiB = 2024 KiB). Die Erase-Block-Größe findet sich auf dem Zielsystem in der Datei »/sys/class/mtd/mtdx/erasesize« . Die neu erstellten Partitionen sind in »/proc/mtd« zu lesen, die Größen sind hexadezimal kodiert (Listing 2).
Listing 2
/proc/mtd
01 dev: size erasesize name 02 mtd0: 00020000 00020000 "X-Loader" 03 mtd1: 00040000 00020000 "U-Boot" 04 mtd2: 00020000 00020000 "Environment" 05 mtd3: 00400000 00020000 "Kernel" 06 mtd4: 02000000 00020000 "File System" 07 mtd5: 0dbc0000 00020000 "Data"
Eigenständige Geräte
Hier zeigt sich ein weiterer Unterschied zu Blockgeräten: MTD-Partitionen tauchen im Linux-Kernel als eigenständige Geräte auf, einen Namen für den kompletten Speicherchip gibt es nicht. Das Gerät »/dev/mtd1« kann demnach die zweite Partition auf dem ersten Flashspeicher oder auch die erste auf dem zweiten Flash sein.
Die Aufteilung in Listing 2 sieht eine eigene Partition für die Umgebungsvariablen des Bootloaders U-Boot bereit. Das hat einen praktischen Grund: Die Variablen lassen sich ändern, indem man ein neues Image auf die Partition kopiert. Die Entwickler der Firma Free Electrons haben ein Programm zum Erzeugen eines solchen Image geschrieben [1]. MTD-Geräte lassen sich über zwei Schnittstellen ansprechen. Die erste verwendet das zeichenorientierte Gerät »/dev/mtdN« und den Treiber »mtdchar« . Diese stellen I/O-Controls bereit, auf die wiederum die Kommandozeilen-Program- me der MTD-Utilities zugreifen.
Die zweite Schnittstelle liefern das Blockgerät »/dev/mtdblockN« sowie der Treiber »mtdblock« . Dieses Gerät kommt hauptsächlich zum Einsatz, um MTD-Dateisysteme wie JFFS2 und YAFFS2 einzuhängen, denn der Mount-Befehl arbeitet mit blockorientierten Geräten. Zum Schreiben taugt der Treiber aber nicht, da er weder Wear Leveling noch Bad Blocks unterstützt.
Für einfachere Dateisystemoperationen empfehlen sich daher die MTD-Utilities [2], die in vielen Linux-Distributionen im Paket »mtd-utils« stecken. Die wichtigsten Befehle sind »mtdinfo« , das Informationen über ein MTD-Gerät ausgibt, »flash_eraseall« zum vollständigen Löschen sowie »flashcp« zum Schreiben auf NOR-Flash und »nandwrite« zum Schreiben auf NAND-Flash.
JFFS2
Ein ausgewachsenes Dateisystem für MTD-Speicher ist das Journaling Flash File System in Version 2 (JFFS2, [3]). Es ist seit 2011 Teil des Linux-Kernels, unterstützt Wear Leveling und kann mit Bad Blocks umgehen. JFFS2 ist so ausgelegt, dass es sich auch nach einem Stromausfall oder Systemabsturz in einem konsistenten Zustand befindet. Außerdem beherrscht es mehrere Verfahren zur Komprimierung, beispielsweise Zlib und LZO.
Flash-Dateisysteme müssen auf besondere Gegebenheiten Rücksicht nehmen. Um eine bestehende Datei zu ändern, können sie nicht einfach den Inhalt der betroffenen Blöcke in den RAM kopieren, die Blöcke löschen und dann mit Inhalten füllen. Erstens könnte ein Stromausfall bei diesem Vorgang die Daten zerstören, während sie sich nur im RAM befinden. Zweitens würde das einzelne Blocks stark verschleißen.
Eine Alternative wäre es, die neuen Daten in einen neuen Block zu schreiben und die Verweise auf den alten zu aktualisieren. Das würde aber einen weiteren Schreibvorgang notwendig machen, der unter Umständen weitere Verweise im Dateisystem ändert.
JFFS2 löst diese Probleme mit Hilfe des Log-strukturierten Ansatzes [4]. Dabei ist jede Datei in einem Knoten mit Daten und Metadaten abgebildet und jeder Knoten trägt eine Versionsnummer. Statt Dateien an Ort und Stelle zu aktualisieren, speichert JFFS2 eine neue Version der Datei in freien Erase Blocks. Das macht zwar die Schreibvorgänge leichter, kompliziert aber das Lesen, da das Dateisystem die jüngste Version einer Datei finden muss.
Um den Lesevorgang zu optimieren, hält JFFS2 eine Map der jüngsten Knoten für jede Datei im Arbeitsspeicher. Beim Einhängen des Dateisystems muss es dieses Mapping allerdings erst einmal anlegen. Embedded-Systeme mit großen JFFS2-Partitionen brauchen also lange zum Starten. Glücklicherweise gibt es mittlerweile die Kernel-Konfigurationsoption »CONFIG_JFFS2_SUMMARY« . Sie sorgt dafür, dass Linux die Map zwischen den Mount-Vorgängen auf dem Flashmedium speichert, um die Mount-Zeit deutlich zu verkürzen. Diese Option ist standardmäßig aber nicht aktiviert.
JFFS2-Partition
Es gibt zwei Methoden, um eine JFFS2-Partition anzulegen. Bei der ersten löschen und formatieren die beiden folgenden Kommandos zunächst eine Partition und hängen sie anschließen ein:
flash_eraseall -j /dev/mtd2 mount -t jffs2 /dev/mtdblock2 /mnt/flash
Die zweite Möglichkeit passt in der Regel besser zum Arbeitsablauf eines Embedded-Entwicklers. Er erzeugt das Dateisystem zunächst in einer Abbilddatei auf seinem Desktop-Rechner und schreibt diese später auf den Flashspeicher. Zum Anlegen dient das Kommando »mkfs.jffs2« aus den MTD-Utils, außerdem muss die Größe des Erase Block bekannt sein. Der folgende Befehl erzeugt eine Imagedatei mit dem Namen »rootfs.jffs2« und der Blockgröße 256 MiB:
mkfs.jffs2 --pad --no-cleanmarkers--eraseblock=256 -d rootfs/ -o rootfs.jffs2
Der Parameter »-d« bezeichnet das Verzeichnis mit dem gewünschten Inhalt des Dateisystems, die Angabe »–pad« erzeugt ein Image, das ein Vielfaches der Blockgröße umfasst. Die Option »–no-cleanmarkers« sollte nur bei NAND-Flash zum Einsatz kommen. Diese Befehle formatieren die Zielpartition und schreiben das Image hinein:
flash_eraseall /dev/mtd2 nandwrite -p /dev/mtd2 rootfs.jffs2
Dabei darf das Image kleiner als die Partition sein, JFFS2 kann später dennoch den gesamten Speicherplatz nutzen – vorausgesetzt die Partition wurde zuvor komplett formatiert.
YAFFS2
Eine Alternative zu JFFS2 bietet YAFFS2 (Yet Another Flash Filesystem, [5]), das beispielsweise in Android-Smartphones Anwendung findet. Es verwendet keine Komprimierung, bietet aber wesentliche kürzere Mount-Zeiten sowie bessere Performance beim Lesen und Schreiben. Der Code ist dual unter GPL und proprietär lizenziert.
Der größte Nachteil dieses Dateisystems ist, dass es sich nicht im offiziellen Linux-Kernel befindet, sondern als externes Patch mit einigen Hilfsskripten existiert. Obwohl die Lizenz die Aufnahme in den Kernel ermöglichen würde, ist dieses Vorhaben vor etwa einem Jahr gescheitert. Die Kernel-Maintainer hatten Vorgaben gemacht, auf die die YAFFS2-Entwickler nicht eingehen wollten, um das Dateisystem Betriebssystem-unabbhängig zu halten.
Nach dem Patchen des Kernels lässt sich ein neues YAFFS2-Dateisystem mit folgendem Befehl anlegen:
flash_eraseall /dev/mtd2
Beim ersten Mount-Vorgang findet das Formatieren statt:
mount -t yaffs2 /dev/mtdblock2 /mnt/flash
Eine weitere Möglichkeit ist, dafür das Tool »mkyaffs« aus den YAFFS2-Utilities [6] zu verwenden.
UBI und UBIFS
JFFS2 und YAFFS2 haben ein gemeinsames Problem: Sie implementieren das Wear Leveling selbst, wodurch es auf einzelne Partitionen beschränkt bleibt. Das ist jedoch ungünstig, da diese ganz unterschiedlich beansprucht werden. Systempartitionen sind häufig read-only eingehängt, Datenpartitionen dagegen machen viele Schreibvorgänge mit – man nennt sie deshalb auch heiß (hot). Damit heiße Partitionen nicht rasch verschleißen, müssen alle Bereiche des Flashspeichers am Wear Leveling teilnehmen. Dafür sorgt das Projekt Unsorted Block Images (UBI, [7]).
UBI bildet eine Schicht oberhalb von MTD. Es übernimmt das Wear Leveling für das gesamte Speichergerät und entlastet die Dateisysteme von dieser Aufgabe. Daneben ermöglicht es flexible Partitionen beziehungsweise Volumes, wie es der Logical Volume Manager für blockorientierte Geräte tut.
Es implementiert Logical Erase Blocks (LEB), die es auf Physical Erase Blocks (PEB) abbildet (Abbildung 5). Höhere Schichten wie etwa Dateisysteme haben nur Zugriff auf LEB. Schreibt das Betriebssystem häufig auf einen bestimmten logischen Block, ändert UBI die Verweise und ersetzt den heißen PEB durch einen weniger beanspruchten. Das Linux-MTD-Projekt hat ein passendes Dateisystem entwickelt, das auf UBI aufsetzt. Es heißt UBIFS und ist als Nachfolger für JFFS2 gedacht. UBIFS bietet schnellere Lese- und Schreibvorgänge, lässt sich rasch einhängen und unterstützt Komprimierung.

Abbildung 5: UBI verwaltet logische Volumes, ähnlich dem Logical Volume Manager. Unter den physischen Blocks sorgt es für ausgeglichenen Verschleiß.
Unter Linux lässt sich UBI mit UBIFS mit ein paar Befehlen initialisieren. Zunächst muss Root das Geräteverzeichnis »/dev« als »tmpfs« -Pseudodateisystem einhängen. Das Kommando
ubiformat /dev/mtd1
löscht eine Flashpartition, ohne den Erase Count zurückzusetzen. Der folgende Befehl aktiviert UBI auf der MTD-Partition:
ubiattach /dev/ubi_ctrl -m 1
Dabei entsteht das neue zeichenorientierte Gerät »/dev/ubi0« . Darauf lassen sich nun Volumes anlegen:
ubimkvol /dev/ubi0 -N test -s 116MiB
Oder
ubimkvol /dev/ubi0 -N test -m# (maximale Größe)
Das Einhängen des angelegten Volume »test« erledigt das Mount-Kommando:
mount -t ubifs ubi0:test /mnt/flash
Nun kann man das Dateisystem mit Dateien füllen.
Eine alternative Vorgehensweise ist es auch bei UBIFS, zunächst eine Imagedatei des Dateisystems anzulegen, was mit »mkfs.ubifs« erfolgt. Das Programm »ubiupdatevol« kopiert das Abbild auf den Speicher.
Es ist sogar möglich, den gesamten UBI-Speicher zunächst als Image zu erzeugen und später per Bootloader auf das Gerät zu schreiben. Dazu ist eine Konfigurationsdatei wie »ubi.ini« erforderlich, die in Listing 3 zu sehen ist. Sie beschreibt, welche Volumes in welcher Größe zu erstellen sind. Das UBI-Image legt der folgende Befehl an. Er spezifiziert zudem 128 KiB große physische Erase Blocks und 4096 als minimale I/O-Größe:
Listing 3
ubi.ini
01 [RFS-volume] 02 mode=ubi 03 image=rootfs.ubifs 04 vol_id=1 05 vol_size=30MiB 06 vol_type=dynamic 07 vol_name=rootfs 08 vol_flags=autoresize 09 vol_alignment=1
ubinize -o ubi.img -p 128KiB -m 4096 ubi.ini
Zum Übertragen des Abbilds dient ein Tool des Bootloaders, das mit Bad Blocks umgehen können muss.
Außerdem benötigt die Kernel-Kommandozeile als zusätzliche Option »ubi.mtd=1« . Soll UBIFS die Rootpartition aufnehmen, ist noch Folgendes an das Boot-Kommando anzuhängen:
rootfstype=ubifs root=ubi0:rootfs
Ein weiteres Dateisystem für Flashspeicher ist Log-FS [8]. Wie der Name andeutet, verwendet es den Log-strukturierten Ansatz. Seit Linux 2.6.34 ist es Teil des Mainline-Kernels. Das innovative Dateisystem könnte es wohl mit UBIFS aufnehmen, doch leider erwies es sich beim jüngsten Test der Firma Free Electrons als instabil und verursachte beim Aushängen Kernel-Oopses. Dank der Integration in den offiziellen Linux-Kernel stehen die Chancen aber gut, dass sich ein Entwickler dieser Probleme annimmt.
Performance
Das Unternehmen Free Electrons hat die Performance der Flash-Dateisysteme in verschiedenen Kernelversionen untersucht. Die Ergebnisse (Abbildung 6) sind im Detail unter [9] nachzulesen. Zusammenfassend lässt sich feststellen, dass JFFS2 die schlechteste Performance zeigt und unbedingt mit der Option »CONFIG_JFFS2_SUMMARY« kompiliert gehört, um den Mount zu beschleunigen.

Abbildung 6: Das Diagramm zeigt die CPU-Zeit, die die Dateisysteme beim Einhängen brauchen. Die langen roten Balken verdeutlichen den zeitaufwändigen Mount-Prozess bei JFFS2.
Davon abgesehen stellt es aber einen guten Kompromiss für Szenarien mit kleinen Flashpartitionen dar, weil es Komprimierung unterstützt und weniger Overhead erzeugt als UBIFS.
Dank der Fortschritte in den letzten Jahren zeigt YAFFS2 in vielen Testszenarien sehr gute Ergebnisse, manchmal sogar die besten des Testfelds. Nachteilig ist dennoch, dass es keine Kompression bietet und nicht im Linux-Kernel integriert ist. UBIFS stellt hinsichtlich Geschwindigkeit und Platzbedarf die beste Lösung dar. Lediglich auf sehr kleinen Partitionen stört sein zusätzlicher Platzbedarf. Daneben erfordert es beim Deployment etwas mehr Arbeit als die anderen Kandidaten.
Daneben gibt es noch ein paar einfache Faustregeln für die Arbeit mit Flashspeicher. Dazu gehört zum Beispiel, keine Swap-Partition auf Flash auszulagern. Wann immer möglich, sollte man Partitionen read-only einhängen. Volatile Daten, beispielsweise Logfiles, gehören in den Arbeitsspeicher, wohin sie das Pseudodateisystem »tmpfs« befördert.
Billigheimer
Rohe Flashspeicher bieten dem Embedded-Entwickler im Zusammenspiel mit Linux viele Optimierungsmöglichkeiten. Der Trend bei den Hardwareherstellern geht allerdings weg von den flexiblen NAND-Speichern hin zu Embedded-MMC. Diese direkt auf der Platine aufgelöteten Speicherkarten benutzen eine Schnittstelle, die eher der einer externen Karte entspricht. Sie verbergen die Details der Bad Blocks und des Wear Leveling vor dem Betriebssystem. Da sie sehr preisgünstig sind, werden sie vermutlich das kostspieligere rohe Flash verdrängen.
Zum Glück bleibt EMMC nicht vollständig undurchsichtig. Der Kernelentwickler Arnd Bergmann hat ein Tool namens Flashbench [10] geschrieben, mit dem man die Charakteristiken von Speichermedien, etwa die Größe der Erase Blocks, experimentell ermitteln kann. Mit Hilfe dieser Befunde lassen sich dann auch die Parameter der eingesetzten Dateisysteme optimieren. Bergmann beschreibt seine Arbeit in einem Online-Artikel von 2011 [11].
DELUG-DVD
Auf der DELUG-DVD finden sich über 500 Seiten Trainingsfolien und Übungsaufgaben der Firma Free Electrons für die Arbeit mit Embedded Linux.
Infos
- Image-Tool für U-Boot-Environment:http://free-electrons.com/blog/mkenvimage-uboot-binary-env-generator/
- MTD-Utils: http://git.infradead.org/mtd-utils.git
- JFFS2: http://www.linux-mtd.infradead.org/faq/jffs2.html
- Log-strukturiertes Dateisystem:http://en.wikipedia.org/wiki/Log-structured_file_system
- YAFFS2: http://www.yaffs.net
- YAFFS2-Utilities: http://code.google.com/p/yaffs2utils/
- UBI und UBIFS: http://www.linux-mtd.infradead.org/doc/ubifs.html
- Log-FS-Repository: https://github.com/prasad-joshi/logfs
- Benchmarks für Flash-Dateisysteme: http://elinux.org/Flash_Filesystem_Benchmarks
- Benchmark-Tool Flashbench: http://git.linaro.org/gitweb?p=people/arnd/flashbench.git;a=summary
- Arnd Bergmann, “Optimizing Linux with cheap flash drives”: Linux Weekly News 2011: http://lwn.net/Articles/428584/







