Preallocation avec FAT

Le
Pascal Hambourg
Bonjour,

Est-il possible de préallouer de l'espace pour un fichier dans un
système de fichiers FAT en marquant seulement les blocs comme alloués
sans écrire de données ? Mes essais avec fallocate(1) écrivent
systématiquement des 0 Í  hauteur de la taille spécifiée.
  • Partager ce contenu :
Vos réponses
Trier par : date / pertinence
Nicolas George
Le #26570520
Pascal Hambourg , dans le message
Est-il possible de préallouer de l'espace pour un fichier dans un
système de fichiers FAT en marquant seulement les blocs comme alloués
sans écrire de données ? Mes essais avec fallocate(1) écrivent
systématiquement des 0 Í  hauteur de la taille spécifiée.

La structure d'un filesystem FAT, c'est d'avoir une entrée toute petite (12,
16 ou 32 bits) pour chaque groupe de secteurs (cluster). Si le cluster
appartient Í  un fichier, son entrée dans la FAT désigne le cluster suivant
du fichier, façon liste chaÍ®née. S'il est libre, elle contient un code
ad-hoc.
Donc il n'y a pas moyen de coder qu'un cluster appartient Í  un fichier mais
mais ne contient pas de données.
Attribuer un secteur Í  un fichier sans le remplir de zéros est techniquement
possible, mais sans bit d'information pour marquer ce fait, une lecture du
fichier donnerait accès aux données préalables, ce qui serait un trou de
sécurité monumental.
Note que les systèmes du genre ext2/3/4 n'ont pas plus de bit disponible
pour marquer un bloc alloué mais pas initialisé, donc il n'est pas non plus
possible de pré-allouer des blocs pour un fichier.
Marc SCHAEFER
Le #26570518
Nicolas George
Note que les systèmes du genre ext2/3/4 n'ont pas plus de bit disponible
pour marquer un bloc alloué mais pas initialisé, donc il n'est pas non plus
possible de pré-allouer des blocs pour un fichier.

Mais voici ce qu'on peut faire avec la plupart des systèmes de fichiers
POSIX: des fichiers Í  trous (sparse files): un fichier de 1 G dont
seulement quelques blocs sont alloués. Pratique pour certaines bases
de données indexées ou des images de machines virtuelles.
:/tmp/tt$ dd if=/dev/zero seek=1G bs=1 count=1 of=toto
1+0 records in
1+0 records out
1 byte copied, 0.000147507 s, 6.8 kB/s
:/tmp/tt$ ls -lah toto
-rw-r--r-- 1 schaefer schaefer 1.1G Mar 21 16:32 toto
:/tmp/tt$ du -hs toto
4.0K toto
Evidemment ici, les blocs ne sont même pas référencés.
Nicolas George
Le #26570517
Marc SCHAEFER , dans le message écrit :
Mais voici ce qu'on peut faire avec la plupart des systèmes de fichiers
POSIX: des fichiers Í  trous (sparse files)

Oui, mais c'est exactement le contraire d'une pré-réservation, ça.
En FAT, on ne peut pas faire de fichiers Í  trous, Í  cause de la structure de
liste chaÍ®née. On pourrait faire un unique trou Í  la fin, mais comme les
autres implémentations le traiteraient comme une corruption en pratique on
ne le fait pas.
Marc SCHAEFER
Le #26570516
Nicolas George
Oui, mais c'est exactement le contraire d'une pré-réservation, ça.

Oui, c'est pour cela qu'il y a la pré-allocation via la glibc ou ext4,
par exemple:
https://ext4.wiki.kernel.org/index.php/Ext4_Howto#Persistent_preallocation
cf posix_fallocate().
Je ne sais pas ce que ça fait, sinon que contrairement aux sparse file,
il n'y a aucun risque que le fs soit plein au moment o͹ on crée
effectivement le bloc de données.
Nicolas George
Le #26570515
Marc SCHAEFER , dans le message écrit :
Je ne sais pas ce que ça fait, sinon que contrairement aux sparse file,
il n'y a aucun risque que le fs soit plein au moment o͹ on crée
effectivement le bloc de données.

Ça ne fait pas grand chose d'intelligent :
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/posix_fallocate.c;h b379c94d7cf779b1192fefae361398732509fb;hb=HEAD#l96
Il peut y avoir des implémentations plus efficaces dépendant du système.
Mais le point central demeure : il n'y a pas dans ext2/3/4 d'endroit o͹
stocker l'information qu'un bloc est alloué mais pas initialisé.
Marc SCHAEFER
Le #26570514
Nicolas George
Il peut y avoir des implémentations plus efficaces dépendant du système.

