TacOS-team / tacos

Système d'exploitation / Operating System
GNU General Public License v3.0
9 stars 4 forks source link

[FS] Revoir le listing des dossiers #91

Closed MaximeCheramy closed 12 years ago

MaximeCheramy commented 12 years ago

Actuellement, pour lire le contenu d'un dossier, on utilise une fonction readdir qui prend (je simplifie) le chemin et un indice pour indiquer quel fichier nous intéresse. Ce qui fait que si un dossier possède N fichiers, alors pour lister tout le contenu, on ouvre N fois le dossier et à chaque fois, on reparcourt tout le dossier pour trouver le ième élément. Bref, c'est du (N^2)/2, c'est tout naze et ça se sent.

Une solution plus propre serait bien-sûr d'ouvrir et lire l'ensemble des éléments contenu dans le dossier une seule fois et laisser à la libC la charge de gérer les itérations sur les éléments.

Donc à faire : 1) Se renseigner sur ce qui se fait. Voir s'il y a un truc écrit sur ça dans POSIX. 2) Coder :D

Idéalement, pouvoir avoir un truc similaire au prototype imposé par fuse serait sympa pour garder un code très proche.

MaximeCheramy commented 12 years ago

Je viens de regarder le code de glibc pour savoir comment ça marchait. En fait ils utilisent un mécanisme très similaire aux dossiers dans Ext2 :

DIR* (struct __dirstream) contient : fd : file descriptor allocation : taille allouée pour le block. Pour ça il prend la valeur retournée par un call à stat (blksize) size : valid data pour le block offset : pour savoir où on en est dans la lecture du block filepos : position de la prochaine entrée à lire (car un readdir va itérer et donc fait monter cette valeur) data : les données (char data[allocation]). L'aspect tableau à taille variable est géré par un malloc(sizeof DIR + allocation)

Les données contiennent donc sous la forme d'un tableau d'octets les entrées du dossier. Et c'est là où c'est similaire à ext2.

struct dirent : d_fileno : inode du fichier. 0 si entrée supprimée. d_off : position dans le dossier de la prochaine entrée d_reclen : taille de l'entrée (éventuellement d_type) d_name : le nom de l'entrée (avec un \0 à la fin sauf si sa taille est de 255...).

J'ai l'impression que d_off et d_reclen font double usage (selon ce que l'architecture fournie) : d_off donne l'adresse en absolue et d_reclen en relatif. Ils ont mis des define pour indiquer ce qui est dispo dans la structure (#define _DIRENT_HAVE_D_TYPE par exemple)

Donc maintenant que j'ai bien compris le truc je vais faire quelque chose de similaire. Pour résumer, on ouvre le dossier comme un fichier sauf qu'on utilise le syscall getdents pour récupérer des directory entries. Sous linux il existe aussi le syscal readdir qui ne lit qu'un dirent à la fois. Un peu dommage de faire un syscall par entrée quand même. Ensuite c'est juste du parsing pour respecter le format...

Faut encore que je réfléchisse aux interfaces que je mets au niveau du VFS mais je ne vais pas trop avoir de choix en fait... Et faut que je recode le readdir du FAT et du EXT2.

(Pour comparaison, un dossier au format ext2 : 4 inode 2 rec_len 1 name_len 1 file_type 0-255 name)

MaximeCheramy commented 12 years ago

Bon, ce qui me prend plus de temps que prévu : Faut que je recode le readdir de procfs, devfs et du vfs. Pour le FAT c'est fait et ça marche.

MaximeCheramy commented 12 years ago

Done.