Abgründige allgemeine dm-Krypta (LUKS) Schreibleistung

21

Ich untersuche ein Problem, bei dem das Verschlüsseln eines Blockgeräts beim Schreiben eine enorme Leistungseinbuße mit sich bringt . Stundenlanges Lesen und Experimentieren im Internet verschafften mir kein richtiges Verständnis, geschweige denn eine Lösung.

Die Frage in Kürze: Warum bekomme ich perfekt schnelle Schreibgeschwindigkeiten, wenn ich ein BTRFS auf ein Blockgerät lege (~ 170MB / s), während die Schreibgeschwindigkeit (~ 20MB / s) sinkt, wenn ich eine dm-Krypta / LUKS dazwischen lege? Dateisystem und das Blockgerät, obwohl das System mehr als in der Lage ist, einen ausreichend hohen Verschlüsselungsdurchsatz aufrechtzuerhalten?

Szenario

/home/schlimmchen/randomist eine 4.0 GB große Datei, die mit Daten aus /dev/urandomfrüheren Versionen gefüllt ist .

dd if=/dev/urandom of=/home/schlimmchen/Documents/random bs=1M count=4096

Das Lesen geht super schnell:

$ dd if=/home/schlimmchen/Documents/random of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 6.58036 s, 648 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 0.786102 s, 5.4 GB/s

(Das zweite Mal wurde die Datei offensichtlich aus dem Cache gelesen.)

Unverschlüsselte BTRFS

Das Gerät ist direkt mit btrfs formatiert (keine Partitionstabelle auf dem Blockgerät).

$ sudo mkfs.btrfs /dev/sdf
$ sudo mount /dev/sdf /mnt
$ sudo chmod 777 /mnt

Die Schreibgeschwindigkeit erreicht bis zu ~ 170 MB / s:

$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 27.1564 s, 157 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test2 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 25.1882 s, 169 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test3 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 29.8419 s, 143 MB/s

Die Lesegeschwindigkeit liegt deutlich über 200 MB / s.

$ dd if=/mnt/dd-test1 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.8265 s, 215 MB/s
$ dd if=/mnt/dd-test2 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.9821 s, 213 MB/s
$ dd if=/mnt/dd-test3 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.8561 s, 215 MB/s

Verschlüsselte BTRFS auf Block-Gerät

Das Gerät ist mit LUKS formatiert, und das resultierende Gerät ist mit btrfs formatiert:

$ sudo cryptsetup luksFormat /dev/sdf
$ sudo cryptsetup luksOpen /dev/sdf crypt
$ sudo mkfs.btrfs /dev/mapper/crypt
$ sudo mount /dev/mapper/crypt /mnt
$ sudo chmod 777 /mnt
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 210.42 s, 20.3 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test2 bs=1M 
4265841146 bytes (4.3 GB) copied, 207.402 s, 20.6 MB/s

Die Lesegeschwindigkeit leidet nur geringfügig (warum überhaupt?):

$ dd if=/mnt/dd-test1 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 22.2002 s, 192 MB/s
$ dd if=/mnt/dd-test2 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 22.0794 s, 193 MB/s

luksDump: http://pastebin.com/i9VYRR0p

Verschlüsselte BTRFS in Datei auf BTRFS auf Blockgerät

Die Schreibgeschwindigkeit "steigt" auf über 150 MB / s, wenn in eine verschlüsselte Datei geschrieben wird. Ich habe ein BTRFS auf das Block-Gerät gelegt und eine 16-GB-Datei zugewiesen, die ich lukfsFormatbearbeitet und gemountet habe.

$ sudo mkfs.btrfs /dev/sdf -f
$ sudo mount /dev/sdf /mnt
$ sudo chmod 777 /mnt
$ dd if=/dev/zero of=/mnt/crypted-file bs=1M count=16384 conv=fsync
17179869184 bytes (17 GB) copied, 100.534 s, 171 MB/s
$ sudo cryptsetup luksFormat /mnt/crypted-file
$ sudo cryptsetup luksOpen /mnt/crypted-file crypt
$ sudo mkfs.btrfs /dev/mapper/crypt
$ sudo mount /dev/mapper/crypt /tmp/nested/
$ dd if=/home/schlimmchen/Documents/random of=/tmp/nested/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 26.4524 s, 161 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/tmp/nested/dd-test2 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 27.5601 s, 155 MB/s

Warum steigt die Schreibleistung so? Was bewirkt diese spezielle Verschachtelung von Dateisystemen und Blockgeräten, um hohe Schreibgeschwindigkeiten zu erzielen?

Installieren

