Comment corriger les erreurs intermittentes «Il n'y a plus d'espace sur l'appareil» pendant le MV lorsque l'appareil a beaucoup d'espace?

21
  • Ubuntu 14.04 sur un bureau
  • Lecteur source: / dev / sda1: 5 To ext4 single
    drive volume
  • Volume cible: / dev / mapper / archive-lvarchive: volume raid6 (mdadm) 18 To avec
    partition lvm et ext4

Il y a environ 15 millions de fichiers à déplacer, et certains peuvent être des doublons (je ne veux pas écraser les doublons).

La commande utilisée (à partir du répertoire source) était:

ls -U |xargs -i -t mv -n {} /mnt/archive/targetDir/{}

Cela dure depuis quelques jours comme prévu, mais je reçois l'erreur d'augmenter la fréquence. Quand il a démarré, le lecteur cible était rempli à environ 70%, maintenant à environ 90%. Auparavant, environ 1/200 des mouvements indiquaient des erreurs, maintenant c'est environ 1/5. Aucun des fichiers ne dépasse 100 Mo, la plupart font environ 100 Ko

Quelques informations:

$ df -h
Filesystem                     Size  Used Avail Use% Mounted on
/dev/sdb3                      155G  5.5G  142G   4% /
none                           4.0K     0  4.0K   0% /sys/fs/cgroup
udev                           3.9G  4.0K  3.9G   1% /dev
tmpfs                          797M  2.9M  794M   1% /run
none                           5.0M  4.0K  5.0M   1% /run/lock
none                           3.9G     0  3.9G   0% /run/shm
none                           100M     0  100M   0% /run/user
/dev/sdb1                       19G   78M   18G   1% /boot
/dev/mapper/archive-lvarchive   18T   15T  1.8T  90% /mnt/archive
/dev/sda1                      4.6T  1.1T  3.3T  25% /mnt/tmp

$ df -i
Filesystem                       Inodes    IUsed     IFree IUse% Mounted on
/dev/sdb3                      10297344   222248  10075096    3% /
none                            1019711        4   1019707    1% /sys/fs/cgroup
udev                            1016768      500   1016268    1% /dev
tmpfs                           1019711     1022   1018689    1% /run
none                            1019711        5   1019706    1% /run/lock
none                            1019711        1   1019710    1% /run/shm
none                            1019711        2   1019709    1% /run/user
/dev/sdb1                       4940000      582   4939418    1% /boot
/dev/mapper/archive-lvarchive 289966080 44899541 245066539   16% /mnt/archive
/dev/sda1                     152621056  5391544 147229512    4% /mnt/tmp

Voici ma sortie:

mv -n 747265521.pdf /mnt/archive/targetDir/747265521.pdf 
mv -n 61078318.pdf /mnt/archive/targetDir/61078318.pdf 
mv -n 709099107.pdf /mnt/archive/targetDir/709099107.pdf 
mv -n 75286077.pdf /mnt/archive/targetDir/75286077.pdf 
mv: cannot create regular file ‘/mnt/archive/targetDir/75286077.pdf’: No space left on device
mv -n 796522548.pdf /mnt/archive/targetDir/796522548.pdf 
mv: cannot create regular file ‘/mnt/archive/targetDir/796522548.pdf’: No space left on device
mv -n 685163563.pdf /mnt/archive/targetDir/685163563.pdf 
mv -n 701433025.pdf /mnt/archive/targetDir/701433025.pd

J'ai trouvé BEAUCOUP de messages sur cette erreur, mais le pronostic ne convient pas. Des problèmes tels que "votre lecteur est réellement plein" ou "vous avez manqué d'inodes" ou même "votre / volume de démarrage est plein". La plupart du temps, cependant, ils traitent avec des logiciels tiers provoquant un problème en raison de la façon dont il gère les fichiers, et ils sont tous constants, ce qui signifie que chaque mouvement échoue.

Merci.

EDIT: voici un exemple de fichier ayant échoué et réussi:

ÉCHEC (toujours sur le lecteur source)

ls -lhs 702637545.pdf
16K -rw-rw-r-- 1 myUser myUser 16K Jul 24 20:52 702637545.pdf

