Recorte con LVM y dm-crypt

21

Intenté configurar TRIM con LVM y dm-crypt en ubuntu 13.04 siguiendo este tutorial:

http://blog.neutrino.es/2013/howto-properly-activate-trim-for-your-ssd-on-linux-fstrim-lvm-and-dmcrypt/

Consulte las notas sobre mi configuración y mi procedimiento de prueba a continuación.

Preguntas

  1. ¿Existe una prueba confiable si TRIM funciona correctamente?

  2. ¿Mi rutina de prueba es incorrecta o mi TRIM no funciona?

  3. Si no funciona: ¿qué hay de malo en mi configuración?

  4. ¿Cómo puedo depurar TRIM para mi configuración y hacer que TRIM funcione?

Configuración

Aquí está mi configuración:

cat /etc/crypttab

sda3_crypt UUID=[...] none luks,discard

y

cat /etc/lvm/lvm.conf

# [...]
devices  {
      # [ ... ]
      issue_discards = 1
      # [ ... ]
   }
# [...]

El SSD es un Samsung 840 Pro.

Aquí está mi procedimiento de prueba

Para probar la configuración que acabo de hacer, sudo fstrim -v /que resultó en

/: [...] bytes were trimmed

Hacer esto nuevamente resultó en lo /: 0 bytes were trimmedque parece tener sentido e indicó que TRIM parece funcionar.

Sin embargo, entonces hice esta prueba:

dd if=/dev/urandom of=tempfile count=100 bs=512k oflag=direct

sudo hdparm --fibmap tempfile                                 

tempfile:
 filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors
           0    5520384    5521407       1024
      524288    5528576    5529599       1024
     1048576    5523456    5525503       2048
     2097152    5607424    5619711      12288
     8388608    5570560    5603327      32768
    25165824    5963776    5980159      16384
    33554432    6012928    6029311      16384
    41943040    6275072    6291455      16384
    50331648    6635520    6639615       4096

sync

sudo hdparm --read-sector 5520384 /dev/sda                    

/dev/sda:
reading sector 5520384: succeeded
7746 4e11 bf42 0c93 25d3 2825 19fd 8eda
bd93 8ec6 9942 bb98 ed55 87eb 53e1 01d5
c61a 3f52 19a1 0ae5 0798 c6e2 39d9 771a
b89f 3fc5 e786 9b1d 3452 d5d7 9479 a80d
114a 7528 a79f f475 57dc aeaf 25f4 998c
3dd5 b44d 23bf 77f3 0ad9 8688 6518 28ee
81db 1473 08b5 befe 8f2e 5b86 c84e c7d2
1bdd 1065 6a23 fd0f 2951 d879 e823 021b
fa84 b9c1 eadd 9154 c9f4 2ebe cd70 64ec
75a8 4d93 c8fa 3174 7277 1ffb e858 5eca
7586 8b2e 9dbc ab12 40ab eb17 8187 e67d
5e0d 0005 5867 b924 5cfd 6723 9e4a 6f5f
99a4 a3b0 eeac 454a 83b6 c528 1106 6682
ca77 4edf 2180 bf0c b175 fabb 3d4b 37e2
b834 9e3e 82f2 2fdd 2c6a c6ca 873f e71e
f979 160f 5778 356f 2aea 6176 46b6 72b9
f76e ee51 979c 326b 1436 7cfe f677 bfcd
4c3c 9e11 4747 45c1 4bb2 4137 03a1 e4c8
e9dd 43b4 a3b4 ce1b d218 4161 bf64 727b
75d8 dcc2 e14c ebec 2126 25da 0300 12bd
6b1a 28b3 824f 3911 c960 527d 97cd de1b
9f08 9a8e dcdc e65f 1875 58ca be65 82bf
e844 50b8 cc1b 7466 58b8 e708 bd3d c01f
64fb 9317 a77a e43b 671f e1fb e328 93a9
c9c7 291c 56e0 c6c1 f011 b94d 9dc7 71e6
c8b1 5720 b8c9 b1a6 14f1 7299 9122 912b
312a 0f2f a31a 8bf9 9f8c 54e6 96f3 60b8
04a7 7dc9 3caa db0a a837 e5d7 2752 b477
c22d 7598 44e1 84e9 25d4 5db5 9f19 f73b
85a0 c656 373a ec34 55fb e1fc 124e 4674
1ba8 1a84 6aa4 7cb5 455e f416 adc6 a125
c4d4 8323 4eee 2493 2920 4e38 524c 1981

