\documentclass{beamer}
%\documentclass[notes=hide,compress]{beamer}       % Navigation schmal, ohne Notizfolien
%\documentclass[notes=onlyslideswithnotes]{beamer} % nur Notizfolien

\usetheme{Luebeck}

%%% Handoutformat:
\usepackage{pgfpages} % für Handoutformat nötig
%\pgfpagesuselayout{2 on 1}[a4paper,border shrink=10mm]
%\setbeameroption{show notes}
%%% Notizen neben der Folie:
%\setbeameroption{show notes on second screen}


%\usepackage{tikz}
%\usepackage{beamerthemebars}
%\usepackage{graphicx} % PGF ist deutlich fähiger und kann auch schöner skalieren
%\usepackage{graphics} % s. graphicx (+ PGF ist PDFlatex fähig :))
%\usepackage{pgfshade}
%\usepackage{fleqn}
%\usepackage{multirow}
%\usepackage{multicol}
\usepackage[ngerman]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{latexsym}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{upgreek}   % non-italic griechische Buchstaben
\usepackage{subfigure} % mehrere Bilder in einer figure
\usepackage{textcomp}  % für Promille Zeichen
\usepackage{verbatim}  % verbatim-Umgebung (festbreiten, ohne Escaping)
\usepackage{listings}  % listing-Umgebung

%\setbeamercovered{transparent}            % transparente Overlays
\setbeamertemplate{navigation symbols}{}   % Navi-Symbole AUS
\setbeamertemplate{footline}[frame number] % FolienNr/Gesamt in Fußzeile

\title{VFS: Virtual Filesystem Switch}
\subtitle{Seminar: Dateisysteme -- SoSe07}
\author{Dinh Khoa Nguyen \& Eric Müller}
\date{8. Mai 2007}
%\keywords{Seminarvortrag} % PDF Keywords


\begin{document}
%\setcounter{part}{2} % falls man Vortrag aufteilt => parts => mehrere TableOfContents

\frame { \titlepage }

\part{VFS: Virtual Filesystem II}
\begin{frame}
 \frametitle{Überblick}
 \begin{columns}
  \begin{column}{0.5\linewidth}
   % nur die erste Section anzeigen in der linken Spalte
   \tableofcontents[sections=-1,subsectionstyle=shaded]
  \end{column}
  \begin{column}{0.5\linewidth}
   % in der rechten Spalte Sections 2-3
   \tableofcontents[sections=2-,subsectionstyle=shaded]
  \end{column}
 \end{columns}
\end{frame}


% ### FOLIENSATZ --- START --- FOLIENSATZ ### %

\begin{frame}
 \frametitle{Überleitung}
 \begin{itemize}
  \item VFS -- bisher:
  \begin{itemize}
   \item aus Sicht des Anwenders: Datei-Objekt (\texttt{struct file})
   \item interne Datenstrukturen \& Methoden: Superblock, Inode, Dentry
  \end{itemize}
  \item Frage: Wie werden konkrete Dateisysteme in VFS eingebunden?
 \end{itemize}
\end{frame}

\note{
 % leere Notiz -- damit der Handout korrekte Aufteilung hat
}

% --------------------------- %
%                             %
% -Anbindung an Dateisysteme- %
%                             %
% --------------------------- %
\section{Anbindung an konkrete Dateisysteme}
% \subsection{Überblick}
% \begin{frame}[fragile,label=overviewfs]
%  \frametitle{Überblick}
%  Der Linuxkernel unterstützt verschiedenste Dateisystemtypen:
%  \begin{itemize}
%   \item Lokale Dateisysteme wie ext2/3, ReiserFS, XFS, JFFS2
%   \item Netzwerkdateisysteme wie NFS, CODA, NCPFS, SMBFS
%   \item spezielle Dateisysteme: bdev, devpts, eventpollfs, futexfs, pipefs, proc, \alert{rootfs}, shm, mqueue, sockfs, sysfs, tmpfs, usbfs
%   \hyperlink{specialfs}{\beamergotobutton{vollständigere Liste}}
%   \item Darstellung der Dateisysteme im Kernel durch Objekte vom Typ \verb|struct file_system_type|
%  \end{itemize}
% \end{frame}
% 
% \note{}

\subsection{Anmelden/Registrieren eines Dateisystems}
%%% Frames mit verbatim-Inhalten kann Latex nicht in einem Durchgang rendern
%%% [fragile] führt zu xyz.vrb-Files, die vorgerendert werden
\begin{frame}[fragile,label=register]
 \frametitle{(un)-\texttt{register\_filesystem()}, \texttt{get\_fs\_type()}}
 \begin{itemize}
  \item Betriebssystem verwaltet eine Liste der bekannten Dateisysteme
  \item \verb|register_filesystem(struct file_system_type *)| meldet ein Dateisystem an
  \item \verb|unregister_filesystem(struct file_system_type *)| meldet ein Dateisystem ab
  \item \verb|get_fs_type(char * xyz)| sucht innerhalb der Liste der bekannten Dateisysteme nach dem Dateisystemnamen \verb|xyz|
 \end{itemize}
\end{frame}

\note{
 \begin{itemize}
  \item \texttt{register\_filesystem()}: Ein \texttt{file\_system\_type}-Objekt wird angelegt und in die Liste der Dateisystemtypen eingefügt.
  \item \texttt{unregister\_filesystem()}: Das entsprechende \texttt{file\_system\_type}-Objekt wird aus der Liste der Dateisysteme entfernt und danach gelöscht.
  \item \texttt{get\_fs\_type(char * xyz)}: Ein Zeiger auf das zu \texttt{xyz} gehörige \texttt{file\_system\_type}-Objekt wird zurückgegeben, falls es in der Liste gefunden wird.
  \item zur Compilezeit angegebene Dateisysteme werden während des Bootvorgangs registriert, modulare Dateisysteme werden entsprechend beim Laden des Kernelmoduls registriert und können auch wieder deregistriert werden, falls das Modul entladen wird.
 \end{itemize}
}

