Performances d'écriture dys-crypt générales abyssales (LUKS)

21

J'étudie un problème où le cryptage d'un périphérique de bloc impose une énorme pénalité de performance lors de l' écriture . Des heures de lecture et d'expériences sur Internet ne m'ont pas permis de bien comprendre, encore moins de trouver une solution.

La question en bref: pourquoi est-ce que j'obtiens des vitesses d'écriture parfaitement rapides lorsque je place un btrfs sur un périphérique de bloc (~ 170 Mo / s), alors que la vitesse d'écriture chute (~ 20 Mo / s) lorsque je place un dm-crypt / LUKS entre les système de fichiers et le périphérique de bloc, bien que le système soit plus que capable de maintenir un débit de cryptage suffisamment élevé?

Scénario

/home/schlimmchen/randomest un fichier de 4,0 Go rempli de données /dev/urandomantérieures.

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

La lecture est super rapide:

$ 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

(la deuxième fois, le fichier a évidemment été lu dans le cache).

Btrfs non chiffrés

Le périphérique est directement formaté avec btrfs (pas de table de partition sur le périphérique bloc).

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

La vitesse d'écriture atteint ~ 170 Mo / 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

La vitesse de lecture est bien supérieure à 200 Mo / 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

Btrfs chiffrés sur périphérique bloc

Le périphérique est formaté avec LUKS et le périphérique résultant est formaté avec btrfs:

$ 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

La vitesse de lecture ne souffre que marginalement (pourquoi le fait-elle?):

$ 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

Btrfs chiffrés dans un fichier sur btrfs sur un périphérique bloc

La vitesse d'écriture "monte en flèche" à plus de 150 Mo / s lors de l'écriture dans un fichier crypté. J'ai mis un btrfs sur le périphérique bloc, alloué un fichier de 16 Go, que j'ai lukfsFormatédité et monté.

$ 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

Pourquoi les performances d'écriture augmentent-elles ainsi? Qu'est-ce que cette imbrication particulière de systèmes de fichiers et de périphériques de blocs permet d'obtenir à des vitesses d'écriture élevées?

Installer

Le problème est reproductible sur deux systèmes exécutant la même distribution et le même noyau. Cependant, j'ai également observé les faibles vitesses d'écriture avec le noyau 3.19.0 sur System2.

  • Périphérique: clé USB SanDisk Extreme 64 Go USB 3.0
  • System1: Intel NUC 5i5RYH, i5-5250U (Broadwell), 8 Go de RAM, Samsung 840 EVO 250 Go SSD
  • System2: Lenovo T440p, i5-4300M (Haswell), 16 Go de RAM, Samsung 850 PRO 256 Go SSD
  • Distro / Kernel: Debian Jessie, 3.16.7
  • cryptsetup: 1.6.6
  • /proc/cryptopour System1: http://pastebin.com/QUSGMfiS
  • cryptsetup benchmarkpour System1: http://pastebin.com/4RxzPFeT
  • btrfs (-tools) est la version 3.17
  • lsblk -t /dev/sdf: http://pastebin.com/nv49tYWc

Pensées

  • L'alignement n'est pas la cause pour autant que je puisse voir. Même si la taille de page de la clé est de 16 Ko, le début de la charge utile de cryptsetup est de toute façon aligné sur 2 Mo.
  • --allow-discards (pour luksOpen de cryptsetup) n'a pas aidé, comme je m'y attendais.
  • En faisant beaucoup moins d'expériences avec lui, j'ai observé un comportement très similaire avec un disque dur externe, connecté via un adaptateur USB3.0.
  • Il me semble que le système écrit des blocs de 64 Ko. Un script systemtrap que j'ai essayé indique au moins cela. /sys/block/sdf/statsoutient cette hypothèse car de nombreuses écritures sont fusionnées. Donc, je suppose que l'écriture dans des blocs trop petits n'est pas la cause.
  • Pas de chance de changer le planificateur de file d'attente de périphérique de bloc en NOOP.
  • Mettre la crypte dans un volume LVM n'a pas aidé.
schlimmchen
la source
Vider le cache du disque avant chaque test l'éliminerait comme une raison possible de la vitesse (648 Mo / s ne semblent pas réalisables actuellement, en dehors du RAM)
Xen2050

Réponses:

18

La réponse (comme je le sais maintenant): la concurrence .