sudo rm tempfile

sync

sudo fstrim /

sync

sudo hdparm --read-sector 5520384 /dev/sda

/dev/sda:
reading sector 5520384: succeeded
7746 4e11 bf42 0c93 25d3 2825 19fd 8eda
bd93 8ec6 9942 bb98 ed55 87eb 53e1 01d5
c61a 3f52 19a1 0ae5 0798 c6e2 39d9 771a
b89f 3fc5 e786 9b1d 3452 d5d7 9479 a80d
114a 7528 a79f f475 57dc aeaf 25f4 998c
3dd5 b44d 23bf 77f3 0ad9 8688 6518 28ee
81db 1473 08b5 befe 8f2e 5b86 c84e c7d2
1bdd 1065 6a23 fd0f 2951 d879 e823 021b
fa84 b9c1 eadd 9154 c9f4 2ebe cd70 64ec
75a8 4d93 c8fa 3174 7277 1ffb e858 5eca
7586 8b2e 9dbc ab12 40ab eb17 8187 e67d
5e0d 0005 5867 b924 5cfd 6723 9e4a 6f5f
99a4 a3b0 eeac 454a 83b6 c528 1106 6682
ca77 4edf 2180 bf0c b175 fabb 3d4b 37e2
b834 9e3e 82f2 2fdd 2c6a c6ca 873f e71e
f979 160f 5778 356f 2aea 6176 46b6 72b9
f76e ee51 979c 326b 1436 7cfe f677 bfcd
4c3c 9e11 4747 45c1 4bb2 4137 03a1 e4c8
e9dd 43b4 a3b4 ce1b d218 4161 bf64 727b
75d8 dcc2 e14c ebec 2126 25da 0300 12bd
6b1a 28b3 824f 3911 c960 527d 97cd de1b
9f08 9a8e dcdc e65f 1875 58ca be65 82bf
e844 50b8 cc1b 7466 58b8 e708 bd3d c01f
64fb 9317 a77a e43b 671f e1fb e328 93a9
c9c7 291c 56e0 c6c1 f011 b94d 9dc7 71e6
c8b1 5720 b8c9 b1a6 14f1 7299 9122 912b
312a 0f2f a31a 8bf9 9f8c 54e6 96f3 60b8
04a7 7dc9 3caa db0a a837 e5d7 2752 b477
c22d 7598 44e1 84e9 25d4 5db5 9f19 f73b
85a0 c656 373a ec34 55fb e1fc 124e 4674
1ba8 1a84 6aa4 7cb5 455e f416 adc6 a125
c4d4 8323 4eee 2493 2920 4e38 524c 1981

Esto parece indicar que TRIM no funciona. Ya que

sudo hdparm -I /dev/sda | grep -i TRIM                        
       *    Data Set Management TRIM supported (limit 8 blocks)
       *    Deterministic read ZEROs after TRIM

Editar

Aquí está la salida de sudo dmsetup table

lubuntu--vg-root: 0 465903616 linear 252:0 2048
lubuntu--vg-swap_1: 0 33308672 linear 252:0 465905664
sda3_crypt: 0 499222528 crypt aes-xts-plain64 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0 8:3 4096 1 allow_discards

Aquí está mi /etc/fstab:

# <file system> <mount point>   <type>  <options>       <dump>  <pass>
/dev/mapper/lubuntu--vg-root /               ext4    errors=remount-ro 0       1
# /boot was on /dev/sda2 during installation
UUID=f700d855-96d0-495e-a480-81f52b965bda /boot           ext2    defaults        0       2
# /boot/efi was on /dev/sda1 during installation
UUID=2296-2E49  /boot/efi       vfat    defaults        0       1
/dev/mapper/lubuntu--vg-swap_1 none            swap    sw              0       0
# tmp
tmpfs /tmp tmpfs nodev,nosuid,noexec,mode=1777          0       0 

Editar:

Finalmente lo informé como un error en https://bugs.launchpad.net/ubuntu/+source/lvm2/+bug/1213631

Espero que alguien encuentre una solución allí o al menos pruebe la configuración y verifique el error.

Actualizar

Ahora funciona, ver respuesta aceptada.