\subsection{Zugehörige Datenstruktur: \texttt{struct file\_system\_type}}
\begin{frame}[label=registerfs]
 \frametitle{\texttt{file\_system\_type}-Objekt}
 \begin{tabular}{lll}
  Typ & Variable & Beschreibung\\\hline
  \texttt{const char *} & \texttt{name} & Dateisystemname\\ 
  \texttt{int} & \texttt{fs\_flags} & Typflags\\ 
  \texttt{super\_block} & \texttt{get\_sb} & SB anlegen\\ 
  \texttt{void} & \texttt{kill\_sb} & SB entfernen\\ 
  \texttt{module *} & \texttt{owner} & Zeiger auf DS-Objekt\\ 
  \texttt{file\_system\_type *} & \texttt{next} & Liste vorhandener DS\\ 
  \texttt{list\_head} & \texttt{fs\_supers} & (siehe Bild)
 \end{tabular}
%%% mit PDF-Hyperlinks klickbare Buttons... [label=XYZ]-Option für den Frame
%%% im Handoutformat (also 2 on 1) funktionieren Links nicht :(
 \hyperlink{structfstype}{\beamergotobutton{Quellcode}}
%%% pgf zum Bilder einfügen... height=xyz oder width=\textwidth...
 \pgfimage[height=3cm]{fs_supers}
\end{frame}

\note{
 Dateisysteme werden im Linuxkernel durch \texttt{struct file\_system\_type}-Objekte dargestellt. Diese bestehen aus:
\begin{itemize}
 \item dem Dateisystemnamen (\texttt{name})
 \item einem Flagsfeld \texttt{fs\_flags} (FS\_REQUIRES\_DEV; FS\_BINARY\_MOUNTDATA; FS\_REVAL\_DOT, FS\_ODD\_RENAME für Netzwerkdateisysteme)
 \item Funktionszeiger auf Methoden zum Erstellen \texttt{get\_sb} und Löschen \texttt{kill\_sb} eines Superblocks (Dateisystemspezifisch)
 \item Modulzeiger auf Kernelmodul, das das Dateisystem implementiert
 \item Zeiger \texttt{next} auf nächstes Dateisystem (Liste aller dem Kernel bekannten Dateisysteme)
 \item Zeiger \texttt{fs\_supers} auf die Liste aller Superblöcke vom Dateisystemtyp \texttt{name} (vgl. \texttt{s\_instances}-Feld im Superblock-Objekt).
\end{itemize}
}

\subsection{An- und Abhängen von Dateisystemen}
\begin{frame}
 \frametitle{An- und Abhängen von Dateisystemen}
 \begin{itemize}
  \item Prozesse greifen auf beliebige Dateien zu
  \item Dateien liegen i.A. auf verschiedenen Dateisystemen
  \item Identifizierung des unterliegenden Dateisystems durch: Mountpunkte (Userspace) bzw. \texttt{struct vfsmount} (Kernelspace)
  \item darauffolgender Schritt: Anhängen eines Dateisystems
 \end{itemize}
\end{frame}

\note{
 \begin{itemize}
  \item Der Linuxkernel stellt Prozesse als \texttt{struct task\_struct}s dar
  \item Hauptteil dieser Prozessbeschreibung für Scheduling und andere Ressourcen (v.a. Speicherverwaltung)
  \item \texttt{struct fs\_struct * fs} und \texttt{struct files\_struct files} beschreiben Prozesskontext bzgl. VFS.
  \begin{enumerate}
   \item \texttt{int umask} Berechtigungen beim Öffnen einer Datei, \texttt{struct dentry * root} Wurzelverzeichnis, \texttt{struct dentry * pwd} Arbeitsverzeichnis, \texttt{struct vfsmount * rootmnt}, \texttt{struct vfsmount * pwdmnt} -- also Umgebung des Prozesses im Dateisystem
   \item v.a. \texttt{struct file ** fd} Zeiger auf Feld von (geöffneten) Fileobjekten
  \end{enumerate}
 \end{itemize}
}

\begin{frame}[fragile]
 \frametitle{Mountstruktur -- üblich}
 \begin{columns}
 \begin{column}{6cm}
  \begin{verbatim}
$ mount /dev/hdc1 /mnt/a
$ mount -o ro /dev/hdc1 /mnt/b
  \end{verbatim}
 \end{column}
 \begin{column}{6cm}
   \pgfimage[height=7cm]{mountstruktur1}
  \end{column}
 \end{columns}
\end{frame}

\note{
 \begin{itemize}
  \item entgegen der klassischen Unixsemantik können unter Linux Dateisysteme mehrfach gemountet werden
  \item Das unterliegende Dateisystem bleibt natürlich eindeutig: (Schreib-)Operationen innerhalb des einen Mountpunktes wirken sich direkt auf andere Mountpunkte aus -- das gilt allerdings nur für lokale Dateisysteme!
  \item in Hinblick auf NFS4 sind auch Mount-Bindungen (\texttt{mount --bind /opt/cad /exports/software/cad}) wichtig
 \end{itemize}
}

\begin{frame}[fragile]
 \frametitle{Mountstruktur -- unüblich}
 \begin{columns}
 \begin{column}{6cm}
  \begin{verbatim}
$ mount /dev/hdc1 /mnt/a
$ mkdir /mnt/a/b
$ mount /dev/hdc1 /mnt/a/b
$ touch /mnt/a/file
  \end{verbatim}
  \begin{itemize}
   \item \texttt{/mnt/a/file} und \texttt{/mnt/a/b/file} sind die gleiche Datei
  \end{itemize}
 \end{column}
 \begin{column}{6cm}
  \pgfimage[height=7cm]{mountstruktur2}
 \end{column}
 \end{columns}
\end{frame}

\note{
 \begin{itemize}
  \item Beliebige Hierachieren können gebildet werden: Hier wurde als Mountpunkt eines Dateissystems ein Verzeichnis innerhalb desgleichen gewählt.
  \item auch das übereinandermounten von verschiedenen (oder gleichen) Dateisystemen auf einen Mountpunkt ist möglich -- beim Auflösen von Pfaden gibt der Kernel jedoch nur die Sicht auf das \glqq{}oberste\grqq{} Dateisytem frei
 \end{itemize}
}

\begin{frame}
 \frametitle{\texttt{struct vfsmount} -- Gesamtbild}
 \pgfimage[width=\linewidth]{vfsmount}
\end{frame}

\note{
 \begin{itemize}
  \item Hier: \texttt{struct vfsmount * rootmnt, pwdmnt} (Zeiger im \texttt{struct fs\_struct} des Tasks) zeigen auf gleiches vfsmount -- d.h. Working Directory und Root Directory sind gleich.)
  \item \texttt{vfsmount}-Datenstruktur wird mehrfach referenziert:
  \begin{itemize}
   \item in \texttt{mount\_hashtable} -- Zugriff über Dentry-Eintrag des Mountpunktes (Größe der Hashtabelle abh. von \#RAM)
   \item bei Kollision wichtig: Verkettete Liste -- \texttt{mnt\_hash} enthält Zeiger auf adjazente Elemente dieser Liste
   \item jedes Kinddateisystem (d.h. Dateisystem unterhalb des durch \texttt{vfsmount} referenzierten DS) wird in \texttt{mnt\_mounts} verkettet gespeichert
   \item adjazente Dateisysteme werden mittels \texttt{mnt\_child} erreicht
  \end{itemize}
  \item \texttt{vfsmount\_lock} verhindert parallelen Zugriff
  %\item \texttt{mnt\_flags}: \texttt{MNT\_NOSUID}, \texttt{MNT\_NODEV}, \texttt{MNT\_NOEXEC}
 \end{itemize}
}

\begin{frame}
 \frametitle{\texttt{struct vfsmount} -- Details}
 \pgfimage[width=\linewidth]{vfsmount_zentral}
\end{frame}

\note{
 \begin{itemize}
  \item \texttt{mnt\_mountpoint} verweist auf den Dentry des Mountpunktes des Dateisystems, \texttt{mnt\_root} auf Wurzel des Dateisystems (also ein Ebene über dem jetzigen Mountpunkt -- \glqq{}der Mountpunkt des darunterliegenden Dateisystems\grqq{})
  \item \texttt{mnt\_parent} ist das Gegenstück zu \texttt{mnt\_mounts} -- verweist also auf darunterliegendes Dateisystem
  \item \texttt{mnt\_child} verkettete alle Kinddateisysteme (vgl. mnt\_mounts)
  \item \texttt{mnt\_sb} verweist auf den Superblock des Dateisystems
  \item einige Funktionen, die mit \texttt{vfsmount}-Datenstruktur arbeiten: \texttt{alloc\_vfsmnt(name)}, \texttt{free\_vfsmnt(mnt)}, \texttt{lookup\_mnt(mnt, dentry)}
 \end{itemize}
}

\begin{frame}[label=mounten]
 \frametitle{\texttt{mount()}}
 \pgfimage[width=\linewidth]{mount1}
\end{frame}

\note{
 \begin{columns}
 \begin{column}{0.5\textwidth}
  \begin{itemize}
  \item in unix-artigen BS sind alle Dateisysteme in einem Verzeichnisbaum eingehängt
  \item um weiteres DS einzuhängen wird der \texttt{mount()}-Syscall benötigt
  \item \texttt{mount()} prüft Parameter
  \item ruft dann \texttt{sys\_mount()} auf
  \end{itemize}
 \end{column}
 \begin{column}{0.5\textwidth}
  \begin{block}{Häufige Mountflags}
  \begin{itemize}
  \scriptsize
  \item MS\_RDONLY kein Schreibzugriff
  \item MS\_NOSUID keine setuid/setgid-Flags
  \item MS\_NODEV keine Zugriff auf Gerätedateien
  \item MS\_NOEXEC keine Ausführung
  \item MS\_SYNCHRONOUS kein asynchroner Zugriff
  \item MS\_REMOUNT bestehende Mountflags ändern
  %\item MS\_DIRSYNC kein asynchroner Zugriff bei Verzeichnissen
  \item MS\_NOATIME Zugriffzeiten werden nicht aktualisiert
  %\item MS\_NODIRATIME nur Zugriffzeiten für Verzeichnisse werden nicht aktualisiert
  \end{itemize}
  \end{block}
 \end{column}
 \end{columns}
}

\begin{frame}
 \frametitle{\texttt{sys\_mount()}}
 \pgfimage[width=\linewidth]{mount2}
\end{frame}

\note{
 \texttt{sys\_mount()}-Parameter:
  \begin{itemize}
   \item Pfad zum Blockgerät bzw. \texttt{NULL} (für Netzwerk- oder spezielle Dateisysteme)
   \item Pfad zum Mountpoint (Verzeichnis im Verzeichnisbaum)
   \item Dateisystemtyp
   \item Mountflags (z.B. read-only, noatime)
   \item Zeiger auf dateisystemspezifische Datenstruktur
  \end{itemize}
 \texttt{sys\_mount()}:
 \begin{itemize}
  \item Speicher allokieren
  \item sperrt (Big Kernel Lock: \texttt{lock\_kernel()}), d.h. serialisiert Zugriff
  \item ruft \texttt{do\_mount()} auf
  \item schliesslich entsperren (\texttt{unlock\_kernel()}) und Speicher wieder freigeben
 \end{itemize}
}

\begin{frame}
 \frametitle{\texttt{do\_mount()}}
 \pgfimage[width=\linewidth]{mount3}
\end{frame}

\note{
 \texttt{do\_mount()}:
 \begin{itemize}
  \item Auflösen des Pfades zum Mountpoint: \texttt{path\_lookup()}
  \item Prüfung der Mountflags
  \begin{itemize}
   \item im Falle des Remounts (\texttt{MS\_REMOUNT}) wird \texttt{do\_remount()} aufgerufen
   \item ist das \texttt{MS\_MOVE}-Flag gesetzt, so wird \texttt{do\_move\_mount()} aufgerufen, welche den Mountpoint atomar versetzt
   \item sonst wird \texttt{do\_new\_mount()} aufgerufen
  \end{itemize}
  \item Aufruf von \texttt{path\_release()} um Speicher wieder frei zugeben
 \end{itemize}
}

\begin{frame}
 \frametitle{\texttt{do\_new\_mount()}}
 \pgfimage[width=\linewidth]{mount4}
\end{frame}

\note{
 \texttt{do\_new\_mount()}:
 \begin{itemize}
  \item im häufigsten Falle, dass ein lokales, physisches Dateisystem angehängt werden soll (also auch ein zugehöriges Blockdevice vorhanden ist) 
  \item ruft \texttt{do\_kern\_mount()} mit \texttt{fs\_type}, \texttt{mnt\_flags}, \texttt{source} (Blockdevice) auf
 \end{itemize} 
}

\begin{frame}
 \frametitle{\texttt{do\_kern\_mount()}}
 \pgfimage[width=\linewidth]{mount5}
\end{frame}

\note{
 \texttt{do\_kern\_mount()}:
 \begin{itemize}
  \item Parameter: \texttt{fs\_type}, \texttt{mnt\_flags}, \texttt{source}, \texttt{priv\_data} (für \texttt{read\_super})
  \item \texttt{get\_fs\_type()} liefert Zeiger auf entsprechendes \texttt{struct file\_system\_type}
  \item \texttt{alloc\_vfsmnt()} liefert Zeiger \texttt{mnt} auf neuen DS-Deskriptor
  \item \texttt{type->get\_sb()} (dateisystemspezifische) initialisiert den Superblock
  \item initialisiert \texttt{mnt->mnt\_sb} als Zeiger auf das neue Superblock-Objekt
  \item initialisiert \texttt{mnt->mnt\_root} als Zeiger auf Dentry-Objekt, welches die Wurzel des anzuhängenden DS repräsentiert
  \item initialisiert weiterhin \texttt{mnt->mnt\_parent}, \texttt{mnt->mnt\_namespace}
  \item gibt Zeiger auf das DS-Deskriptor \text{mnt} zurück
 \end{itemize}
}

\begin{frame}
 \frametitle{\texttt{do\_add\_mount()}}
 \pgfimage[width=\linewidth]{mount6}
\end{frame}

\note{
 \texttt{do\_add\_mount()}:
 \begin{itemize}
  \item erhält RW-Semaphor \texttt{namespace->sem}, denn der Namespace wird verändert
  \item falls mittlerweile weiterer Prozess ein Dateisystem in das \texttt{target}-Verzeichnis eingehängt, oder sogar das Wurzelverzeichnis des Prozesses verändert wurde, so wird hier eine Fehlercode zurückgegeben, aufgeräumt, und irregulär beendet
  \item initialisiert \texttt{mnt\_flags} 
  \item ruft \texttt{graft\_tree()} auf, was DS-Objekt
  \begin{itemize}
   \item in Namespace-Liste einfügt
   \item in die Hashtabelle einfügt
   \item in die Children-Liste des Elterndateisystems (\texttt{mnt\_parent})
  \end{itemize}
  \item gibt den RW-Semaphor \texttt{namespace->sem} wieder frei
 \end{itemize}
}



% --------------------------- %
%                             %
% --- ### PATH LOOKUP ### --- %
%                             %
% --------------------------- %
\section{Path Lookup}
\subsection{Vorgehen}
\begin{frame}[label=pathlookup]
 \frametitle{Dateipfade}
 \begin{itemize}
  \item Prozesse verwenden Pfade um Dateien zu spezifizieren
  \item Abbildung intern auf Dentries und Inodes (\texttt{struct nameidata})
  \item Frage: Woher bekommt man diese Informationen?
 \end{itemize}
\end{frame}

\note{
 \begin{itemize}
  \item Dentry -- Verzeichniseintrag
  \item Unterscheidung zwischen absoluten (\texttt{/path/to/file}) und relativen Pfaden (\texttt{../path/./to/file})
  \item \texttt{.} in der Pfadkomponente als \glqq{}Identität\grqq{}
 \end{itemize}
}

\subsection{Datenstruktur: \texttt{struct nameidata}}
\begin{frame}[label=nameidata]
 \frametitle{\texttt{struct nameidata}}
 \begin{tabular}{lll}
 Typ & Variable & Beschreibung \\\hline
 \texttt{struct dentry *} & \texttt{dentry} & Zeiger auf Dentry-Objekt \\ 
 \texttt{struct vfsmount *} & \texttt{mnt} & angehängtes DS-Objekt \\ 
 \texttt{unsigned int} & \texttt{flags} & Flags\\ 
 \texttt{struct qstr} & \texttt{last} & Letzte Pfadkomponente \\ 
 \texttt{int} & \texttt{last\_type} & Typ der Letzten
 %\texttt{unsigned} & \texttt{depth} & \\ 
 %\texttt{char *} & \texttt{saved\_names[MAX\_NESTED\_LINKS + 1]} & \\ 
 %\texttt{union} & \texttt{intent} &
 \end{tabular}
 \hyperlink{structnameidata}{\beamergotobutton{Quellcode}}
\end{frame}

\note{
 \begin{columns}
 \begin{column}{0.5\textwidth}
  \begin{itemize}
   \item Zeiger \texttt{dentry} auf Dentry-Eintrag der Datei
   \item Zeiger \texttt{mnt} auf zugehöriges Mounted-Dateisystem-Objekt (\texttt{vfsmount})
   \item \texttt{last} beinhaltet Pfadsuffix nach letztem \texttt{/}
  \end{itemize}
 \end{column}
 \begin{column}{0.5\textwidth}
  \begin{block}{\texttt{unsigned int flags}}
   \scriptsize
  \begin{itemize}
   \item LOOKUP\_FOLLOW Symlink
   \item LOOKUP\_DIRECTORY Verzeichnis
   \item LOOKUP\_CONTINUE noch nicht fertig
   \item LOOKUP\_PARENT Verzeichnis, das Datei beinhaltet noch suchen
   \item LOOKUP\_OPEN Datei soll geöffnet werden
   \item LOOKUP\_CREATE Datei soll (falls nicht existent) erstellt werden
   \item LOOKUP\_ACCESS Dateirechte prüfen
  \end{itemize}
  \end{block}
 \end{column}
 \end{columns}
}

\subsection{\texttt{path\_lookup()}}
\begin{frame}
 \frametitle{\texttt{link\_path\_walk()}}
 \texttt{do \{}
 \begin{enumerate}
  \item Berechtigungen überprüfen
  \item 32-bit Hashwert der nächsten Pfadkomponente berechnen
  \item \texttt{..} behandeln (\texttt{.} hat keinen Effekt im Pfad)
  \item zugehöriges Dentry-Objekt: \texttt{do\_lookup()}
  \item auf Mountpunkt prüfen: \texttt{follow\_mount()}
  \item zur Behandlung von Symlink: \texttt{follow\_link()}
 \end{enumerate}
 \texttt{\} while (weitere Komponente vorhanden);}
\end{frame}

\note{
 \begin{itemize}
  \item Pfadkomponenten sind durch \texttt{/} abgetrennt
  \item äußere Schleife um komponentenweise den Pfad aufzulösen
  \item absoluter Pfad -- von links nach rechts
  \item relativer Pfad -- Elternverzeichnis auflösen (PARENT-Lookup)
  \item Dentry-Objekt der Komponente: \texttt{do\_lookup()})
  \item in etwaiges Kinddateisystem aufsteigen \texttt{follow\_mount()})
  \item etwaigen Symlink auflösen: \texttt{follow\_symlink()}) -- Achtung i.A. nicht zyklenfrei!
 \end{itemize}
}

