Add instructions to change NFS_MAX_FILE_IO_SIZE
This commit is contained in:
@@ -14,6 +14,9 @@ Commands:
|
|||||||
- [upgrade](#upgrade)
|
- [upgrade](#upgrade)
|
||||||
- [defrag](#defrag)
|
- [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
|
## Pseudo-FS
|
||||||
|
|
||||||
Simplified pseudo-FS proxy is used for file-based image access emulation. It's not
|
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
|
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.
|
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
|
## Horizontal scaling
|
||||||
|
|
||||||
Linux NFS 3.0 client doesn't support built-in scaling or failover, i.e. you can't
|
Linux NFS 3.0 client doesn't support built-in scaling or failover, i.e. you can't
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
- [upgrade](#upgrade)
|
- [upgrade](#upgrade)
|
||||||
- [defrag](#defrag)
|
- [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 не поддерживает встроенное масштабирование или отказоустойчивость.
|
Клиент Linux NFS 3.0 не поддерживает встроенное масштабирование или отказоустойчивость.
|
||||||
|
|||||||
@@ -162,10 +162,12 @@ apt-get install linux-headers-`uname -r`
|
|||||||
apt-get build-dep linux-image-`uname -r`-unsigned
|
apt-get build-dep linux-image-`uname -r`-unsigned
|
||||||
apt-get source linux-image-`uname -r`-unsigned
|
apt-get source linux-image-`uname -r`-unsigned
|
||||||
cd linux*/drivers/vdpa
|
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
|
cat Module.symvers >> /lib/modules/`uname -r`/build/Module.symvers
|
||||||
cd ../virtio
|
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
|
depmod -a
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -165,10 +165,12 @@ apt-get install linux-headers-`uname -r`
|
|||||||
apt-get build-dep linux-image-`uname -r`-unsigned
|
apt-get build-dep linux-image-`uname -r`-unsigned
|
||||||
apt-get source linux-image-`uname -r`-unsigned
|
apt-get source linux-image-`uname -r`-unsigned
|
||||||
cd linux*/drivers/vdpa
|
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
|
cat Module.symvers >> /lib/modules/`uname -r`/build/Module.symvers
|
||||||
cd ../virtio
|
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
|
depmod -a
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user