# Virtual File System

Virtual File System ou VFS (ou encore Virtual Filesystem Switch) est le nom commun de différents systèmes de fichiers virtuels fonctionnant sur la famille de systèmes d'exploitation de type UNIX. Il est apparu dans la version 2.0 de SunOS, puis il a été adopté par les autres Unix et enfin par Linux. Comme tout système de fichiers virtuel, il s'agit d'une couche logicielle permettant de faire coexister plusieurs systèmes de fichiers et de jouer l'intermédiaire entre les processus utilisateurs et les drivers.
VFS joue un rôle essentiel dans l'unification par les systèmes UNIX des ressources contenues dans les différents périphériques de stockage dans une seule arborescence, et ce quel que soit le format des systèmes de fichiers présents sur ces périphériques. Les différents systèmes de fichiers sont montés sur des répertoires pour permettre l'accès aux fichiers, ce qui a pour résultat notable de faire l'économie de la notion de volume, familière dans le monde Windows. Cette économie est parfaitement conforme à la philosophie d'UNIX, qui est d'intégrer dans une arborescence unique un grand nombre d'éléments divers considérés comme des fichiers.

## Histoire
### Création

VFS est le résultat de la rencontre, en 1985, de deux systèmes de fichiers : UFS et NFS. Dans les années 1980, les réseaux prennent de l'importance. Sun développe différents produits orientés réseaux : une version du protocole RPC pour Unix, le protocole NIS pour centraliser les informations sur un réseau UNIX, et NFS, un système de fichiers distribué. Le développement de NFS tente de répondre à une contrainte simple à énoncer : l'accès aux fichiers distants doit se réaliser de manière transparente pour les processus utilisateur, c'est-à-dire que ces processus ne doivent pas se soucier de savoir si ces fichiers sont locaux ou distants. Pour cela, NFS doit être capable de prendre en charge les mêmes appels système que le système de fichiers local (à l'époque on passe d'UFS à FFS). Sun choisit, avec le développement de VFS, de concevoir une couche d'abstraction capable de prendre en charge les appels système usuels (open, read, etc.) et de les transmettre à des couches inférieures chargées de manipuler les systèmes de fichiers concrets (NFS et UFS).
L'architecture de VFS est conçue pour répondre aux contraintes suivantes :
* l'implémentation du système de fichiers est divisée en deux couches, l'une indépendante des systèmes de fichiers concrets, l'autre dépendante de ces systèmes ;
* l'architecture doit supporter les systèmes de fichiers UNIX et non UNIX, les systèmes de fichiers avec ou sans état ;
* elle doit supporter le côté serveur des systèmes de fichiers distants comme NFS ;
* les opérations doivent être atomiques pour éviter l'usage des verrous.
Dans la foulée, la couche logicielle qui gère UFS est adaptée par Sun pour fonctionner avec la couche basse de VFS. Il apparaît rapidement que, même en l'absence de NFS, VFS est un système particulièrement efficace pour faire fonctionner différents systèmes de fichiers dans une arborescence unifiée. Sun développera rapidement une autre couche logicielle pour le système de fichiers FAT de MS-DOS.

### Maturité

À la même époque, System V intègre à sa version 3 (SVR3) un dispositif semblable nommé File System Switch (FSS). FSS est un système de fichiers virtuel, et en tant que tel donc capable de supporter plusieurs systèmes de fichiers concrets. Chaque système de fichiers concret possède une structure qui contient l'ensemble des opérations dépendantes de ce système. Un pointeur sur la structure adéquate est placé dans chaque inode (l'abstraction fondamentale utilisée par le système pour manipuler un fichier), de manière que les opérations soient accessibles de manière transparente.
Sun et AT&T unissent leurs efforts pour produire une synthèse et VFS et FSS. Cette synthèse, qui apparaît dans SVR4 en 1990, va rester remarquablement stable. L'architecture de VFS pour les systèmes Solaris est encore aujourd'hui très proche de celle de SVR4.

### Évolutions

Pourtant, des évolutions ont été proposées pour améliorer l'extensibilité et la modularité de VFS : celle de Rosenthal et celle de l'Université de Californie à Los Angeles (UCLA), par Heidemann et Popek. Les deux modèles ont en commun l'idée de diviser VFS en couches, mais leur approche est fondamentalement différente. Le prototype de Rosenthal consiste à empiler les couches d'abstractions les unes au-dessus des autres, de manière que la couche n-1 soit considérée comme le système de fichiers concret par la couche n, et s'adresse à la couche n-2 comme à un système de fichiers concret. Heidemann et Popek prennent au contraire le parti de diviser VFS en couches hétérogènes, chacune remplissant une fonction bien spécifique et fournissant des services déterminés à la couche supérieure (ce modèle est proche du modèle OSI, par exemple). Ce modèle est appelé modèle UCLA, en raison du lieu où il a été conçu. Nommage, stockage des données, chiffrement... sont quelques-unes des couches proposées par Heidemann. Le but du modèle UCLA est de permettre la réutilisation du code dans le développement de nouveaux systèmes de fichiers virtuels. Un exemple simple est celui du chiffrement : la couche peut-être intégrée ou non dans le système sans qu'il y ait à se soucier de recoder l'ensemble. De plus, le modèle UCLA ne limite pas les opérations sur un système de fichiers, ce qui permet une grande extensibilité.
En 1991, Heidemann implémente le modèle UCLA sur 4.4BSD. Le modèle est présent sur toutes les versions modernes de BSD, dont FreeBSD et Mac OS X.