\begin{frame}
 \frametitle{\texttt{do\_lookup()}}
 \pgfimage[width=\linewidth]{indentrycache}
\end{frame}

\note{
 \begin{itemize}
  \item \texttt{real\_lookup()} ruft dateisystemspezifische Funktion \texttt{lookup()} (der Inode) auf, um Daten von Platte zu lesen und einen Dentry-Eintrag zu erstellen
  \item \texttt{do\_revalidate()} überprüft, ob Eintrag im Cache noch gültig ist (für Netzwerkdateisystem wichtig -- lokales Caching!)
  \item \texttt{do\_lookup()} gibt \texttt{dentry} der Pfadkomponente und zugehöriges \texttt{vfsmount} zurück
 \end{itemize}
}

\begin{frame}
 \frametitle{\texttt{follow\_mount()}}
 \begin{itemize}
  \item \texttt{next.dentry->d\_mounted} $> 0$:
  \begin{itemize}
   \item prüft, ob aktuelle Komponente (\texttt{next.dentry}) sich auf ein Verzeichnis bezieht, das Mountpunkt für ein Dateisystem ist
  \end{itemize}
  \item in diesem Falle setzt \texttt{follow\_mount()} \texttt{next.dentry} und \texttt{next.mnt} so, dass sie auf das dentry-Objekt bzw. vfsmount-Objekt verweisen, das dem obersten, dort angehängten Dateisystem entspricht
 \end{itemize}