Das Problem ist auf zwei Systemen reproduzierbar, auf denen dieselbe Distribution und derselbe Kernel ausgeführt werden. Allerdings habe ich auch die niedrigen Schreibgeschwindigkeiten mit Kernel 3.19.0 auf System2 beobachtet.

  • Gerät: SanDisk Extreme 64 GB USB 3.0 USB-Stick
  • System 1: Intel NUC 5i5RYH, i5-5250U (Broadwell), 8 GB RAM, Samsung 840 EVO 250 GB SSD
  • System 2: Lenovo T440p, i5-4300M (Haswell), 16 GB RAM, Samsung 850 PRO 256 GB SSD
  • Distribution / Kernel: Debian Jessie, 3.16.7
  • Cryptsetup: 1.6.6
  • /proc/cryptofür System1: http://pastebin.com/QUSGMfiS
  • cryptsetup benchmarkfür System1: http://pastebin.com/4RxzPFeT
  • btrfs (-tools) ist Version 3.17
  • lsblk -t /dev/sdf: http://pastebin.com/nv49tYWc

Gedanken

  • Die Ausrichtung ist meines Erachtens nicht die Ursache. Selbst wenn die Seitengröße des Sticks 16 KB beträgt, ist der Start der Cryptsetup-Nutzdaten ohnehin auf 2 MB ausgerichtet.
  • --allow-discards (für luksOpen von cryptsetup) hat nicht geholfen, wie ich erwartet hatte.
  • Während ich viel weniger Experimente damit machte, beobachtete ich ein sehr ähnliches Verhalten bei einer externen Festplatte, die über einen USB3.0-Adapter angeschlossen war.
  • Es scheint mir, dass das System 64-KB-Blöcke schreibt. Ein Systemtrap-Skript, das ich ausprobiert habe, zeigt dies zumindest an. /sys/block/sdf/statunterstützt diese Hypothese, da viele Schreibvorgänge zusammengeführt werden. Ich vermute also, dass das Schreiben in zu kleinen Blöcken nicht die Ursache ist.
  • Kein Glück, den Warteschlangenplaner für Blockgeräte auf NOOP zu ändern.
  • Das Einfügen der Krypta in ein LVM-Volume hat nicht geholfen.
schlimmchen
quelle
Das Löschen des Festplattencaches vor jedem Test würde dies als möglichen Grund für die Geschwindigkeit beseitigen (648 MB / s klingt derzeit außerhalb des RAM nicht erreichbar)
Xen2050,

Antworten:

18

Die Antwort (wie ich jetzt weiß): Parallelität .

Kurz gesagt : Mein sequentielles Schreiben , entweder unter Verwendung ddoder beim Kopieren einer Datei (wie ... im täglichen Gebrauch), wird zu einem Pseudozufallsschreiben (schlecht), da vier Threads gleichzeitig daran arbeiten, die verschlüsselten Daten nach dem gleichzeitigen Schreiben auf das Blockgerät zu schreiben Verschlüsselung (gut).

Minderung (für "ältere" Kernel)

Der negative Effekt kann abgeschwächt werden, indem die Anzahl der Anforderungen in der Warteschlange des E / A-Schedulers wie folgt erhöht wird:

echo 4096 | sudo tee /sys/block/sdc/queue/nr_requests

In meinem Fall verdreifacht sich der Durchsatz für den in meiner Frage erläuterten 4-GB-Zufallsdatentest nahezu (~ 56 MB / s). Natürlich ist die Leistung im Vergleich zu unverschlüsselten E / A-Vorgängen immer noch unter 100 MB / s.

Ermittlung

Multicore blktrace

Ich habe das problematische Szenario weiter untersucht, in dem ein BTRFS auf einem LUKS-verschlüsselten Blockgerät platziert wird. Um mir zu zeigen, welche Schreibanweisungen für das aktuelle Blockgerät ausgegeben werden, habe ich Folgendes verwendet blktrace:

sudo blktrace -a write -d /dev/sdc -o - | blkparse -b 1 -i - | grep -w D

Das bedeutet (soweit ich das nachvollziehen konnte), dass ich eine E / A-Anforderung /dev/sdcvom Typ " Schreiben " verfolge , diese dann auf eine vom Menschen lesbare Ausgabe analysiere, die Ausgabe jedoch weiter auf die Aktion " D " einschränke , die (gemäß man blkparse) Msgstr " IO an Treiber ausgegeben ".

Das Ergebnis war ungefähr so (siehe etwa 5000 Zeilen Ausgabe des Multicore-Protokolls ):