RÉUSSITE (Sur le volume cible)

ls -lhs /mnt/archive/targetDir/704886680.pdf
104K -rw-rw-r-- 1 myUser myUser 103K Jul 25 01:22 /mnt/archive/targetDir/704886680.pdf

De plus, bien que tous les fichiers n'échouent pas, un fichier qui échoue échouera TOUJOURS. Si je recommence encore et encore, c'est cohérent.

EDIT: quelques commandes supplémentaires par demande de @mjturner

$ ls -ld /mnt/archive/targetDir
drwxrwxr-x 2 myUser myUser 1064583168 Aug 10 05:07 /mnt/archive/targetDir

$ tune2fs -l /dev/mapper/archive-lvarchive
tune2fs 1.42.10 (18-May-2014)
Filesystem volume name:   <none>
Last mounted on:          /mnt/archive
Filesystem UUID:          af7e7b38-f12a-498b-b127-0ccd29459376
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr dir_index filetype needs_recovery extent 64bit flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              289966080
Block count:              4639456256
Reserved block count:     231972812
Free blocks:              1274786115
Free inodes:              256343444
First block:              0
Block size:               4096
Fragment size:            4096
Group descriptor size:    64
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         2048
Inode blocks per group:   128
RAID stride:              128
RAID stripe width:        512
Flex block group size:    16
Filesystem created:       Thu Jun 25 12:05:12 2015
Last mount time:          Mon Aug  3 18:49:29 2015
Last write time:          Mon Aug  3 18:49:29 2015
Mount count:              8
Maximum mount count:      -1
Last checked:             Thu Jun 25 12:05:12 2015
Check interval:           0 (<none>)
Lifetime writes:          24 GB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:           256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      3ea3edc4-7638-45cd-8db8-36ab3669e868
Journal backup:           inode blocks

$ tune2fs -l /dev/sda1
tune2fs 1.42.10 (18-May-2014)
Filesystem volume name:   <none>
Last mounted on:          /mnt/tmp
Filesystem UUID:          10df1bea-64fc-468e-8ea0-10f3a4cb9a79
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              152621056
Block count:              1220942336
Reserved block count:     61047116
Free blocks:              367343926
Free inodes:              135953194
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      732
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         4096
Inode blocks per group:   256
Flex block group size:    16
Filesystem created:       Thu Jul 23 13:54:13 2015
Last mount time:          Tue Aug  4 04:35:06 2015
Last write time:          Tue Aug  4 04:35:06 2015
Mount count:              3
Maximum mount count:      -1
Last checked:             Thu Jul 23 13:54:13 2015
Check interval:           0 (<none>)
Lifetime writes:          150 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:           256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      a266fec5-bc86-402b-9fa0-61e2ad9b5b50
Journal backup:           inode blocks
Chris.Caldwell
la source
Les fichiers sont-ils copiés dans plusieurs répertoires ou essayez-vous d'écrire des fichiers de 1,5 million dans un seul répertoire cible?
snoopy
pas 1,5 m, 15 m et oui, tous dans le même répertoire. En fait, il y a déjà plus de 40 m là-bas, et environ 30 m de plus au total.
Chris.Caldwell
oh regarde, le troll aléatoire downvote a frappé à nouveau. Je ne pense pas que vous voudriez mentionner pourquoi vous votez?
Chris.Caldwell
1
Le vote négatif était probablement dû au fait que votre question est mieux adaptée à Unix.stackexchange ou askubuntu car elle n'est pas liée à la programmation. S'il n'y a pas de langage de programmation dans vos balises, il obtiendra probablement un vote négatif.
technosaurus
@Chris - semble similaire à ce problème sur SF: serverfault.com/questions/384541/…
snoopy

Réponses:

25

Bug dans l'implémentation de la fonction ext4 dir_indexque vous utilisez sur votre système de fichiers de destination.

Solution: recréez le système de fichiers sans dir_index. Ou désactivez la fonctionnalité à l'aide de tune2fs (une certaine prudence est requise, voir le lien associé Novell SuSE 10/11: Désactiver l'indexation de l'arborescence H sur un système de fichiers ext3 qui, bien que lié à ext3, peut nécessiter une prudence similaire.