\end{frame}

\note{
}

\begin{frame}
 \frametitle{\texttt{follow\_link()}}
 \pgfimage[width=\linewidth]{follow_link}
\end{frame}

\note{
 \begin{itemize}
  \item Auflösen eines Symlinks durch rekursiven Aufruf von \texttt{link\_path\_walk()}
  \item dabei wichtig: Zyklen sind möglich!
  \item max. Verschachtelungstiefe \texttt{link\_count} typischerweise 5
  \item für den Fall, dass beim Auflösen eines Pfaden eine Mischung aus realen Pfad und Symlinks auftritt muss auch hier die Rekursionstiefe begrenzt werden: \texttt{total\_link\_count} 
 \end{itemize}
}



% --------------------------- %
%                             %
% ----- ### Probleme ### ---- %
%                             %
% --------------------------- %
\section{Probleme}
\subsection{Semantik \& Moderne Dateisysteme}
\begin{frame}
 \frametitle{Messaufbau I}
 \begin{itemize}
  \item \texttt{df -i} gibt Informationen bzgl. der freien Inodes aus
  \item moderne Dateisysteme verwenden allerdings keine starren Vorgaben für max. Inodezahl mehr
  \item Messung für ext2, ext3, xfs, jfs, reiserfs(3), reiser4
  \item \texttt{dd if=/dev/zero of=/tmp/XYZ bs=1024 count=102400}
  \item \texttt{mkfs.XYZ /tmp/XYZ}, d.h. default Parameter
  \item \texttt{mount -o loop /tmp/XYZ /mnt/test/XYZ}
 \end{itemize}
