Wie behebt man zeitweise auftretende "Kein Platz mehr auf dem Gerät" -Fehler während der MV, wenn das Gerät viel Platz hat?

21
  • Ubuntu 14.04 auf einem Desktop
  • Quelllaufwerk: / dev / sda1: 5 TB ext4-Volume mit einem einzelnen
    Laufwerk
  • Zieldatenträger: / dev / mapper / archive-lvarchive: raid6 (mdadm) 18-TB-Datenträger mit lvm-
    Partition und ext4

Es müssen ungefähr 15 Millionen Dateien verschoben werden, und einige können Duplikate sein (ich möchte keine Duplikate überschreiben).

Der verwendete Befehl (aus dem Quellverzeichnis) war:

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

Dies hat wie erwartet einige Tage gedauert, aber ich erhalte den Fehler in zunehmender Häufigkeit. Als es gestartet wurde, war das Ziellaufwerk zu ungefähr 70% voll, jetzt sind es ungefähr 90%. Früher waren es ungefähr 1/200 der Züge, die angaben und Fehler machten, jetzt sind es ungefähr 1/5. Keine der Dateien ist größer als 100 MB, die meisten sind ungefähr 100 KB groß

Einige Infos:

$ 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

Hier ist meine Ausgabe:

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

Ich habe VIELE Postings zu diesem Fehler gefunden, aber die Prognose passt nicht. Probleme wie "Ihr Laufwerk ist tatsächlich voll" oder "Ihnen gehen die Inodes aus" oder sogar "Ihr / boot-Volume ist voll". In den meisten Fällen handelt es sich jedoch um Software von Drittanbietern, die aufgrund der Handhabung der Dateien ein Problem verursacht, und sie sind alle konstant, was bedeutet, dass JEDE Bewegung fehlschlägt.

Vielen Dank.

BEARBEITEN: Hier ist ein Beispiel einer fehlgeschlagenen und erfolgreichen Datei:

FEHLGESCHLAGEN (noch auf dem Quelllaufwerk)

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

ERFOLGREICH (Auf Zielvolumen)

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

Auch wenn nicht alle Dateien fehlschlagen, schlägt eine fehlgeschlagene Datei IMMER fehl. Wenn ich es immer wieder versuche, ist es konsistent.

BEARBEITEN: Einige zusätzliche Befehle auf Anfrage von @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
quelle
Werden die Dateien in mehrere Verzeichnisse kopiert oder versuchen Sie, 1,5 Millionen Dateien in ein einziges Zielverzeichnis zu schreiben?
Snoopy
nicht 1,5 m, 15 m und ja, alle in dasselbe Verzeichnis. Tatsächlich sind dort bereits über 40 m und insgesamt noch etwa 30 m zu bewältigen.
Chris.Caldwell
oh schau, der zufällige downvote troll schlug wieder zu. Ich vermute nicht, dass Sie erwähnen möchten, WARUM Sie abstimmen?
Chris.Caldwell
1
Die Abwärtsabstimmung war wahrscheinlich, weil Ihre Frage besser für Unix.stackexchange oder askubuntu geeignet ist, da sie nicht mit der Programmierung zusammenhängt. Wenn Ihre Tags keine Programmiersprache enthalten, wird diese wahrscheinlich abgelehnt.
Technosaurus
@ Chris - scheint ähnlich zu diesem Thema auf SF: serverfault.com/questions/384541/...
snoopy

Antworten:

25

Fehler bei der Implementierung der ext4-Funktion, dir_indexdie Sie auf Ihrem Zieldateisystem verwenden.