En bref : mon écriture séquentielle , en utilisant ddou lors de la copie d'un fichier (comme ... dans une utilisation quotidienne), devient une écriture pseudo-aléatoire (mauvaise) car quatre threads travaillent simultanément sur l'écriture des données chiffrées sur le périphérique de bloc après simultané cryptage (bon).

Atténuation (pour les noyaux "plus anciens")

L'effet négatif peut être atténué en augmentant le nombre de demandes en file d'attente dans la file d'attente du planificateur d'E / S comme suit:

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

Dans mon cas, cela triple presque (~ 56 Mo / s) le débit pour le test de données aléatoires de 4 Go expliqué dans ma question. Bien sûr, les performances sont toujours inférieures à 100 Mo / s par rapport aux E / S non chiffrées.

Enquête

Multicore blktrace

J'ai en outre étudié le scénario problématique dans lequel un btrfs est placé sur le dessus d'un périphérique de bloc crypté LUKS. Pour me montrer quelles instructions d'écriture sont envoyées au périphérique de bloc réel, j'ai utilisé blktracecomme ceci:

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

Ce que cela fait (pour autant que je puisse comprendre) trace les demandes d'E / S /dev/sdcauxquelles sont de type " écriture ", puis analyse ceci sur une sortie lisible par l'homme mais restreint davantage la sortie à l'action " D ", qui est (selon man blkparse) " IO délivré au conducteur ".

Le résultat était quelque chose comme ça (voir environ 5000 lignes de sortie du journal multicœur ):

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]
  • Colonne 1: majeur, mineur du périphérique bloc
  • Colonne 2: ID du processeur
  • Colonne 3: numéro de séquence
  • Colonne 4: horodatage
  • Colonne 5: ID de processus
  • Colonne 6: action
  • Colonne 7: données RWBS (type, secteur, longueur)

Il s'agit d'un extrait de la sortie produite pendant ddle chargement des données aléatoires de 4 Go sur le système de fichiers monté. Il est clair qu'au moins deux processus sont impliqués. Le journal restant montre que les quatre processeurs y travaillent réellement. Malheureusement, les demandes d'écriture ne sont plus ordonnées. Alors que CPU0 écrit quelque part autour du secteur 38038416th, CPU1, qui est prévu par la suite, écrit quelque part autour du secteur 35713872nd. C'est mauvais.

Singlecore blktrace

J'ai fait la même expérience après avoir désactivé le multithread et désactivé le deuxième cœur de mon processeur. Bien sûr, un seul processeur est impliqué dans l'écriture sur la clé. Mais plus important encore, les demandes d'écriture sont correctement séquentielles, c'est pourquoi les performances d'écriture complètes de ~ 170 Mo / s sont obtenues dans la même configuration.

Jetez un œil à environ 5 000 lignes de sortie dans le journal à un seul cœur .

Discussion

Maintenant que je connais la cause et les termes de recherche google appropriés, les informations sur ce problème remontent à la surface. Il s'avère que je ne suis pas le premier à le remarquer.

Corrigé dans les noyaux actuels (> = 4.0.2)

Parce que j'ai (plus tard) trouvé que la validation du noyau visait visiblement ce problème précis, je voulais essayer un noyau mis à jour. [Après l'avoir compilé moi-même et avoir découvert qu'il est déjà dedans debian/sid] Il s'avère que le problème est en effet résolu. Je ne connais pas la version exacte du noyau dans laquelle le correctif est apparu, mais le commit d'origine donnera des indices à toute personne intéressée.

Pour mémoire:

$ 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

Un petit chapeau à Mikulas Patocka, qui est l'auteur du commit.

schlimmchen
la source
1
J'utilise btrfs sur luks avec le noyau 4.12.12 et le ralentissement est toujours là!
brauliobo
pourquoi dites-vous que le ralentissement est toujours là? Quelle référence utilisez-vous pour ne pas avoir connu de ralentissement? quelle est votre configuration? avez-vous vérifié les performances du lecteur lorsque vous supprimez uniquement LUKS?
schlimmchen
a confirmé qu'il était toujours lié à LUKS unix.stackexchange.com/a/393521/39985
brauliobo
1
Maintenant, je comprends pourquoi vous écririez à propos de l'expérience d'un "ralentissement". Cependant, votre problème est simplement lié à celui-ci, ce n'est certainement pas le même problème (retard contre faible performance). J'éprouve également ces conneries ennuyeuses, donc je suis très reconnaissant que vous ayez signalé votre problème ici! Ne pas utiliser LUKS n'est pas une option, mais bon de savoir qu'il semble être lié à la cause.
schlimmchen