\end{frame}

\note{
 \begin{itemize}
  \item Vanilla 2.6.20 Kernel mit Reiser4 Patches
  \item Testpartitionen jeweils 100MB groß
  \item jeweils über Loopdevice gemountet
  \item dabei default Optionen bei mount und mkfs
 \end{itemize}
}

\begin{frame}[fragile]
 \frametitle{Messaufbau II}
 \begin{scriptsize}
  \begin{verbatim}
/root@saturn:~/fs# mount | grep /mnt/test
/root/fs/ext2 on /mnt/test/ext2 type ext2 (rw,loop=/dev/loop0)
/root/fs/ext3 on /mnt/test/ext3 type ext3 (rw,loop=/dev/loop1)
/root/fs/reiserfs on /mnt/test/reiserfs type reiserfs (rw,loop=/dev/loop2)
/root/fs/jfs on /mnt/test/jfs type jfs (rw,loop=/dev/loop3)
/root/fs/xfs on /mnt/test/xfs type xfs (rw,loop=/dev/loop4)
/root/fs/reiser4 on /mnt/test/reiser4 type reiser4 (rw,loop=/dev/loop5)
  \end{verbatim}
 \end{scriptsize}
 \begin{itemize}
  \item mittels \texttt{touch} wurden bis zu 754.743 Files angelegt
  \item nach 100, 1.000, 10.000, 30.000, 50.000, 100.000, 200.000, 500.000 jeweils \texttt{df -i/-h}
 \end{itemize}