(get a really good backup made of the filesystem)
(unmount the filesystem)
tune2fs -O ^dir_index /dev/foo
e2fsck -fDvy /dev/foo
(mount the filesystem)

ext4 a une fonctionnalité appelée dir_index activée par défaut, qui est assez sensible aux collisions de hachage.

......

ext4 a la possibilité de hacher les noms de fichiers de son contenu. Cela améliore les performances, mais a un «petit» problème: ext4 ne développe pas sa table de hachage lorsqu'il commence à se remplir. Au lieu de cela, il renvoie -ENOSPC ou «aucun espace laissé sur l'appareil».

Steve
la source
3
oh merde, ça sonne exactement comme ça, et comme une douleur complète à réparer. Son environ un mois pour recopier. cela peut-il être fait sans perdre le contenu? Je vais devoir chercher dir_index etc plus demain. Wow, je n'aurais jamais pensé à ça.
Chris.Caldwell
Ajout de la commande tune2fs pour désactiver les index, au cas où vous voudriez essayer cela.
steve
6
@Steve bien repéré. Malheureusement, la désactivation dir_indexréduira probablement les performances d'accès avec 70 millions de fichiers dans un seul répertoire.
mjturner
3
Ouais. Je n'ai pas besoin de performances de pointe, mais une recherche fs pour chaque fichier serait horrible. Alors maintenant, je regarde xfs ou un tableau de 10k ou sous-dossiers. Les sous-dossiers sont une solution raisonnable, mais avec ext4, je continue de courir le risque de collision. xfs souffre-t-il du même problème? J'ai lu qu'il utilise un arbre B +, mais cela ne signifie pas tant pour moi que d'assurer qu'il n'y a jamais de collision. Il y a un monde de désinformation là-bas, et j'ai entendu dire qu'il ralentit considérablement plus d'un million de fichiers, et qu'il ne le fait pas.
Chris.Caldwell
2
Je pense que c'est une excellente réponse, et j'aimerais la marquer comme telle, mais je pense que ce serait bien si nous pouvions trouver une solution, pas seulement un diagnostic. Est-ce que quelqu'un sait si xfs souffre de quelque chose comme ça? J'ai lu des critiques mitigées qui mesurent bien, ou pas plus de 1 m.
Chris.Caldwell
8

Suggestions de choix meilleurs que ext4 pour stocker des masses de petits fichiers:

Si vous utilisez le système de fichiers comme magasin d'objets, vous voudrez peut-être envisager d'utiliser un système de fichiers spécialisé dans ce domaine, peut-être au détriment d'autres caractéristiques. Une recherche rapide sur Google a trouvé Ceph , qui semble être open source, et peut être monté en tant que système de fichiers POSIX, mais également accessible avec d'autres API. Je ne sais pas si cela vaut la peine d'être utilisé sur un seul hôte, sans profiter de la réplication.

Un autre système de stockage d'objets est le Swift d'OpenStack . Ses documents de conception indiquent qu'il stocke chaque objet dans un fichier séparé, avec des métadonnées dans xattrs . Voici un article à ce sujet. Leur guide de déploiement indique qu'ils ont trouvé que XFS offrait les meilleures performances pour le stockage d'objets. Donc, même si la charge de travail n'est pas la meilleure solution pour XFS, elle était apparemment meilleure que les concurrents lorsque RackSpace testait les choses. Il est possible que Swift favorise XFS car XFS prend en charge correctement / rapidement les attributs étendus. Il se peut que ext3 / ext4 fonctionne correctement sur des disques simples en tant que backend de stockage d'objets si des métadonnées supplémentaires n'étaient pas nécessaires (ou si elles étaient conservées dans le fichier binaire).

