Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68985bee0a |
@@ -414,24 +414,6 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
test_level_placement:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: /root/vitastor/tests/test_level_placement.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_snapshot:
|
test_snapshot:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
@@ -1944,21 +1926,3 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
test_nfs_unaligned_append:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: /root/vitastor/tests/test_nfs_unaligned_append.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12)
|
|||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
set(VITASTOR_VERSION "3.0.1")
|
set(VITASTOR_VERSION "3.0.0")
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
VITASTOR_VERSION ?= v3.0.1
|
VITASTOR_VERSION ?= v3.0.0
|
||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ spec:
|
|||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
allowPrivilegeEscalation: true
|
allowPrivilegeEscalation: true
|
||||||
image: vitalif/vitastor-csi:v3.0.1
|
image: vitalif/vitastor-csi:v3.0.0
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ spec:
|
|||||||
privileged: true
|
privileged: true
|
||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
image: vitalif/vitastor-csi:v3.0.1
|
image: vitalif/vitastor-csi:v3.0.0
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ package vitastor
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
vitastorCSIDriverName = "csi.vitastor.io"
|
vitastorCSIDriverName = "csi.vitastor.io"
|
||||||
vitastorCSIDriverVersion = "3.0.1"
|
vitastorCSIDriverVersion = "3.0.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct fills the parameters of request or user input
|
// Config struct fills the parameters of request or user input
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
vitastor (3.0.1-1) unstable; urgency=medium
|
vitastor (3.0.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
* Bugfixes
|
* Bugfixes
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
VITASTOR_VERSION ?= v3.0.1
|
VITASTOR_VERSION ?= v3.0.0
|
||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Desired Vitastor version
|
# Desired Vitastor version
|
||||||
VITASTOR_VERSION=v3.0.1
|
VITASTOR_VERSION=v3.0.0
|
||||||
|
|
||||||
# Additional arguments for all containers
|
# Additional arguments for all containers
|
||||||
# For example, you may want to specify a custom logging driver here
|
# For example, you may want to specify a custom logging driver here
|
||||||
|
|||||||
+9
-16
@@ -682,10 +682,7 @@ with replicated pools and reach the best possible write performance.
|
|||||||
|
|
||||||
Default value is auto-detected during OSD initialization from
|
Default value is auto-detected during OSD initialization from
|
||||||
`/sys/block/xx/queue/atomic_write_max_bytes` or assumed to be 4096 bytes
|
`/sys/block/xx/queue/atomic_write_max_bytes` or assumed to be 4096 bytes
|
||||||
because all known disks support 4 KB atomic writes. Auto-detection is only used for
|
because all known disks support 4 KB atomic writes.
|
||||||
NVMe disks because SAS disks require the explicit WRITE ATOMIC command which requires
|
|
||||||
RWF_ATOMIC (see below [#use_atomic_flag]) but that flag works incorrectly in current
|
|
||||||
Linux versions.
|
|
||||||
|
|
||||||
You can also check if your NVMe drives support atomic writes by running
|
You can also check if your NVMe drives support atomic writes by running
|
||||||
the command `nvme id-ctrl /dev/nvme0n1 | grep awupf`. If the reported value,
|
the command `nvme id-ctrl /dev/nvme0n1 | grep awupf`. If the reported value,
|
||||||
@@ -700,16 +697,12 @@ reducing Write Amplification and improving write performance up to 2 times.
|
|||||||
|
|
||||||
- Type: boolean
|
- Type: boolean
|
||||||
|
|
||||||
This option controls whether Vitastor OSDs use RWF_ATOMIC write flag with atomic writes.
|
This option controls whether the Vitastor OSD uses RWF_ATOMIC write flag with atomic
|
||||||
This flag is supported since Linux 6.11 and adds some safety to atomic writes - the kernel
|
writes. This flag is only supported on Linux kernel since 6.11. Atomic writes are
|
||||||
guarantees to not fragment write requests with it and also to check them against the actual
|
generally only safe to use with this flag because it tells the kernel to never fragment
|
||||||
device atomic write capabilities.
|
write requests and also to check the write against the actual atomic write capabilities
|
||||||
|
of the device.
|
||||||
|
|
||||||
However, the option is disabled by default because the flag is currently UNUSABLE - Linux
|
This option is enabled by default when atomic_write_size is set to a value larger than 4 KB.
|
||||||
incorrectly requires writes with that flag to be of power-of-2 length and length-aligned.
|
You can disable it if you're sure that your disks support atomic writes and you want to
|
||||||
I.e., for example, 12 KB writes and not-8-KB aligned 8 KB writes are forbidden by the kernel,
|
bypass the Linux atomic write checks.
|
||||||
even though the NVMe specification allows them.
|
|
||||||
|
|
||||||
For NVMe disks with `scheduler=none` writes aren't fragmented anyway so it's not a big deal.
|
|
||||||
However, you can rebuild your kernel with [this patch](../../patches/linux-fix-atomic-write-checks.diff)
|
|
||||||
and turn this option on. It will make your atomic writes a bit safer.
|
|
||||||
|
|||||||
+7
-15
@@ -717,9 +717,6 @@ pg_minsize OSD во время переключений, что может по
|
|||||||
Значение по умолчанию авто-определяется во время инициализации OSD из
|
Значение по умолчанию авто-определяется во время инициализации OSD из
|
||||||
`/sys/block/xx/queue/atomic_write_max_bytes` либо принимается равным 4096,
|
`/sys/block/xx/queue/atomic_write_max_bytes` либо принимается равным 4096,
|
||||||
так как все известные диски поддерживают атомарную запись 4 КБ блоков.
|
так как все известные диски поддерживают атомарную запись 4 КБ блоков.
|
||||||
Автоопределение применяется только для NVMe-дисков, так как SAS диски требуют
|
|
||||||
использования отдельной команды WRITE ATOMIC, а для неё нужен флаг RWF_ATOMIC
|
|
||||||
(см. ниже [#use_atomic_flag]), а он в текущих версиях Linux работает некорректно.
|
|
||||||
|
|
||||||
Вы также можете проверить, поддерживают ли ваши NVMe-диски атомарную запись,
|
Вы также можете проверить, поддерживают ли ваши NVMe-диски атомарную запись,
|
||||||
с помощью команды `nvme id-ctrl /dev/nvme0n1 | grep awupf`. Если значение awupf
|
с помощью команды `nvme id-ctrl /dev/nvme0n1 | grep awupf`. Если значение awupf
|
||||||
@@ -738,16 +735,11 @@ pg_minsize OSD во время переключений, что может по
|
|||||||
- Тип: булево (да/нет)
|
- Тип: булево (да/нет)
|
||||||
|
|
||||||
Данная опция контролирует использование Vitastor OSD флага RWF_ATOMIC при атомарной записи
|
Данная опция контролирует использование Vitastor OSD флага RWF_ATOMIC при атомарной записи
|
||||||
блоков. Этот флаг поддерживается, начиная с версии ядра Linux 6.11 и добавляет немного корректности
|
блоков. Этот флаг поддерживается только в ядрах Linux начиная с 6.11. Атомарная запись
|
||||||
атомарным записям - ядро гарантирует отсутствие фрагментации запросов записи с этим флагом и
|
является безопасной только при использовании этого флага, так как он сообщает ядру о том,
|
||||||
проверяет их на соответствие реальным возможностям устройства.
|
что запрос записи нельзя фрагментировать и о том, что запрос нужно проверить на соответствие
|
||||||
|
реальным возможностям атомарной записи устройства.
|
||||||
|
|
||||||
Однако, данная опция по умолчанию отключена, так как флаг в текущих версиях Linux работает
|
Опция включается по умолчанию, когда atomic_write_size устанавливается в значение больше 4 КБ.
|
||||||
абсолютно НЕКОРРЕКТНО - при нём Linux требует, чтобы запросы записи имели длину, равную
|
Вы можете явно отключить её, если уверены, что ваши диски поддерживают атомарную запись и
|
||||||
степени двойки и были выровнены на эту длину. То есть, например, 12 КБ запросы записи, а также
|
хотите обойти проверки уровня ядра.
|
||||||
8 КБ запросы записи по не-кратному 8 КБ смещению запрещаются ядром, хотя спецификация NVMe их
|
|
||||||
разрешает.
|
|
||||||
|
|
||||||
Для NVMe-дисков с `scheduler=none` запросы записи и так не фрагментируются, так что это не так
|
|
||||||
уж и важно, однако вы можете пересобрать своё ядро с [этим патчем](../../patches/linux-fix-atomic-write-checks.diff)
|
|
||||||
и включить данную опцию. Это сделает вашу атомарную запись капельку безопаснее.
|
|
||||||
|
|||||||
+16
-31
@@ -813,10 +813,7 @@
|
|||||||
|
|
||||||
Default value is auto-detected during OSD initialization from
|
Default value is auto-detected during OSD initialization from
|
||||||
`/sys/block/xx/queue/atomic_write_max_bytes` or assumed to be 4096 bytes
|
`/sys/block/xx/queue/atomic_write_max_bytes` or assumed to be 4096 bytes
|
||||||
because all known disks support 4 KB atomic writes. Auto-detection is only used for
|
because all known disks support 4 KB atomic writes.
|
||||||
NVMe disks because SAS disks require the explicit WRITE ATOMIC command which requires
|
|
||||||
RWF_ATOMIC (see below [#use_atomic_flag]) but that flag works incorrectly in current
|
|
||||||
Linux versions.
|
|
||||||
|
|
||||||
You can also check if your NVMe drives support atomic writes by running
|
You can also check if your NVMe drives support atomic writes by running
|
||||||
the command `nvme id-ctrl /dev/nvme0n1 | grep awupf`. If the reported value,
|
the command `nvme id-ctrl /dev/nvme0n1 | grep awupf`. If the reported value,
|
||||||
@@ -837,9 +834,6 @@
|
|||||||
Значение по умолчанию авто-определяется во время инициализации OSD из
|
Значение по умолчанию авто-определяется во время инициализации OSD из
|
||||||
`/sys/block/xx/queue/atomic_write_max_bytes` либо принимается равным 4096,
|
`/sys/block/xx/queue/atomic_write_max_bytes` либо принимается равным 4096,
|
||||||
так как все известные диски поддерживают атомарную запись 4 КБ блоков.
|
так как все известные диски поддерживают атомарную запись 4 КБ блоков.
|
||||||
Автоопределение применяется только для NVMe-дисков, так как SAS диски требуют
|
|
||||||
использования отдельной команды WRITE ATOMIC, а для неё нужен флаг RWF_ATOMIC
|
|
||||||
(см. ниже [#use_atomic_flag]), а он в текущих версиях Linux работает некорректно.
|
|
||||||
|
|
||||||
Вы также можете проверить, поддерживают ли ваши NVMe-диски атомарную запись,
|
Вы также можете проверить, поддерживают ли ваши NVMe-диски атомарную запись,
|
||||||
с помощью команды `nvme id-ctrl /dev/nvme0n1 | grep awupf`. Если значение awupf
|
с помощью команды `nvme id-ctrl /dev/nvme0n1 | grep awupf`. Если значение awupf
|
||||||
@@ -855,31 +849,22 @@
|
|||||||
- name: use_atomic_flag
|
- name: use_atomic_flag
|
||||||
type: bool
|
type: bool
|
||||||
info: |
|
info: |
|
||||||
This option controls whether Vitastor OSDs use RWF_ATOMIC write flag with atomic writes.
|
This option controls whether the Vitastor OSD uses RWF_ATOMIC write flag with atomic
|
||||||
This flag is supported since Linux 6.11 and adds some safety to atomic writes - the kernel
|
writes. This flag is only supported on Linux kernel since 6.11. Atomic writes are
|
||||||
guarantees to not fragment write requests with it and also to check them against the actual
|
generally only safe to use with this flag because it tells the kernel to never fragment
|
||||||
device atomic write capabilities.
|
write requests and also to check the write against the actual atomic write capabilities
|
||||||
|
of the device.
|
||||||
|
|
||||||
However, the option is disabled by default because the flag is currently UNUSABLE - Linux
|
This option is enabled by default when atomic_write_size is set to a value larger than 4 KB.
|
||||||
incorrectly requires writes with that flag to be of power-of-2 length and length-aligned.
|
You can disable it if you're sure that your disks support atomic writes and you want to
|
||||||
I.e., for example, 12 KB writes and not-8-KB aligned 8 KB writes are forbidden by the kernel,
|
bypass the Linux atomic write checks.
|
||||||
even though the NVMe specification allows them.
|
|
||||||
|
|
||||||
For NVMe disks with `scheduler=none` writes aren't fragmented anyway so it's not a big deal.
|
|
||||||
However, you can rebuild your kernel with [this patch](../../patches/linux-fix-atomic-write-checks.diff)
|
|
||||||
and turn this option on. It will make your atomic writes a bit safer.
|
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Данная опция контролирует использование Vitastor OSD флага RWF_ATOMIC при атомарной записи
|
Данная опция контролирует использование Vitastor OSD флага RWF_ATOMIC при атомарной записи
|
||||||
блоков. Этот флаг поддерживается, начиная с версии ядра Linux 6.11 и добавляет немного корректности
|
блоков. Этот флаг поддерживается только в ядрах Linux начиная с 6.11. Атомарная запись
|
||||||
атомарным записям - ядро гарантирует отсутствие фрагментации запросов записи с этим флагом и
|
является безопасной только при использовании этого флага, так как он сообщает ядру о том,
|
||||||
проверяет их на соответствие реальным возможностям устройства.
|
что запрос записи нельзя фрагментировать и о том, что запрос нужно проверить на соответствие
|
||||||
|
реальным возможностям атомарной записи устройства.
|
||||||
|
|
||||||
Однако, данная опция по умолчанию отключена, так как флаг в текущих версиях Linux работает
|
Опция включается по умолчанию, когда atomic_write_size устанавливается в значение больше 4 КБ.
|
||||||
абсолютно НЕКОРРЕКТНО - при нём Linux требует, чтобы запросы записи имели длину, равную
|
Вы можете явно отключить её, если уверены, что ваши диски поддерживают атомарную запись и
|
||||||
степени двойки и были выровнены на эту длину. То есть, например, 12 КБ запросы записи, а также
|
хотите обойти проверки уровня ядра.
|
||||||
8 КБ запросы записи по не-кратному 8 КБ смещению запрещаются ядром, хотя спецификация NVMe их
|
|
||||||
разрешает.
|
|
||||||
|
|
||||||
Для NVMe-дисков с `scheduler=none` запросы записи и так не фрагментируются, так что это не так
|
|
||||||
уж и важно, однако вы можете пересобрать своё ядро с [этим патчем](../../patches/linux-fix-atomic-write-checks.diff)
|
|
||||||
и включить данную опцию. Это сделает вашу атомарную запись капельку безопаснее.
|
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ at Vitastor Kubernetes operator: https://github.com/Antilles7227/vitastor-operat
|
|||||||
The instruction is very simple.
|
The instruction is very simple.
|
||||||
|
|
||||||
1. Download a Docker image of the desired version: \
|
1. Download a Docker image of the desired version: \
|
||||||
`docker pull vitalif/vitastor:v3.0.1`
|
`docker pull vitalif/vitastor:v3.0.0`
|
||||||
2. Install scripts to the host system: \
|
2. Install scripts to the host system: \
|
||||||
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.1 install.sh`
|
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.0 install.sh`
|
||||||
3. Reload udev rules: \
|
3. Reload udev rules: \
|
||||||
`udevadm control --reload-rules`
|
`udevadm control --reload-rules`
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ Vitastor можно установить в Docker/Podman. При этом etcd,
|
|||||||
Инструкция по установке максимально простая.
|
Инструкция по установке максимально простая.
|
||||||
|
|
||||||
1. Скачайте Docker-образ желаемой версии: \
|
1. Скачайте Docker-образ желаемой версии: \
|
||||||
`docker pull vitalif/vitastor:v3.0.1`
|
`docker pull vitalif/vitastor:v3.0.0`
|
||||||
2. Установите скрипты в хост-систему командой: \
|
2. Установите скрипты в хост-систему командой: \
|
||||||
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.1 install.sh`
|
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.0 install.sh`
|
||||||
3. Перезагрузите правила udev: \
|
3. Перезагрузите правила udev: \
|
||||||
`udevadm control --reload-rules`
|
`udevadm control --reload-rules`
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
# Proxmox VE
|
# Proxmox VE
|
||||||
|
|
||||||
To enable Vitastor support in Proxmox Virtual Environment (6.4-9.x are supported):
|
To enable Vitastor support in Proxmox Virtual Environment (6.4-8.x are supported):
|
||||||
|
|
||||||
- Add the corresponding Vitastor Debian repository into sources.list on Proxmox hosts:
|
- Add the corresponding Vitastor Debian repository into sources.list on Proxmox hosts:
|
||||||
trixie for 9.0+, bookworm for 8.1+, pve8.0 for 8.0, bullseye for 7.4, pve7.3 for 7.3, pve7.2 for 7.2, pve7.1 for 7.1, buster for 6.4
|
trixie for 9.0+, bookworm for 8.1+, pve8.0 for 8.0, bullseye for 7.4, pve7.3 for 7.3, pve7.2 for 7.2, pve7.1 for 7.1, buster for 6.4
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
# Proxmox VE
|
# Proxmox VE
|
||||||
|
|
||||||
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-9.x):
|
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-8.x):
|
||||||
|
|
||||||
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
|
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
|
||||||
trixie для 9.0+, bookworm для 8.1+, pve8.0 для 8.0, bullseye для 7.4, pve7.3 для 7.3, pve7.2 для 7.2, pve7.1 для 7.1, buster для 6.4
|
trixie для 9.0+, bookworm для 8.1+, pve8.0 для 8.0, bullseye для 7.4, pve7.3 для 7.3, pve7.2 для 7.2, pve7.1 для 7.1, buster для 6.4
|
||||||
|
|||||||
@@ -95,8 +95,6 @@ Options (single-device mode):
|
|||||||
Options (both modes):
|
Options (both modes):
|
||||||
|
|
||||||
```
|
```
|
||||||
--tags tag1,tag2 Set new OSD tag(s)
|
|
||||||
--weight <number> Set new OSD weight (between 0 to 1)
|
|
||||||
--journal_size 1G/32M Set journal size (area or partition size)
|
--journal_size 1G/32M Set journal size (area or partition size)
|
||||||
--block_size 1M/128k Set blockstore object size
|
--block_size 1M/128k Set blockstore object size
|
||||||
--bitmap_granularity 4k Set bitmap granularity
|
--bitmap_granularity 4k Set bitmap granularity
|
||||||
|
|||||||
@@ -96,8 +96,6 @@ vitastor-disk - инструмент командной строки для уп
|
|||||||
Опции для обоих режимов:
|
Опции для обоих режимов:
|
||||||
|
|
||||||
```
|
```
|
||||||
--tags tag1,tag2 Задать теги для новых OSD
|
|
||||||
--weight <number> Задать вес для новых OSD (от 0 до 1)
|
|
||||||
--journal_size 1G/32M Задать размер журнала (области или раздела журнала)
|
--journal_size 1G/32M Задать размер журнала (области или раздела журнала)
|
||||||
--block_size 1M/128k Задать размер объекта хранилища
|
--block_size 1M/128k Задать размер объекта хранилища
|
||||||
--bitmap_granularity 4k Задать гранулярность битовых карт
|
--bitmap_granularity 4k Задать гранулярность битовых карт
|
||||||
|
|||||||
+1
-1
@@ -87,7 +87,7 @@ function make_hier_tree(global_config, tree)
|
|||||||
tree[''] = { children: [] };
|
tree[''] = { children: [] };
|
||||||
for (const node_id in tree)
|
for (const node_id in tree)
|
||||||
{
|
{
|
||||||
if (node_id === '')
|
if (node_id === '' || !(tree[node_id].children||[]).length && (tree[node_id].size||0) <= 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vitastor-mon",
|
"name": "vitastor-mon",
|
||||||
"version": "3.0.1",
|
"version": "3.0.0",
|
||||||
"description": "Vitastor SDS monitor service",
|
"description": "Vitastor SDS monitor service",
|
||||||
"main": "mon-main.js",
|
"main": "mon-main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+1
-1
@@ -178,7 +178,7 @@ async function generate_pool_pgs(state, global_config, pool_id, osd_tree, levels
|
|||||||
const rules = use_rules ? get_pg_rules(pool_id, pool_cfg, global_config.placement_levels) : null;
|
const rules = use_rules ? get_pg_rules(pool_id, pool_cfg, global_config.placement_levels) : null;
|
||||||
const folded = fold_failure_domains(Object.values(pool_tree), use_rules ? rules : [ [ [ pool_cfg.failure_domain ] ] ]);
|
const folded = fold_failure_domains(Object.values(pool_tree), use_rules ? rules : [ [ [ pool_cfg.failure_domain ] ] ]);
|
||||||
// FIXME: Remove/merge make_hier_tree() step somewhere, however it's needed to remove empty nodes
|
// FIXME: Remove/merge make_hier_tree() step somewhere, however it's needed to remove empty nodes
|
||||||
const folded_tree = make_hier_tree(global_config, folded.nodes.reduce((a, c) => { a[c.id] = c; return a; }, {}));
|
const folded_tree = make_hier_tree(global_config, folded.nodes);
|
||||||
const old_pg_count = prev_pgs.length;
|
const old_pg_count = prev_pgs.length;
|
||||||
const optimize_cfg = {
|
const optimize_cfg = {
|
||||||
osd_weights: folded.nodes.reduce((a, c) => { if (Number(c.id)) { a[c.id] = c.size; } return a; }, {}),
|
osd_weights: folded.nodes.reduce((a, c) => { if (Number(c.id)) { a[c.id] = c.size; } return a; }, {}),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vitastor",
|
"name": "vitastor",
|
||||||
"version": "3.0.1",
|
"version": "3.0.0",
|
||||||
"description": "Low-level native bindings to Vitastor client library",
|
"description": "Low-level native bindings to Vitastor client library",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ from cinder.volume import configuration
|
|||||||
from cinder.volume import driver
|
from cinder.volume import driver
|
||||||
from cinder.volume import volume_utils
|
from cinder.volume import volume_utils
|
||||||
|
|
||||||
VITASTOR_VERSION = '3.0.1'
|
VITASTOR_VERSION = '3.0.0'
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
From 98d3f68a40130c438854f61db6025f9e9b099cb6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vitaliy Filippov <vitalifster@gmail.com>
|
|
||||||
Date: Sat, 20 Dec 2025 14:44:35 +0300
|
|
||||||
Subject: [PATCH] Do not require atomic writes to be power of 2 sized and
|
|
||||||
aligned on length boundary
|
|
||||||
|
|
||||||
It contradicts NVMe specification where alignment is only required when atomic
|
|
||||||
write boundary (NABSPF/NABO) is set and highly limits usage of NVMe atomic writes
|
|
||||||
|
|
||||||
Signed-off-by: Vitaliy Filippov <vitalifster@gmail.com>
|
|
||||||
---
|
|
||||||
fs/read_write.c | 8 --------
|
|
||||||
1 file changed, 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/fs/read_write.c b/fs/read_write.c
|
|
||||||
index 833bae068770..5467d710108d 100644
|
|
||||||
--- a/fs/read_write.c
|
|
||||||
+++ b/fs/read_write.c
|
|
||||||
@@ -1802,17 +1802,9 @@ int generic_file_rw_checks(struct file *file_in, struct file *file_out)
|
|
||||||
|
|
||||||
int generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter)
|
|
||||||
{
|
|
||||||
- size_t len = iov_iter_count(iter);
|
|
||||||
-
|
|
||||||
if (!iter_is_ubuf(iter))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
- if (!is_power_of_2(len))
|
|
||||||
- return -EINVAL;
|
|
||||||
-
|
|
||||||
- if (!IS_ALIGNED(iocb->ki_pos, len))
|
|
||||||
- return -EINVAL;
|
|
||||||
-
|
|
||||||
if (!(iocb->ki_flags & IOCB_DIRECT))
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
--
|
|
||||||
2.51.0
|
|
||||||
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 3.0.1
|
Version: 3.0.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Vitastor, a fast software-defined clustered block storage
|
Summary: Vitastor, a fast software-defined clustered block storage
|
||||||
|
|
||||||
License: Vitastor Network Public License 1.1
|
License: Vitastor Network Public License 1.1
|
||||||
URL: https://vitastor.io/
|
URL: https://vitastor.io/
|
||||||
Source0: vitastor-3.0.1.el7.tar.gz
|
Source0: vitastor-3.0.0.el7.tar.gz
|
||||||
|
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
BuildRequires: devtoolset-9-gcc-c++
|
BuildRequires: devtoolset-9-gcc-c++
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 3.0.1
|
Version: 3.0.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Vitastor, a fast software-defined clustered block storage
|
Summary: Vitastor, a fast software-defined clustered block storage
|
||||||
|
|
||||||
License: Vitastor Network Public License 1.1
|
License: Vitastor Network Public License 1.1
|
||||||
URL: https://vitastor.io/
|
URL: https://vitastor.io/
|
||||||
Source0: vitastor-3.0.1.el8.tar.gz
|
Source0: vitastor-3.0.0.el8.tar.gz
|
||||||
|
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
BuildRequires: gcc-toolset-9-gcc-c++
|
BuildRequires: gcc-toolset-9-gcc-c++
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 3.0.1
|
Version: 3.0.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Vitastor, a fast software-defined clustered block storage
|
Summary: Vitastor, a fast software-defined clustered block storage
|
||||||
|
|
||||||
License: Vitastor Network Public License 1.1
|
License: Vitastor Network Public License 1.1
|
||||||
URL: https://vitastor.io/
|
URL: https://vitastor.io/
|
||||||
Source0: vitastor-3.0.1.el9.tar.gz
|
Source0: vitastor-3.0.0.el9.tar.gz
|
||||||
|
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
BuildRequires: gcc-c++
|
BuildRequires: gcc-c++
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/local/?$")
|
|||||||
endif()
|
endif()
|
||||||
set(ENABLE_COVERAGE false CACHE BOOL "Enable code coverage")
|
set(ENABLE_COVERAGE false CACHE BOOL "Enable code coverage")
|
||||||
|
|
||||||
add_definitions(-DVITASTOR_VERSION="3.0.1")
|
add_definitions(-DVITASTOR_VERSION="3.0.0")
|
||||||
add_definitions(-D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -fno-omit-frame-pointer -fvisibility=hidden -I ${CMAKE_SOURCE_DIR}/src)
|
add_definitions(-D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -fno-omit-frame-pointer -fvisibility=hidden -I ${CMAKE_SOURCE_DIR}/src)
|
||||||
add_link_options(-fno-omit-frame-pointer)
|
add_link_options(-fno-omit-frame-pointer)
|
||||||
if (${WITH_ASAN})
|
if (${WITH_ASAN})
|
||||||
|
|||||||
@@ -2190,15 +2190,6 @@ void blockstore_heap_t::apply_inflight(heap_inflight_lsn_t & inflight)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool blockstore_heap_t::is_lsn_completed(uint64_t lsn)
|
|
||||||
{
|
|
||||||
if (lsn <= completed_lsn)
|
|
||||||
return true;
|
|
||||||
assert(lsn-first_inflight_lsn < inflight_lsn.size());
|
|
||||||
auto it = inflight_lsn.begin() + (lsn-first_inflight_lsn);
|
|
||||||
return (it->flags & HEAP_INFLIGHT_DONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t blockstore_heap_t::get_completed_lsn()
|
uint64_t blockstore_heap_t::get_completed_lsn()
|
||||||
{
|
{
|
||||||
return completed_lsn;
|
return completed_lsn;
|
||||||
|
|||||||
@@ -314,7 +314,6 @@ public:
|
|||||||
void start_block_write(uint32_t block_num);
|
void start_block_write(uint32_t block_num);
|
||||||
void complete_block_write(uint32_t block_num);
|
void complete_block_write(uint32_t block_num);
|
||||||
void complete_lsn_write(uint64_t lsn);
|
void complete_lsn_write(uint64_t lsn);
|
||||||
bool is_lsn_completed(uint64_t lsn);
|
|
||||||
uint64_t get_completed_lsn();
|
uint64_t get_completed_lsn();
|
||||||
uint64_t get_fsynced_lsn();
|
uint64_t get_fsynced_lsn();
|
||||||
void mark_lsn_fsynced(uint64_t lsn);
|
void mark_lsn_fsynced(uint64_t lsn);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ int blockstore_impl_t::dequeue_read(blockstore_op_t *op)
|
|||||||
uint64_t result_version = 0;
|
uint64_t result_version = 0;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
uint32_t skip_csum = 0;
|
uint32_t skip_csum = 0;
|
||||||
uint32_t blk_start = op->offset, blk_end = op->offset+op->len;
|
uint32_t blk_start = 0, blk_end = 0;
|
||||||
bool need_skip = dsk.csum_block_size > dsk.bitmap_granularity && !perfect_csum_update;
|
bool need_skip = dsk.csum_block_size > dsk.bitmap_granularity && !perfect_csum_update;
|
||||||
if (need_skip)
|
if (need_skip)
|
||||||
{
|
{
|
||||||
@@ -32,28 +32,12 @@ int blockstore_impl_t::dequeue_read(blockstore_op_t *op)
|
|||||||
if (blk_end % dsk.csum_block_size)
|
if (blk_end % dsk.csum_block_size)
|
||||||
blk_end += dsk.csum_block_size - (blk_end % dsk.csum_block_size);
|
blk_end += dsk.csum_block_size - (blk_end % dsk.csum_block_size);
|
||||||
}
|
}
|
||||||
bool need_wait = false;
|
|
||||||
heap->iterate_with_stable(obj, obj->lsn, [&](heap_entry_t *wr, bool stable)
|
heap->iterate_with_stable(obj, obj->lsn, [&](heap_entry_t *wr, bool stable)
|
||||||
{
|
{
|
||||||
if (wr->type() == BS_HEAP_DELETE)
|
if (wr->type() == BS_HEAP_DELETE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!heap->is_lsn_completed(wr->lsn))
|
|
||||||
{
|
|
||||||
if (wr->type() == BS_HEAP_BIG_INTENT && wr->big_intent().offset < blk_end && wr->big_intent().offset+wr->big_intent().len > blk_start ||
|
|
||||||
wr->type() == BS_HEAP_INTENT_WRITE && wr->small().offset < blk_end && wr->small().offset+wr->small().len > blk_start)
|
|
||||||
{
|
|
||||||
// Wait until intent write is completed
|
|
||||||
need_wait = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (wr->type() == BS_HEAP_SMALL_WRITE && wr->small().offset < blk_end && wr->small().offset+wr->small().len > blk_start)
|
|
||||||
{
|
|
||||||
// Skip entry and read the previous one
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (op->version >= wr->version && !found)
|
if (op->version >= wr->version && !found)
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
@@ -63,6 +47,12 @@ int blockstore_impl_t::dequeue_read(blockstore_op_t *op)
|
|||||||
memcpy(op->bitmap, wr->get_ext_bitmap(heap), dsk.clean_entry_bitmap_size);
|
memcpy(op->bitmap, wr->get_ext_bitmap(heap), dsk.clean_entry_bitmap_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (need_skip && wr->lsn < heap->get_completed_lsn() &&
|
||||||
|
(wr->type() == BS_HEAP_BIG_INTENT && wr->big_intent().offset < blk_end && wr->big_intent().offset+wr->big_intent().len > blk_start ||
|
||||||
|
wr->type() == BS_HEAP_INTENT_WRITE && wr->small().offset < blk_end && wr->small().offset+wr->small().len > blk_start))
|
||||||
|
{
|
||||||
|
skip_csum = COPY_BUF_SKIP_CSUM;
|
||||||
|
}
|
||||||
if (op->version >= wr->version)
|
if (op->version >= wr->version)
|
||||||
{
|
{
|
||||||
fulfilled += prepare_read(PRIV(op)->read_vec, obj, wr, op->offset, op->offset+op->len,
|
fulfilled += prepare_read(PRIV(op)->read_vec, obj, wr, op->offset, op->offset+op->len,
|
||||||
@@ -75,23 +65,13 @@ int blockstore_impl_t::dequeue_read(blockstore_op_t *op)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (need_skip && wr->type() == BS_HEAP_SMALL_WRITE &&
|
if (need_skip && (wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE) &&
|
||||||
wr->small().offset < blk_end && wr->small().offset+wr->small().len > blk_start)
|
wr->small().offset < blk_end && wr->small().offset+wr->small().len > blk_start)
|
||||||
{
|
{
|
||||||
// Small write may mutate big write checksums during flush
|
|
||||||
skip_csum = COPY_BUF_SKIP_CSUM;
|
skip_csum = COPY_BUF_SKIP_CSUM;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (need_wait)
|
|
||||||
{
|
|
||||||
undo_wait:
|
|
||||||
// Need to wait. undo added requests, unlock lsn
|
|
||||||
heap->unlock_entry(op->oid);
|
|
||||||
free_read_buffers(rv);
|
|
||||||
rv.clear();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
// May happen if there are entries but all of them are > requested version
|
// May happen if there are entries but all of them are > requested version
|
||||||
@@ -104,7 +84,11 @@ undo_wait:
|
|||||||
assert(fulfilled == op->len);
|
assert(fulfilled == op->len);
|
||||||
if (!fulfill_read(op))
|
if (!fulfill_read(op))
|
||||||
{
|
{
|
||||||
goto undo_wait;
|
// Need to wait. undo added requests, unlock lsn
|
||||||
|
heap->unlock_entry(op->oid);
|
||||||
|
free_read_buffers(rv);
|
||||||
|
rv.clear();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
op->version = result_version;
|
op->version = result_version;
|
||||||
if (!PRIV(op)->pending_ops)
|
if (!PRIV(op)->pending_ops)
|
||||||
|
|||||||
@@ -868,8 +868,7 @@ void cluster_client_t::execute_cas(cluster_op_t *op)
|
|||||||
{
|
{
|
||||||
int expected = part->req.hdr.opcode == OSD_OP_DELETE ? 0 : part->req.rw.len;
|
int expected = part->req.hdr.opcode == OSD_OP_DELETE ? 0 : part->req.rw.len;
|
||||||
op->retval = part->reply.hdr.retval;
|
op->retval = part->reply.hdr.retval;
|
||||||
if (op->retval != expected && op->retval >= 0)
|
op->retval = op->retval == expected ? 0 : (op->retval >= 0 ? -EIO : op->retval);
|
||||||
op->retval = -EIO;
|
|
||||||
op->retval = op->retval == -EPIPE ? -EINTR : op->retval;
|
op->retval = op->retval == -EPIPE ? -EINTR : op->retval;
|
||||||
auto peer_it = msgr.osd_peer_fds.find(op->parts[0].osd_num);
|
auto peer_it = msgr.osd_peer_fds.find(op->parts[0].osd_num);
|
||||||
if (op->retval != 0 || (op->flags & OP_IMMEDIATE_COMMIT))
|
if (op->retval != 0 || (op->flags & OP_IMMEDIATE_COMMIT))
|
||||||
@@ -900,11 +899,8 @@ void cluster_client_t::execute_cas(cluster_op_t *op)
|
|||||||
},
|
},
|
||||||
.callback = [this, op](osd_op_t *part)
|
.callback = [this, op](osd_op_t *part)
|
||||||
{
|
{
|
||||||
if (part->reply.hdr.retval != 0)
|
op->retval = part->reply.hdr.retval;
|
||||||
{
|
op->retval = op->retval == -EPIPE ? -EINTR : op->retval;
|
||||||
op->retval = part->reply.hdr.retval;
|
|
||||||
op->retval = op->retval == -EPIPE ? -EINTR : op->retval;
|
|
||||||
}
|
|
||||||
auto cb = std::move(op->callback);
|
auto cb = std::move(op->callback);
|
||||||
cb(op);
|
cb(op);
|
||||||
},
|
},
|
||||||
@@ -1257,9 +1253,9 @@ void cluster_client_t::slice_rw(cluster_op_t *op)
|
|||||||
{
|
{
|
||||||
op->bitmap_buf = realloc_or_die(op->bitmap_buf, bitmap_mem);
|
op->bitmap_buf = realloc_or_die(op->bitmap_buf, bitmap_mem);
|
||||||
op->part_bitmaps = (uint8_t*)op->bitmap_buf + object_bitmap_size;
|
op->part_bitmaps = (uint8_t*)op->bitmap_buf + object_bitmap_size;
|
||||||
memset(op->bitmap_buf+op->bitmap_buf_size, 0, bitmap_mem-op->bitmap_buf_size);
|
|
||||||
op->bitmap_buf_size = bitmap_mem;
|
op->bitmap_buf_size = bitmap_mem;
|
||||||
}
|
}
|
||||||
|
memset(op->bitmap_buf, 0, bitmap_mem);
|
||||||
}
|
}
|
||||||
int iov_idx = 0;
|
int iov_idx = 0;
|
||||||
size_t iov_pos = 0;
|
size_t iov_pos = 0;
|
||||||
@@ -1405,7 +1401,7 @@ int cluster_client_t::try_send(cluster_op_t *op, int i, std::function<void(osd_o
|
|||||||
if (peer_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peer_fds.end())
|
||||||
{
|
{
|
||||||
int peer_fd = peer_it->second;
|
int peer_fd = peer_it->second;
|
||||||
part->flags |= PART_SENT|PART_VALID;
|
part->flags |= PART_SENT;
|
||||||
op->inflight_count++;
|
op->inflight_count++;
|
||||||
uint64_t pg_bitmap_size = (pool_cfg.data_block_size / pool_cfg.bitmap_granularity / 8) * (
|
uint64_t pg_bitmap_size = (pool_cfg.data_block_size / pool_cfg.bitmap_granularity / 8) * (
|
||||||
pool_cfg.scheme == POOL_SCHEME_REPLICATED ? 1 : pool_cfg.pg_size-pool_cfg.parity_chunks
|
pool_cfg.scheme == POOL_SCHEME_REPLICATED ? 1 : pool_cfg.pg_size-pool_cfg.parity_chunks
|
||||||
@@ -1618,11 +1614,14 @@ void cluster_client_t::handle_op_part(cluster_op_part_t *part)
|
|||||||
dirty_osds.insert(part->osd_num);
|
dirty_osds.insert(part->osd_num);
|
||||||
part->flags |= PART_DONE;
|
part->flags |= PART_DONE;
|
||||||
op->done_count++;
|
op->done_count++;
|
||||||
if ((op->opcode == OSD_OP_READ || op->opcode == OSD_OP_READ_BITMAP || op->opcode == OSD_OP_READ_CHAIN_BITMAP)
|
if (op->opcode == OSD_OP_READ || op->opcode == OSD_OP_READ_BITMAP || op->opcode == OSD_OP_READ_CHAIN_BITMAP)
|
||||||
&& op->inode == op->cur_inode)
|
|
||||||
{
|
{
|
||||||
// Read only returns the version of the uppermost layer
|
copy_part_bitmap(op, part);
|
||||||
op->version = op->parts.size() == 1 ? part->op.reply.rw.version : 0;
|
if (op->inode == op->cur_inode)
|
||||||
|
{
|
||||||
|
// Read only returns the version of the uppermost layer
|
||||||
|
op->version = op->parts.size() == 1 ? part->op.reply.rw.version : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (op->opcode == OSD_OP_WRITE || op->opcode == OSD_OP_DELETE)
|
else if (op->opcode == OSD_OP_WRITE || op->opcode == OSD_OP_DELETE)
|
||||||
{
|
{
|
||||||
@@ -1630,13 +1629,6 @@ void cluster_client_t::handle_op_part(cluster_op_part_t *part)
|
|||||||
}
|
}
|
||||||
if (op->inflight_count == 0 && !op->retry_after)
|
if (op->inflight_count == 0 && !op->retry_after)
|
||||||
{
|
{
|
||||||
// Copy part bitmaps only after finishing all part reads
|
|
||||||
if (op->opcode == OSD_OP_READ || op->opcode == OSD_OP_READ_BITMAP || op->opcode == OSD_OP_READ_CHAIN_BITMAP)
|
|
||||||
{
|
|
||||||
for (auto & part: op->parts)
|
|
||||||
if (part.flags == (PART_SENT|PART_VALID|PART_DONE))
|
|
||||||
copy_part_bitmap(op, &part);
|
|
||||||
}
|
|
||||||
if (op->opcode == OSD_OP_SYNC)
|
if (op->opcode == OSD_OP_SYNC)
|
||||||
continue_sync(op);
|
continue_sync(op);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#define PART_DONE 2
|
#define PART_DONE 2
|
||||||
#define PART_ERROR 4
|
#define PART_ERROR 4
|
||||||
#define PART_RETRY 8
|
#define PART_RETRY 8
|
||||||
#define PART_VALID 16
|
|
||||||
#define CACHE_DIRTY 1
|
#define CACHE_DIRTY 1
|
||||||
#define CACHE_WRITTEN 2
|
#define CACHE_WRITTEN 2
|
||||||
#define CACHE_FLUSHING 3
|
#define CACHE_FLUSHING 3
|
||||||
|
|||||||
@@ -431,6 +431,8 @@ msgr_rdma_connection_t *msgr_rdma_connection_t::create(msgr_rdma_context_t *ctx,
|
|||||||
conn->max_recv = max_recv;
|
conn->max_recv = max_recv;
|
||||||
conn->max_sge = max_sge;
|
conn->max_sge = max_sge;
|
||||||
conn->max_msg = max_msg;
|
conn->max_msg = max_msg;
|
||||||
|
conn->in_credit = max_recv;
|
||||||
|
conn->out_credit = max_recv;
|
||||||
|
|
||||||
ibv_qp_init_attr init_attr = {
|
ibv_qp_init_attr init_attr = {
|
||||||
.send_cq = ctx->cq,
|
.send_cq = ctx->cq,
|
||||||
@@ -571,9 +573,11 @@ static void try_send_rdma_wr(osd_client_t *cl, ibv_sge *sge, int op_sge)
|
|||||||
.wr_id = (uint64_t)(cl->peer_fd*2+1),
|
.wr_id = (uint64_t)(cl->peer_fd*2+1),
|
||||||
.sg_list = sge,
|
.sg_list = sge,
|
||||||
.num_sge = op_sge,
|
.num_sge = op_sge,
|
||||||
.opcode = IBV_WR_SEND,
|
.opcode = IBV_WR_SEND_WITH_IMM,
|
||||||
.send_flags = IBV_SEND_SIGNALED,
|
.send_flags = IBV_SEND_SIGNALED,
|
||||||
|
.imm_data = cl->rdma_conn->in_credit,
|
||||||
};
|
};
|
||||||
|
cl->rdma_conn->in_credit = 0;
|
||||||
int err = ibv_post_send(cl->rdma_conn->qp, &wr, &bad_wr);
|
int err = ibv_post_send(cl->rdma_conn->qp, &wr, &bad_wr);
|
||||||
if (err || bad_wr)
|
if (err || bad_wr)
|
||||||
{
|
{
|
||||||
@@ -581,6 +585,7 @@ static void try_send_rdma_wr(osd_client_t *cl, ibv_sge *sge, int op_sge)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
cl->rdma_conn->cur_send++;
|
cl->rdma_conn->cur_send++;
|
||||||
|
cl->rdma_conn->out_credit--;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int try_send_rdma_copy(osd_client_t *cl, uint8_t *dst, int dst_len)
|
static int try_send_rdma_copy(osd_client_t *cl, uint8_t *dst, int dst_len)
|
||||||
@@ -608,7 +613,7 @@ static int try_send_rdma_copy(osd_client_t *cl, uint8_t *dst, int dst_len)
|
|||||||
void osd_messenger_t::try_send_rdma_odp(osd_client_t *cl)
|
void osd_messenger_t::try_send_rdma_odp(osd_client_t *cl)
|
||||||
{
|
{
|
||||||
auto rc = cl->rdma_conn;
|
auto rc = cl->rdma_conn;
|
||||||
if (!cl->send_list.size() || rc->cur_send >= rc->max_send)
|
if (!cl->send_list.size() || rc->cur_send >= rc->max_send || !rc->out_credit)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -623,7 +628,7 @@ void osd_messenger_t::try_send_rdma_odp(osd_client_t *cl)
|
|||||||
try_send_rdma_wr(cl, sge, op_sge);
|
try_send_rdma_wr(cl, sge, op_sge);
|
||||||
op_sge = 0;
|
op_sge = 0;
|
||||||
op_size = 0;
|
op_size = 0;
|
||||||
if (rc->cur_send >= rc->max_send)
|
if (rc->cur_send >= rc->max_send || !rc->out_credit)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -672,7 +677,7 @@ void osd_messenger_t::try_send_rdma_nodp(osd_client_t *cl)
|
|||||||
uint8_t *dst = NULL;
|
uint8_t *dst = NULL;
|
||||||
int dst_len = 0;
|
int dst_len = 0;
|
||||||
int copied = 1;
|
int copied = 1;
|
||||||
while (!rc->send_out_full && copied > 0 && rc->cur_send < rc->max_send)
|
while (!rc->send_out_full && copied > 0 && rc->cur_send < rc->max_send && rc->out_credit > 0)
|
||||||
{
|
{
|
||||||
dst = (uint8_t*)rc->send_out.buf + rc->send_out_pos;
|
dst = (uint8_t*)rc->send_out.buf + rc->send_out_pos;
|
||||||
dst_len = (rc->send_out_pos < rc->send_out_size ? rc->send_out_size-rc->send_out_pos : rc->send_done_pos-rc->send_out_pos);
|
dst_len = (rc->send_out_pos < rc->send_out_size ? rc->send_out_size-rc->send_out_pos : rc->send_done_pos-rc->send_out_pos);
|
||||||
@@ -696,6 +701,16 @@ void osd_messenger_t::try_send_rdma_nodp(osd_client_t *cl)
|
|||||||
rc->send_sizes.push_back(copied);
|
rc->send_sizes.push_back(copied);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rc->cur_send < rc->max_send && rc->in_credit > 0)
|
||||||
|
{
|
||||||
|
ibv_sge sge = {
|
||||||
|
.addr = (uintptr_t)NULL,
|
||||||
|
.length = (uint32_t)0,
|
||||||
|
.lkey = 0,
|
||||||
|
};
|
||||||
|
try_send_rdma_wr(cl, &sge, 1);
|
||||||
|
rc->send_sizes.push_back(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_messenger_t::try_send_rdma(osd_client_t *cl)
|
void osd_messenger_t::try_send_rdma(osd_client_t *cl)
|
||||||
@@ -726,6 +741,7 @@ static void try_recv_rdma_wr(osd_client_t *cl, void *buf)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
cl->rdma_conn->cur_recv++;
|
cl->rdma_conn->cur_recv++;
|
||||||
|
cl->rdma_conn->in_credit++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool osd_messenger_t::init_recv_rdma(osd_client_t *cl)
|
bool osd_messenger_t::init_recv_rdma(osd_client_t *cl)
|
||||||
@@ -799,6 +815,10 @@ void osd_messenger_t::handle_rdma_events(msgr_rdma_context_t *rdma_context)
|
|||||||
if (!is_send)
|
if (!is_send)
|
||||||
{
|
{
|
||||||
// Reset OSD ping state - client is obviously alive
|
// Reset OSD ping state - client is obviously alive
|
||||||
|
if (wc[i].wc_flags & IBV_WC_WITH_IMM)
|
||||||
|
{
|
||||||
|
rc->out_credit += wc[i].imm_data;
|
||||||
|
}
|
||||||
cl->ping_time_remaining = 0;
|
cl->ping_time_remaining = 0;
|
||||||
cl->idle_time_remaining = osd_idle_timeout;
|
cl->idle_time_remaining = osd_idle_timeout;
|
||||||
rc->cur_recv--;
|
rc->cur_recv--;
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ struct msgr_rdma_connection_t
|
|||||||
int send_out_pos = 0, send_done_pos = 0, send_out_size = 0;
|
int send_out_pos = 0, send_done_pos = 0, send_out_size = 0;
|
||||||
bool send_out_full = false;
|
bool send_out_full = false;
|
||||||
|
|
||||||
|
uint32_t out_credit = 0, in_credit = 0;
|
||||||
|
|
||||||
~msgr_rdma_connection_t();
|
~msgr_rdma_connection_t();
|
||||||
static msgr_rdma_connection_t *create(msgr_rdma_context_t *ctx, uint32_t max_send, uint32_t max_recv, uint32_t max_sge, uint32_t max_msg);
|
static msgr_rdma_connection_t *create(msgr_rdma_context_t *ctx, uint32_t max_send, uint32_t max_recv, uint32_t max_sge, uint32_t max_msg);
|
||||||
int connect(msgr_rdma_address_t *dest);
|
int connect(msgr_rdma_address_t *dest);
|
||||||
|
|||||||
@@ -326,10 +326,8 @@ void osd_messenger_t::handle_send(int result, bool prev, bool more, osd_client_t
|
|||||||
int expected = cl->send_list.size() < IOV_MAX ? cl->send_list.size() : IOV_MAX;
|
int expected = cl->send_list.size() < IOV_MAX ? cl->send_list.size() : IOV_MAX;
|
||||||
if (done != expected)
|
if (done != expected)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Client %d socket write error: expected to send "
|
fprintf(stderr, "BUG (maybe kernel): Expected to send %d iovecs with MSG_WAITALL but sent %d\n", expected, done);
|
||||||
"%d iovecs with MSG_WAITALL but sent %d. Disconnecting client\n", cl->peer_fd, expected, done);
|
exit(1);
|
||||||
stop_client(cl->peer_fd);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
cl->zc_free_list.push_back(NULL); // end marker
|
cl->zc_free_list.push_back(NULL); // end marker
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,13 +158,6 @@ osd_client_t::~osd_client_t()
|
|||||||
}
|
}
|
||||||
// Cancel outbound ops
|
// Cancel outbound ops
|
||||||
cancel_ops();
|
cancel_ops();
|
||||||
for (osd_op_t *op: zc_free_list)
|
|
||||||
{
|
|
||||||
if (op)
|
|
||||||
{
|
|
||||||
delete op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef __MOCK__
|
#ifndef __MOCK__
|
||||||
#ifdef WITH_RDMA
|
#ifdef WITH_RDMA
|
||||||
if (rdma_conn)
|
if (rdma_conn)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
|||||||
|
|
||||||
Name: Vitastor
|
Name: Vitastor
|
||||||
Description: Vitastor client library
|
Description: Vitastor client library
|
||||||
Version: 3.0.1
|
Version: 3.0.0
|
||||||
Libs: -L${libdir} -lvitastor_client
|
Libs: -L${libdir} -lvitastor_client
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -111,7 +111,7 @@ struct dd_in_info_t
|
|||||||
{
|
{
|
||||||
in_granularity = 512;
|
in_granularity = 512;
|
||||||
}
|
}
|
||||||
if (lseek(ifd, 1, SEEK_SET) != (off_t)1)
|
if (lseek(ifd, 1, SEEK_SET) == (off_t)-1)
|
||||||
{
|
{
|
||||||
in_seekable = false;
|
in_seekable = false;
|
||||||
}
|
}
|
||||||
@@ -389,7 +389,7 @@ struct cli_dd_t
|
|||||||
int state = 0;
|
int state = 0;
|
||||||
int copy_error = 0;
|
int copy_error = 0;
|
||||||
int in_waiting = 0, out_waiting = 0;
|
int in_waiting = 0, out_waiting = 0;
|
||||||
cli_result_t result = {};
|
cli_result_t result;
|
||||||
|
|
||||||
bool is_done()
|
bool is_done()
|
||||||
{
|
{
|
||||||
@@ -931,8 +931,7 @@ close_end:
|
|||||||
oinfo.close_output(parent);
|
oinfo.close_output(parent);
|
||||||
iinfo.close_input(parent);
|
iinfo.close_input(parent);
|
||||||
// Done
|
// Done
|
||||||
if (copy_error)
|
result.err = copy_error;
|
||||||
result.err = copy_error;
|
|
||||||
state = 100;
|
state = 100;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -120,23 +120,12 @@ resume_1:
|
|||||||
else
|
else
|
||||||
osd_cfg.erase("noout");
|
osd_cfg.erase("noout");
|
||||||
}
|
}
|
||||||
if (osd_cfg_mod_rev)
|
compare.push_back(json11::Json::object {
|
||||||
{
|
{ "target", "MOD" },
|
||||||
compare.push_back(json11::Json::object {
|
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/osd/"+std::to_string(osd_num)) },
|
||||||
{ "target", "MOD" },
|
{ "result", "LESS" },
|
||||||
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/osd/"+std::to_string(osd_num)) },
|
{ "mod_revision", osd_cfg_mod_rev+1 },
|
||||||
{ "result", "LESS" },
|
});
|
||||||
{ "mod_revision", osd_cfg_mod_rev+1 },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
compare.push_back(json11::Json::object {
|
|
||||||
{ "target", "VERSION" },
|
|
||||||
{ "key", base64_encode(parent->cli->st_cli.etcd_prefix+"/config/osd/"+std::to_string(osd_num)) },
|
|
||||||
{ "version", 0 },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!osd_cfg.size())
|
if (!osd_cfg.size())
|
||||||
{
|
{
|
||||||
success.push_back(json11::Json::object {
|
success.push_back(json11::Json::object {
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ static const char *help_text =
|
|||||||
" --force Bypass partition safety checks (for emptiness and so on)\n"
|
" --force Bypass partition safety checks (for emptiness and so on)\n"
|
||||||
" \n"
|
" \n"
|
||||||
" Options (both modes):\n"
|
" Options (both modes):\n"
|
||||||
" --tags tag1,tag2 Set new OSD tag(s)\n"
|
|
||||||
" --weight <number> Set new OSD weight (between 0 and 1)\n"
|
|
||||||
" --journal_size 32M/1G Set journal size (area or partition size)\n"
|
" --journal_size 32M/1G Set journal size (area or partition size)\n"
|
||||||
" --block_size 128k/1M Set blockstore object size\n"
|
" --block_size 128k/1M Set blockstore object size\n"
|
||||||
" --bitmap_granularity 4k Set bitmap granularity\n"
|
" --bitmap_granularity 4k Set bitmap granularity\n"
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ struct disk_tool_t
|
|||||||
uint32_t new_meta_format = 0;
|
uint32_t new_meta_format = 0;
|
||||||
int new_journal_fd = -1, new_meta_fd = -1;
|
int new_journal_fd = -1, new_meta_fd = -1;
|
||||||
resizer_data_moving_t *moving_blocks = NULL;
|
resizer_data_moving_t *moving_blocks = NULL;
|
||||||
bool atomic_warned = false;
|
|
||||||
|
|
||||||
bool started = false;
|
bool started = false;
|
||||||
void *small_write_data = NULL;
|
void *small_write_data = NULL;
|
||||||
|
|||||||
@@ -78,37 +78,25 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options, int is_
|
|||||||
if (check_existing_partition(dev) != 0)
|
if (check_existing_partition(dev) != 0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (options.find("weight") != options.end())
|
|
||||||
{
|
|
||||||
double reweight = json11::Json(options["weight"]).number_value();
|
|
||||||
if (reweight < 0 || reweight > 1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "OSD weight must be between 0 and 1\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (options.find("atomic_write_size") == options.end())
|
if (options.find("atomic_write_size") == options.end())
|
||||||
{
|
{
|
||||||
auto data_dev = realpath_str(options["data_device"], false);
|
auto data_dev = realpath_str(options["data_device"], false);
|
||||||
if (data_dev.substr(0, 9) == "/dev/nvme")
|
uint64_t atomic_write_size = get_atomic_write_size(data_dev);
|
||||||
|
if (atomic_write_size > 4096)
|
||||||
{
|
{
|
||||||
uint64_t atomic_write_size = get_atomic_write_size(data_dev);
|
fprintf(stderr, "Data device %s supports atomic writes up to %ju bytes, enabling. Enjoy faster writes!\n",
|
||||||
if (atomic_write_size > 4096)
|
data_dev.c_str(), atomic_write_size);
|
||||||
{
|
options["atomic_write_size"] = std::to_string(atomic_write_size);
|
||||||
// FIXME: Enable use_atomic_flag when the kernel does checks correctly
|
options["use_atomic_flag"] = "1";
|
||||||
fprintf(stderr, "Data device %s supports atomic writes up to %ju bytes, enabling. Enjoy faster writes!\n",
|
|
||||||
data_dev.c_str(), atomic_write_size);
|
|
||||||
options["atomic_write_size"] = std::to_string(atomic_write_size);
|
|
||||||
if (!atomic_warned)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "WARNING: RWF_ATOMIC can't be used because Linux checks atomic writes incorrectly.\n"
|
|
||||||
" Please don't change scheduler from default 'none' and check use_atomic_flag documentation for more details.\n");
|
|
||||||
atomic_warned = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (options.find("use_atomic_flag") == options.end() &&
|
||||||
|
parse_size(options["atomic_write_size"]) > 4096)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Atomic writes larger than 4 KB are enabled manually, enabling use_atomic_flag too.\n");
|
||||||
|
options["use_atomic_flag"] = "1";
|
||||||
|
}
|
||||||
for (auto dev: std::vector<std::string>{"data", "meta", "journal"})
|
for (auto dev: std::vector<std::string>{"data", "meta", "journal"})
|
||||||
{
|
{
|
||||||
if (options[dev+"_device"] != "" && options["disable_"+dev+"_fsync"] == "auto")
|
if (options[dev+"_device"] != "" && options["disable_"+dev+"_fsync"] == "auto")
|
||||||
@@ -250,28 +238,9 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options, int is_
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
sb["osd_num"] = osd_num;
|
sb["osd_num"] = osd_num;
|
||||||
if (options.find("weight") != options.end() || options.find("tags") != options.end())
|
// Zero out metadata and journal
|
||||||
{
|
if (write_zero(dsk.meta_fd, sb["meta_offset"].uint64_value(), dsk.meta_area_size) != 0 ||
|
||||||
std::vector<std::string> cmd = { "vitastor-cli", "modify-osd", std::to_string(osd_num) };
|
write_zero(dsk.journal_fd, sb["journal_offset"].uint64_value(), dsk.journal_len) != 0)
|
||||||
if (options.find("weight") != options.end())
|
|
||||||
{
|
|
||||||
cmd.push_back("--reweight");
|
|
||||||
cmd.push_back(options["weight"]);
|
|
||||||
}
|
|
||||||
if (options.find("tags") != options.end())
|
|
||||||
{
|
|
||||||
cmd.push_back("--tags");
|
|
||||||
cmd.push_back(options["tags"]);
|
|
||||||
}
|
|
||||||
if (shell_exec(cmd, "", NULL, NULL) != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed to modify OSD %ju tags and/or reweight\n", osd_num);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Zero out the first block of metadata and journal - OSD will zero the rest on the first run
|
|
||||||
if (write_zero(dsk.meta_fd, sb["meta_offset"].uint64_value(), 4096) != 0 ||
|
|
||||||
write_zero(dsk.journal_fd, sb["journal_offset"].uint64_value(), 4096) != 0)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to zero out metadata or journal: %s\n", strerror(errno));
|
fprintf(stderr, "Failed to zero out metadata or journal: %s\n", strerror(errno));
|
||||||
dsk.close_all();
|
dsk.close_all();
|
||||||
|
|||||||
+2
-4
@@ -104,10 +104,8 @@ struct nfs_rmw_t
|
|||||||
nfs_proxy_t *parent = NULL;
|
nfs_proxy_t *parent = NULL;
|
||||||
uint64_t ino = 0;
|
uint64_t ino = 0;
|
||||||
uint64_t offset = 0;
|
uint64_t offset = 0;
|
||||||
uint8_t *buf1 = NULL;
|
uint8_t *buf = NULL;
|
||||||
uint64_t size1 = 0;
|
uint64_t size = 0;
|
||||||
uint8_t *buf2 = NULL;
|
|
||||||
uint64_t size2 = 0;
|
|
||||||
uint8_t *part_buf = NULL;
|
uint8_t *part_buf = NULL;
|
||||||
uint64_t version = 0;
|
uint64_t version = 0;
|
||||||
nfs_rmw_t *other = NULL;
|
nfs_rmw_t *other = NULL;
|
||||||
|
|||||||
+27
-45
@@ -185,8 +185,8 @@ void nfs_do_rmw(nfs_rmw_t *rmw)
|
|||||||
{
|
{
|
||||||
auto parent = rmw->parent;
|
auto parent = rmw->parent;
|
||||||
auto align = parent->kvfs->pool_alignment;
|
auto align = parent->kvfs->pool_alignment;
|
||||||
assert(rmw->size1+rmw->size2 < align);
|
assert(rmw->size < align);
|
||||||
assert((rmw->offset/parent->kvfs->pool_block_size) == ((rmw->offset+rmw->size1+rmw->size2-1)/parent->kvfs->pool_block_size));
|
assert((rmw->offset/parent->kvfs->pool_block_size) == ((rmw->offset+rmw->size-1)/parent->kvfs->pool_block_size));
|
||||||
if (!rmw->part_buf)
|
if (!rmw->part_buf)
|
||||||
{
|
{
|
||||||
rmw->part_buf = (uint8_t*)malloc_or_die(align);
|
rmw->part_buf = (uint8_t*)malloc_or_die(align);
|
||||||
@@ -221,7 +221,7 @@ void nfs_do_rmw(nfs_rmw_t *rmw)
|
|||||||
}
|
}
|
||||||
auto align = parent->kvfs->pool_alignment;
|
auto align = parent->kvfs->pool_alignment;
|
||||||
bool is_begin = (rmw->offset % align);
|
bool is_begin = (rmw->offset % align);
|
||||||
bool is_end = ((rmw->offset+rmw->size1+rmw->size2) % align);
|
bool is_end = ((rmw->offset+rmw->size) % align);
|
||||||
auto op = new cluster_op_t;
|
auto op = new cluster_op_t;
|
||||||
op->opcode = OSD_OP_WRITE;
|
op->opcode = OSD_OP_WRITE;
|
||||||
op->inode = rmw->ino;
|
op->inode = rmw->ino;
|
||||||
@@ -232,17 +232,10 @@ void nfs_do_rmw(nfs_rmw_t *rmw)
|
|||||||
{
|
{
|
||||||
op->iov.push_back(rmw->part_buf, rmw->offset % align);
|
op->iov.push_back(rmw->part_buf, rmw->offset % align);
|
||||||
}
|
}
|
||||||
if (rmw->buf1)
|
op->iov.push_back(rmw->buf, rmw->size);
|
||||||
{
|
|
||||||
op->iov.push_back(rmw->buf1, rmw->size1);
|
|
||||||
}
|
|
||||||
if (rmw->buf2)
|
|
||||||
{
|
|
||||||
op->iov.push_back(rmw->buf2, rmw->size2);
|
|
||||||
}
|
|
||||||
if (is_end)
|
if (is_end)
|
||||||
{
|
{
|
||||||
op->iov.push_back(rmw->part_buf + (rmw->offset % align) + rmw->size1 + rmw->size2, align - (rmw->offset % align) - rmw->size1 - rmw->size2);
|
op->iov.push_back(rmw->part_buf + (rmw->offset % align) + rmw->size, align - (rmw->offset % align) - rmw->size);
|
||||||
}
|
}
|
||||||
op->callback = [rmw](cluster_op_t *op)
|
op->callback = [rmw](cluster_op_t *op)
|
||||||
{
|
{
|
||||||
@@ -453,9 +446,9 @@ static void nfs_do_align_write(nfs_kv_write_state *st, uint64_t ino, uint64_t of
|
|||||||
uint64_t good_offset = offset;
|
uint64_t good_offset = offset;
|
||||||
uint64_t good_size = st->size;
|
uint64_t good_size = st->size;
|
||||||
bool begin_shdr = false;
|
bool begin_shdr = false;
|
||||||
|
uint64_t end_pad = 0;
|
||||||
st->waiting++;
|
st->waiting++;
|
||||||
st->rmw[0].buf1 = st->rmw[1].buf1 = NULL;
|
st->rmw[0].buf = st->rmw[1].buf = NULL;
|
||||||
st->rmw[0].buf2 = st->rmw[1].buf2 = NULL;
|
|
||||||
auto make_rmw_cb = [st, state]()
|
auto make_rmw_cb = [st, state]()
|
||||||
{
|
{
|
||||||
return [st, state](nfs_rmw_t *rmw)
|
return [st, state](nfs_rmw_t *rmw)
|
||||||
@@ -480,7 +473,7 @@ static void nfs_do_align_write(nfs_kv_write_state *st, uint64_t ino, uint64_t of
|
|||||||
};
|
};
|
||||||
begin_shdr = true;
|
begin_shdr = true;
|
||||||
good_offset -= sizeof(shared_file_header_t);
|
good_offset -= sizeof(shared_file_header_t);
|
||||||
offset -= sizeof(shared_file_header_t);
|
offset = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -499,8 +492,8 @@ static void nfs_do_align_write(nfs_kv_write_state *st, uint64_t ino, uint64_t of
|
|||||||
.parent = st->proxy,
|
.parent = st->proxy,
|
||||||
.ino = ino,
|
.ino = ino,
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
.buf1 = st->buf,
|
.buf = st->buf,
|
||||||
.size1 = s,
|
.size = s,
|
||||||
.cb = make_rmw_cb(),
|
.cb = make_rmw_cb(),
|
||||||
};
|
};
|
||||||
st->waiting++;
|
st->waiting++;
|
||||||
@@ -508,26 +501,14 @@ static void nfs_do_align_write(nfs_kv_write_state *st, uint64_t ino, uint64_t of
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((end % alignment) &&
|
if ((end % alignment) &&
|
||||||
((end-1)/alignment > offset/alignment || offset == ((end-1) & ~(alignment-1))))
|
(offset == 0 || end/alignment > (offset-1)/alignment))
|
||||||
{
|
{
|
||||||
// Requires read-modify-write in the end
|
// Requires read-modify-write in the end
|
||||||
assert(st->offset+st->size <= st->new_size);
|
assert(st->offset+st->size <= st->new_size);
|
||||||
if ((end-1)/alignment == offset/alignment && begin_shdr)
|
if (st->offset+st->size == st->new_size)
|
||||||
{
|
{
|
||||||
// end is at the same moment the beginning with a shared header
|
// rmw can be skipped at end - we can just zero pad the request
|
||||||
assert(!(offset % alignment) && good_size == st->size);
|
end_pad = alignment - (end % alignment);
|
||||||
st->rmw[1] = (nfs_rmw_t){
|
|
||||||
.parent = st->proxy,
|
|
||||||
.ino = ino,
|
|
||||||
.offset = offset,
|
|
||||||
.buf1 = (uint8_t*)&st->shdr,
|
|
||||||
.size1 = sizeof(shared_file_header_t),
|
|
||||||
.buf2 = st->buf,
|
|
||||||
.size2 = st->size,
|
|
||||||
.cb = make_rmw_cb(),
|
|
||||||
};
|
|
||||||
good_size = 0;
|
|
||||||
begin_shdr = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -540,28 +521,29 @@ static void nfs_do_align_write(nfs_kv_write_state *st, uint64_t ino, uint64_t of
|
|||||||
.parent = st->proxy,
|
.parent = st->proxy,
|
||||||
.ino = ino,
|
.ino = ino,
|
||||||
.offset = end - s,
|
.offset = end - s,
|
||||||
.buf2 = st->buf + st->size - s,
|
.buf = st->buf + st->size - s,
|
||||||
.size2 = s,
|
.size = s,
|
||||||
.cb = make_rmw_cb(),
|
.cb = make_rmw_cb(),
|
||||||
};
|
};
|
||||||
|
if (st->rmw[0].buf)
|
||||||
|
{
|
||||||
|
st->rmw[0].other = &st->rmw[1];
|
||||||
|
st->rmw[1].other = &st->rmw[0];
|
||||||
|
}
|
||||||
|
st->waiting++;
|
||||||
|
nfs_do_rmw(&st->rmw[1]);
|
||||||
}
|
}
|
||||||
if (st->rmw[0].buf1)
|
|
||||||
{
|
|
||||||
st->rmw[0].other = &st->rmw[1];
|
|
||||||
st->rmw[1].other = &st->rmw[0];
|
|
||||||
}
|
|
||||||
st->waiting++;
|
|
||||||
nfs_do_rmw(&st->rmw[1]);
|
|
||||||
}
|
}
|
||||||
assert(!begin_shdr || good_size > 0);
|
if (good_size > 0 || end_pad > 0 || begin_shdr)
|
||||||
if (good_size > 0)
|
|
||||||
{
|
{
|
||||||
// Normal write
|
// Normal write
|
||||||
nfs_do_write(ino, good_offset, (begin_shdr ? sizeof(shared_file_header_t) : 0)+good_size, [&](cluster_op_t *op)
|
nfs_do_write(ino, good_offset, (begin_shdr ? sizeof(shared_file_header_t) : 0)+good_size+end_pad, [&](cluster_op_t *op)
|
||||||
{
|
{
|
||||||
if (begin_shdr)
|
if (begin_shdr)
|
||||||
op->iov.push_back(&st->shdr, sizeof(shared_file_header_t));
|
op->iov.push_back(&st->shdr, sizeof(shared_file_header_t));
|
||||||
op->iov.push_back(good_buf, good_size);
|
op->iov.push_back(good_buf, good_size);
|
||||||
|
if (end_pad)
|
||||||
|
op->iov.push_back(st->proxy->kvfs->zero_block.data(), end_pad);
|
||||||
}, st, state);
|
}, st, state);
|
||||||
}
|
}
|
||||||
st->waiting--;
|
st->waiting--;
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ OLD=1 SCHEME=ec IMMEDIATE_COMMIT=1 ./test_interrupted_rebalance.sh
|
|||||||
|
|
||||||
./test_failure_domain.sh
|
./test_failure_domain.sh
|
||||||
|
|
||||||
./test_level_placement.sh
|
|
||||||
|
|
||||||
./test_snapshot.sh
|
./test_snapshot.sh
|
||||||
SCHEME=ec ./test_snapshot.sh
|
SCHEME=ec ./test_snapshot.sh
|
||||||
OLD=1 ./test_snapshot.sh
|
OLD=1 ./test_snapshot.sh
|
||||||
@@ -147,4 +145,3 @@ TEST_NAME=old_csum_4k_dj OLD=1 OSD_ARGS="--data_csum_type crc32c --inmemory_jo
|
|||||||
TEST_NAME=old_csum_4k OLD=1 OSD_ARGS="--data_csum_type crc32c" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh
|
TEST_NAME=old_csum_4k OLD=1 OSD_ARGS="--data_csum_type crc32c" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh
|
||||||
|
|
||||||
./test_nfs.sh
|
./test_nfs.sh
|
||||||
./test_nfs_unaligned_append.sh
|
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash -ex
|
|
||||||
|
|
||||||
. `dirname $0`/common.sh
|
|
||||||
|
|
||||||
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
|
|
||||||
MON_PID=$!
|
|
||||||
wait_etcd
|
|
||||||
|
|
||||||
TIME=$(date '+%s')
|
|
||||||
$ETCDCTL put /vitastor/config/global '{"placement_levels":{"rack":1,"host":2,"osd":3},"immediate_commit":"none"}'
|
|
||||||
$ETCDCTL put /vitastor/config/node_placement '{"rack1":{"level":"rack"},"rack2":{"level":"rack"},"rack3":{"level":"rack"},"rack4":{"level":"rack"},
|
|
||||||
"host1":{"level":"host","parent":"rack1"},"host2":{"level":"host","parent":"rack1"},
|
|
||||||
"host3":{"level":"host","parent":"rack2"},"host4":{"level":"host","parent":"rack2"},
|
|
||||||
"host5":{"level":"host","parent":"rack3"},"host6":{"level":"host","parent":"rack3"},
|
|
||||||
"host7":{"level":"host","parent":"rack4"},"host8":{"level":"host","parent":"rack4"}}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/1 '{"host":"host1","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/2 '{"host":"host1","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/3 '{"host":"host2","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/4 '{"host":"host2","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/5 '{"host":"host3","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/6 '{"host":"host3","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/7 '{"host":"host4","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/8 '{"host":"host4","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/9 '{"host":"host5","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/10 '{"host":"host5","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/11 '{"host":"host6","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/12 '{"host":"host6","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/13 '{"host":"host7","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/14 '{"host":"host7","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/15 '{"host":"host8","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
$ETCDCTL put /vitastor/osd/stats/16 '{"host":"host8","size":1073741824,"time":"'$TIME'"}'
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool --failure_domain host --level_placement rack=112233 --ec 4+2 -n 32
|
|
||||||
sleep 2
|
|
||||||
$ETCDCTL get --prefix /vitastor/pg/config --print-value-only | \
|
|
||||||
jq -s -e '([ .[0].items["1"] | .[].osd_set | map_values(. | tonumber) | select(
|
|
||||||
(. | map_values((. - 1) / 2 | floor) | unique | length) == 6 and
|
|
||||||
(. | map_values((. - 1) / 4 | floor) | unique | length) == 3) ] | length) == 32'
|
|
||||||
|
|
||||||
format_green OK
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#!/bin/bash -ex
|
|
||||||
|
|
||||||
GLOBAL_CONFIG=',"client_enable_writeback":false'
|
|
||||||
IMMEDIATE_COMMIT=1
|
|
||||||
PG_COUNT=16
|
|
||||||
. `dirname $0`/run_3osds.sh
|
|
||||||
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 10G fsmeta
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool --used-for-app fs:fsmeta testpool
|
|
||||||
build/src/nfs/vitastor-nfs start --fs fsmeta --etcd_address $ETCD_URL --portmap 0 --port 2050 --foreground 1 --trace 1 >>./testdata/nfs.log 2>&1 &
|
|
||||||
NFS_PID=$!
|
|
||||||
|
|
||||||
mkdir -p testdata/nfs
|
|
||||||
sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp
|
|
||||||
MNT=$(pwd)/testdata/nfs
|
|
||||||
trap "sudo umount -f $MNT"' || true; kill -9 $(jobs -p)' EXIT
|
|
||||||
|
|
||||||
# big file
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd if=/dev/urandom of=./testdata/ref_data.bin bs=1M count=32 seek=1024B
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd if=./testdata/ref_data.bin of=$MNT/testfile oflag=direct bs=1M iodepth=4 seek=1024B skip=1024B
|
|
||||||
cp $MNT/testfile ./testdata/nfs_data.bin
|
|
||||||
if ! diff -q ./testdata/ref_data.bin $MNT/testfile; then
|
|
||||||
format_error 'Data lost during parallel unaligned writes to VitastorFS'
|
|
||||||
fi
|
|
||||||
|
|
||||||
# small shared file
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd if=/dev/urandom of=./testdata/ref_small.bin bs=10 count=500 seek=15B
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd if=./testdata/ref_small.bin of=$MNT/smallfile oflag=direct bs=10 iodepth=4 seek=15B skip=15B
|
|
||||||
cp $MNT/smallfile ./testdata/nfs_small.bin
|
|
||||||
if ! diff -q ./testdata/ref_small.bin $MNT/smallfile; then
|
|
||||||
format_error 'Data lost during parallel unaligned writes to a small file in VitastorFS'
|
|
||||||
fi
|
|
||||||
|
|
||||||
format_green OK
|
|
||||||
@@ -13,18 +13,13 @@ build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 128M testchain -p
|
|||||||
|
|
||||||
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
||||||
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 -fsync=1 -rw=write \
|
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 -fsync=1 -rw=write \
|
||||||
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
|
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd
|
||||||
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@snap1 -p testpool2
|
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@snap1 -p testpool2
|
||||||
|
|
||||||
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
||||||
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
|
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
|
||||||
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
|
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd
|
||||||
|
|
||||||
# Read from the first snapshot
|
|
||||||
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=128k iodepth=4 --log_level 10
|
|
||||||
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
|
|
||||||
|
|
||||||
# Create a second snapshot - there was a bug where snapshotted reads from another pool
|
# Create a second snapshot - there was a bug where snapshotted reads from another pool
|
||||||
# were working only when the image and the snapshot were modified in the same revision
|
# were working only when the image and the snapshot were modified in the same revision
|
||||||
@@ -33,7 +28,7 @@ build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@snap2
|
|||||||
|
|
||||||
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
||||||
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
|
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
|
||||||
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
|
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd
|
||||||
|
|
||||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=128k iodepth=4 --log_level 10
|
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=128k iodepth=4 --log_level 10
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user