diff --git a/docs/usage/nfs.en.md b/docs/usage/nfs.en.md index 57873fc4..c4cc94c1 100644 --- a/docs/usage/nfs.en.md +++ b/docs/usage/nfs.en.md @@ -14,6 +14,9 @@ Commands: - [upgrade](#upgrade) - [defrag](#defrag) +⚠️ Important: follow the instructions from [Linux NFS write size](#linux-nfs-write-size) +for optimal Vitastor NFS performance if you use EC and HDD and mount your NFS from Linux. + ## Pseudo-FS Simplified pseudo-FS proxy is used for file-based image access emulation. It's not @@ -100,6 +103,62 @@ Other notable missing features which should be addressed in the future: in the DB. The FS is implemented is such way that this garbage doesn't affect its function, but having a tool to clean it up still seems a right thing to do. +## Linux NFS write size + +Linux NFS client (nfs/nfsv3/nfsv4 kernel modules) has a hard-coded maximum I/O size, +currently set to 1 MB - see `rsize` and `wsize` in [man 5 nfs](https://linux.die.net/man/5/nfs). + +This means that when you write to a file in an FS mounted over NFS, the maximum write +request size is 1 MB, even in the O_DIRECT mode and even if the original write request +is larger. + +However, for optimal linear write performance in Vitastor EC (erasure-coded) pools, +the size of write requests should be a multiple of [block_size](../config/layout-cluster.en.md#block_size), +multiplied by the data chunk count of the pool ([pg_size](../config/pool.en.md#pg_size)-[parity_chunks](../config/pool.en.md#parity_chunks)). +When write requests are smaller or not a multiple of this number, Vitastor has to first +read paired data blocks from disks, calculate new parity blocks and only then write them +back. Obviously this is 2-3 times slower than a simple disk write. + +Vitastor HDD setups use 1 MB block_size by default. So, for optimal performance, if +you use EC 2+1 and HDD, you need your NFS client to send 2 MB write requests, if you +use EC 4+1 - 4 MB and so on. + +But Linux NFS client only writes in 1 MB chunks. 😢 + +The good news is that you can fix it by rebuilding Linux NFS kernel modules 😉 🤩! +You need to change NFS_MAX_FILE_IO_SIZE in nfs_xdr.h and then rebuild and reload modules. + +The instruction, using Debian as an example (should be ran under root): + +``` +# download current Linux kernel headers required to build modules +apt-get install linux-headers-`uname -r` + +# replace NFS_MAX_FILE_IO_SIZE with a desired number (here it's 4194304 - 4 MB) +sed -i 's/NFS_MAX_FILE_IO_SIZE\s*.*/NFS_MAX_FILE_IO_SIZE\t(4194304U)/' /lib/modules/`uname -r`/source/include/linux/nfs_xdr.h + +# download current Linux kernel source +mkdir linux_src +cd linux_src +apt-get source linux-image-`uname -r`-unsigned + +# build NFS modules +cd linux-*/fs/nfs +make -C /lib/modules/`uname -r`/build M=$PWD -j8 modules +make -C /lib/modules/`uname -r`/build M=$PWD modules_install + +# move default NFS modules away +mv /lib/modules/`uname -r`/kernel/fs/nfs ~/nfs_orig_`uname -r` +depmod -a + +# unload old modules and load the new ones +rmmod nfsv3 nfs +modprobe nfsv3 +``` + +After these (not much complicated 🙂) manipulations NFS begins to be mounted +with new wsize and rsize by default and it fixes Vitastor-NFS linear write performance. + ## Horizontal scaling Linux NFS 3.0 client doesn't support built-in scaling or failover, i.e. you can't diff --git a/docs/usage/nfs.ru.md b/docs/usage/nfs.ru.md index 9e57d651..83798f80 100644 --- a/docs/usage/nfs.ru.md +++ b/docs/usage/nfs.ru.md @@ -14,6 +14,9 @@ - [upgrade](#upgrade) - [defrag](#defrag) +⚠️ Важно: для оптимальной производительности Vitastor NFS в Linux при использовании +HDD и EC (erasure кодов) выполните инструкции из раздела [Размер записи Linux NFS](#размер-записи-linux-nfs). + ## Псевдо-ФС Упрощённая реализация псевдо-ФС используется для эмуляции файлового доступа к блочным @@ -104,6 +107,66 @@ JSON-формате :-). Для инспекции содержимого БД записи. ФС устроена так, что на работу они не влияют, но для порядка и их стоит уметь подчищать. +## Размер записи Linux NFS + +Клиент Linux NFS (модули ядра nfs/nfsv3/nfsv4) имеет фиксированный в коде максимальный +размер запроса ввода-вывода, равный 1 МБ - см. `rsize` и `wsize` в [man 5 nfs](https://linux.die.net/man/5/nfs). + +Это означает, что когда вы записываете в файл в примонтированной по NFS файловой системе, +максимальный размер запроса записи составляет 1 МБ, даже в режиме O_DIRECT и даже если +исходный запрос записи был больше. + +Однако для оптимальной скорости линейной записи в Vitastor при использовании EC-пулов +(пулов с кодами коррекции ошибок) запросы записи должны быть по размеру кратны +[block_size](../config/layout-cluster.ru.md#block_size), умноженному на число частей +данных пула ([pg_size](../config/pool.ru.md#pg_size)-[parity_chunks](../config/pool.ru.md#parity_chunks)). +Если запросы записи меньше или не кратны, то Vitastor приходится сначала прочитать +с дисков старые версии парных блоков данных, рассчитать новые блоки чётности и только +после этого записать их на диски. Естественно, это в 2-3 раза медленнее простой записи +на диск. + +При этом block_size на жёстких дисках по умолчанию устанавливается равным 1 МБ. +Таким образом, если вы используете EC 2+1 и HDD, для оптимальной скорости записи вам +нужно, чтобы NFS-клиент писал по 2 МБ, если EC 4+1 и HDD - то по 4 МБ, и т.п. + +А Linux NFS-клиент пишет только по 1 МБ. 😢 + +Но это можно исправить, пересобрав модули ядра Linux NFS 😉 🤩! Для этого нужно +поменять значение переменной NFS_MAX_FILE_IO_SIZE в заголовочном файле nfs_xdr.h, +после чего пересобрать модули NFS. + +Инструкция по пересборке на примере Debian (выполнять под root): + +``` +# скачиваем заголовки для сборки модулей для текущего ядра Linux +apt-get install linux-headers-`uname -r` + +# заменяем в заголовках NFS_MAX_FILE_IO_SIZE на желаемый (здесь 4194304 - 4 МБ) +sed -i 's/NFS_MAX_FILE_IO_SIZE\s*.*/NFS_MAX_FILE_IO_SIZE\t(4194304U)/' /lib/modules/`uname -r`/source/include/linux/nfs_xdr.h + +# скачиваем исходный код текущего ядра +mkdir linux_src +cd linux_src +apt-get source linux-image-`uname -r`-unsigned + +# собираем модули NFS +cd linux-*/fs/nfs +make -C /lib/modules/`uname -r`/build M=$PWD -j8 modules +make -C /lib/modules/`uname -r`/build M=$PWD modules_install + +# убираем в сторону штатные модули NFS +mv /lib/modules/`uname -r`/kernel/fs/nfs ~/nfs_orig_`uname -r` +depmod -a + +# выгружаем старые модули и загружаем новые +rmmod nfsv3 nfs +modprobe nfsv3 +``` + +После такой (относительно нехитрой 🙂) манипуляции NFS начинает по умолчанию +монтироваться с новыми wsize и rsize, и производительность линейной записи в Vitastor-NFS +исправляется. + ## Горизонтальное масштабирование Клиент Linux NFS 3.0 не поддерживает встроенное масштабирование или отказоустойчивость. diff --git a/docs/usage/qemu.en.md b/docs/usage/qemu.en.md index 1191a593..44e2ab14 100644 --- a/docs/usage/qemu.en.md +++ b/docs/usage/qemu.en.md @@ -162,10 +162,12 @@ apt-get install linux-headers-`uname -r` apt-get build-dep linux-image-`uname -r`-unsigned apt-get source linux-image-`uname -r`-unsigned cd linux*/drivers/vdpa -make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules modules_install +make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules +make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m modules_install cat Module.symvers >> /lib/modules/`uname -r`/build/Module.symvers cd ../virtio -make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules modules_install +make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules +make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m modules_install depmod -a ``` diff --git a/docs/usage/qemu.ru.md b/docs/usage/qemu.ru.md index 2a8d2a73..17b13950 100644 --- a/docs/usage/qemu.ru.md +++ b/docs/usage/qemu.ru.md @@ -165,10 +165,12 @@ apt-get install linux-headers-`uname -r` apt-get build-dep linux-image-`uname -r`-unsigned apt-get source linux-image-`uname -r`-unsigned cd linux*/drivers/vdpa -make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules modules_install +make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules +make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m modules_install cat Module.symvers >> /lib/modules/`uname -r`/build/Module.symvers cd ../virtio -make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules modules_install +make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules +make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m modules_install depmod -a ```