8,32   0    32732   127.148240056     3  D   W 38036976 + 240 [ksoftirqd/0]
8,32   0    32734   127.149958221     3  D   W 38038176 + 240 [ksoftirqd/0]
8,32   0    32736   127.160257521     3  D   W 38038416 + 240 [ksoftirqd/0]
8,32   1    30264   127.186905632    13  D   W 35712032 + 240 [ksoftirqd/1]
8,32   1    30266   127.196561599    13  D   W 35712272 + 240 [ksoftirqd/1]
8,32   1    30268   127.209431760    13  D   W 35713872 + 240 [ksoftirqd/1]
  • Spalte 1: Dur, Moll des Blockgerätes
  • Spalte 2: CPU ID
  • Spalte 3: laufende Nummer
  • Spalte 4: Zeitstempel
  • Spalte 5: Prozess-ID
  • Spalte 6: Aktion
  • Spalte 7: RWBS-Daten (Typ, Sektor, Länge)

Dies ist ein Ausschnitt der Ausgabe, die erzeugt wird, während dddie 4-GB-Zufallsdaten auf das bereitgestellte Dateisystem übertragen werden. Es ist klar, dass mindestens zwei Prozesse beteiligt sind. Das verbleibende Protokoll zeigt, dass alle vier Prozessoren tatsächlich daran arbeiten. Leider werden die Schreibanfragen nicht mehr bestellt. Während CPU0 irgendwo um den 38038416-ten Sektor schreibt, schreibt CPU1, was später geplant ist, irgendwo um den 35713872-ten Sektor. Das ist schlecht.

Einzelprozessor blktrace

Nach dem Deaktivieren von Multithreading und dem Deaktivieren des zweiten Kerns meiner CPU habe ich dasselbe Experiment durchgeführt. Natürlich ist nur ein Prozessor am Schreiben des Sticks beteiligt. Noch wichtiger ist jedoch, dass die Schreibanfragen ordnungsgemäß sequenziell sind, weshalb die volle Schreibleistung von ~ 170 MB / s im ansonsten gleichen Setup erzielt wird.

Sehen Sie sich im Singlecore-Protokoll etwa 5000 Ausgabezeilen an .

Diskussion

Jetzt, da ich die Ursache und die richtigen Google-Suchbegriffe kenne, sprudelt die Information über dieses Problem an die Oberfläche. Wie sich herausstellt, bin ich nicht der erste, der es bemerkt.

Behoben in aktuellen Kerneln (> = 4.0.2)

Da ich (später) feststellte, dass das Kernel-Commit offensichtlich genau auf dieses Problem abzielte, wollte ich einen aktualisierten Kernel ausprobieren. [Nachdem ich es selbst kompiliert habe und dann herausgefunden habe, dass es bereits vorhanden ist debian/sid] Es stellt sich heraus, dass das Problem tatsächlich behoben ist. Ich kenne nicht die genaue Kernel-Version, in der der Fix erschienen ist, aber das ursprüngliche Commit wird allen Interessierten Hinweise geben.

Für die Aufzeichnung:

$ uname -a
Linux t440p 4.0.0-1-amd64 #1 SMP Debian 4.0.2-1 (2015-05-11) x86_64 GNU/Linux
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test bs=1M conv=fsync
4294967296 bytes (4.3 GB) copied, 29.7559 s, 144 MB/s

Ein Tipp an Mikulas Patocka, der das Commit geschrieben hat.

schlimmchen
quelle
1
Ich benutze btrfs auf luks mit dem Kernel 4.12.12 und die Verlangsamung ist immer noch da!
Brauliobo
Warum ist die Verlangsamung immer noch da? Welche Referenz verwenden Sie, damit Sie keine Verlangsamung feststellen konnten? Was ist dein Setup? Haben Sie die Laufwerksleistung überprüft, als Sie nur LUKS entfernt haben?
Schlimmchen
hat bestätigt, dass es immer noch mit LUKS verwandt ist unix.stackexchange.com/a/393521/39985
brauliobo
1
Jetzt verstehe ich, warum Sie darüber schreiben würden, immer noch eine "Verlangsamung" zu erleben. Ihr Problem hängt jedoch nur mit diesem zusammen, es ist definitiv nicht dasselbe Problem (Verzögerung im Vergleich zu geringer Leistung). Ich erlebe diese nervigen Probleme auch, deshalb bin ich sehr dankbar, dass Sie hier auf Ihr Problem hingewiesen haben! Die Verwendung von LUKS ist keine Option, aber es ist gut zu wissen, dass es mit der Ursache zusammenhängt.
schlimmchen