estudiante
fuente
LVM parece faltar los descartes, debe ser issue_discardsno issue discardssi eso no era un error tipográfico. allow_discardsdebería aparecer en la tabla dmsetup para las particiones LVM.
frostschutz
Lo siento, esto fue un error tipográfico. Tengo issue_discards = 1en mi archivo de configuración.
estudiante
Si fuera usted, trataría de usar un objetivo iSCSI y probarlo a través de tcpdump / wireshark para ver si la configuración funciona, aunque no sé si el objetivo iSCSI de Linux admite recortar o no. Creo que dm-crypt no debería dejar en blanco los bloques en el disco físico porque eso hace que sea más fácil ignorar el espacio libre en el dispositivo al intentar forzarlo (no sé si lo hace o no) ) Además, no se requiere que los SSD devuelvan ceros después de la supresión, ya que la nivelación de desgaste puede redirigir la lectura a un bloque diferente al que está en blanco.
Didi Kohen
1
De acuerdo con bugzilla.redhat.com/show_bug.cgi?id=958096 no entendí el issue_discards = 1.
frostschutz

Respuestas:

23

Sugiero usar un método de prueba diferente. hdparmes un poco extraño ya que proporciona direcciones de dispositivo en lugar de direcciones de sistema de archivos, y no dice con qué dispositivo se relacionan esas direcciones (por ejemplo, resuelve particiones, pero no objetivos de mapeador de dispositivos, etc.). Es mucho más fácil usar algo que se adhiere a las direcciones del sistema de archivos, de esa manera es consistente (tal vez excepto para sistemas de archivos no tradicionales como zfs / btrfs).

Crear un archivo de prueba: (no aleatorio a propósito)

# yes | dd iflag=fullblock bs=1M count=1 of=trim.test 

Obtenga la dirección, longitud y tamaño de bloque: (el comando exacto depende de la filefragversión)

# filefrag -s -v trim.test
File size of trim.test is 1048576 (256 blocks, blocksize 4096)
 ext logical physical expected length flags
   0       0    34048             256 eof
trim.test: 1 extent found

Obtenga el dispositivo y el punto de montaje:

# df trim.test
/dev/mapper/something  32896880 11722824  20838512   37% /mount/point

Con esta configuración, tiene un archivo trim.testlleno con yes-pattern on /dev/mapper/somethingat address 34048con longitud de 256bloques de 4096bytes.

Leer eso desde el dispositivo directamente debería producir el yespatrón:

# dd bs=4096 skip=34048 count=256 if=/dev/mapper/something | hexdump -C
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
00100000

Si TRIM está habilitado, este patrón debería cambiar cuando elimine el archivo. Tenga en cuenta que las memorias caché también deben eliminarse, de lo contrario ddno volverá a leer los datos del disco.

# rm trim.test
# sync
# fstrim -v /mount/point/ # when not using 'discard' mount option
# echo 1 > /proc/sys/vm/drop_caches
# dd bs=4096 skip=34048 count=256 if=/dev/mapper/something | hexdump -C

En la mayoría de los SSD, el resultado sería un patrón cero:

00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00100000

Si el cifrado está involucrado, verá un patrón aleatorio en su lugar:

00000000  1f c9 55 7d 07 15 00 d1  4a 1c 41 1a 43 84 15 c0  |..U}....J.A.C...|
00000010  24 35 37 fe 05 f7 43 93  1e f4 3c cc d8 83 44 ad  |$57...C...<...D.|
00000020  46 80 c2 26 13 06 dc 20  7e 22 e4 94 21 7c 8b 2c  |F..&... ~"..!|.,|

Eso es porque físicamente recortado, la capa criptográfica lee ceros y descifra esos ceros a datos "aleatorios".

Si el yespatrón persiste, lo más probable es que no se haya recortado.

Frostschutz
fuente
1
@student: Me siento mal por no notar esto antes, edité la respuesta para soltar cachés antes hexdump.
frostschutz
1
Gracias, ese era el punto perdido. ¡Ahora parece funcionar!
estudiante
2
Todavía no estoy seguro de si el núcleo no debería soltar cachés por sí solo cada vez que recorta algo en un SSD. Se supone que los cachés no devuelven datos incorrectos. También es un desperdicio de memoria caché si está ocupado por algo que ya no está allí ... oh, bueno.
frostschutz
1
@frostschutz Gracias por esta gran solución. Hice un script para automatizar el proceso si alguna persona perezosa viene aquí.
desgua
1
Recién llegados , tengan en cuenta que el comando TRIM no siempre "rellenará con ceros" los bloques de inmediato. Mira aquí , aquí y aquí . Aunque debería, en el caso de OP, ya que su hdparm -Iresultado indica "CERO de lectura determinista después de TRIM".
Marc.2377
3

