\input{confighandout} \subsection{Unsorted Block Images (UBI)} \subsubsection{Was ist UBI?} UBI kann am ehesten als Logical Volume Manager (LVM) f\"ur mtd-Devices bezeichnet werden. Beim Start scanned UBI das mtd-Device und baut eine Liste der vorhandenen Erasebl\"ocke auf. Dabei werden auch Bad Blocks richtig behandelt, da das MTD-Subsystem, auf dem UBI aufsetzt, diese bereits erkennt. Dieser Gesamtvorrat an physikalischen Erasebl\"ocken wird jetzt im n\"achsten Schritt an sogenannte UBI-Volumes verteilt. \subsubsection{UBI-Volumes} UBI-Volumes entsprechen etwa den Partitionen anderer Systeme. Der von einem mtd-Device bereitgestellte Speicher wird also in mehrere unabh\"angige Einheiten aufgeteilt. Im Vergleich zu den Partitionen, die das MTD-Subsystem auf einem Flash anlegen kann, sind UBI-Volumes aber erheblich leistungsf\"ahiger und flexibler. Aus diesem Grund empfiehlt es sich, so wenig wie m\"oglich mtd-Partitionen anzulegen, und UBI eine m\"oglichst gro\ss e Partition zur Verwaltung zu \"ubergeben. MTD-Partitionen haben eine strikt festgelegte Zuordnung von physikalischen Erasebl\"ocken zu Partitionen. UBI kann dagegen Erasebl\"ocke bei Bedarf beliebig zwischen den Volumes umverteilen. Dies geschieht beispielsweise beim Wear-Leveling, das UBI ebenfalls durchf\"uhrt. Ebenso k\"onnen defekte Erasebl\"ocke durch andere Bl\"ocke ersetzt werden. Durch den von UBI verwendeten Algorithmus ist es selbst beim Neuanlegen eines Volumes kaum vorhersagbar, welche physikalischen Erasebl\"ocke auf dem Flash es belegt. W\"ahrend eine MTD-Partition immer in denselben aufeinanderfolgenden Bl\"ocken liegt, \"andert sich die Zuordnung von physikalischen Erasebl\"ocken des Flash zu logischen Erasebl\"ocken des Volumes im laufenden Betrieb dynamisch. Ein UBI-Volume mit drei Erasebl\"ocken kann also durchaus die Bl\"ocke 814, 27 und 1013 belegen. Aus diesem Ansatz ergibt sich auch der Name \emph{Unsorted Block Images}. \emph{Hinweis:} Auf klassischen Festplatten wird ein solches Verhalten als \emph{Fragmentierung} bezeichnet und ist dort unerw\"unscht, da eine mechanische Platte signifikante Seek-Zeiten aufweist. Man versucht dort, Daten m\"oglichst in aufeinander folgenden Bl\"ocken zu speichern, um zu verhindern, dass der mechanische Schreib-/Lesekopf von einem Ende der Platte zum anderen bewegt werden muss. Auf Flash-Speichern gibt es keine Seek-Zeiten, was UBI hier zugunsten eines auf Flash optimierten Designs ausnutzt. \paragraph{Statische Volumes} Statische Volumes sind f\"ur Anwendungen gedacht, die kein Dateisystem ben\"otigen. Ein praktisches Beispiel ist ein kleines Volume, das lediglich einen Kernel enth\"alt, der vom Bootloader geladen und gestartet wird. Mit einem statischen Volume muss der Bootloader keinerlei Dateisystem implementieren. Er muss lediglich aus den UBI-Headern herausfinden, welche physikalischen Erasebl\"ocke zu dem statischen Volume geh\"oren. Ausserdem erf\"ahrt er von UBI, wie viele Bytes tats\"achlich durch Daten belegt sind. Er l\"adt diese Daten, im Beispiel einen Kernel, ins RAM und springt sie an. Dies ist mit relativ wenig Code (einige kB) m\"oglich. Statische Volumes enthalten also immer nur einen einzigen Datenblock, der in einem Vorgang geschrieben werden muss. \paragraph{Dynamische Volumes} Dynamische Volumes sind daf\"ur gedacht, ein Dateisystem zu enthalten. Man verwendet sie also beispielsweise f\"ur ein Root-Filesystem oder f\"ur Volumes, die Nutzerdaten enthalten. Dynamische Volumes verwendet man am Besten mit dem Dateisystem ubifs. \paragraph{UBIGLUEBI} UBIGLUEBI ist ein Aufsatz auf UBI, der f\"ur jedes Volume wieder ein mtd-Device bereitstellt. Dies klingt zun\"achst \"uberraschend, da UBI ja schon auf einem mtd-Device aufsetzt. Der Hintergrund ist, dass \"altere Flash-Dateisysteme wie jffs2 ein mtd-Device ben\"otigen. Um deren Einsatz zu erm\"oglichen, wurde dieser Zusatz geschaffen. Heute gibt es ubifs, das direkt auf UBI aufsetzt und folglich kein mtd-Device ben\"otigt. Da ubifs ohnehin in allen Bereichen deutliche Vorteile gegen\"uber jffs2 hat, wird UBIGLUEBI in der Regel nicht mehr ben\"otigt. \includegraphics[width=8cm]{images/ubi-big-picture.png} \paragraph{Fastmap} UBI legt in jedem Eraseblock einen Information Header an, der Metadaten wie z.b. die Zuordnung von physikalischem Eraseblock (PEB) zu logischem Eraseblock (LEB) beinhaltet. Diese Informationen müssen beim Hinzufügen eines UBI Devices (ubiattach) eingesammelt werden. Hierzu wird das entsprechende MDT Volume komplett gelesen und die Metadaten zusammengetragen. Der Aufwand für diesen Vorgang steigt damit linear zur Größe des Flash-Speichers. Um den Aufwand für das Zusammentragen der Metadaten beim Hinzufügen eines UBI Devices zu reduzieren, werden bei UBI Fastmap diese Metadaten persistent im Flash selbst abgelegt. Während des Vorgangs müssen dann nur noch die Speicherbereiche gelesen werden, in der die Metadaten abgelegt wurden. Die Zeitersparnis für ein Attach sinkt damit beträchtlich. Vor allem bei steigenden Flash Größen macht sich die Ersparnis deutlich bemerkbar. Hierzu legt UBI in den ersten 64 Eraseblocks einen Superblock an, der eine Referenz auf den Eraseblock enthält, in welchem die eigentliche Fastmap hinterlegt ist. Die Fastmap beinhaltet unter anderem statistische Informationen (belegte, freie und defekte PEBs), sogenannten Pools (Listen von belegten und freien PEBs), sowie den Metadaten der Volumes. Sowohl die Fastmap selbst, als auch die Pools können sich ihrerseits wiederum über mehrere verkettete PEBs erstrecken. Diese Referenzkette verhindert ein wear-out bestimmter Flash-Bereiche. So muss der Superblock nur dann schreibend modifiziert werden, wenn die Fastmap, z.B. Aufgrund eines Bit-Flips, in einem anderen PEB verlegt wird. Die Fastmap wiederum muss nur dann schreibend modifiziert werden, wenn sich die Lokation eines oder mehrerer Pools ändert. UBI Fastmap ist vollständig rückwärts kompatibel, d.h. ein mit UBI Fastmap generiertes UBI Volume ist auch mit einem älteren Kernel ohne UBI Fastmap problemlos verwendbar. Natürlich kommt hierbei der Geschwindigkeitszuwachs beim Attach nicht zum tragen. Ebenso ist es möglich ein bestehendes UBI Volume ohne Fastmap in ein UBI Volume mit Fastmap umzuwandeln, vorausgesetzt, es gibt genügend freie PEBs für das Ablegen der Fastmap. Ebenso ist es möglich, eine beschädigte oder unvollständige Fastmap zu rekonstruieren. In beiden Fällen muss dazu aber der gesamte Flashbereich des UBI Volumes gescannt werden. Die Geschwindigkeitsvorteile von Fastmap greifen dann erst wieder bei einem neuerlichen Attach (z.B. nach einem Reboot). UBI Fastmap ist so robust wie UBI selbst. Denn selbst wenn die Fastmap nicht gelesen werden kann oder wenn nicht genügend Platz auf dem UBI Volume vorhanden ist um die Fastmap zu speichern, so bleibt das UBI Volume trotzdem voll funktionsfähig. \subsubsection{UBI-Tools} Da UBI von den MTD-Entwicklern implementiert wurde, sind die UBI-Tools Bestandteil der MTD-Tool-Kollektion. Diese gibt es mittlerweile als Paket in den meisten Distributionen. Unter Debian installiert man das Paket \cmd{mtd-utils}: \begin{lstlisting} aptitude install mtd-utils \end{lstlisting} Hier die wichtigsten UBI-Aktionen in Kurzform: Die Kontrolle \"uber ein mtd-Device an UBI \"ubertragen: \begin{lstlisting} ubiattach /dev/ubi_ctrl -m 2 \end{lstlisting} Dies verbindet \cmd{/dev/mtd2} mit UBI. Ein Volume anlegen: \begin{lstlisting} ubimkvol /dev/ubi0 -s 3MiB -t static -N kernel -n 1 \end{lstlisting} Hier wird ein 3MiB gro\ss es statisches Volume mit dem Namen \cmd{kernel} angelegt. Das Volume erh\"alt die Nummer 1. Daten in ein statisches Volume schreiben: \begin{lstlisting} ubiupdatevol /dev/ubi0_1 zImage \end{lstlisting} Die Daten aus der Datei \cmd{zImage} werden in das statische Volume mit der Nummer 1 geschrieben. Nat\"urlich lassen sich komplette Volumes auch wieder entfernen: \begin{lstlisting} ubirmvol/dev/ubi0 -n 1 \end{lstlisting} Das Volume mit der Nummer 1 wird entfernt. Der mit Abstand aufwendigste Befehl ist \cmd{ubinize}. Damit lassen sich vollst\"andige UBI-Images f\"ur ein mtd-Device anfertigen. Diese k\"onnen anschlie\ss end mit \cmd{nandwrite} in das mtd-Device geschrieben werden. Alternativ kann das Image nat\"urlich auch mit einem geeigneten JTAGer in das Flash \"ubertragen werden. Da \cmd{ubinize} sehr vielseitig ist und relativ viele Flash- und Layout-Parameter ber\"ucksichtigt werden m\"ussen, kann hier nur ein einfaches Beispiel gegeben werden. Zun\"achst ist eine Konfigurationsdatei erforderlich, in der die einzelnen Volumes sowie die in ihnen unterzubringenden Images beschrieben werden. Diese Datei folgt in ihrer Syntax dem bekannten INI-Format. Ein Volume wird beispielsweise so angegeben: \begin{lstlisting} [rootfs-volume] mode=ubi image=../my-ubifs.img vol_id=1 vol_size=100MiB vol_type=dynamic vol_name=rootfs vol_flags=autoresize vol_alignment=1 \end{lstlisting} Unter der Annahme, dass alle Volumes in der oben angegebenen Weise in der Datei \cmd{ubi-cfg.ini} beschrieben wurden, kann man das UBI-Image mit einem Befehl erzeugen, der etwa so aussieht: \begin{lstlisting} ubinize -o ubi.img -p 128KiB -m 2048 -s 512 ubi-cfg.ini \end{lstlisting} Im Beispiel wird eine Eraseblock-Gr\"o\ss e von 128k angegeben, ausserdem eine Pagegr\"o\ss e von 2048 Bytes sowie eine Subpage-Gr\"o\ss e von 512 Bytes. Das fertige Image landet in der Datei \cmd{ubi.img}. Weitere Informationen sind unter folgender URL erh\"altlich: \begin{lstlisting} http://www.linux-mtd.infradead.org/doc/general.html \end{lstlisting} \input{tailhandout}