\end{frame}

% \note{}

\begin{frame}[fragile]
 \frametitle{Start}
 \begin{scriptsize}
  \begin{verbatim}
root@saturn:~/fs# df -i | grep -e '\(Datei\|.\+/mnt/test\)'
Dateisystem            INodes  IBenut.  IFrei IBen% Eingehängt auf
/root/fs/ext2          25688      11   25677    1% /mnt/test/ext2
/root/fs/ext3          25688      11   25677    1% /mnt/test/ext3
/root/fs/reiserfs          0       0       0    -  /mnt/test/reiserfs
/root/fs/jfs          202048       4  202044    1% /mnt/test/jfs
/root/fs/xfs           98304       3   98301    1% /mnt/test/xfs
/root/fs/reiser4           0       0       0    -  /mnt/test/reiser4
root@saturn:~/fs# df -h | grep -e '\(Datei\|.\+/mnt/test\)'
Dateisystem            Größe Benut  Verf Ben% Eingehängt auf
/root/fs/ext2          97M  1,6M   91M   2% /mnt/test/ext2
/root/fs/ext3          97M  5,6M   87M   7% /mnt/test/ext3
/root/fs/reiserfs     100M   33M   68M  33% /mnt/test/reiserfs
/root/fs/jfs           99M  148K   99M   1% /mnt/test/jfs
/root/fs/xfs           92M  224K   92M   1% /mnt/test/xfs
/root/fs/reiser4       96M  100K   95M   1% /mnt/test/reiser4
  \end{verbatim}
 \end{scriptsize}
\end{frame}

% \note{}

\begin{frame}[fragile]
 \frametitle{30.000 Files}
 \begin{scriptsize}
  \begin{semiverbatim}
Dateisystem            INodes  IBenut.  IFrei IBen\% Eingehängt auf
\alert{/root/fs/ext2          25688   25688       0  100\% /mnt/test/ext2}
\alert{/root/fs/ext3          25688   25688       0  100\% /mnt/test/ext3}
/root/fs/reiserfs          0       0       0    -  /mnt/test/reiserfs
/root/fs/jfs          197920   30004  167916   16\% /mnt/test/jfs
/root/fs/xfs           98304   30003   68301   31\% /mnt/test/xfs
/root/fs/reiser4           0       0       0    -  /mnt/test/reiser4
Dateisystem            Größe Benut  Verf Ben\% Eingehängt auf
\alert{/root/fs/ext2          97M  1,9M   90M   3\% /mnt/test/ext2}
\alert{/root/fs/ext3          97M  6,1M   86M   7\% /mnt/test/ext3}
/root/fs/reiserfs     100M   35M   66M  35\% /mnt/test/reiserfs
/root/fs/jfs           99M   17M   82M  18\% /mnt/test/jfs
/root/fs/xfs           92M  8,5M   83M  10\% /mnt/test/xfs
/root/fs/reiser4       96M  4,4M   91M   5\% /mnt/test/reiser4
  \end{semiverbatim}
 \end{scriptsize}
 \begin{itemize}
  \item 25.678: ext2 \& ext3 haben keine freien Inodes mehr
 \end{itemize}
\end{frame}

% \note{}

\begin{frame}[fragile]
 \frametitle{100.000 Files}
 \begin{scriptsize}
  \begin{semiverbatim}
Dateisystem            INodes  IBenut.  IFrei IBen\% Eingehängt auf
/root/fs/reiserfs          0       0       0    -  /mnt/test/reiserfs
/root/fs/jfs          188160  100004   88156   54\% /mnt/test/jfs
\alert{/root/fs/xfs           98304   98304       0  100\% /mnt/test/xfs}
/root/fs/reiser4           0       0       0    -  /mnt/test/reiser4
Dateisystem            Größe Benut  Verf Ben\% Eingehängt auf
/root/fs/reiserfs     100M   42M   59M  42\% /mnt/test/reiserfs
/root/fs/jfs           99M   56M   44M  57\% /mnt/test/jfs
\alert{/root/fs/xfs           92M   28M   65M  30\% /mnt/test/xfs}
/root/fs/reiser4       96M   15M   81M  16\% /mnt/test/reiser4
  \end{semiverbatim}
 \end{scriptsize}
 \begin{itemize}
  \item 98.302: xfs hat keine freie Inode mehr
 \end{itemize}
\end{frame}

% \note{}

\begin{frame}[fragile]
 \frametitle{200.000 Files}
 \begin{scriptsize}
  \begin{semiverbatim}
Dateisystem            INodes  IBenut.  IFrei IBen\% Eingehängt auf
/root/fs/reiserfs          0       0       0    -  /mnt/test/reiserfs
\alert{/root/fs/jfs          177280  177248      32  100\% /mnt/test/jfs}
/root/fs/reiser4           0       0       0    -  /mnt/test/reiser4
Dateisystem            Größe Benut  Verf Ben\% Eingehängt auf
/root/fs/reiserfs     100M   51M   50M  51\% /mnt/test/reiserfs
\alert{/root/fs/jfs           99M   99M   20K 100\% /mnt/test/jfs}
/root/fs/reiser4       96M   30M   66M  31\% /mnt/test/reiser4
  \end{semiverbatim}
 \end{scriptsize}
 \begin{itemize}
  \item 177.245: jfs hat keine freie Inode mehr
 \end{itemize}