Su rutina de prueba es incorrecta: está obteniendo números de sector relativos al dispositivo de bloque en el que se encuentra el sistema de archivos, que en este caso es un volumen lógico. El volumen lógico, por supuesto, no comienza en el primer sector del volumen físico (y puede que ni sea contiguo).

Incluso si el volumen lógico comenzó en el sector 0 del volumen físico (que no lo hace), entonces el volumen físico es en realidad otro objetivo del mapeador de dispositivos, este para el cifrado. Y probablemente haya un encabezado LUKS al frente, por lo que los números de sector tampoco coinciden allí.

Si desea trabajar mediante la asignación del número de sector al disco subyacente, dmsetup tablesle dará la información que necesita. Si lo pega aquí, asegúrese de que la suya sea una versión que no muestre la clave en la salida (¡debería mostrar todos los 0 en su lugar)! (No hay recuperación de revelar el número- no se puede cambiar -Es mucho peor que la divulgación de la contraseña).

Sugiero que para depurar (una vez que se haya resuelto el mapeo del sector) comience en el nivel más bajo y confirme que funciona allí. CORTE un sistema de archivos directamente en / dev / sdaX y asegúrese de que funcione (es muy posible que el dispositivo mienta y el corte no lea ceros de nuevo). Luego dm-crypt además de eso, y recorte un sistema de archivos en eso, y asegúrese de que funcione. Finalmente, coloque LVM en la parte superior y verifique que funcione.

derobert
fuente
@student OK, ese es el sector equivocado (los dos primeros párrafos de mi respuesta). Editaré mi respuesta para eliminar esa oración sobre el sector 6575104, ya que ya no es relevante.
derobert
No estoy seguro de qué dispositivo debo tomar dmsetup. Acabo de hacerlo: lo sudo dmsetup table /dev/mapper/lubuntu--vg-rootque da0 465903616 linear 252:0 2048
estudiante
@student Eso significa que el sector 0 está en el sector 2048 en el dispositivo 252: 0. Tendrás que descubrir qué es 252: 0, supongo que es tu dispositivo criptográfico dm (ese es el número mayor y menor, por ejemplo, aparecerá en / dev). Y deberá mirar la tabla de ese dispositivo, para continuar persiguiéndolo hasta un bloque en un dispositivo subyacente.
derobert
3

Este es solo un guión que me gustaría compartir si alguna persona perezosa viene aquí. Fue hecho de la respuesta aceptada de frostschutz .

#! / bin / bash
# #
# Este script se proporciona "tal cual" sin garantía de ningún tipo, ya sea expresa o implícita, incluidas, entre otras, las garantías implícitas de comerciabilidad, idoneidad para un propósito particular o no infracción.
# #
# Licencia GPL2
# #
# por desgua 29/04/2014

función LIMPIAR {
cd "$ pasta"
[-f test-trim-by-desgua] && rm test-trim-by-desgua && echo "Archivo temporal eliminado"
echo "Adios"
salida 0
}

trampa 'eco; echo "Abortado". ; LIMPIAR; eco ; salida 0 'INT HUP

if [["$ (echo $ USER)"! = "root"]]; luego

leer -n 1 -p '¿Convertirse en root? [S / n] 'a
    si [[$ a == "Y" || $ a == "y" || $ a == ""]]; luego
        sudo $ 0 $ 1
        salida 0
    más
        eco "
        Este script necesita privilegios de root.
        "
        salida 1

    fi

fi


