Отделка с LVM и дм-криптом

21

Я попытался настроить TRIM с LVM и dm-crypt в Ubuntu 13.04, следуя этому руководству:

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

См. Примечания о моей конфигурации и моей процедуре тестирования ниже.

Вопросов

  1. Есть ли надежный тест, если TRIM работает правильно?

  2. Моя тестовая процедура неверна или TRIM не работает?

  3. Если не работает: что не так с моей настройкой?

  4. Как я могу отладить TRIM для моей установки и заставить работать TRIM?

конфигурация

Вот моя конфигурация:

cat /etc/crypttab

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

а также

cat /etc/lvm/lvm.conf

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

SSD - это Samsung 840 Pro.

Вот моя тест-процедура

Чтобы проверить настройку, которую я только что сделал, sudo fstrim -v /что привело к

/: [...] bytes were trimmed

Выполнение этого снова привело к тому, /: 0 bytes were trimmedчто, кажется, имеет смысл и указало, что TRIM, кажется, работает.

Однако тогда я сделал этот тест:

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

Кажется, это указывает на то, что TRIM не работает. поскольку

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

редактировать

Вот вывод 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

Вот мой /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 

Редактировать:

Я наконец сообщил об этом как об ошибке в https://bugs.launchpad.net/ubuntu/+source/lvm2/+bug/1213631

Надеюсь, что кто-нибудь найдет решение или, по крайней мере, протестирует установку и подтвердит ошибку.

Обновить

Теперь это работает, смотрите принятый ответ.

ученик
источник
LVM , кажется, отсутствует выброс рыбы, должен быть issue_discardsне , issue discardsесли это не опечатка. allow_discardsдолжен появиться в таблице dmsetup для разделов LVM.
frostschutz
Извините, это была опечатка. У меня есть issue_discards = 1в моем конфигурационном файле.
студент
На вашем месте я бы попытался использовать цель iSCSI и протестировать ее с помощью tcpdump / wireshark, чтобы проверить, работает ли установка, хотя я не знаю, поддерживает ли цель Linux iSCSI обрезку или нет. Я действительно считаю, что dm-crypt не должен очищать блоки на физическом диске, потому что это облегчает игнорирование свободного места на устройстве при попытке перебора (я не знаю, делает ли это это или нет, хотя ). Кроме того, твердотельные накопители не обязаны возвращать нули после гашения, поскольку выравнивание износа может перенаправить считывание в другой блок, чем в бланкированный.
Диди Кохен
1
Согласно bugzilla.redhat.com/show_bug.cgi?id=958096, я неправильно понял Issue_Discards = 1.
frostschutz

Ответы:

23

Я предлагаю использовать другой метод тестирования. hdparmэто немного странно, поскольку он дает адреса устройств, а не адреса файловой системы, и не говорит, к какому устройству относятся эти адреса (например, он разрешает разделы, но не цели устройства и т. д.). Гораздо проще использовать то, что привязано к адресам файловой системы, таким образом, это согласованно (возможно, за исключением нетрадиционных файловых систем, таких как zfs / btrfs).

Создать тестовый файл: (не случайно)

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

Получить адрес, длину и размер блока: (точная команда зависит от filefragверсии)

# 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

Получите устройство и точку монтирования:

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

С этой настройкой у вас есть файл, trim.testзаполненный yes-pattern on /dev/mapper/somethingпо адресу 34048с длиной 256блоков 4096байтов.

Чтение этого непосредственно с устройства должно привести к yes-pattern:

# 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

Если TRIM включен, этот шаблон должен измениться при удалении файла. Обратите внимание, что кэши также необходимо удалить, иначе ddони не будут перечитывать данные с диска.

# 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

На большинстве SSD это приведет к нулевому шаблону:

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

Если используется шифрование, вы увидите случайный шаблон:

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..&... ~"..!|.,|

Это связано с тем, что физически обрезанный криптослой считывает нули и дешифрует эти нули до «случайных» данных.

Если yes-pattern сохраняется, скорее всего, обрезка не была выполнена.