\end{frame}

% \note{}

\begin{frame}[fragile]
 \frametitle{754.743 Files}
 \begin{scriptsize}
  \begin{semiverbatim}
Dateisystem            INodes  IBenut.  IFrei IBen\% Eingehängt auf
/root/fs/reiserfs          0       0       0    -  /mnt/test/reiserfs
/root/fs/reiser4           0       0       0    -  /mnt/test/reiser4
Dateisystem            Größe Benut  Verf Ben\% Eingehängt auf
/root/fs/reiserfs     100M  100M     0 100\% /mnt/test/reiserfs
/root/fs/reiser4       96M   95M  236K 100\% /mnt/test/reiser4
  \end{semiverbatim}
 \end{scriptsize}
 \begin{itemize}
  \item 670.124: reiser4 hat keinen freien Plattenplatz mehr
  \item 754.743: reiserfs(3) hat keinen freien Plattenplatz mehr
 \end{itemize}
\end{frame}

% \note{}

\begin{frame}[fragile]
 \frametitle{Reiser4: Kompression}
 \begin{itemize}
  \item Reiser4 unterstützt auch transparente Kompression:
   \begin{scriptsize}
    \begin{semiverbatim}
Dateisystem            Größe Benut  Verf Ben\% Eingehängt auf
/root/fs/reiser4       96M   20M   76M  21\% /mnt/test/reiser4

root@saturn:/mnt/test/reiser4\# ls -lish
insgesamt 1000M
 65536 1000M -rw-r--r-- 1 root root \alert{1000M} 2007-05-05 18:18 test
    \end{semiverbatim}
   \end{scriptsize}
 \end{itemize}
\end{frame}

\note{
 \begin{itemize}
  \item \texttt{mkfs.reiser4 -f -o create=ccreg40 /root/fs/reiser4}
  \item 1000MB Datei auf einer 100MB Partition, wobei noch 75MB frei sind... :-)
 \end{itemize}
}

\subsection{Lazy Unmount}
\begin{frame}[fragile]
 \frametitle{Lazy Unmount}
 \begin{itemize}
  \item Problem: Abhängen eines Dateisystemes, wenn ein Prozess noch Dateien offen hält? Z.B. falls der NFS-Server nicht erreichbar ist\dots
  \item Lösung: Lazy Unmount
  \item nach dem \texttt{umount -l} kann kein Prozess mehr einen Dateideskriptor öffnen
  \item sobald alle bestehenden Dateideskriptoren geschlossen sind, ist auch das Dateisystem sauber abgehängt
 \end{itemize}
\end{frame}

\note{
}

\subsection{Shutdown \& Unmount}
\begin{frame}[fragile]
 \frametitle{Wurzeldateisystem nach Shutdown clean?}
 \begin{itemize}
  \item Der Init-Prozess hält mehrere Dateideskriptoren auf das Wurzelverzeichnis (\verb|/|) offen
  \item Frage: Was passiert beim Runterfahren mit dem gemounteten Wurzeldateisystem?
 \end{itemize}
\begin{lstlisting}[language=bash,basicstyle=\tiny,stringstyle=\color{red},commentstyle={\em\color{red}},keywordstyle={\bfseries\color{blue}},showstringspaces=false,frame=lines]
root@merkur:~# lsof -p 1
CMD PID USER   FD   TYPE  DEVICE    SIZE   NODE NAME
init  1 root  cwd    DIR     8,5    4096      2 /
init  1 root  rtd    DIR     8,5    4096      2 /
init  1 root  txt    REG     8,5   88672 620182 /sbin/init
init  1 root  mem    REG     0,0              0 [heap]
init  1 root  mem    REG     8,5 1307104  83440 /lib/xyz/libc-2.5.so
init  1 root  mem    REG     8,5  109268 244815 /lib/ld-2.5.so
\end{lstlisting}
\end{frame}

