В последнее время громадную популярность завоевали т.н. твердотельные накопители (Solid State Drives, SSD). Для простого пользователя они представляют особый интерес тем, что позволяют значительно расширить «бутылочное горлышко» производительности системы, которая упирается в быстродействие жёстких дисков. SSD потребительского класса по скорости чтения/записи превосходят жёсткие диски в несколько раз, а в некоторых задачах — даже на порядок.
Да, нынешние SSD уже готовы заменить жёсткие диски на десктопах и в ноутбуках в полной мере, но не для всех пользователей это приемлемо, и причин этому несколько. Во-первых, вызывает вопросы та самая надёжность. Тут обычно спасают бекапы, главное — вовремя их делать. Вторая причина связана с конфиденциальностью. Если на HDD использование LUKS не вызывает вопросов, то на SSD включение TRIM понижает защищённость информации. Без TRIM же есть шансы просадить производительность дисковых операций.
Ещё одна сфера использования SSD — кеширование дискового ввода-вывода. Не ставя под угрозу сохранность информации, можно значительно повысить скорость доступа к ней. Причём это осуществимо без остановки рабочей станции или сервера, что предотвращает нежелательные потери времени.
Для операционной системы Linux представлено несколько технологий кеширования данных на SSD — bcache, EnhanceIO, dm-cache и т.п. Использование их позволяет ощутить прирост быстродействия дисковых операций, при этом надёжность функционирования системы хранения данных останется на прежнем уровне.
В любом случае, выбор технологии остаётся за конечным пользователем (всё зависит от преследуемой цели), моя задача — показать в этой статье, как организовывается кеширование данных на SSD с помощью EnhanceIO.
Почему EnhanceIO? Во-первых, эта технология базируется на наработках проекта flashcache, опробованного в Facebook, что само по себе уже о чём-то свидетельствует. Во-вторых, EnhanceIO позволяет включать и выключать кеширование без остановки системы, а также подключать SSD к отдельным разделам или к диску в целом в качестве кеша прямо «на лету». К недостаткам EnhanceIO относится то, что наработки этого проекта ещё не включены в ядро, однако собрать его самостоятельно не составит труда.
Более того, можно воспользоваться либо патчем pf-kernel (начиная с версии 3.8.1-pf), если нет желания перебирать исходный код ядра руками, либо вообще загрузить готовые бинарные сборки и протестировать EnhanceIO, не запуская компилятор.
Тем не менее, исходный код проекта EnhanceIO доступен на github. Оттуда мы его и стянем:
git clone git://github.com/stec-inc/EnhanceIO.git
В каталоге EnhanceIO обнаружится несколько подкаталогов и файлов. В каталоге CLI расположена консольная утилита для управления EnhanceIO. В каталоге Driver — собственно код драйвера (модуля ядра). В каталог Documents разработчики поместили шаблон правила для udev, оно нам нужно для того, чтобы кеш автоматически включался при появлении соответствующих устройств.
Опытный пользователь без труда соберёт ядро самостоятельно, обычному же пользователю стоит либо обратиться к соответствующему руководству, либо пропустить этот шаг, воспользовавшись готовыми сборками pf-kernel для нескольких дистрибутивов. Тем же, кто таки решится собирать ядро самостоятельно, рекомендуется к прочтению файл Install.txt — всё, что нужно сделать, это скопировать каталог с модулем в дерево исходный кодов ядра и применить небольшой патчик, модифицирующий систему сборки так, чтобы она увидела этот новый модуль. Если будут вопросы конкретно по компиляции ядра, готов ответить на них лично.
Кроме того, недавно разработчики добавили возможность собирать модули EnhanceIO с помощью dkms. Это позволяет вообще не заниматься компилированием ядра. Нужный файл dkms.conf также находится в подкаталоге Driver/enhanceio.
Всем же пользователям нужно будет из каталога CLI скопировать консольную утилиту eio_cli в /usr/local/sbin (а не в /sbin, это чтобы не засорять системные каталоги внепакетными файлами):
cp CLI/eio_cli /usr/local/sbin
исправить используемую версию Python'а (по крайней мере, в Arch Linux), заменив начальную строчку в этом файле на
#!/usr/bin/python2.7
а потом исправить права доступа:
chown root:root /usr/local/sbin/eio_cli
chmod 755 /usr/local/sbin/eio_cli
Дальнейшие манипуляции опробованы в дистрибутиве Arch Linux, в иных дистрибутивах что-то может отличаться в деталях, но в целом действия будут одни и те же.
Итак, предположим, что жёсткий диск видится в системе как устройство /dev/sda, а SSD — как устройство /dev/sdb. Скопируем файл Documents/94-Enhanceio.template в /etc/udev/rules.d/94-enhanceio-sda.rules:
cp Documents/94-Enhanceio.template /etc/udev/rules.d/94-enhanceio-sda.rules
и откроем его на редактирование:
vim /etc/udev/rules.d/94-enhanceio-sda.rules
В этом файле нужно заменить несколько шаблонных вставок. <cache_match_expr>
заменяем на это:
ENV{ID_SERIAL}=="<ID SERIAL OF YOUR CACHE DEVICE>", ENV{DEVTYPE}=="<DEVICE TYPE OF YOUR CACHE DEVICE>"
Здесь в свою очередь нужно заменить вставки <ID SERIAL OF YOUR CACHE DEVICE>
и <DEVICE TYPE OF YOUR CACHE DEVICE>
на идентификаторы SSD. Их можно узнать командой:
$ udevadm info --query=env --name=/dev/sdb
К слову, правило определения можно составить самостоятельно. Это может понадобиться, если кеширующие (или кешируемые) разделы зашифрованы. У меня правило вместо ID_SERIAL содержит DM_UUID.
Аналогичные действия следует выполнить для <source_match_expr>
, только подставлять нужно значения для жёсткого диска, т.е., в нашем случае, /dev/sda:
$ udevadm info --query=env --name=/dev/sda
Также в правиле udev нужно заменить <cache_name>
на sda, <block_size>
— на 4096, а путь к утилите с /sbin/eio_cli изменить на /usr/local/sbin/eio_cli.
Эти же манипуляции с шаблоном правила для udev описаны в файле Documents/Persistence.txt.
Теперь немного о стратегиях кеширования. В файле правила это отражается вставкой <mode>
. Её нужно поменять на одно из следующих значений:
- ro (сокращение от Read Only) — режим, при котором данные будут писаться только на HDD, при первом их чтении они будут записываться на SSD, повторные чтения будут происходить с SSD. Это самый безопасный режим, но не слишком быстрый.
- wt (сокращение от Write-Through) — режим, при котором данные будут писаться как на HDD, так и на SSD. Таким образом, данные будут считываться с SSD уже при первом обращении к ним. Тоже безопасный режим, но значительно быстрее предыдущего.
- wb (сокращение от Write-Back) — режим, при котором данные будут писаться сначала на SSD, а потом в асинхронном режиме копироваться на HDD. Чтение также будет производиться с SSD. Опасный режим, т.к. при сбое можно не только потерять данные, которые не успели записаться на HDD, но и даже повредить всю файловую систему.
Выбирать, опять же, конечному пользователю (всё зависит от задач), я остановился на Write-Through.
После написания правила для udev нужно обеспечить загрузку модулей ядра при старте системы. В Arch Linux это означает добавление модулей в файл /etc/modules-load.d/boot.conf. Вот его содержимое:
enhanceio
enhanceio_fifo
enhanceio_lru
FIFO и LRU — это алгоритмы вытеснения блоков при нехватке места в кеше. FIFO работает по принципу «вытеснять самые первые записанные блоки в кеше», LRU — по принципу «вытеснять те блоки, которые не использовались дольше всего». LRU можно считать квазиоптимальным алгоритмом по соотношению «время доступа/затраты памяти», но нужно отметить, что памяти он таки жрёт больше FIFO. Детальнее о FIFO и LRU можно прочитать в этой книжке, а также в файле README.txt в дереве исходных кодов EnhanceIO.
Выбрать же нужный алгоритм вытеснения блоков можно передав утилите eio_cli ключик -p со значением lru, fifo или rand. В последнем случае вытесняться будет случайный блок.
Теперь создадим кеш:
/usr/local/sbin/eio_cli create -d /dev/sda -s /dev/sdb -m wt -b 4096 -c sda
После проделанных действий можно перезагрузить компьютер. Во время загрузки, в момент определения кеширующего и кешируемого устройств, udev выполнит правило, включающее кеш. Если всё пройдёт успешно, можно посмотреть статистику кеширования:
cat /proc/enhanceio/sda/stats
Интересны строчки ssd_reads и ssd_writes. Они показывают количество информации, считанной с SSD и записанной на него соответственно. Если эти показатели отличны от нуля, то кеширование заработало. Если ssd_reads превышает ssd_writes или имеет значение одного порядка с ним — кеширование можно считать эффективным. Поначалу это будет не так, но со временем кеш будет наполняться, уменьшая количество операций с жёстким диском.
Наконец, вкратце о подводных камнях. Я столкнулся с двумя. Первый относится к тому, что не стоит включать кеширование для устройства с зашифрованными разделами. Если нужно кешировать зашифрованную информацию, кеширование следует включать для устройства, которое создаёт Device Mapper после открытия шифрованного раздела. Соответственно, кешировать тоже нужно на зашифрованное устройство, чтобы не было утечки информации. При другом раскладе у меня повреждалась файловая система на зашифрованном разделе, и её приходилось чинить с помощью fsck вручную. Второй подводный камень связан с тем, что во время загрузки для инициализации EnhanceIO требуется определённое время, а перед выключением, перезагрузкой или гибернацией ядро долго сбрасывает кеш на SSD. В принципе, это не так критично, поскольку во время работы с компьютером это компенсируется более высокой производительностью, но о такой специфической вещи нужно помнить.
Автор: pfactum