Abysmal general dm-crypt (LUKS) performance di scrittura


21

Sto studiando un problema in cui la crittografia di un dispositivo a blocchi impone un'enorme penalità di prestazione quando si scrive su di esso. Ore di lettura ed esperimenti su Internet non mi hanno fornito una comprensione adeguata, figuriamoci una soluzione.

La domanda in breve: perché ottengo velocità di scrittura perfettamente elevate quando inserisco un btrfs su un dispositivo a blocchi (~ 170 MB / s), mentre la velocità di scrittura precipita (~ 20 MB / s) quando inserisco un dm-crypt / LUKS tra file system e dispositivo a blocchi, sebbene il sistema sia più che in grado di sostenere un throughput di crittografia sufficientemente elevato?

Scenario

/home/schlimmchen/randomè un file da 4.0 GB pieno di dati /dev/urandomprecedenti.

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

Leggerlo è super veloce:

$ 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 seconda volta, il file è stato ovviamente letto dalla cache).

Btrfs non crittografato

Il dispositivo viene formattato direttamente con btrfs (nessuna tabella delle partizioni sul dispositivo a blocchi).

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

La velocità di scrittura arriva fino a ~ 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

La velocità di lettura è ben al di sopra di 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

Btrfs crittografato sul dispositivo a blocchi

Il dispositivo è formattato con LUKS e il dispositivo risultante è formattato con 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 velocità di lettura soffre solo marginalmente (perché lo fa affatto?):

$ 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 crittografato nel file su btrfs sul dispositivo a blocchi

La velocità di scrittura "sale alle stelle" a oltre 150 MB / s quando si scrive in un file crittografato. Ho messo un btrfs sul dispositivo a blocchi, ho assegnato un file da 16 GB, che ho lukfsFormateditato e montato.

$ 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

Perché le prestazioni di scrittura aumentano in questo modo? Che cosa ottiene questo particolare annidamento di filesystem e dispositivi a blocchi per aiutare ad alte velocità di scrittura?

Impostare

Il problema è riproducibile su due sistemi che eseguono la stessa distribuzione e kernel. Tuttavia, ho anche osservato le basse velocità di scrittura con il kernel 3.19.0 su System2.

  • Dispositivo: chiavetta USB 3.0 USB SanDisk Extreme da 64 GB
  • System1: Intel NUC 5i5RYH, i5-5250U (Broadwell), 8 GB di RAM, SSD Samsung 840 EVO da 250 GB
  • System2: Lenovo T440p, i5-4300M (Haswell), 16GB RAM, SSD Samsung 850 PRO 256GB
  • Distro / Kernel: Debian Jessie, 3.16.7
  • cryptsetup: 1.6.6
  • /proc/cryptoper System1: http://pastebin.com/QUSGMfiS
  • cryptsetup benchmarkper System1: http://pastebin.com/4RxzPFeT
  • btrfs (-tools) è la versione 3.17
  • lsblk -t /dev/sdf: http://pastebin.com/nv49tYWc

Pensieri

  • L'allineamento non è la causa per quanto posso vedere. Anche se la dimensione della pagina dello stick è di 16 KiB, l'inizio del payload di cryptsetup è comunque allineato a 2MiB.
  • --allow-discards (per luksOpen di cryptsetup) non ha aiutato, come mi aspettavo.
  • Mentre facevo molti meno esperimenti con esso, ho osservato un comportamento molto simile con un disco rigido esterno, collegato tramite un adattatore USB 3.0.
  • Mi sembra che il sistema stia scrivendo blocchi da 64 KiB. Uno script systemtrap che ho provato indica almeno questo. /sys/block/sdf/statsostiene questa ipotesi poiché molte scritture sono state unite. Quindi la mia ipotesi è che scrivere in blocchi troppo piccoli non sia la causa.
  • Nessuna fortuna con la modifica dello scheduler della coda dei dispositivi a blocchi su NOOP.
  • Mettere la cripta in un volume LVM non ha aiutato.

Svuotare la cache del disco prima di ogni test lo eliminerebbe come possibile ragione della velocità (648 MB / s suona attualmente irrealizzabile, al di fuori del ram)
Xen2050

Risposte:


18

La risposta (come ora so): concorrenza .