frostschutz
источник
1
@student: Мне плохо из-за того, что я не заметил этого раньше, отредактировал ответ для удаления кешей раньше hexdump.
frostschutz
1
Спасибо, это был упущенный момент. Теперь это похоже на работу!
студент
2
Я до сих пор не уверен, что ядро ​​не должно сбрасывать кэши, когда оно что-то урезает на SSD. Кэши не должны возвращать неверные данные. Это также бесполезная трата кеш-памяти, если она занята чем-то, чего больше нет ... о, хорошо.
frostschutz
1
@frostschutz Спасибо за это отличное решение. Я сделал скрипт для автоматизации процесса, если сюда придет какой-нибудь ленивый человек.
Desgua
1
Новички , обратите внимание, что команда TRIM не всегда сразу "обнуляет" блоки. Смотрите здесь , здесь и здесь . Хотя в случае OP это должно hdparm -Iпроизойти , поскольку его результат указывает на «детерминированные чтения нулей после TRIM».
23
3

Ваша процедура тестирования неверна - вы получаете номера секторов относительно блочного устройства, на котором находится файловая система, - который в данном случае является логическим томом. Логический том, конечно, не начинается с первого сектора физического тома (и может даже не быть смежным).

Даже если логический том начинался в секторе 0 физического тома (чего он не делает), то физический том на самом деле является еще одной целью сопоставления устройств, в том числе для шифрования. И, вероятно, впереди есть заголовок LUKS, поэтому номера секторов там тоже не совпадают.

Если вы хотите выполнить сопоставление номера сектора с базовым диском, dmsetup tablesвам предоставят необходимую информацию. Если вы вставите его сюда, убедитесь, что у вас есть версия, которая не показывает ключ в выводе (вместо него должны быть показаны все 0)! (Нет восстановления после раскрытия ключа - его нельзя изменить - это намного хуже, чем раскрытие пароля).

Я предлагаю, чтобы для отладки (как только вы установили отображение сектора) вы начинаете с самого низкого уровня и подтверждаете, что он работает там. TRIM файловой системы непосредственно в / dev / sdaX и убедитесь, что она работает (вполне возможно, что устройство лежит, а trim не считывает нули). Затем добавьте dm-crypt, подрежьте файловую систему и убедитесь, что она работает. Наконец, поместите LVM сверху и проверьте, что работает.

derobert
источник
@student Хорошо, тогда это не тот сектор (первые два абзаца моего ответа). Я отредактирую свой ответ, чтобы удалить это предложение о секторе 6575104, так как оно больше не актуально.
Дероберт
Я не уверен, какое устройство мне взять dmsetup. Я только что сделал: sudo dmsetup table /dev/mapper/lubuntu--vg-rootчто дает0 465903616 linear 252:0 2048
студент
@student Это означает, что сектор 0 находится в секторе 2048 на устройстве 252: 0. Вы должны выяснить, что такое 252: 0, я думаю, это ваше крипто-устройство dm (это старшее и младшее число, например, появится в / dev). И вам нужно будет посмотреть на таблицу для этого устройства, чтобы продолжить поиск его в блоке на базовом устройстве.
Дероберт
3

Это всего лишь сценарий, которым я хотел бы поделиться, если сюда придет какой-нибудь ленивый человек. Это было сделано из принятого ответа от frostschutz .

#! / Bin / Баш
#
# Этот сценарий предоставляется «как есть» без каких-либо явных или подразумеваемых гарантий, включая, помимо прочего, подразумеваемые гарантии товарной пригодности, пригодности для конкретной цели или отсутствия нарушений.
#
# Лицензия GPL2
#
# by desgua 2014/04/29

функция CLEAN {
cd "$ pasta"
[-f test-trim-by-desgua] && rm test-trim-by-desgua && echo "Удален временный файл"
эхо "До свидания"
выход 0
}

ловушка эхо; эхо "Прервано". ; ОЧИСТКА; эхо; выход 0 'INT HUP

if [["$ (echo $ USER)"! = "root"]]; тогда

read -n 1 -p 'Стать пользователем root? [Да / Нет] 'а
    если [[$ a == "Y" || $ a == "y" || $ a == ""]]; тогда
        sudo $ 0 $ 1
        выход 0
    еще
        эхо "
        Этот скрипт нуждается в привилегии суперпользователя.
        "
        выход 1

    фи

фи


