По умолчанию запись во все файлы, открытые без флага O_DIRECT, осуществляется через write-back cache. Это не только уменьшает latency (время ожидания) записи данных на диск для приложения (системный вызов write() завершится, как только данные будут скопированы в write-back cache, не дожидаясь реальной записи на диск), но и позволяет планировщику I/O ядра эффективнее распределять ресурсы диска между процессами, группируя I/O запросы от приложений.
При этом некоторые категории приложений, например, базы данных, сами эффективно управляют записью своих данных, выполняя большие последовательные I/O запросы. Поэтому зачастую такие приложения открывают файлы с флагом O_DIRECT, который указывает ядру писать данные в такой файл, минуя write-back cache, напрямую из памяти пользовательского приложения. В случае работы одной базы данных на хосте такой подход оказывается эффективнее, чем запись через кэш, поскольку I/O запросы от базы данных уже выстроены оптимальным образом и нет необходимости в дополнительном копировании памяти из пользовательского приложения в write-back cache.
В случае работы нескольких контейнеров с базами данных на одном хосте данное предположение оказывается неверным, так как планировщик I/O в ядре Linux не может оптимально распределять ресурсы диска между приложениями, использующими Direct I/O. Поэтому по умолчанию в ядре OpenVZ Direct I/O для контейнеров выключено, и все данные пишутся через write-back cache. Это вносит небольшие накладные расходы в виде дополнительного копирования памяти из пользовательского приложения в write-back cache, при этом позволяя планировщику I/O ядра эффективнее распределять ресурсы диска.
Если заранее известно, что подобной ситуации на хосте не будет, то можно избежать дополнительных накладных расходов и разрешить использование Direct I/O всем или части контейнеров. Настроить поведение ядра можно, используя файл /proc/sys/fs/odirect_enable. Возможные значения данного файла в случае настройки на host node (глобальные настройки):
0 флаг O_DIRECT игнорируется для контейнеров, вся запись происходит через write-back cache (значение по умолчанию)
1 флаг O_DIRECT в контейнерах работает как обычно
Возможные значения данного файла в случае настройки внутри конкретного контейнера:
0 флаг O_DIRECT игнорируется для данного контейнера, вся запись происходит через write-back cache
1 флаг O_DIRECT для данного контейнера работает как обычно
2 использовать глобальные настройки (значение по умолчанию)