Swift effectue la réplication / l'équilibrage de charge pour vous et vous suggère de lui donner des systèmes de fichiers créés sur des disques bruts, pas RAID . Il souligne que sa charge de travail est essentiellement le pire des cas pour RAID5 (ce qui est logique si nous parlons d'une charge de travail avec des écritures de petits fichiers. XFS ne les emballe généralement pas complètement, donc vous ne le faites pas obtenir des écritures pleine bande, et RAID5 doit faire quelques lectures pour mettre à jour la bande de parité. Les documents Swift parlent également de l'utilisation de 100 partitions par lecteur. Je suppose que c'est un terme Swift, et ne parle pas de créer 100 systèmes de fichiers XFS différents sur chaque Disque SATA.

L'exécution d'un XFS distinct pour chaque disque est en fait une énorme différence . Au lieu d'une gigantesque carte d'inode libre, chaque disque aura un XFS distinct avec des listes libres distinctes. De plus, cela évite la pénalité RAID5 pour les petites écritures.

Si vous avez déjà créé votre logiciel pour utiliser un système de fichiers directement comme magasin d'objets, plutôt que de passer par quelque chose comme Swift pour gérer la réplication / équilibrage de charge, vous pouvez au moins éviter d'avoir tous vos fichiers dans un seul répertoire. (Je n'ai pas vu les documents Swift dire comment ils disposaient leurs fichiers dans plusieurs répertoires, mais je suis certain qu'ils le font.)

Avec presque n'importe quel système de fichiers normal, il sera utile d'utiliser une structure comme

1234/5678   # nested medium-size directories instead of
./12345678   # one giant directory

Probablement environ 10 000 entrées sont raisonnables, donc prendre 4 caractères bien répartis de vos noms d'objets et les utiliser comme répertoires est une solution facile. Il n'a pas besoin d'être très bien équilibré. Le répertoire impair de 100k ne sera probablement pas un problème notable, pas plus que certains répertoires vides.

XFS n'est pas idéal pour d'énormes masses de petits fichiers. Il fait ce qu'il peut, mais il est plus optimisé pour le streaming d'écritures de fichiers plus volumineux. C'est très bon dans l'ensemble pour une utilisation générale. Il n'a pas ENOSPCde collisions dans son indexation d'annuaire (AFAIK), et peut gérer avoir un annuaire avec des millions d'entrées. (Mais il vaut toujours mieux utiliser au moins un arbre à un niveau.)

Dave Chinner a fait quelques commentaires sur les performances XFS avec un grand nombre d'inodes alloués , ce qui a conduit à des touchperformances lentes . Trouver un inode libre à allouer commence à prendre plus de temps CPU, car le bitmap d'inode gratuit est fragmenté. Notez que ce n'est pas un problème de répertoire unique par rapport à plusieurs répertoires, mais plutôt un problème de nombreux inodes utilisés sur l'ensemble du système de fichiers. La division de vos fichiers en plusieurs répertoires permet de résoudre certains problèmes, comme celui qui s'est étouffé dans ext4 dans l'OP, mais pas le problème du disque entier de garder une trace de l'espace libre. Le système de fichiers séparé par disque de Swift y contribue, par rapport à XFS géant sur RAID5.

Je ne sais pas si btrfs est bon dans ce domaine, mais je pense que c'est possible. Je pense que Facebook emploie son développeur principal pour une raison. : P Quelques repères que j'ai vus, des trucs comme décompresser une source du noyau Linux, montrent que btrfs marche bien.

Je sais que reiserfs a été optimisé pour ce cas, mais il est à peine, voire pas du tout, maintenu. Je ne peux vraiment pas recommander d'aller avec reiser4. Il pourrait cependant être intéressant d'expérimenter. Mais c'est de loin le choix le moins pérenne. J'ai également vu des rapports de dégradation des performances sur les anciens reiserFS, et il n'y a pas de bon outil de défragmentation. (Google filesystem millions of small files, et regardez certaines des réponses existantes de stackexchange.)