## L'exemple de Linux

Linux possède lui aussi son propre VFS, Linux VFS, dont l'objet n'est pas d'être extensible, mais de fournir une interface à tout système de fichiers imaginable. De plus, de nombreuses opérations peuvent être prises en charge par des fonctions par défaut, ce qui facilite grandement le développement de la couche qui est dépendante du système de fichiers.
Linux VFS s'adapte au modèle de fichier natif Linux, mettons ext2 pour fixer les idées. Les abstractions fondamentales de Linux VFS sont donc :
* soit inspirées de la structure du système ext2, comme les objets superblock et inode ;
* soit calquées sur les objets qui permettent à Linux de manipuler le système ext2, avec les objets dentry et file.
Cela permet à Linux de faire fonctionner ses systèmes de fichiers natifs avec le minimum de médiation.

### L'objet superblock

Cette structure contient les informations fondamentales portant sur un système de fichiers monté :
* l'identifiant du périphérique qui contient le système ;
* la taille de bloc du système ;
* les numéros du premier inode du système de l'inode du répertoire où est monté le système ;
* un pointeur sur la structure file_system_type associée au système de fichiers (qui contient un pointeur qui permet de lire le superblock, le nom du système de fichiers, et si ce système de fichiers a besoin d'un périphérique) ;
* un pointeur sur des informations propres au système ;
* une structure super_operations qui contient des pointeurs sur les fonctions propres au superblock du système de fichiers concret.

### L'objet inode

Cette structure décrit de manière unique chaque fichier et répertoire du système de fichiers. Les inodes de VFS sont très semblables à ceux de ext2, et construits à partir des systèmes de fichiers sous-jacents. Les inodes les plus souvent utilisés sont contenus dans un cache.
On trouve dans cette structure :
* l'identifiant du périphérique qui contient le fichier ;
* la taille de bloc du fichier ;
* le numéro de l'inode ;
* les permissions d'accès ;
* les identifiants du propriétaire, groupe, etc. ;
* les informations de temps ;
* un compteur de références ;
* un marqueur de verrou ;
* un marqueur d'écriture ;
* des informations sur le système de fichiers ;
* une structure inode_operations (pour les opérations dépendantes du système de fichiers).

### L'objet dentry

L'objet dentry (d-irectory entry) représente un chemin d'accès. C'est une structure créée à la volée lorsqu'un appel système utilise un chemin complet. Elle contient les informations suivantes :
* nom du fichier (avec son chemin) ;
* un pointeur sur l'inode associé ;
* un pointeur sur le dentry parent ;
* éventuellement des pointeurs sur les dentries enfants ;
* une structure dentry_operations (pour les opérations dépendantes du système de fichiers).
Ces dentries sont stockés par VFS dans un cache, ce qui permet d'accélérer la recherche de fichier.

### L'objet file

Cette structure est la représentation d'un fichier en mémoire. Une telle structure est créée à chaque fois qu'un processus ouvre un fichier. Elle contient :
* le dentry associé au fichier ;
* le mode d'accès au fichier ;
* l'index de lecture ou d'écriture sur le fichier ;
* une structure file_operations (pour les opérations dépendantes du système de fichiers).
Les structures super_operations, inode_operations, dentry_operations et file_operations existent pour chaque système de fichiers concret considéré. Elles implémentent les opérations dépendantes du système de fichiers et constituent donc la couche logicielle dépendante de celui-ci, par opposition à la couche indépendante.

### En pratique

On effectue le montage d'un système de fichiers FAT avec la commande shell suivante :
En interne, VFS va trouver la structure file_system_type associée à FAT et exécuter la fonction read_super. Cette fonction fait partie de la couche dépendante du système de fichiers concret (en l'occurrence, FAT). Elle crée une structure superblock et lit sur le disque les informations nécessaires au remplissage de la structure ; elle fournit en particulier les fonctions dépendantes de FAT (dans super_operations).
La recherche d'un fichier, la lecture ou l'écriture se réalisent ensuite au moyen des opérations dépendantes du système de fichiers concret. Par exemple, pour la plupart des systèmes de fichiers concrets, l'objet inode n'existe pas en tant que structure de données sur le disque, mais la fonction read_inode permet à VFS de fonctionner comme si c'était le cas. Cette fonction lit les données sur le disque et remplit la structure inode de VFS.
Le système de fichiers /proc est un cas particulier qui illustre la puissance de VFS. Ce système de fichiers n'existe pas sur disque, mais est créé par le système afin de fournir une interface entre l'utilisateur et le noyau. Ce système de fichiers est enregistré par VFS (il possède sa propre structure file_system_type). Les répertoires et fichiers sont simplement créés à la volée par la couche dépendante du système de fichiers concret ici fictif, à partir des informations du noyau.