Consignes
Le rendu de ce TP se fera uniquement par TPLab et consistera en une archive (zip, tar, etc.) contenant impérativement l'arborescence suivante :
TP3-votre_login/ ├─ Makefile ├─ copy.c ├─ fcopy.c ├─ README ├─ ... ├─ ... └─ sfs/ ├─ RAPPORT ├─ Makefile ├─ ... └─ ...
Attention :
-
Chaque fichier .c doit contenir une entête avec votre nom / prénom ainsi que les réponses aux questions et vos remarques pertinentes.
-
Makefile doit compiler tous vos fichiers C (vous pouvez vous inspirer de ce fichier Makefile), (si vous ne connaissez pas les fichiers Makefile, je vous conseille de suivre ce tutoriel)
-
votre Makefile doit compiler les programmes C avec les options --std=c99 -Wall -Wextra -pedantic -Werror,
-
votre code pour la deuxième partie (SFS) doit compiler avec le fichier Makefile fourni (options --std=gnu99 -D_FILE_OFFSET_BITS=64 -Wall -Wextra -pedantic -Werror -Wno-unused-parameter)
-
sfs/RAPPORT doit être un fichier texte contenant vos réponses et commentaires pertinents concernant la seconde partie du TP. Vous donnerez notamment l'état d'avancement de votre code par rapport aux questions du TP.
Tout non respect d'une ou plusieurs de ces consignes entrainera automatiquement un retrait de points sur votre note de TP !
Liens utiles
-
l'archive du TP : sfs.tar
-
encadrant de TP : Pierre.Hyvernat@univ-smb.fr, Francois.Boussion@univ-smb.fr et Gerald.Cavallini@univ-smb.fr
1. Programmation et fichiers
Préliminaires (facultatif)
N'oubliez pas que vous pouvez utiliser la commande man pour obtenir la documentation des fonctions C des bibliothèques standards :
$ man 3 read
$ man 3 fwrite
Le 3 permet de préciser que vous voulez la documentation des fonctions C. (Par exemple, le shell possède une commande read, et par défaut, man read ouvre cette page de documentation. Vous pouvez trouver la liste des sections avec leur numéro dans la documentation de la commande man...)
Le langage C offre deux interfaces pour les fichiers :
-
une interface bas niveau avec les fonctions
open
,close
,write
,read
etlseek
; -
une interface haut niveau avec les fonctions
fopen
,fclose
,fwrite
,fread
etfseek
.
Dans le premier cas, les fichiers sont représentés par un entier appelé
descripteur de fichiers, et dans le second cas, par un élément du type
FILE
.
-
Écrivez deux programmes copy.c et fcopy.c qui recopient un fichier vers un autre. Une fois compilé, les exécutables s'utiliseront comme la command cp:
$ ./copy <SOURCE> <DESTINATION> $ ./fcopy <SOURCE> <DESTINATION>
-
le programme copy.c utilisera les fonctions "bas niveau",
-
le programme fcopy.c utilisera les fonctions "haut niveau".
-
-
Comparez les temps d'exécution des deux programmes en fonction du nombre d'octets que vous lisez à chaque fois (un octet à la fois, ou 2 par 2, ou 1024 par 1024, etc.)
Note : pour la version avec
fread
etc., utilisez un argumentsize
(deuxième argument pourfread
etfwrite
) de1
, et un argumentnmemb
(troisième argument pourfread
etfwrite
) égal au nombre d'octets que vous voulez lire... -
Modifiez la taille des buffers (et leur types) dans fcopy avec la fonction
setvbuf
et comparez les temps d'exécution. -
Décrivez vos tests et les résultats dans le fichier README.
La fonction open
prend un troisième argument optionnel qui
précise les droits d'accès à donner au fichier s'il est créé. Lorsque vous
donnez le drapeau O_CREAT
, il est important de donner cet
argument :
int fd = open(..., ... | O_CREAT, 0644);
0644
(644 en octal) donne les
droit de lecture et d'écriture à l'utilisateur courant et les droits de
lecture aux autres.
Vous pouvez trouver une description complète des droits d'accès avec
$ man sys_stat.h
1.1. Blocs
-
Si vous travaillez sur les machines de l'université, le répertoire /tmp/ est accessible en lecture et contient un système de fichiers avec inodes. Vous pouvez faire des tests dans ce répertoire.
-
Si vous travaillez sur votre portable, vous pouvez facilement créer un système ext? dans un fichier en utilisant les commandes
$ dd if=/dev/zero of=fs.ext2 bs=4096 count=1024 $ sudo mkfs.ext2 fs.ext2 $ mkdir EXT2 $ sudo mount fs.ext2 EXT2
Le répertoire EXT2 contiendra alors un système de fichiers ext2 !
Vous pouvez remplacer ext2 par d'autre systèmes de fichiers comme ext3, ext4, fat...
-
La commande df -T affiche la liste des systèmes de fichiers montés, ainsi que leur type.
-
Pour les systèmes de fichiers ext[234], la commande dump2fs -h /dev/... permet d'afficher les paramètres du système. (Attention, il faut les droits administrateurs pour accéder au périphérique /dev/...)
Chaque partition d'un support de stockage utilise un système de fichiers. Sous Linux, le système de fichiers le plus courant est ext4 (successeur de ext2 et ext3).
Tous les systèmes de fichiers "interactifs" découpent les fichiers en blocs de taille fixe. La taille d'un fichier peut donc vouloir dire deux choses distinctes :
-
le nombre d'octets de données du fichier : c'est ce qui est affiché par la commande ls -lh,
-
le nombre d'octets occupés par le fichier sur le support : c'est ce qui est affiché par la commande ls -sh.
Faites (et décrivez dans le fichier README) quelques expériences simples pour deviner la taille des blocs de votre système de fichier. (Vous pouvez faire ces expériences sur plusieurs supports / partitions...)
1.2. Taille des répertoires
À FAIRE SUR UNE PARTITION EXT2, EXT3 OU EXT4, OU DANS /TMP/ (MACHINE DE L'UNIVERSITÉ)
NE FONCTIONNE PAS DANS LES SOUS-RÉPERTOIRES DE ~/HomeUSMB (SYSTÈME DE FICHIER CIFS)
-
Quelle est la taille des données d'un répertoire ext2/3/4 ? (commande ls -lhd <DIR>)
-
Quelle est la taille occupée sur le disque par répertoire ext2/3/4 ? (commande ls -shd <DIR>)
-
Est-ce que la taille des fichiers contenus dans le répertoire impacte la taille occupée sur le disque par le répertoire ?
1.3. Taille des liens symboliques
À FAIRE SUR UNE PARTITION EXT2, EXT3 OU EXT4, OU DANS /TMP/ (MACHINE DE L'UNIVERSITÉ)
NE FONCTIONNE PAS DANS LES SOUS-RÉPERTOIRES DE ~/homeUSMB (SYSTÈME DE FICHIER CIFS)
La commande suivante permet de créer un lien symbolique appelé LIEN pointant vers le chemin CHEMIN
$ ln -s <CHEMIN> <LIEN>
-
Qu'elle est la taille occupée sur le disque par un lien symbolique dont le chemin cible (argument CHEMIN) est "court" (quelques caractères) ?
Qu'elle est la taille occupée sur le disque par un lien symbolique dont le chemin cible (argument CHEMIN) est "long" (plusieurs dizaines de caractères) ?
Attention : je parle bien de la taille des chemins et non pas de la taille des fichiers.
-
À quoi correspond la taille des données (affichée par ls -l) pour un lien symbolique ?
-
À votre avis, comment est stockée la cible d'un lien symbolique ?
1.4. Fichiers creux
En général, la taille des données est plus petite que la taille occupée sur le support, qui est toujours un multiple de la taille des blocs.
Les fichiers creux (sparse files en anglais) sont une exception. Un tel fichier peut contenir des trous. Le plus simple pour créer un fichier creux est de suivre la procédure suivante :
-
ouvrir un fichier en écriture
-
écrire quelques octets au début (facultatif)
-
se déplacer pour dépasser la fin du fichier (fonction
lseek
) -
écrire quelques octets au nouvel emplacement
-
fermer le fichier
En C :
int size = 1<<20; // 1 Mio
char* start = "start\n";
char* end = "\nend";
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
write(fd, start, strlen(start));
lseek(fd, size - strlen(end), SEEK_SET);
write(fd, end, strlen(end));
close(fd);
-
Écrivez un petit programme C qui permet de créer des fichiers creux.
Une fois compilé, votre programme s'utilisera comme suit :
$ ./sparse <FILENAME> <TOTAL_SIZE>
-
Testez votre programme sur plusieurs partitions pour voir celles qui autorisent de tels fichiers.
Décrivez comment vous procédez.
-
Facultatif : expérimentez avec la commande cp et l'argument --sparse, et expliquez ce que vous observez...
La commande shell truncate (et l'appel système
POSIX truncate
) permet de modifier la taille d'un fichier :
-
si on augmente la taille, les blocs ajoutés au fichier sont des "trous",
-
si on diminue la taille, les blocs à la fin du fichier sont désalloués.
2. Un système de fichiers tout simple (??)
La seconde partie du TP consiste à regarder les sources d'un système de fichiers très simple, créé pour l'occasion, appelé SFS (Simple FileSystem). L'objectif est de rajouter quelques fonctionnalités à ce système de fichiers.
Il s'agit d'un système de fichiers basé sur une notion simplifiée d'inode. Les volumes SFS sont en fait simplement stockées dans des fichiers standards. Un volume SFS peut donc être vu comme une archive contenant une arborescence de fichiers / répertoires.
Pour compiler SFS, vous devez avoir la bibliothèque de développement libfuse. Sous Debian / Ubuntu,
$ sudo apt install libfuse-dev rlwrap
devrait suffire. (rlwrap est un utilitaire pour gérer un historique de commandes dans une application textuelle...)
2.1. Petite visite guidé du code fourni
L'archive contenant le code fourni se trouve ici.
2.1.1. Architecture du projet
Le répertoire sfs contient les fichiers suivants
- Makefile
-
pour compiler les sources
- sfs.h
-
contenant les définitions de types et macros globales
- sfs_parameters.h
-
contenant les paramètres fixes des systèmes de fichiers SFS. Vous pouvez si vous le souhaitez changer les valeurs des trois paramètres de base.
- sfs_log.[ch]
-
contenant une petite fonction de log pour enregistrer des informations de debug dans un fichier (sfs.log par défaut)
- sfs_volume.[ch]
-
contenant la gestion de la partition SFS (contenue en fait dans un fichier Unix)
- sfs_low_level.[ch]
-
pour le code bas niveau : manipulation des blocs et des inodes, écriture et lecture, etc.
- sfs_posix.[ch]
-
contenant le code haut niveau : Autant que possible, les fonctions dans ces fichiers utilisent le même prototype que les appels système correspondant aux appels système POSIX usuels. Par exemple, la fonction
sfs_write
utilise le même prototype que la fonctionwrite
... - sfs_shell.[ch]
-
contenant un petit shell interactif pour manipuler les systèmes de fichiers SFS
- sfs_fuse.[ch]
-
contenant les définitions nécessaires pour utiliser un système de fichiers SFS avec libfuse
Vous ne devez normalement modifier que le fichier sfs_low_level.c.
2.1.2. Inodes
SFS est basé sur le type d'inodes suivant (fichier sfs_volume.h):
typedef struct inode {
int type; // inode type: S_IFREG, S_IFDIR, S_IFLNK
int size; // size of the corresponding file in bytes
int nlinks; // number of hard links to this inode (0 means the inode is free)
int blocks[NB_DIRECT_BLOCKS+2]; // blocks for the data (last 2 blocks for single / double indirection blocks)
} inode_t;
Les constantes S_IFREG
("regular file"), S_IFDIR
("directory"), S_IFLNK
("symbolic link") et
NB_DIRECT_BLOCKS
sont définies dans le fichiers sfs_volume.h.
Chaque inode est représenté par son numéro (type int
), avec les
constantes suivantes :
-
l'inode
0
n'est pas utilisé, -
l'inode
1
(constanteBADBLOCKS_INODE
) pourrait servir à référencer les blocs défectueux, -
l'inode
2
(constanteROOT_INODE
) est l'inode de la racine de la partition.
2.1.3. Blocs de données
Les blocs de données sont représentés par des tableaux :
// size (in bytes) of blocks
#define BLOCK_SIZE 512
// type synonym for "raw" bytes
typedef unsigned char byte;
// type synonym for blocks
typedef byte block_t[BLOCK_SIZE];
2.1.4. Fonctions importantes
Les blocs et les inodes sont représentés par des entiers (positifs). Les
fonctions sfs_get_inode
/ sfs_get_block
prennent un
argument entier et renvoient un pointeur vers l'inode / bloc correspondant.
Attention, ces fonctions ne font aucune vérification sur l'entier qui leur est fourni. Si vous les utilisez avec des entiers trop grands (ou négatifs), le résultat n'est pas spécifié et votre programme risque de provoquer une erreur de segmentation.
2.1.5. Utilisation "bas niveau"
La compilation produit un exécutable sfs_shell qui lance un interpréteur pour lancer des commandes sur les systèmes de fichiers SFS :
$ ./sfs_shell <FILE>
lance ce shell et monte automatiquement la "partition" SFS contenue dans le fichier FILE. (Il faut auparavant avoir créé la partition SFS dans le fichier FILE comme expliqué plus bas.)
Les commandes disponibles dans sfs_shell sont brièvement décrites par la commande help (ou ?). Il s'agit essentiellement des commandes du fichiers sfs_low_level.c. Vous pouvez par exemple :
-
créer une partition
-
afficher un inode
-
afficher le contenu d'un bloc (en mode data, adresses ou entrées de répertoire)
-
afficher la bitmap des blocs libres
-
...
Le shell SFS ne gère ni les touches "flèches" ni l'historique des commandes. Pour cela, utilisez l'utilitaire rlwrap pour lancer le shell SFS:
$ rlwrap ./sfs_shell [FILE]
2.1.6. Utilisation "haut niveau", libfuse
La compilation produit également un exécutable sfs_fuse.
libfuse est une bibliothèque pour créer des
systèmes de fichiers sans modifier le noyau Linux. Il suffit de programmer les
fonctions de bases comme open, read, mkdir, (cf
fichier sfs_posix.[ch]) etc. et il est possible
de manipuler un système de fichiers "virtuel" (comme SFS) comme un système de
fichiers réel. Par exemple, la commande cp sur
un système monté avec libfuse utilisera
automatiquement les fonctions fopen
, fread
et
fwrite
correspondantes...
La commande sfs_fuse écrit des informations dans le fichier sfs.log du répertoire courant. Il est conseillé de regarder le contenu de ce fichier en lançant la commande
$ tail -f ./sfs.log
dans un autre terminal...
Pour faciliter les tests, l'archive contient un script test-fuse.sh qui fait les choses suivantes :
-
compile SFS
-
créé un volume SFS dans le fichier TEST.sfs (avec la commande sfs_shell)
-
monte le volume TEST.sfs dans le répertoire TEST (avec la commande sfs_fuse)
-
démonte le répertoire TEST lorsque que le shell se termine (avec la commande fusermount -u ...)
Si vous voulez faire ces opérations à la main (déconseillé),
-
la commande pour monter un volume SFS est
$ ./sfs_fuse -o use_ino <FILE> <DIR>
-
la commande pour démonter un volume SFS est
$ fusermount -u <DIR>
2.2. Un premier exercice
-
Copiez le code sur une partition "standard" :
-
si vous êtes sur votre portable, n'importe quelle partition devrait fonctionner
-
si vous êtes sur une machine de l'université, un sous-répertoire direct de votre répertoire personnel, ou bien /tmp/ devrait fonctionner. (Votre répertoire ~/homeUSMB/ est stocké sur une partition réseau de type CIFS, qui pose des problèmes de synchronisation pour SFS.)
-
-
Compilez le code fourni et lancez le shell SFS :
$ rlwrap ./sfs_shell
-
Créez un système de fichiers dans le fichier TEST.sfs
(NULL)% mkfs TEST.sfs
-
Regarder le contenu de l'inode 2 (la racine)
(TEST.sfs)% show_inode 2
et regarder le contenu du premier bloc de données associé :
(TEST.sfs)% dump_hexa <N> (TEST.sfs)% dump_entries <N>
Dans les commandes précédentes, <N> doit être le numéro du premier bloc de données de la racine. La première commande affiche le contenu du bloc en hexadécimal et la seconde affiche le contenu du bloc lorsque ses octets sont interprétés comme des entrées de répertoires (type
dir_entry_t
défini dans sfs_low_level.h). -
Initialisez un inode de fichier vide avec la commande
(TEST.sfs)% create_file
et vérifier que l'inode utilisé a bien le type "regular file", et une taille de 0 octet.
-
Ajoutez cet inode dans le repertoire / avec la commande
(TEST.sfs)% add_entry 2 <NAME> <N>
N'oubliez pas de choisir un nom pour votre fichier (deuxième argument) et d'utiliser le numéro d'inode approprié (troisième argument).
-
Vérifiez que le fichier apparait bien dans les entrées du répertoire racine.
-
Écrivez une petite chaine de caractères dans ce fichier avec la commande write du shell SFS.
Vérifiez qu'un nouveau bloc de données à été alloué, et qu'il contient bien la chaine choisie...
-
Quittez le shell SFS et lancez l'interface fuse :
$ ./test-fuse.sh
Le répertoire TEST doit maintenant contenir le fichier que vous avez créé dans le shell SFS :
-
vous pouvez obtenir son numéro d'inode avec ls -i
-
vous pouvez obtenir sa taille avec ls -lh et ls -sh
-
vous pouvez visualisez sont contenu avec cat <FILENAME>
-
L'appel système statvfs
permet d'obtenir des informations sur un
système de fichiers :
-
taille des blocs
-
taille du système de fichiers
-
nombre de blocs libres
-
...
La fonction sfs_statvfs
du fichier sfs_posix.c contient des appels aux fonction
-
sfs_count_free_blocks
, -
sfs_count_free_inodes
.
Écrivez ces fonctions (fichier sfs_low_level.c).
Remarques: vous aurez probablement besoin des fonctions et données suivantes :
-
DATA_SIZE
: taille de la partition, en nombre de blocs (fichier sfs_parameters.h) -
sfs_block_in_use
pour vérifier dans la bitmap si un numéro de bloc correspond à un bloc utilisé -
ROOT_INODE
: premier numéro d'inode utilisable (pour la racine) -
NB_INODES
: nombre total d'inodes sur la partition -
sfs_get_inode
: pour récupérer un inode à partir de son numéro.
Vous pouvez vérifiez que ces fonctions marchent avec la commande info dans le shell SFS, ou bien avec df et df -i si vous
avez monté un volume SFS avec fuse. (La
commande df utilise l'appel système
statvfs
...)
2.3. Amélioration du système de fichiers
Pour la suite du TP, vous allez implanter des fonctionnalités manquantes au système de fichiers.
Les fonctionnalités à ajouter sont données par ordre croissant de difficulté mais sont indépendantes les unes des autres.
Une estimation de la taille des modifications est donnée dans chaque question. Il s'agit uniquement d'une indication pour vous donner un ordre de grandeur...
2.3.1. Liens physiques (facile)
Il s'agit d'ajouter la gestions des liens physiques sur les fichiers.
Ajoutez la gestion des liens physiques dans SFS.
Il faudra pour ceci modifier les fonctions sfs_unlink_inode
et
sfs_link_inode
du fichier sfs_low_level.c.
Taille des modifications : quelques lignes pour chacune des fonctions.
Pour tester, vous pouvez utiliser test-fuse.sh et créer des liens physique avec ln :
$ ln <TARGET> <LINK>
Le compteur de liens (visible dans le résultat de ls -l doit passer à 2), et les numéros d'inodes (visible dans le résultat de ls -i) doivent coïncider.
2.3.2. Liens symboliques
Il s'agit maintenant d'ajouter la gestions des liens symboliques sur les
fichiers. Les liens symboliques sont représentés par des inodes de type
S_IFLNK
.
Un lien symbolique n'a pas de données réelles mais doit contenir un chemin d'accès cible.
Pour ajoutez la gestion des liens symboliques dans SFS, il faut compléter les deux fonctions (dans le fichier sfs_low_level.c)
-
sfs_writelink_inode
qui permet d'initialiser un inode au typeS_IFLNK
et d'inscrire la cible du lien au bon endroit. -
sfs_readlink_inode
qui récupère la cible d'un lien symbolique.
Dans le code fournit, ces deux fonctions récupèrent l'inode demandé et renvoient une erreur s'il ne s'agit pas d'un lien symbolique. Elle ne stockent, ni ne renvoie la cible du lien symbolique.
-
Dans un premier temps, stockez la cible du lien symbolique directement dans le tableau
nd->blocks
de l'inode en utilisantstrncpy
. Vous pourrez stocker la taille de la chaine cible dans le champssize
de l'inode. -
La stratégie précédente ne fonctionne que si la cible est suffisamment petite pour tenir sur les quelques dizaines d'octets du tableau
nd->nb_blocks
. Si la cible est trop grande, utilisez la fonctionsfs_write_to_block
pour stocker la cible dans un nouveau bloc de données associé à l'inode. Vous pourrez également stocker la taille de la chaine cible dans le champssize
de l'inode.
Taille des modifications (total) : environ une dizaine de lignes très similaires pour chacune des fonctions.
Pour tester, vous pouvez utiliser test-fuse.sh et créer des liens symboliques avec ln -s :
$ ln -s <TARGET> <LINK>
La commande ls -l doit afficher la cible des liens symbolique...
Vous pourrez également faire la question 4 pour comparer avec ce qui est fait sur votre système de fichiers favori...
2.3.3. Blocs à accès indirect
Actuellement, les blocs de données associés à un inode dans SFS sont tous à
accès direct. Le tableau blocks
d'un inode contient
NB_DIRECT_BLOCKS
cases référençant des blocs de données. La
taille maximale d'un fichier est donc égale a NB_DIRECT_BLOCKS *
BLOCK_SIZE
, soit quelques kibioctets...
Pour augmenter légèrement la taille possible des fichiers, nous allons
ajouter la gestion de blocs indirects. Le tableau blocks
d'un
inode contient une case supplémentaire, actuellement non utilisée. Lorsque
cela est nécessaire, cette case sera utilisée pour référencer un bloc
contenant BLOCK_SIZE / sizeof(int)
blocs de données.
Il n'est pas nécessaire d'ajouter la gestion des blocs indirects pour les répertoires ou les liens symboliques. La limite sur le nombre de fichiers dans un répertoire ou la taille de la cible d'un lien ne sont pas très contraignantes.
Ajoutez la gestion des blocs indirects pour les fichiers dans SFS.
Les fonctions POSIX qui accèdent au contenu du fichier sont read
et write
, ainsi que truncate
.
-
La fonction
sfs_read
(sfs_posix.c) est programmée à partir de la fonctionsfs_read_from_inode
(sfs_low_level.c), elle même programmée à partir desfs_read_from_block
(sfs_low_level.c), qui utilise-
sfs_get_data_block_nb_from_inode
pour chercher les numéros de blocs à lire.
-
-
La fonction
sfs_write
(sfs_posix.c) est programmée à partir de la fonctionsfs_write_to_inode
(sfs_low_level.c), elle même programmée à partir de :-
sfs_write_to_block
(sfs_low_level.c).
-
Taille des modifications :
-
sfs_get_data_block_nb_from_inode
, quelques lignes -
sfs_write_to_block
, une quinzaine de lignes
N'oubliez pas de documenter (dans le fichier RAPPORT) vos tests pour mettre en ouvre cette gestion des blocs indirects.
Vous pouvez, si vous le souhaitez, modifier la fonction do_info
du fichier sfs_shell.c pour mettre à jours la
taille maximale autorisée des fichiers.
2.3.4. Fichiers creux
Les systèmes avec inodes permettent de créer des fichiers creux : il
suffit de mettre un numéro de bloc spécial qui n'est pas alloué sur le
support. Les opérations de lecture sur un tel bloc renvoient des
0
, et les opérations d'écriture vont provoquer l'allocation d'un
vrai bloc...
Pour SFS, nous allons utiliser le numéro de bloc ZERO_BLOCK
(constante définie à 0
) pour représenter un bloc de 0 non alloué... (Plus précisément, ce bloc est alloué
mais en "lecture seule".
Ajoutez la gestion des fichiers creux dans SFS.
Comme précédemment, les fonctions POSIX qui accèdent au contenu du fichier
sont read
et write
(ainsi que
truncate
). Comme le bloc ZERO_BLOCK
est un vrai bloc
ne contenant que des 0
, il n'est pas nécessaire de modifier les
fonctions de lecture. Il reste donc sfs_truncate_inode
, qui
accède aux blocs à travers les fonctions
-
allocate_datablocks
qui doit toujours allouer le blocZERO_BLOCK
comme nouveau bloc, -
deallocate_datablocks
qui doit libérer les blocs standards, mais ne rien libérer lorsqu'il s'agit d'un bloc de zéros..
Pour l'appel système write
, il faudra modifier la fonction
-
sfs_write_to_block
.
C'est notamment cette fonction qui, lors de l'écriture dans un blocs de
zéros, le remplacera par un bloc standard, cherché avec la fonction
sfs_find_free_block
.
Il faut également modifier la fonction
-
sfs_count_used_blocks_inode
qui permet de calculer la taille occupée par les données d'un inode.
Taille des modifications :
-
allocate_datablocks
, une ligne, -
deallocate_datablocks
, quelques lignes, -
sfs_write_to_block
, une dizaine de lignes, -
sfs_count_used_blocks_inode
, quelques lignes.
N'oubliez pas de documenter vos modifications dans le fichier RAPPORT...
Pour faciliter la correction, copiez la version de
sfs_write_to_block
dans votre fichier RAPPORT (pour la question 10) avant de la modifier
pour cette question !
2.4. Pour aller plus loin
-
écrire une fonction
badblocks
qui recherche les blocs défectueux et les associe à l'inodeBADBLOCKS_INODE
(pour modéliser de blocs défectueux, vous pouvez par exemple considérer les blocs dont les premiers octets sont de ad be ef), -
gérer les blocs avec deux indirections dans les inodes, pour augmenter la taille maximale des fichiers,
-
écrire une fonction
checkfs
qui vérifie la cohérence du volume SFS, -
gérer une date de modification.