Les meilleures implémentations n'utilisent ce code de fallback (qui
d'après la manpage a en plus des race conditions) que si l'appel
système fallocate(2) retourne EOPNOTSUPP.
La manpage fallocate(2) mentionne que ext4 supporte au moins une partie
des fonctions mais pour des kernels récents >= 4.1.
Petit test:
le programme:
#include #include #include #include int main(int argc, char **argv) {
FILE *f;
f = fopen("toto", "r+");
if (f) {
if (posix_fallocate(fileno(f), 1000, 2000)) {
perror("posix_fallocate()");
exit(EXIT_FAILURE);
}
fclose(f); /* err. ign. */
exit(EXIT_SUCCESS);
}
else {
perror("fopen()");
exit(EXIT_FAILURE);
}
/* NOT REACHED */
}
exécution:
:/tmp/tt$ > toto
:/tmp/tt$ ls -la
total 104
drwxr-xr-x 2 schaefer schaefer 4096 Mar 21 17:26 .
drwxrwxrwt 14 root root 73728 Mar 21 17:26 ..
-rwxr-xr-x 1 schaefer schaefer 16872 Mar 21 17:26 a.out
-rw-r--r-- 1 schaefer schaefer 447 Mar 21 17:25 main.c
-rw-r--r-- 1 schaefer schaefer 0 Mar 21 17:28 toto
:/tmp/tt$ strace ./a.out
[ ... ]
openat(AT_FDCWD, "toto", O_RDWR) = 3
fallocate(3, 0, 1000, 2000) = 0
close(3) = 0
[ ... ]
:/tmp/tt$ ls -la toto
-rw-r--r-- 1 schaefer schaefer 3000 Mar 21 17:29 toto
Donc, fallocate(2) est appelé, sans erreur EOPNOTSUPP.
Mais le point central demeure : il n'y a pas dans ext2/3/4 d'endroit o͹
stocker l'information qu'un bloc est alloué mais pas initialisé.

Aucune idée de ce que ça fait et o͹, mais ce n'est apparemment pas une
copie manuelle dans mon cas (le fallback de la libc). A vérifier avec
l'implémentation du kernel.
Voir aussi cet article: https://lwn.net/Articles/239738/
qui dit:
"Each file system implementation that wants to use this feature will
need to support an inode operation called fallocate. Applications can
use this feature to avoid fragmentation to certain level and thus get
faster access speed. With preallocation, applications also get a
guarantee of space for particular file(s) - even if later the the system
becomes full."
Il y a aussi le blabla sur le fallback de la glibc, avec "Though this
has the advantage of working on all file systems, but it is quite slow
(since it writes zeroes to each block that has to be preallocated).
Without a doubt, file systems can do this more efficiently within the
kernel, by implementing the proposed fallocate() system call."
Je n'ai pas consulté le code kernel du driver ext4 pour vérifier que
fallocate() y existe comme inode operation, mais le fait que l'appel
système mentionné ne retourne pas d'erreur me fait penser que c'est le
cas.
Pascal Hambourg
Le #26570512
Le 21/03/2021 Í  14:49, Nicolas George a écrit :
Pascal Hambourg , dans le message
Est-il possible de préallouer de l'espace pour un fichier dans un
système de fichiers FAT en marquant seulement les blocs comme alloués
sans écrire de données ? Mes essais avec fallocate(1) écrivent
systématiquement des 0 Í  hauteur de la taille spécifiée.


(...)
Attribuer un secteur Í  un fichier sans le remplir de zéros est techniquement
possible, mais sans bit d'information pour marquer ce fait, une lecture du
fichier donnerait accès aux données préalables, ce qui serait un trou de
sécurité monumental.

Je n'avais pas pensé Í  ça.
Note que les systèmes du genre ext2/3/4 n'ont pas plus de bit disponible
pour marquer un bloc alloué mais pas initialisé, donc il n'est pas non plus
possible de pré-allouer des blocs pour un fichier.

Pourtant ça y ressemble furieusement quand j'utilise fallocate(1) sur ext4 :
- l'exécution de fallocate + sync est très rapide
- cela engendre un volume d'I/O bien inférieur Í  la taille spécifiée
- du et df comptabilisent bien l'espace comme utilisé donc ce n'est pas
comme un fichier creux.
- la lecture est quasi-instantanée et engendre un volume d'I/O bien
inférieur Í  la taille du fichier (même après démontage et remontage pour
purger le cache)
Est-ce que ce serait lié aux extents ? fallocate ne marche pas sur un
système de fichier ext4 créé sans extents (-O ^extent).
Nicolas George
Le #26570511
Pascal Hambourg , dans le message
Est-ce que ce serait lié aux extents ? fallocate ne marche pas sur un
système de fichier ext4 créé sans extents (-O ^extent).

Ah, c'est possible. Je ne me suis jamais renseigné sur cette extension.
Poster une réponse
Anonyme