\note{
 \begin{itemize}
  \item Init ist bei unix-artigen Betriebssystemen der erste Prozess (daher immer PID 1)
  \item Init startet alle weiteren Userspaceprozesse (traditionell werden \textit{Runlevel} verwendet (System-V), neuere Linuxdistributionen oder auch Mac OS X verwenden mittlerweile ereignisgesteuerte Initdaemonen (Ubuntu \textit{upstart}, Mac OS X \textit{Launchd})
  \item \texttt{lsof -p PID} zeigt für einen Prozess alle geöffneten Dateien an
 \end{itemize}
}

\begin{frame}[fragile]
 \frametitle{Lösung: Remount}
 \begin{itemize}
  \item beim Shutdown werden alle Prozesse beendet (\verb|kill -5|, anschliessend \verb|kill -9|)
  \item am Ende existiert nur noch der Init-Prozess
  \item Init kann nun alle verbleibenden Dateisysteme, bis auf das Wurzeldateisystem unmounten
  \item danach remountet Init das verbleibende Wurzeldateisystem als read-only (\verb|mount -n -o remount,ro /|)
 \end{itemize}
\end{frame}

\note{
 \begin{itemize}
  \item Ubuntu/Debian: /etc/rc0.d/S60umountroot
  \item \texttt{mount -n -o remount,ro}
 \end{itemize}
}

\section*{}
\begin{frame}
 %\frametitle{VFS -- Zusammenfassung}
 \begin{block}{VFS -- Zusammenfassung}
 \begin{itemize}
  \item Dateisystemschnittstelle zwischen Dateisystemen und Anwendungen
  \item objektorientierte Implementierung (in C) mit vier Grunddatenstrukturen: Superblock, Inode, Datei und Dentry
  \item nicht ganz POSIX-konform ($\rightarrow$ Netzwerkdateisysteme)
  \item BS-Kern verwaltet Liste bekannter DS
  \item \texttt{u/mount()}-Systemaufruf zum ab/anhängen von DS
  \item Auflösen von Pfaden: \texttt{path\_lookup}
  \begin{itemize}
   \item Absolute \& relative Adressierung, Symlinks
  \end{itemize}
  \item traditionelle Unixsemantik (Inodes, Freie Speicherblöcke) problematisch
 \end{itemize}
 \end{block}
\end{frame}

\note{

}

% ### FOLIENSATZ --- ENDE--- FOLIENSATZ ### %


% --- ANHANG --- %
%%% erscheint nicht in der normalen TableOfContents
\appendix
%%% [plain] maximiert Platz auf der Folie (Navi ausgeblendet)
\begin{frame}[containsverbatim,plain]
 \frametitle{Literatur}
 \begin{columns}
  \begin{column}{0.6\linewidth}
   \begin{thebibliography}{}
    \bibitem[Bovet \& Cesati, 2003]{Bovet03} Daniel P. Bovet \& Marco Cesati
    \newblock{\em Understanding the Linux Kernel, 3rd Edition}

    \bibitem[Bar, 2001]{Bar01} Moshe Bar
    \newblock{\em Linux Filesystems}

    \bibitem[Pate, 2003]{Pate03} Steve D. Pate
    \newblock{\em UNIX Filesystems: Evolution, Design and Implementation}

    \bibitem[Brown, 1999]{Brown99} Neil Brown
    \newblock{\href{http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/vfs.html}{\em The Linux Virtual File-system Layer}}

    \bibitem[Kleiman, 1985]{Kleiman85} S.R. Kleiman
    \newblock{\href{http://www.arl.wustl.edu/~fredk/Courses/cs523/fall01/Papers/kleiman86vnodes.pdf}{\em Vnodes: An Architecture for Multiple File System Types in Sun UNIX}}
   \end{thebibliography}
  \end{column}
  \begin{column}{0.4\linewidth}
   \begin{thebibliography}{}
    \bibitem[Kerr, 2000]{Kerr00} Shane Kerr
    \newblock{\href{http://www.time-travellers.org/shane/papers/NFS_considered_harmfull.html}{\em Use of NFS Considered Harmful}}
    \bibitem[Linux NFS FAQ]{LNFSFAQ} Christopher M. Smith
    \newblock{\href{http://nfs.sourceforge.net/}{\em Linux NFS FAQ}}

    \bibitem[RedHat GFS Manual]{RHGFS} RedHat
    \newblock{\href{http://www.redhat.com/docs/manuals/csgfs/}{\em RedHat Cluster Suite Manual \& GFS}}

    \bibitem[Namesys ReiserFS4]{RFS4} ReiserFS 4
    \newblock{\href{http://namesys.com/v4/v4.html}{\em ReiserFS 4 -- Overview}}
   \end{thebibliography}
  \end{column}
 \end{columns}
\end{frame}

%%% weitere Folien in den Anhang, falls sie z.B. nur auf Anfrage gezeigt werden sollen
\begin{frame}[label=specialfs]
 \frametitle{Auswahl spezieller Dateisysteme in Linux}
 \begin{tabular}{lll}
  Name & Mount Point & Beschreibung \\\hline
  bdev & --- & Block Geräte \\ 
  devpts & /dev/pts & Pseudoterminals \\ 
  eventpollfs & --- & Eventpolling \\ 
  futexfs & --- & Fast Userspace Locking \\ 
  pipefs & --- & Pipes \\ 
  proc & /proc & Kernel Datenstrukturen \\ 
  rootfs & --- & für die Bootphase \\ 
  shm & --- & IPC-Shared Memory \\ 
  mqueue & beliebig & POSIX Message Queues \\ 
  sockfs & --- & Sockets \\ 
  sysfs & /sys & Kerneldaten (modern) \\ 
  tmpfs & beliebig & Temponäre Dateien \\ 
  usbfs & /proc/bus/usb & USB Geräte
 \end{tabular}
% \hyperlink{overviewfs}{\beamerreturnbutton{Zurück}}
\end{frame}

\begin{frame}[label=structfstype,fragile]
 \frametitle{struct file\_system\_type}
 \begin{lstlisting}[language=C,basicstyle=\scriptsize,stringstyle=\color{red},commentstyle={\em\color{magenta}},keywordstyle={\bfseries\color{blue}},showstringspaces=false,frame=lines]
struct file_system_type {
    const char *name;
    int fs_flags;
    int (*get_sb) (struct file_system_type *, int,
                   const char *, void *, struct vfsmount *);
    void (*kill_sb) (struct super_block *);
    struct module *owner;
    struct file_system_type * next;
    struct list_head fs_supers;
    struct lock_class_key s_lock_key;
    struct lock_class_key s_umount_key;
};
 \end{lstlisting}
 \hyperlink{registerfs}{\beamerreturnbutton{Zurück}}
\end{frame}

\begin{frame}[label=structnameidata,fragile]
 \frametitle{\texttt{struct nameidata}}
 \begin{lstlisting}[language=C,basicstyle=\scriptsize,stringstyle=\color{red},commentstyle={\em\color{magenta}},keywordstyle={\bfseries\color{blue}},showstringspaces=false,frame=lines]
struct nameidata {
        struct dentry   *dentry;
        struct vfsmount *mnt;
        struct qstr     last;
        unsigned int    flags;
        int             last_type;
        unsigned        depth;
        char *saved_names[MAX_NESTED_LINKS + 1];

        /* Intent data */
        union {
                struct open_intent open;
        } intent;
};
 \end{lstlisting}
 \hyperlink{nameidata}{\beamerreturnbutton{Zurück}}
\end{frame}


\end{document}