nombre = $ (echo $ 0 | sed 's /.*\///')
si [$ # -ne 1]; luego

eco "
Uso: $ nombre / carpeta / a / prueba /

"
salida 1
fi

pasta = $ 1

leer -n 1 -p '¿Usar fstrim? [s / N] 'a
si [[$ a == "Y" || $ a == "y"]]; luego
    fs = 1
fi

método =
while [["$ method"! = "1" && "$ method"! = "2"]]; hacer
read -n 1 -s -p 'Elija un método:
[1] hdparm (fallará en LUKS en LVM)
[2] filefrag (advertencia: puede que tenga que forzar el cierre, cierre el terminal, en algunos casos de recorte exitoso si ve una salida que nunca termina) 
'método
hecho

función SDATEST {
disco = $ (fdisk -l | grep / dev / sda)
if ["$ disk" == ""]; luego
eco "
fdisk no encontró / dev / sda 
"
salida 1
fi
}

prueba de funcionamiento {
echo "Entrada /"; eco
cd $ pasta
echo "Creando el archivo test-trim-by-desgua en $ pasta"; eco
dd if = / dev / urandom of = test-trim-by-desgua count = 10 bs = 512k
echo "Sincronizando y durmiendo 2 segundos". ; eco
sincronizar
dormir 2

hdparm --fibmap test-trim-by-desgua
lbab = $ (hdparm --fibmap test-trim-by-desgua | tail -n1 | awk '{print $ 2}')

echo "Como puede ver, el archivo fue creado y su LBA comienza en $ lbab"; eco

echo "Sincronizando y durmiendo 2 segundos". ; eco
sincronizar
dormir 2

echo "Eliminando el archivo test-trim-by-desgua"; eco
rm test-trim-by-desgua

trampa 'eco; eco ; echo "Abortado". ; eco ; salida 0 'INT
echo "Sincronizando y durmiendo 2 segundos". ; eco
sincronizar
dormir 2

si [["$ fs" == "1"]]; luego
    echo "fstrim $ pasta && sleep 2"; eco
    fstrim $ pasta
    dormir 2
fi

echo "Esto se lee del sector $ lbab:"
hdparm --read-sector $ lbab / dev / sda

pass = $ (hdparm --read-sector $ lbab / dev / sda | grep "0000 0000 0000 0000")

si [[$ pass == ""]]; luego
    eco "
El ajuste falló ... 
Debería ver solo 0000 0000 0000 0000 ...
"
más
    echo "¡Éxito!"
fi
salida 0

}

función LUKSTEST {
# Referencia: /unix/85865/trim-with-lvm-and-dm-crypt#
echo 1> / proc / sys / vm / drop_caches
cd $ pasta
echo "Creando un \" yes \ "archivo".
si | dd iflag = fullblock bs = 1M count = 1 of = test-trim-by-desgua

# position = `filefrag -s -v test-trim-by-desgua | grep "eof" | awk '{print $ 3}' '
position = `filefrag -s -v test-trim-by-desgua | grep "eof" | sed | || g; s |. * 255: || ; s | \. \ .. * || ''
[["$ position" == ""]] && echo "No se pudo encontrar la posición del archivo. ¿Estás en un LUKS en LVM?" && LIMPIO;

dispositivo = `df test-trim-by-desgua | grep "dev /" | awk '{print $ 1}' '

yes = `dd bs = 4096 skip = $ position count = 256 if = $ device | hexdump -C`

echo "En la siguiente línea debería ver un patrón como: 
00000000 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a | aaaaaaaa |
$ si
"

if [["` echo "$ yes" | grep "aaa" `" == ""]]; luego
    echo "No se pudo comprobar el patrón. Algo salió mal. Saliendo".
    LIMPIAR;
más
    echo "Patrón confirmado".
fi

echo "Eliminando el archivo temporal". 
rm test-trim-by-desgua

echo "Sincronización".
sincronizar
dormir 1

si [["$ fs" == "1"]]; luego
    echo "fstrim -v $ pasta && sleep 2"; eco
    fstrim -v $ pasta
    dormir 2
fi

# Drop cache
echo 1> / proc / sys / vm / drop_caches

echo "En la siguiente línea deberías ** NO ** ver un patrón sí como: 
00000000 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a | aaaaaaaa | 
Si ve, entonces recortar no funciona:
`dd bs = 4096 skip = $ recuento de posición = 256 if = $ dispositivo | hexdump -C` "

yes = `dd bs = 4096 skip = $ position count = 256 if = $ device | hexdump -C`
if [["` echo "$ yes" | grep "aaa" `"! = ""]]; luego
    echo "TRIM no funciona".
más
    echo "TRIM está funcionando!"
fi
LIMPIAR;
}

if [["$ method" == "1"]]; luego
    SDATEST;
    PRUEBA;
elif [["$ método" == "2"]]; luego
    LUKSTEST;
fi
salida 0

desgua
fuente