In breve : la mia scrittura sequenziale , utilizzando ddo durante la copia di un file (come ... nell'uso quotidiano), diventa una scrittura pseudo-casuale (errata) perché quattro thread stanno lavorando contemporaneamente sulla scrittura dei dati crittografati sul dispositivo a blocchi dopo la simultanea crittografia (buona).

Mitigazione (per i kernel "più vecchi")

L'effetto negativo può essere mitigato aumentando la quantità di richieste in coda nella coda dello scheduler IO in questo modo:

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

Nel mio caso, quasi triplica (~ 56 MB / s) il throughput per il test di dati casuali da 4 GB spiegato nella mia domanda. Ovviamente, le prestazioni sono ancora inferiori a 100 MB / s rispetto all'IO non crittografato.

Indagine

Multicore blktrace

Ho studiato ulteriormente lo scenario problematico in cui un btrfs è posizionato su un dispositivo a blocchi crittografato LUKS. Per mostrarmi quali istruzioni di scrittura vengono emesse sul dispositivo a blocchi reale, ho usato in blktracequesto modo:

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

Ciò che fa è (per quanto sono stato in grado di comprendere) tracciare richieste IO /dev/sdcdi tipo " scrittura ", quindi analizzarle in output leggibili dall'uomo, ma limitare ulteriormente l'output all'azione " D ", che è (secondo man blkparse) " IO rilasciato al conducente ".

Il risultato è stato qualcosa del genere (vedere circa 5000 righe di output del registro multicore ):

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]
  • Colonna 1: maggiore, minore del dispositivo a blocchi
  • Colonna 2: ID CPU
  • Colonna 3: numero progressivo
  • Colonna 4: data e ora
  • Colonna 5: ID processo
  • Colonna 6: azione
  • Colonna 7: dati RWBS (tipo, settore, lunghezza)

Questo è un frammento dell'output prodotto durante ddl'immissione dei dati casuali da 4 GB sul filesystem montato. È chiaro che sono coinvolti almeno due processi. Il registro rimanente mostra che tutti e quattro i processori ci stanno effettivamente lavorando. Purtroppo, le richieste di scrittura non sono più ordinate. Mentre CPU0 sta scrivendo da qualche parte nel settore 38038416, CPU1, che è programmato in seguito, sta scrivendo da qualche parte nel settore 35713872. Questo è male.

Single core blktrace

Ho fatto lo stesso esperimento dopo aver disabilitato il multi-threading e disabilitato il secondo core della mia CPU. Naturalmente, solo un processore è coinvolto nella scrittura sul bastone. Ma ancora più importante, le richieste di scrittura sono correttamente sequenziali, motivo per cui le prestazioni di scrittura complete di ~ 170 MB / s si ottengono nella stessa configurazione.

Dai un'occhiata a circa 5000 righe di output nel registro dei singoli file .

Discussione

Ora che conosco la causa e i termini di ricerca di Google appropriati, le informazioni su questo problema stanno gorgogliando in superficie. A quanto pare, non sono il primo a notare.

Risolto nei kernel correnti (> = 4.0.2)

Dato che (in seguito) ho scoperto che il commit del kernel ovviamente mirava a questo esatto problema, volevo provare un kernel aggiornato. [Dopo averlo compilato da solo e aver scoperto che è già in debian/sid] Si scopre che il problema è stato risolto. Non conosco la versione esatta del kernel in cui è apparsa la correzione, ma il commit originale fornirà indizi a chiunque sia interessato.

Per il record:

$ 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

Una punta di cappello a Mikulas Patocka, autore del commit.


1
Sto usando btrfs su luks con il kernel 4.12.12 e il rallentamento è ancora lì!
Brauliobo,

perché dici che il rallentamento è ancora lì? quale riferimento stai usando, quindi non hai riscontrato un rallentamento? qual è il tuo setup? hai controllato le prestazioni del disco rimuovendo solo LUKS?
schlimmchen,

ha confermato che è ancora collegato a LUKS unix.stackexchange.com/a/393521/39985
brauliobo

1
Ora capisco perché dovresti scrivere ancora sperimentando un "rallentamento". Tuttavia, il tuo problema è semplicemente correlato a questo, non è sicuramente lo stesso problema (in ritardo rispetto a basse prestazioni). Provo anche questi fastidiosi problemi, quindi sono molto grato che tu abbia sottolineato il tuo problema qui! Non usare LUKS non è un'opzione, ma è bene sapere che sembra essere correlato alla causa.
schlimmchen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.