Il me manque probablement quelque chose, donc dernière recommandation: posez des questions à ce sujet sur serverfault! Si je devais choisir quelque chose en ce moment, je dirais d'essayer BTRFS, mais assurez-vous d'avoir des sauvegardes. (en particulier si vous utilisez la redondance de disques multiples intégrée à BTRFS, au lieu de l'exécuter sur RAID. Les avantages en termes de performances peuvent être importants, car les petits fichiers sont de mauvaises nouvelles pour RAID5, à moins que ce ne soit une charge de travail en lecture principalement.)

Peter Cordes
la source
1
Merci beaucoup. J'ai vu beaucoup de gens utiliser des sous-dossiers, et en fait, il y a des années, j'avais ce type de solution sur une configuration différente, mais c'est une autre couche que j'espérais éviter. Il semble que les frais généraux de procéder de cette façon seront bien moins importants que de trouver un fs qui fonctionne juste à cet effet. RE: XFS, c'est surprenant que son si mauvais au nombre élevé de fichiers depuis sa réponse la plus souvent donnée. BTRFS, wiki: "les entrées de répertoire apparaissent comme des éléments de répertoire, dont les valeurs de clé à droite sont un hachage CRC32C de leur nom de fichier". n'est-ce pas le même problème que nous avons?
Chris.Caldwell
@ Chris.Caldwell: Vous devriez vérifier, mais je suppose que BTRFS gère les collisions de hachage en prenant en charge plusieurs entrées dans le même compartiment de hachage, plutôt que ENOSPC. Avez-vous pensé à simplement garder vos affaires dans une base de données, au lieu de fichiers séparés dans le système de fichiers? Je n'ai jamais eu à construire de système pour gérer ce type de données. J'utilise XFS, ce qui est excellent pour ce que je l'utilise pour (stocker des vidéos, et du code source Unix à usage général et d'autres choses.)
Peter Cordes
1
De la façon dont les systèmes de fichiers sont conçus, un niveau de répertoires est moins lourd. Deux recherches rapides dans de petites tables seront plus rapides qu'une recherche lente dans une table débordante qui stocke plus de données que prévu. Comme je l'ai dit, vous n'avez pas à répartir parfaitement vos fichiers entre les répertoires, vous pouvez donc simplement prendre les 4 premiers caractères de vos noms de fichiers et insérer un /. Espérons que cela n'affectera pas trop d'endroits dans votre code. (Vous devez vous assurer que les répertoires sont créés si la création d'un nouveau fichier échoue avec ENOENT). Demandez sur serverfault s'il existe d'autres systèmes de fichiers.
Peter Cordes
@ Chris.Caldwell: Je devrais vraiment copier cette réponse à une question là où elle est pertinente. Il en existe quelques-uns. J'étais curieux de savoir ce que l'on est censé utiliser pour le stockage d'objets et j'ai trouvé quelques documents sur Swift. Apparemment, il stocke des objets en tant que fichiers séparés sur XFS (mais avec un XFS distinct pour chaque disque, pas RAID. Il gère la redondance elle-même).
Peter Cordes
1

Pour ce problème ci-dessous, voici ce que j'ai fait pour résoudre (vous aurez peut-être besoin d'un accès sudo pour les étapes ci-dessous):

  1. L'espace utilisé des inodes était de 100% qui peut être récupéré en utilisant la commande ci-dessous

    df -i /

Inodes du système de fichiers IUsed IFree IUse% Mounted on

/dev/xvda1            524288   524288  o     100% /
  1. Besoin de libérer l'iNoted, donc besoin de trouver les fichiers qui ont ici le nombre de nœuds i en utilisant la commande ci-dessous:

Essayez de trouver s'il s'agit d'un problème d'inodes avec:

df -ih

Essayez de trouver des dossiers racine avec un grand nombre d'inodes:

for i in /*; do echo $i; find $i |wc -l; done

Essayez de trouver des dossiers spécifiques:

for i in /src/*; do echo $i; find $i |wc -l; done
  1. nous avons maintenant mis à zéro le dossier contenant un grand nombre de fichiers. Exécutez les commandes ci-dessous l'une après l'autre pour éviter toute erreur (dans mon cas, le dossier réel était / var / spool / clientmqueue):
find /var/spool/clientmqueue/ -type f -mtime +1050 -exec rm -f {} +

find /var/spool/clientmqueue/ -type f -mtime +350 -exec rm -f {} +

find /var/spool/clientmqueue/ -type f -mtime +150 -exec rm -f {} +

find /var/spool/clientmqueue/ -type f -mtime +50 -exec rm -f {} +
Barani r
la source