Lösung: Dateisystem ohne dir_index neu erstellen. Oder deaktivieren Sie die Funktion mit tune2fs (Vorsicht ist geboten, siehe verwandten Link Novell SuSE 10/11: Deaktivieren der H-Tree-Indizierung auf einem ext3-Dateisystem, das sich zwar auf ext3 bezieht, aber möglicherweise eine ähnliche Vorsicht erfordert.

(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)

In ext4 ist standardmäßig die Funktion dir_index aktiviert, die sehr anfällig für Hash-Kollisionen ist.

......

ext4 hat die Möglichkeit, die Dateinamen seines Inhalts zu hashen. Dies verbessert die Leistung, hat aber ein "kleines" Problem: ext4 vergrößert seine Hash-Tabelle nicht, wenn es beginnt, sich zu füllen. Stattdessen wird -ENOSPC oder "no space left on device" zurückgegeben.

Steve
quelle
3
Oh Mist, das hört sich genau so an, und es ist wie ein totaler Schmerz, der behoben werden muss. Es ist ungefähr ein Monat, um es zu kopieren. geht das, ohne den inhalt zu verlieren? Ich muss morgen nach dir_index usw. suchen. Wow, daran hätte ich nie gedacht.
Chris.Caldwell
Fügte den Befehl tune2fs hinzu, um die Indizes zu deaktivieren, falls Sie das versuchen möchten.
Steve
6
Gut gesehen @ Steve. Leider wird das Ausschalten dir_indexwahrscheinlich die Zugriffsleistung bei 70-Millionen-Dateien in einem Verzeichnis beeinträchtigen.
mjturner
3
Ja. Ich brauche keine Spitzenleistung, aber eine fs-Suche für jede Datei wäre schrecklich. So, jetzt sehe ich mir xfs oder ein Array von 10k oder so Unterordnern an. Unterordner sind eine vernünftige Lösung, aber mit ext4 bin ich immer noch dem Risiko einer Kollision ausgesetzt. leidet xfs unter dem gleichen Problem? Ich habe gelesen, dass ein B + -Baum verwendet wird, aber das bedeutet mir nicht so viel, dass ich sicherstellen muss, dass es nie zu einer Kollision kommt. Es gibt da draußen eine Welt voller Fehlinformationen, und ich habe gehört, dass es erheblich langsamer wird als eine Million Dateien, und behauptet, dass es das nicht tut.
Chris.Caldwell
2
Ich denke, das ist eine großartige Antwort, und ich würde sie gerne als solche markieren, aber ich denke, es wäre schön, wenn wir eine Lösung finden könnten, nicht nur eine Diagnose. Weiß jemand, ob xfs unter so etwas leidet? Ich habe gemischte Kritiken gelesen, dass es gut skaliert, oder nicht über 1m.
Chris.Caldwell
8

Vorschläge für eine bessere Auswahl als ext4 zum Speichern von Massen kleiner Dateien:

Wenn Sie das Dateisystem als Objektspeicher verwenden, möchten Sie möglicherweise ein darauf spezialisiertes Dateisystem verwenden, möglicherweise zum Nachteil anderer Merkmale. Eine schnelle Google-Suche ergab, dass Ceph Open Source ist und als POSIX-Dateisystem gemountet werden kann, auf das jedoch auch mit anderen APIs zugegriffen werden kann. Ich weiß nicht, ob es sich lohnt, auf einem einzelnen Host zu arbeiten, ohne die Replikation zu nutzen.

Ein weiteres Objektspeichersystem ist OpenStacks Swift . In den Designdokumenten wird angegeben , dass jedes Objekt als separate Datei mit Metadaten in xattrs gespeichert wird . Hier ist ein Artikel darüber. Im Bereitstellungshandbuch heißt es, dass XFS die beste Leistung für die Objektspeicherung erbringt. Obwohl die Workload nicht das ist, was XFS am besten kann, war sie anscheinend besser als die Konkurrenz, als RackSpace die Dinge testete. Möglicherweise bevorzugt Swift XFS, da XFS erweiterte Attribute gut / schnell unterstützt. Es könnte sein, dass ext3 / ext4 auf einzelnen Festplatten als Objektspeicher-Backend funktioniert, wenn keine zusätzlichen Metadaten benötigt werden (oder wenn sie in der Binärdatei gespeichert werden).

Swift übernimmt die Replikation / den Lastenausgleich für Sie und schlägt vor, dass Sie ihm Dateisysteme geben, die auf Raw-Festplatten und nicht auf RAID erstellt wurden . Es wird darauf hingewiesen, dass die Arbeitslast für RAID5 im Wesentlichen der schlechteste Fall ist (was sinnvoll ist, wenn es sich um eine Arbeitslast handelt, bei der kleine Dateien geschrieben werden. XFS packt sie in der Regel nicht vollständig von Kopf bis Fuß, also nicht Wenn Sie Voll-Stripe-Schreibvorgänge ausführen und RAID5 einige Lesevorgänge ausführen muss, um den Paritätsstreifen zu aktualisieren, werden in Swift-Dokumenten auch 100 Partitionen pro Laufwerk beschrieben SATA-Festplatte.

Das Ausführen eines separaten XFS für jede Festplatte ist ein großer Unterschied . Anstelle einer gigantischen Free-Inode-Map hat jede Festplatte ein separates XFS mit separaten Free-Listen. Außerdem wird die RAID5-Strafe für kleine Schreibvorgänge vermieden.

Wenn Sie Ihre Software bereits so erstellt haben, dass sie ein Dateisystem direkt als Objektspeicher verwendet, anstatt Swift zu durchlaufen, um die Replikation / den Lastenausgleich durchzuführen, können Sie zumindest vermeiden, dass sich alle Ihre Dateien in einem einzigen Verzeichnis befinden. (Ich habe nicht gesehen, dass Swift-Dokumente sagen, wie sie ihre Dateien in mehreren Verzeichnissen anordnen, aber ich bin mir sicher, dass sie es tun.)

Bei fast jedem normalen Dateisystem ist es hilfreich, eine Struktur wie diese zu verwenden

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

Wahrscheinlich sind ca. 10.000 Einträge sinnvoll. Daher ist es eine einfache Lösung, gut verteilte 4 Zeichen Ihrer Objektnamen als Verzeichnisse zu verwenden. Es muss nicht sehr gut ausbalanciert sein. Das ungerade 100k-Verzeichnis wird wahrscheinlich kein auffälliges Problem sein, und einige leere Verzeichnisse werden es auch nicht sein.

XFS ist nicht ideal für große Mengen kleiner Dateien. Es macht, was es kann, aber es ist mehr für das Streaming von Schreibvorgängen größerer Dateien optimiert. Es ist jedoch insgesamt sehr gut für den allgemeinen Gebrauch. Es hat keine ENOSPCKollisionen in seiner Verzeichnisindizierung (AFAIK) und kann mit einem Verzeichnis mit Millionen von Einträgen umgehen. (Aber es ist immer noch besser, mindestens einen einstufigen Baum zu verwenden.)

Dave Chinner hatte einige Kommentare zur XFS-Leistung mit einer großen Anzahl von zugewiesenen Inodes , was zu einer langsamen touchLeistung führte. Die Suche nach einem freien Inode für die Zuweisung nimmt mehr CPU-Zeit in Anspruch, da die Bitmap für den freien Inode fragmentiert wird. Beachten Sie, dass dies kein Problem mit einem großen Verzeichnis im Vergleich zu mehreren Verzeichnissen ist, sondern ein Problem mit vielen verwendeten Inodes im gesamten Dateisystem. Das Aufteilen Ihrer Dateien in mehrere Verzeichnisse hilft bei einigen Problemen, z. B. bei dem, bei dem ext4 im OP erstickt ist, jedoch nicht bei dem Problem, den freien Speicherplatz auf der gesamten Festplatte zu überwachen. Swifts separates Dateisystem pro Festplatte hilft dabei, im Vergleich zu Riesen-XFS auf einem RAID5.

Ich weiß nicht, ob BTRFS darin gut ist, aber ich denke, es kann sein. Ich denke, Facebook beschäftigt seinen Hauptentwickler aus einem bestimmten Grund. : P Einige Benchmarks, die ich gesehen habe, zum Beispiel das Dekomprimieren einer Linux-Kernelquelle, zeigen, dass btrfs gut funktioniert.

Ich weiß, dass reiserfs für diesen Fall optimiert wurde, aber es wird kaum oder gar nicht mehr gewartet. Ich kann es wirklich nicht empfehlen, mit reiser4 zu fahren. Es könnte jedoch interessant sein, zu experimentieren. Aber es ist bei weitem die am wenigsten zukunftssichere Wahl. Ich habe auch Berichte über Leistungseinbußen bei älteren reiserFS gesehen, und es gibt kein gutes Defragmentierungswerkzeug. (google filesystem millions of small filesund schau dir einige der vorhandenen Stackexchange-Antworten an.)

Vermutlich fehlt mir etwas, also abschließende Empfehlung: Bei Serverfehler nachfragen! Wenn ich jetzt etwas aussuchen müsste, würde ich BTRFS ausprobieren, aber stellen Sie sicher, dass Sie Backups haben. (Insbesondere, wenn Sie die integrierte Redundanz für mehrere Datenträger von BTRFS verwenden, anstatt sie über RAID auszuführen. Die Leistungsvorteile können groß sein, da kleine Dateien für RAID5 eine schlechte Nachricht sind, es sei denn, es handelt sich um eine Workload, die hauptsächlich gelesen wird.)

Peter Cordes
quelle
1
Vielen Dank. Ich habe eine Menge Leute gesehen, die Unterordner verwendeten, und in der Tat hatte ich vor Jahren diese Art von Lösung in einem anderen Setup, aber es war eine andere Schicht, die ich zu vermeiden hoffte. Es sieht so aus, als ob der Overhead, wenn man es auf diese Weise macht, weitaus geringer sein wird, als ein fs zu finden, das nur für diesen Zweck funktioniert. RE: XFS, es ist überraschend, dass es bei einer hohen Anzahl von Dateien so schlecht ist, da es die häufig gestellte knifflige Antwort ist. BTRFS, Wiki: "Verzeichniseinträge erscheinen als Verzeichniseinträge, deren rechte Schlüsselwerte ein CRC32C-Hash ihres Dateinamens sind". Ist das nicht das gleiche Problem, das wir haben?
Chris.Caldwell
@ Chris.Caldwell: Sie müssten das überprüfen, aber ich gehe davon aus, dass BTRFS Hash-Kollisionen behandelt, indem es mehrere Einträge im selben Hash-Bucket unterstützt und nicht ENOSPC. Haben Sie darüber nachgedacht, Ihre Daten einfach in einer Datenbank zu speichern, anstatt einzelne Dateien im Dateisystem zu speichern? Ich musste noch nie ein System bauen, um diese Art von Daten zu verarbeiten. Ich verwende XFS, was großartig für das ist, wofür ich es verwende (Speichern von Videos und allgemeinem Unix-Quellcode und so weiter.)
Peter Cordes
1
Die Art und Weise, wie Dateisysteme entworfen werden, verringert den Aufwand für Verzeichnisse. Zwei schnelle Suchvorgänge in kleinen Tabellen sind schneller als ein langsamer Suchvorgang in einer überfüllten Tabelle, in der mehr Daten gespeichert werden, als optimiert wurden. Wie ich bereits sagte, müssen Sie Ihre Dateien nicht perfekt auf die Verzeichnisse verteilen, sondern können nur die ersten 4 Zeichen Ihrer Dateinamen verwenden und ein einfügen /. Hoffentlich wirkt sich das nicht auf zu viele Stellen in Ihrem Code aus. (Sie müssen sicherstellen, dass Verzeichnisse erstellt werden, wenn das Erstellen einer neuen Datei mit fehlschlägt. ENOENT) Fragen Sie bei Serverfehler, ob es andere Dateisysteme gibt.
Peter Cordes
@ Chris.Caldwell: Ich sollte diese Antwort wirklich auf eine Frage kopieren, wo es relevant ist. Es gibt einige existierende. Ich war neugierig, was man als Objektspeicher verwenden soll, und fand einige Dokumente über Swift. Anscheinend speichert es Objekte als separate Dateien auf XFS (aber mit einem separaten XFS für jede Festplatte, nicht RAID. Es handhabt die Redundanz selbst).
Peter Cordes
1

Für dieses Problem habe ich folgendes getan (für die folgenden Schritte benötigen Sie möglicherweise sudo-Zugriff):

  1. Der von Inodes belegte Speicherplatz betrug 100%, was mit dem folgenden Befehl abgerufen werden kann

    df -i /

Dateisystem Inodes IUsed IFree IUse% Mounted on

/dev/xvda1            524288   524288  o     100% /
  1. Müssen Sie das iNoted freigeben, daher müssen Sie die Dateien mit der hier angegebenen Anzahl von i-Knoten mit dem folgenden Befehl finden:

Versuchen Sie herauszufinden, ob dies ein Inodes-Problem ist:

df -ih

Versuchen Sie, Stammordner mit einer großen Anzahl von Inodes zu finden:

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

Versuchen Sie, bestimmte Ordner zu finden:

for i in /src/*; do echo $i; find $i |wc -l; done
  1. Jetzt haben wir den Ordner mit einer großen Anzahl von Dateien auf Null gestellt. Führen Sie die folgenden Befehle nacheinander aus, um Fehler zu vermeiden (in meinem Fall war der eigentliche Ordner / 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
quelle