name = $ (echo $ 0 | sed 's /.*\///')
if [$ # -ne 1]; тогда

эхо "
Использование: $ name / folder / to / test /

"
выход 1
фи

макаронные изделия = $ 1

read -n 1 -p 'Использовать fstrim? [y / N] 'a
если [[$ a == "Y" || $ a == "y"]]; тогда
    фс = 1
фи

метод =
while [["$ method"! = "1" && "$ method"! = "2"]]; делать
read -n 1 -s -p 'Выберите метод:
[1] hdparm (потерпит неудачу в LUKS на LVM)
[2] filefrag (предупреждение: вам может потребоваться принудительно завершить работу - закрыть терминал - в некоторых случаях обрезки при успехе, если вы видите вывод, который никогда не заканчивается) 
метод
сделанный

function SDATEST {
диск = $ (fdisk -l | grep / dev / sda)
if ["$ disk" == ""]; тогда
эхо "
fdisk не найден / dev / sda 
"
выход 1
фи
}

function TEST {
эхо "Вступление /"; эхо
паста cd $
echo "Создание файла test-trim-by-desgua в $ pasta"; эхо
дд если = / dev / urandom of = тест-обрезка по счетчику = 10 bs = 512k
echo "Синхронизация и сон 2 секунды". ; эхо
синхронизация
спать 2

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

echo "Как видите, файл создан и его LBA начинается с $ lbab"; эхо

echo "Синхронизация и сон 2 секунды". ; эхо
синхронизация
спать 2

echo "Удаление файла test-trim-by-desgua"; эхо
rm test-trim-by-desgua

ловушка эхо; эхо; эхо "Прервано". ; эхо; выход 0 'INT
echo "Синхронизация и сон 2 секунды". ; эхо
синхронизация
спать 2

if [["$ fs" == "1"]]; тогда
    echo "fstrim $ pasta && sleep 2"; эхо
    fstrim $ pasta
    спать 2
фи

echo "Это прочитано из сектора $ lbab:"
hdparm - начальный сектор $ lbab / dev / sda

pass = $ (hdparm - начальный сектор $ lbab / dev / sda | grep "0000 0000 0000 0000")

if [[$ pass == ""]]; тогда
    эхо "
Подрезать не удалось ... 
Вы должны видеть только 0000 0000 0000 0000 ...
"
еще
    эхо "Удачи !!!"
фи
выход 0

}

функция LUKSTEST {
# Ссылка: /unix/85865/trim-with-lvm-and-dm-crypt#
echo 1> / proc / sys / vm / drop_caches
паста cd $
echo "Создание файла" да "."
да | dd iflag = полный блок 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 's | || г; s | * 255:. || ; s |. \ \ .. * || ''
[["$ position" == ""]] && echo "Не удалось найти позицию файла. Вы в LUKS на LVM?" && CLEAN;

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

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

echo "В следующей строке вы должны увидеть такой шаблон: 
00000000 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a | гггггггг |
$ да
"

if [["` echo "$ yes" | grep "yyy" `" == ""]]; тогда
    echo "Шаблон не может быть проверен. Что-то пошло не так. Выход."
    ОЧИСТКА;
еще
    эхо "Шаблон подтвержден".
фи

echo "Удаление временного файла." 
rm test-trim-by-desgua

эхо "Синхронизация".
синхронизация
спать 1

if [["$ fs" == "1"]]; тогда
    echo "fstrim -v $ pasta && sleep 2"; эхо
    fstrim -v $ pasta
    спать 2
фи

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

echo "В следующей строке вы ** ** не должны видеть шаблон" да ", например: 
00000000 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a 79 0a | гггггггг | 
Если вы видите, то обрезка не работает:
`dd bs = 4096 skip = $ position count = 256 if = $ device | hexdump -C` "

yes = `dd bs = 4096 skip = $ position count = 256 if = $ device | hexdump -C`
if [["` echo "$ yes" | grep "yyy" `"! = ""]]; тогда
    эхо "TRIM не работает."
еще
    эхо "ТРИМ работает!"
фи
ОЧИСТКА;
}

if [["$ method" == "1"]]; тогда
    SDATEST;
    ТЕСТ;
elif [["$ method" == "2"]]; тогда
    LUKSTEST;
фи
выход 0

desgua
источник