No space left on device : inodes épuisés ou blocs pleins

touch: cannot touch 'rapport.txt': No space left on device s’affiche pendant que df -h /var annonce encore 11 Go disponibles. Sur ext4, chaque système de fichiers gère deux ressources indépendantes, les blocs de données et les inodes, et df -h ne montre que la première. L’écriture échoue parce que le compteur d’inodes est à zéro, pas parce que le disque est plein.
Sommaire
- « No space left on device » avec de l’espace libre : df -h lit les blocs, df -i lit les inodes
- Diagnostic en cinq commandes
- Le nombre d’inodes ext4 est fixé par mke2fs à la création et ne se recalcule pas ensuite
- Un fichier supprimé garde son inode et ses blocs tant qu’un processus l’a ouvert
- Blocs réservés à root et espace métadonnées Btrfs : deux ENOSPC que df ne signale pas
- Questions sur les inodes, du –inodes et les fichiers supprimés
touch: cannot touch 'rapport.txt': No space left on device
« No space left on device » avec de l’espace libre : df -h lit les blocs, df -i lit les inodes
GNU df mesure par défaut l’occupation en blocs. L’option -i, décrite dans sa page de manuel comme list inode information instead of block usage, lit le second compteur. Les deux commandes répondent à deux questions différentes : un système de fichiers peut afficher 72 % en blocs et 100 % en inodes. Cette mécanique est propre aux systèmes de fichiers utilisés sous Linux ; elle ne dépend pas de la distribution.
Un inode est l’enregistrement qui décrit une entrée du répertoire : type, droits, propriétaire, horodatages, pointeurs vers les blocs. Chaque fichier, chaque répertoire et chaque lien symbolique en consomme un. Sur ext4, le nombre total d’inodes est calculé au moment de la création du système de fichiers et ne bouge plus. Un volume de 39 Gio peut donc accueillir quelques milliers de gros fichiers ou des millions de petits ; c’est le profil des fichiers qui décide de la ressource épuisée en premier.
df -h / df -i /
Diagnostic en cinq commandes
Les cinq commandes se lancent dans cet ordre, en adaptant le point de montage au répertoire qui refuse l’écriture. La première qui contredit l’hypothèse en cours donne la réponse.
-
Mesurez l’espace en blocs.
df -h /
Ce que vous devez voir : une colonne
Availnon nulle, par exemple11G, avecUse%sous 100.Filesystem Size Used Avail Use% Mounted on /dev/nvme0n1p2 39G 27G 11G 72% /
L’espace disque n’est pas la ressource saturée. Continuez.
-
Mesurez les inodes.
df -i /
Ce que vous devez voir : les colonnes
Inodes,IUsed,IFreeetIUse%.Filesystem Inodes IUsed IFree IUse% Mounted on /dev/nvme0n1p2 2621440 2621440 0 100% /
IUse%à 100 etIFreeà 0 désignent la panne : les inodes sont épuisés. -
Localisez le répertoire qui consomme les inodes, sans suivre les autres systèmes de fichiers.
sudo find / -xdev -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -rn | head -20
Ce que vous devez voir : les vingt répertoires parents comptant le plus d’entrées, le plus chargé en tête.
184213 /var/lib/apt/lists 41207 /var/cache/fontconfig 11988 /usr/share/man/man3
-xdevempêchefindde descendre dans/proc,/syset/run, qui sont d’autres systèmes de fichiers. Le compte affiché est celui des entrées dont le répertoire listé est le parent. -
Confirmez la branche concernée par un comptage des répertoires de premier niveau.
sudo du --inodes -x -d 1 / 2>/dev/null | sort -n
Ce que vous devez voir : un total croissant, le gros consommateur en dernière ligne.
952 /bin 4242 /etc 41230 /usr 187940 /varL’option
--inodesdeducompte les inodes au lieu des blocs. -
Vérifiez qu’aucun fichier supprimé ne retient un inode et ses blocs.
sudo lsof +L1 2>/dev/null | head
Ce que vous devez voir : rien, ou des lignes dont la colonne
NLINKvaut 0.COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME python3 42113 root 3w REG 259,2 9.1G 0 524301 /var/log/app.log (deleted)
+L1ne liste que les fichiers dont le nombre de liens est inférieur à 1, donc détachés du répertoire mais toujours ouverts. Leur inode reste alloué.
Le nombre d’inodes ext4 est fixé par mke2fs à la création et ne se recalcule pas ensuite
mke2fs répartit un inode par tranche de bytes-per-inode. Sa page de manuel est explicite : il n’est pas possible de modifier ce ratio après la création du système de fichiers. La valeur par défaut provient de /etc/mke2fs.conf, dont la section [defaults] fixe inode_ratio = 16384, soit un inode par 16 Kio, avec un cas particulier pour les systèmes de 3 à 512 Mo (small, ratio 4096).
Sur Debian 12 (bookworm, e2fsprogs 1.47.0), la vérification se fait sur le superbloc.
sudo tune2fs -l /dev/nvme0n1p2 | grep -iE 'Inode count|Free inodes|Inode size'
Inode count: 2621440 Free inodes: 0 Inode size: 256
Un volume de 40 Gio formaté avec le ratio 16384 offre environ 2,6 millions d’inodes. Aucune commande ne les augmente sur un système de fichiers existant : tune2fs ne modifie ni le ratio ni le total, et agrandir la partition avec resize2fs ajoute des inodes dans la même proportion, ce qui ne corrige pas un ratio inadapté. La seule correction structurelle est de recréer le système de fichiers avec un ratio plus fin, opération qui efface le contenu de la partition et se prépare donc avec une sauvegarde. Créer une partition home sous Debian détaille la préparation d’un volume avant formatage.
sudo mkfs.ext4 -i 4096 /dev/sdb1
L’option -i 4096 crée un inode par bloc de 4 Kio, et -N fixe directement un nombre d’inodes. Les deux se décident avant le formatage.
Un fichier supprimé garde son inode et ses blocs tant qu’un processus l’a ouvert
rm retire le nom du répertoire. Le noyau ne libère l’inode et les blocs que lorsque plus aucun processus ne détient le fichier ouvert. Un journal de service supprimé pendant que le service tourne continue donc de grossir, df -h ne bouge pas d’un octet, et l’inode reste consommé. C’est le scénario que lsof +L1 révèle à l’étape 5 du diagnostic.
Sur un descripteur ouvert en écriture, vider le fichier libère l’espace sans arrêter le processus.
sudo truncate -s 0 /proc/42113/fd/3 sudo systemctl restart nginx
Redémarrer le service qui détient le descripteur reste la méthode fiable. Sur un serveur qui écrit des journaux, la rotation avec l’option copytruncate de logrotate évite de recréer la situation. La rubrique services et journaux systemd couvre la lecture des journaux qui remplissent /var.
Blocs réservés à root et espace métadonnées Btrfs : deux ENOSPC que df ne signale pas
ext4 réserve par défaut 5 % des blocs au superutilisateur, valeur fixée par mke2fs -m. df calcule l’espace disponible à partir des blocs accessibles au compte courant : un utilisateur ordinaire peut donc recevoir « No space left on device » alors que df -h affiche de l’espace, et sudo touch /test réussir au même instant. La réserve se lit et se règle sans reformater, sur un système de fichiers monté.
sudo tune2fs -l /dev/nvme0n1p2 | grep -iE 'Block count|Reserved block count' sudo tune2fs -m 1 /dev/nvme0n1p2
Un rapport de 0,05 entre les deux valeurs confirme la réserve à 5 %, et -m 1 la ramène à 1 %.
Sur Btrfs, les blocs de données, les blocs système et les blocs de métadonnées sont alloués séparément. La page de manuel de btrfs-filesystem précise que la valeur Free (statfs, df), celle que reprend Avail dans df, est calculée autrement et peut ne pas correspondre à l’espace réellement utilisable. Un volume Btrfs avec des blocs de données libres peut refuser toute écriture parce que la métadonnée est pleine.
btrfs filesystem usage / btrfs balance start -musage=50 /
Sur tmpfs, ni les blocs ni les inodes ne sont figés : le montage fixe size, dont la valeur par défaut est 50 % de la RAM, et nr_inodes, dont la valeur par défaut est la moitié du nombre de pages de RAM. Un /dev/shm ou un /tmp plein sature un plafond déclaré, pas un disque.
| Système de fichiers | Ressource qui sature | Commande de lecture | Valeur par défaut | Geste correctif |
|---|---|---|---|---|
| ext4 | les inodes, si le ratio est trop large pour le profil de fichiers | df -i |
un inode par 16384 octets (inode_ratio) |
supprimer des fichiers, ou recréer le système de fichiers avec un ratio plus fin |
| Btrfs | les blocs de métadonnées, distincts des blocs de données | btrfs filesystem usage / |
types Data, System et Metadata alloués séparément | btrfs balance start -musage=50 / ou -dusage=0 / |
| tmpfs | la taille et les inodes, tous deux déclarés au montage | df -i /dev/shm |
size à 50 % de la RAM, nr_inodes à la moitié des pages de RAM |
vider le point de montage, ou remonter avec size= et nr_inodes= |
Questions sur les inodes, du –inodes et les fichiers supprimés
Peut-on augmenter le nombre d’inodes d’une partition ext4 sans la reformater ?
Non. Le ratio bytes-per-inode et le nombre d’inodes sont inscrits à la création par mke2fs, et ni tune2fs ni resize2fs ne les modifient sur un système existant. Il reste à supprimer des fichiers, ou à sauvegarder, recréer le système de fichiers avec un ratio plus fin et restaurer.
df -i affiche IUse% à 100 mais du -sh donne quelques gigaoctets : où sont passés les inodes ?
Les inodes sont consommés par le nombre d’entrées, pas par leur poids. Des millions de fichiers de quelques octets, dans un cache de paquets, un dossier de sessions ou une arborescence de dépendances, saturent le compteur sans peser lourd. du --inodes et find -printf '%h\n' désignent le répertoire en cause.
rm n’a pas fait baisser df -h, que faire ?
Vérifier avec lsof +L1 qu’un processus ne détient pas le fichier supprimé, puis redémarrer ce processus. Tant qu’un descripteur reste ouvert, l’inode et les blocs restent alloués.
du –inodes répond unrecognized option ‘–inodes’, pourquoi ?
L’option arrive avec GNU coreutils 8.22, publié le 13 décembre 2013. Une distribution antérieure à cette version ne la connaît pas. À défaut, find / -xdev -printf '%h\n' | sort | uniq -c | sort -rn remplit la même fonction sur les inodes.
df -h indique 60 % d’utilisation et l’écriture échoue : où regarder après les inodes ?
Sur le point de montage exact de la cible. Un /tmp monté en tmpfs, un /dev/shm plafonné à 50 % de la RAM ou un volume Btrfs dont la métadonnée est pleine produisent le même message qu’un disque saturé, sur un système de fichiers que df -h / n’affiche pas.