Compare commits

..
1 Commits
Author SHA1 Message Date
Vitaliy Filippov 68985bee0a WIP RDMA credits 2025-12-12 18:11:36 +00:00
108 changed files with 552 additions and 1272 deletions
-54
View File
@@ -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
@@ -1818,24 +1800,6 @@ jobs:
echo "" echo ""
done done
test_old_partwr_csum:
runs-on: ubuntu-latest
needs: build
container: ${{env.TEST_IMAGE}}:${{github.sha}}
steps:
- name: Run test
id: test
timeout-minutes: 3
run: OLD=1 /root/vitastor/tests/test_partwr_csum.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_heal_old_csum_32k_dmj: test_heal_old_csum_32k_dmj:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
@@ -1962,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
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12)
project(vitastor) project(vitastor)
set(VITASTOR_VERSION "3.0.2") set(VITASTOR_VERSION "3.0.0")
include(CTest) include(CTest)
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.2 VITASTOR_VERSION ?= v3.0.0
all: build push all: build push
+1 -1
View File
@@ -49,7 +49,7 @@ spec:
capabilities: capabilities:
add: ["SYS_ADMIN"] add: ["SYS_ADMIN"]
allowPrivilegeEscalation: true allowPrivilegeEscalation: true
image: vitalif/vitastor-csi:v3.0.2 image: vitalif/vitastor-csi:v3.0.0
args: args:
- "--node=$(NODE_ID)" - "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -121,7 +121,7 @@ spec:
privileged: true privileged: true
capabilities: capabilities:
add: ["SYS_ADMIN"] add: ["SYS_ADMIN"]
image: vitalif/vitastor-csi:v3.0.2 image: vitalif/vitastor-csi:v3.0.0
args: args:
- "--node=$(NODE_ID)" - "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -5,7 +5,7 @@ package vitastor
const ( const (
vitastorCSIDriverName = "csi.vitastor.io" vitastorCSIDriverName = "csi.vitastor.io"
vitastorCSIDriverVersion = "3.0.2" vitastorCSIDriverVersion = "3.0.0"
) )
// Config struct fills the parameters of request or user input // Config struct fills the parameters of request or user input
+1 -1
View File
@@ -1,4 +1,4 @@
vitastor (3.0.2-1) unstable; urgency=medium vitastor (3.0.0-1) unstable; urgency=medium
* Bugfixes * Bugfixes
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.2 VITASTOR_VERSION ?= v3.0.0
all: build push all: build push
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# Desired Vitastor version # Desired Vitastor version
VITASTOR_VERSION=v3.0.2 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 -36
View File
@@ -67,8 +67,6 @@ with an OSD restart or, for some of them, even without restarting by updating co
- [pg_lock_retry_interval_ms](#pg_lock_retry_interval_ms) - [pg_lock_retry_interval_ms](#pg_lock_retry_interval_ms)
- [atomic_write_size](#atomic_write_size) - [atomic_write_size](#atomic_write_size)
- [use_atomic_flag](#use_atomic_flag) - [use_atomic_flag](#use_atomic_flag)
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
## bind_address ## bind_address
@@ -684,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,
@@ -702,34 +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.
## pg_reshard_chunk_size
- Type: integer
- Default: 100000
Pool PG count change is a CPU-intensive operation because OSDs store the full object database
in memory and have to move all entries between old and new PGs. Thus it's performed in chunks,
with pauses between chunks to prevent blocking OSD's event loop and other clients' operations.
This option sets the maximum number of object is a chunk. Moving 100k objects usually takes
50-100ms. Chunk size equal to 0 means unlimited.
## pg_reshard_chunk_pause_ms
- Type: milliseconds
- Default: 100
This option sets the interval between handling two PG count change chunks.
+7 -36
View File
@@ -68,8 +68,6 @@
- [pg_lock_retry_interval_ms](#pg_lock_retry_interval_ms) - [pg_lock_retry_interval_ms](#pg_lock_retry_interval_ms)
- [atomic_write_size](#atomic_write_size) - [atomic_write_size](#atomic_write_size)
- [use_atomic_flag](#use_atomic_flag) - [use_atomic_flag](#use_atomic_flag)
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
## bind_address ## bind_address
@@ -719,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
@@ -740,35 +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)
и включить данную опцию. Это сделает вашу атомарную запись капельку безопаснее.
## pg_reshard_chunk_size
- Тип: целое число
- Значение по умолчанию: 100000
Изменение числа PG в пуле заметно загружает процессор, так как OSD хранят полную базу данных
объектов в памяти и им приходится перемещать все записи объектов между старыми и новыми PG.
Поэтому изменение применяется порциями, с паузами между порциями, чтобы не блокировать обработку
событий OSD и операции остальных клиентов. Данная опция задаёт максимальное число объектов
в порции. Перемещение 100 тысяч объектов (значение по умолчанию) обычно занимает порядка
50-100 миллисекунд. Значение опции 0 отключает лимит размера порции.
## pg_reshard_chunk_pause_ms
- Тип: миллисекунды
- Значение по умолчанию: 100
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
+16 -54
View File
@@ -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,54 +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)
и включить данную опцию. Это сделает вашу атомарную запись капельку безопаснее.
- name: pg_reshard_chunk_size
type: int
default: 100000
info: |
Pool PG count change is a CPU-intensive operation because OSDs store the full object database
in memory and have to move all entries between old and new PGs. Thus it's performed in chunks,
with pauses between chunks to prevent blocking OSD's event loop and other clients' operations.
This option sets the maximum number of object is a chunk. Moving 100k objects usually takes
50-100ms. Chunk size equal to 0 means unlimited.
info_ru: |
Изменение числа PG в пуле заметно загружает процессор, так как OSD хранят полную базу данных
объектов в памяти и им приходится перемещать все записи объектов между старыми и новыми PG.
Поэтому изменение применяется порциями, с паузами между порциями, чтобы не блокировать обработку
событий OSD и операции остальных клиентов. Данная опция задаёт максимальное число объектов
в порции. Перемещение 100 тысяч объектов (значение по умолчанию) обычно занимает порядка
50-100 миллисекунд. Значение опции 0 отключает лимит размера порции.
- name: pg_reshard_chunk_pause_ms
type: ms
default: 100
info: |
This option sets the interval between handling two PG count change chunks.
info_ru: |
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
+2 -2
View File
@@ -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.2` `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.2 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`
+2 -2
View File
@@ -25,9 +25,9 @@ Vitastor можно установить в Docker/Podman. При этом etcd,
Инструкция по установке максимально простая. Инструкция по установке максимально простая.
1. Скачайте Docker-образ желаемой версии: \ 1. Скачайте Docker-образ желаемой версии: \
`docker pull vitalif/vitastor:v3.0.2` `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.2 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`
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
-2
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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;
} }
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "vitastor-mon", "name": "vitastor-mon",
"version": "3.0.2", "version": "3.0.0",
"description": "Vitastor SDS monitor service", "description": "Vitastor SDS monitor service",
"main": "mon-main.js", "main": "mon-main.js",
"scripts": { "scripts": {
@@ -9,7 +9,7 @@
"author": "Vitaliy Filippov", "author": "Vitaliy Filippov",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"antietcd": "^1.2.2", "antietcd": "^1.1.3",
"sprintf-js": "^1.1.2", "sprintf-js": "^1.1.2",
"ws": "^7.2.5" "ws": "^7.2.5"
}, },
+1 -15
View File
@@ -52,7 +52,6 @@ function recheck_primary(state, global_config, up_osds, osd_tree)
continue; continue;
} }
const aff_osds = get_affinity_osds(pool_cfg, up_osds, osd_tree); const aff_osds = get_affinity_osds(pool_cfg, up_osds, osd_tree);
let paused = false;
for (let pg_num = 1; pg_num <= pool_cfg.pg_count; pg_num++) for (let pg_num = 1; pg_num <= pool_cfg.pg_count; pg_num++)
{ {
if (!state.pg.config.items[pool_id]) if (!state.pg.config.items[pool_id])
@@ -75,19 +74,6 @@ function recheck_primary(state, global_config, up_osds, osd_tree)
); );
new_pg_config.items[pool_id][pg_num].primary = new_primary; new_pg_config.items[pool_id][pg_num].primary = new_primary;
} }
paused = paused || !!pg_cfg.pause;
}
}
if (paused)
{
if (!new_pg_config)
{
new_pg_config = JSON.parse(JSON.stringify(state.pg.config));
}
console.log(`Resuming paused pool ${pool_id}`);
for (const pg in new_pg_config.items[pool_id])
{
delete new_pg_config.items[pool_id][pg].pause;
} }
} }
} }
@@ -192,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 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "vitastor", "name": "vitastor",
"version": "3.0.2", "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": [
+1 -1
View File
@@ -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.2' 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
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.2 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.2.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++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.2 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.2.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++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.2 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.2.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
View File
@@ -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.2") 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})
-6
View File
@@ -183,12 +183,6 @@ public:
// Update configuration // Update configuration
virtual void parse_config(blockstore_config_t & config) = 0; virtual void parse_config(blockstore_config_t & config) = 0;
// Reshard database for a pool in chunks
// MUST be called only when nobody makes any modifications to the DB for this pool
virtual void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit) = 0;
virtual bool reshard_continue(void *reshard_state, uint64_t chunk_limit) = 0;
virtual void reshard_abort(void *reshard_state) = 0;
// Event loop // Event loop
virtual void loop() = 0; virtual void loop() = 0;
+36 -156
View File
@@ -29,15 +29,6 @@
#define IMAP_MALLOC_LOW_BITS ((size_t)0x0F) #define IMAP_MALLOC_LOW_BITS ((size_t)0x0F)
#define IMAP_MAX_LOW 16 #define IMAP_MAX_LOW 16
void inode_map_put(void* & inode_idx, heap_list_item_t* li);
void inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_list_item_t* & li, uint64_t stripe);
void inode_map_free(void* inode_idx);
bool inode_map_is_big(void* & inode_idx);
void inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)> cb);
void inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* new_li);
void inode_map_erase(robin_hood::unordered_flat_map<inode_t, void*, i64hash_t> & pg_idx, void* & inode_idx,
const heap_inode_map_t::iterator & li_it, heap_list_item_t* li);
static inline heap_list_item_t *list_item(heap_entry_t *wr) static inline heap_list_item_t *list_item(heap_entry_t *wr)
{ {
return (heap_list_item_t*)((uint8_t*)wr - offsetof(struct heap_list_item_t, entry)); return (heap_list_item_t*)((uint8_t*)wr - offsetof(struct heap_list_item_t, entry));
@@ -667,8 +658,7 @@ void blockstore_heap_t::recheck_buffer(heap_entry_t *cwr, uint8_t *buf)
else if (!calc_checksums(cwr, buf, false)) else if (!calc_checksums(cwr, buf, false))
{ {
// write entry is invalid, erase it and mark newer entries with garbage bit // write entry is invalid, erase it and mark newer entries with garbage bit
auto & pg_idx = block_index[get_pg_id(cwr->inode, cwr->stripe)]; auto & inode_idx = block_index[get_pg_id(cwr->inode, cwr->stripe)][cwr->inode];
auto & inode_idx = pg_idx[cwr->inode];
heap_inode_map_t::iterator li_it; heap_inode_map_t::iterator li_it;
heap_list_item_t *li = NULL; heap_list_item_t *li = NULL;
inode_map_get(inode_idx, li_it, li, cwr->stripe); inode_map_get(inode_idx, li_it, li, cwr->stripe);
@@ -694,7 +684,7 @@ void blockstore_heap_t::recheck_buffer(heap_entry_t *cwr, uint8_t *buf)
{ {
fprintf(stderr, "Notice: the whole object %jx:%jx only has unfinished writes, rolling back\n", fprintf(stderr, "Notice: the whole object %jx:%jx only has unfinished writes, rolling back\n",
cwr->inode, cwr->stripe); cwr->inode, cwr->stripe);
inode_map_erase(pg_idx, inode_idx, li_it, li); inode_map_erase(inode_idx, li_it, li);
} }
free_entry(li); free_entry(li);
} }
@@ -953,138 +943,44 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit
return res; return res;
} }
struct heap_reshard_state_t void blockstore_heap_t::reshard(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size)
{
int state = 0;
uint64_t pool_id = 0;
uint32_t old_pg_count = 0;
uint32_t pg_count = 0;
uint32_t pg_stripe_size = 0;
uint64_t chunk_size = 0;
heap_block_index_t new_shards;
heap_block_index_t old_shards;
heap_block_index_t::iterator sh_it;
robin_hood::unordered_flat_map<inode_t, void*, i64hash_t>::iterator inode_it;
heap_inode_map_t *stripe_map = NULL;
heap_inode_map_t::iterator stripe_it;
void add(heap_list_item_t *li);
bool run(uint64_t chunk_limit);
};
void heap_reshard_state_t::add(heap_list_item_t *li)
{
// like map_to_pg()
uint64_t pg_num = (li->entry.stripe / pg_stripe_size) % pg_count + 1;
uint64_t shard_id = (pool_id << (64-POOL_ID_BITS)) | pg_num;
inode_map_put(new_shards[shard_id][li->entry.inode], li);
chunk_size++;
}
bool heap_reshard_state_t::run(uint64_t chunk_limit)
{
chunk_size = 0;
if (state == 1)
goto resume_1;
else if (state == 2)
goto resume_2;
sh_it = old_shards.begin();
for (; sh_it != old_shards.end(); sh_it++)
{
inode_it = sh_it->second.begin();
for (; inode_it != sh_it->second.end(); inode_it++)
{
if (!inode_map_is_big(inode_it->second))
{
if (chunk_limit > 0 && chunk_size >= chunk_limit)
{
state = 1;
return false;
}
resume_1:
inode_map_iterate(inode_it->second, [&](heap_list_item_t *li) { add(li); });
}
else
{
stripe_map = (heap_inode_map_t*)inode_it->second;
stripe_it = stripe_map->begin();
for (; stripe_it != stripe_map->end(); stripe_it++)
{
if (chunk_limit > 0 && chunk_size >= chunk_limit)
{
state = 2;
return false;
}
resume_2:
add(*stripe_it);
}
}
inode_map_free(inode_it->second);
}
}
return true;
}
void* blockstore_heap_t::reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit)
{ {
auto & pool_settings = pool_shard_settings[pool]; auto & pool_settings = pool_shard_settings[pool];
if (pool_settings.pg_count == pg_count && pool_settings.pg_stripe_size == pg_stripe_size) if (pool_settings.pg_count == pg_count && pool_settings.pg_stripe_size == pg_stripe_size)
{ {
return NULL; return;
} }
heap_reshard_state_t *st = new heap_reshard_state_t; uint32_t old_pg_count = !pool_settings.pg_count ? 1 : pool_settings.pg_count;
st->pool_id = (uint64_t)pool; uint64_t pool_id = (uint64_t)pool;
st->pg_count = pg_count; heap_block_index_t new_shards;
st->pg_stripe_size = pg_stripe_size; for (uint32_t pg_num = 0; pg_num <= old_pg_count; pg_num++)
st->old_pg_count = !pool_settings.pg_count ? 1 : pool_settings.pg_count;
for (uint32_t pg_num = 0; pg_num <= st->old_pg_count; pg_num++)
{ {
auto sh_it = block_index.find((st->pool_id << (64-POOL_ID_BITS)) | pg_num); auto sh_it = block_index.find((pool_id << (64-POOL_ID_BITS)) | pg_num);
if (sh_it != block_index.end()) if (sh_it == block_index.end())
{ {
st->old_shards[pg_num] = std::move(sh_it->second); continue;
block_index.erase(sh_it);
} }
for (auto & inode_pair: sh_it->second)
{
inode_map_iterate(inode_pair.second, [&](heap_list_item_t *li)
{
// like map_to_pg()
uint64_t pg_num = (li->entry.stripe / pg_stripe_size) % pg_count + 1;
uint64_t shard_id = (pool_id << (64-POOL_ID_BITS)) | pg_num;
inode_map_put(new_shards[shard_id][li->entry.inode], li);
});
inode_map_free(inode_pair.second);
}
block_index.erase(sh_it);
} }
bool finished = reshard_continue(st, chunk_limit); for (auto sh_it = new_shards.begin(); sh_it != new_shards.end(); sh_it++)
return finished ? NULL : st;
}
bool blockstore_heap_t::reshard_continue(void *reshard_state, uint64_t chunk_limit)
{
heap_reshard_state_t *st = (heap_reshard_state_t*)reshard_state;
if (!st->run(chunk_limit))
{
return false;
}
for (auto sh_it = st->new_shards.begin(); sh_it != st->new_shards.end(); sh_it++)
{ {
block_index[sh_it->first] = std::move(sh_it->second); block_index[sh_it->first] = std::move(sh_it->second);
} }
pool_shard_settings[st->pool_id] = (pool_shard_settings_t){ pool_settings = (pool_shard_settings_t){
.pg_count = st->pg_count, .pg_count = pg_count,
.pg_stripe_size = st->pg_stripe_size, .pg_stripe_size = pg_stripe_size,
}; };
delete st;
return true;
}
bool blockstore_heap_t::reshard_check(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size)
{
auto set_it = pool_shard_settings.find(pool);
return (set_it != pool_shard_settings.end() &&
set_it->second.pg_count == pg_count &&
set_it->second.pg_stripe_size == pg_stripe_size);
}
void blockstore_heap_t::reshard_abort(void* reshard_state)
{
heap_reshard_state_t *st = (heap_reshard_state_t*)reshard_state;
for (auto sh_it = st->old_shards.begin(); sh_it != st->old_shards.end(); sh_it++)
{
block_index[sh_it->first] = std::move(sh_it->second);
}
delete st;
} }
heap_entry_t *blockstore_heap_t::lock_and_read_entry(object_id oid) heap_entry_t *blockstore_heap_t::lock_and_read_entry(object_id oid)
@@ -2275,12 +2171,11 @@ void blockstore_heap_t::apply_inflight(heap_inflight_lsn_t & inflight)
if (!next) if (!next)
{ {
assert(!prev); assert(!prev);
auto & pg_idx = block_index[get_pg_id(wr->inode, wr->stripe)]; auto & inode_idx = block_index[get_pg_id(wr->inode, wr->stripe)][wr->inode];
auto & inode_idx = pg_idx[wr->inode];
heap_inode_map_t::iterator li_it; heap_inode_map_t::iterator li_it;
heap_list_item_t *old_li = NULL; heap_list_item_t *old_li = NULL;
inode_map_get(inode_idx, li_it, old_li, wr->stripe); inode_map_get(inode_idx, li_it, old_li, wr->stripe);
inode_map_erase(pg_idx, inode_idx, li_it, old_li); inode_map_erase(inode_idx, li_it, old_li);
} }
else else
{ {
@@ -2295,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;
@@ -2373,7 +2259,7 @@ void blockstore_heap_t::recalc_inode_space_stats(uint64_t pool_id, bool per_inod
// This is some really crazy shit but it seems to work well :) // This is some really crazy shit but it seems to work well :)
// At the same time it has almost zero overhead and works just as fast for fat inodes. // At the same time it has almost zero overhead and works just as fast for fat inodes.
void inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_list_item_t* & li, uint64_t stripe) void blockstore_heap_t::inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_list_item_t* & li, uint64_t stripe)
{ {
size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS); size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!map_n) if (!map_n)
@@ -2400,7 +2286,7 @@ void inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_lis
} }
} }
void inode_map_free(void* inode_idx) void blockstore_heap_t::inode_map_free(void* inode_idx)
{ {
size_t n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS); size_t n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!n) if (!n)
@@ -2413,12 +2299,7 @@ void inode_map_free(void* inode_idx)
} }
} }
bool inode_map_is_big(void* & inode_idx) void blockstore_heap_t::inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)> cb)
{
return !((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
}
void inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)> cb)
{ {
size_t n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS); size_t n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!n) if (!n)
@@ -2445,7 +2326,7 @@ void inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)>
} }
} }
void inode_map_put(void* & inode_idx, heap_list_item_t* li) void blockstore_heap_t::inode_map_put(void* & inode_idx, heap_list_item_t* li)
{ {
if (!inode_idx) if (!inode_idx)
{ {
@@ -2514,7 +2395,7 @@ void inode_map_put(void* & inode_idx, heap_list_item_t* li)
} }
} }
void inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* new_li) void blockstore_heap_t::inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* new_li)
{ {
size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS); size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!map_n) if (!map_n)
@@ -2540,8 +2421,7 @@ void inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_
} }
} }
void inode_map_erase(robin_hood::unordered_flat_map<inode_t, void*, i64hash_t> & pg_idx, void* & inode_idx, void blockstore_heap_t::inode_map_erase(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* li)
const heap_inode_map_t::iterator & li_it, heap_list_item_t* li)
{ {
size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS); size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!map_n) if (!map_n)
@@ -2566,7 +2446,7 @@ void inode_map_erase(robin_hood::unordered_flat_map<inode_t, void*, i64hash_t> &
else if (map_n == 1) else if (map_n == 1)
{ {
// Erase // Erase
pg_idx.erase(li->entry.inode); block_index[get_pg_id(li->entry.inode, li->entry.stripe)].erase(li->entry.inode);
} }
else else
{ {
+8 -8
View File
@@ -137,8 +137,6 @@ struct heap_compact_t
bool do_delete; bool do_delete;
}; };
struct heap_reshard_state_t;
struct heap_li_hash struct heap_li_hash
{ {
size_t operator()(const heap_list_item_t* li) const noexcept size_t operator()(const heap_list_item_t* li) const noexcept
@@ -207,13 +205,19 @@ class blockstore_heap_t
std::function<void(bool is_data, uint64_t offset, uint64_t len, uint8_t* buf, std::function<void()>)> recheck_cb; std::function<void(bool is_data, uint64_t offset, uint64_t len, uint8_t* buf, std::function<void()>)> recheck_cb;
int recheck_queue_depth = 0; int recheck_queue_depth = 0;
void inode_map_put(void* & inode_idx, heap_list_item_t* li);
void inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_list_item_t* & li, uint64_t stripe);
void inode_map_free(void* inode_idx);
void inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)> cb);
void inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* new_li);
void inode_map_erase(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* li);
uint64_t get_pg_id(inode_t inode, uint64_t stripe); uint64_t get_pg_id(inode_t inode, uint64_t stripe);
bool validate_object(heap_entry_t *obj); bool validate_object(heap_entry_t *obj);
void fill_recheck_queue(); void fill_recheck_queue();
int mark_used_blocks(); int mark_used_blocks();
void recheck_buffer(heap_entry_t *cwr, uint8_t *buf); void recheck_buffer(heap_entry_t *cwr, uint8_t *buf);
void defragment_block(uint32_t block_num); void defragment_block(uint32_t block_num);
void reshard_add(heap_reshard_state_t *st, heap_list_item_t *li);
int allocate_entry(uint32_t entry_size, uint32_t *block_num, bool allow_last_free); int allocate_entry(uint32_t entry_size, uint32_t *block_num, bool allow_last_free);
void insert_list_item(heap_list_item_t *li); void insert_list_item(heap_list_item_t *li);
@@ -245,10 +249,7 @@ public:
// recheck small write data after reading the database from disk // recheck small write data after reading the database from disk
bool recheck_small_writes(std::function<void(bool is_data, uint64_t offset, uint64_t len, uint8_t* buf, std::function<void()>)> read_buffer, int queue_depth); bool recheck_small_writes(std::function<void(bool is_data, uint64_t offset, uint64_t len, uint8_t* buf, std::function<void()>)> read_buffer, int queue_depth);
// reshard database according to the pool's PG count // reshard database according to the pool's PG count
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit); void reshard(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size);
bool reshard_continue(void* reshard_state, uint64_t chunk_limit);
bool reshard_check(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size);
void reshard_abort(void* reshard_state);
void set_no_inode_stats(const std::vector<uint64_t> & pool_ids); void set_no_inode_stats(const std::vector<uint64_t> & pool_ids);
void recalc_inode_space_stats(uint64_t pool_id, bool per_inode); void recalc_inode_space_stats(uint64_t pool_id, bool per_inode);
// read an object entry and lock it against removal // read an object entry and lock it against removal
@@ -313,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);
+7 -24
View File
@@ -23,7 +23,6 @@ blockstore_impl_t::blockstore_impl_t(blockstore_config_t & config, ring_loop_i *
dsk.open_meta(); dsk.open_meta();
dsk.open_journal(); dsk.open_journal();
dsk.calc_lengths(); dsk.calc_lengths();
dsk.check_lengths();
} }
catch (std::exception & e) catch (std::exception & e)
{ {
@@ -32,13 +31,16 @@ blockstore_impl_t::blockstore_impl_t(blockstore_config_t & config, ring_loop_i *
} }
meta_superblock = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.meta_block_size); meta_superblock = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.meta_block_size);
memset(meta_superblock, 0, dsk.meta_block_size); memset(meta_superblock, 0, dsk.meta_block_size);
}
void blockstore_impl_t::init()
{
flusher = new journal_flusher_t(this); flusher = new journal_flusher_t(this);
if (dsk.inmemory_journal) if (dsk.inmemory_journal)
{ {
buffer_area = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.journal_len); buffer_area = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.journal_len);
} }
heap = new blockstore_heap_t(&dsk, buffer_area, log_level); heap = new blockstore_heap_t(&dsk, buffer_area, log_level);
ringloop->wakeup();
} }
blockstore_impl_t::~blockstore_impl_t() blockstore_impl_t::~blockstore_impl_t()
@@ -323,13 +325,9 @@ void blockstore_impl_t::process_list(blockstore_op_t *op)
FINISH_OP(op); FINISH_OP(op);
return; return;
} }
// Check if the DB is sharded correctly // Check if the DB needs resharding
if (!heap->reshard_check(INODE_POOL(min_inode), pg_count, pg_stripe_size)) // (we don't know about PGs from the beginning, we only create "shards" here)
{ heap->reshard(INODE_POOL(min_inode), pg_count, pg_stripe_size);
op->retval = -EAGAIN;
FINISH_OP(op);
return;
}
obj_ver_id *result = NULL; obj_ver_id *result = NULL;
size_t stable_count = 0, unstable_count = 0; size_t stable_count = 0, unstable_count = 0;
int res = heap->list_objects(list_pg, op->min_oid, op->max_oid, &result, &stable_count, &unstable_count); int res = heap->list_objects(list_pg, op->min_oid, op->max_oid, &result, &stable_count, &unstable_count);
@@ -396,18 +394,3 @@ std::string blockstore_impl_t::get_op_diag(blockstore_op_t *op)
snprintf(buf, sizeof(buf), "state=%d", priv->op_state); snprintf(buf, sizeof(buf), "state=%d", priv->op_state);
return std::string(buf); return std::string(buf);
} }
void* blockstore_impl_t::reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit)
{
return heap->reshard_start(pool, pg_count, pg_stripe_size, chunk_limit);
}
bool blockstore_impl_t::reshard_continue(void *reshard_state, uint64_t chunk_limit)
{
return heap->reshard_continue(reshard_state, chunk_limit);
}
void blockstore_impl_t::reshard_abort(void *reshard_state)
{
return heap->reshard_abort(reshard_state);
}
+1 -4
View File
@@ -142,6 +142,7 @@ public:
int metadata_buf_size; int metadata_buf_size;
blockstore_init_meta* metadata_init_reader; blockstore_init_meta* metadata_init_reader;
void init();
void check_wait(blockstore_op_t *op); void check_wait(blockstore_op_t *op);
void init_op(blockstore_op_t *op); void init_op(blockstore_op_t *op);
@@ -189,10 +190,6 @@ public:
void parse_config(blockstore_config_t & config); void parse_config(blockstore_config_t & config);
void parse_config(blockstore_config_t & config, bool init); void parse_config(blockstore_config_t & config, bool init);
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
bool reshard_continue(void *reshard_state, uint64_t chunk_limit);
void reshard_abort(void *reshard_state);
// Event loop // Event loop
void loop(); void loop();
+10 -1
View File
@@ -72,6 +72,7 @@ resume_1:
} }
if (is_zero((uint64_t*)bs->meta_superblock, bs->dsk.meta_block_size)) if (is_zero((uint64_t*)bs->meta_superblock, bs->dsk.meta_block_size))
{ {
bs->dsk.check_lengths();
{ {
blockstore_meta_header_v3_t *hdr = (blockstore_meta_header_v3_t *)bs->meta_superblock; blockstore_meta_header_v3_t *hdr = (blockstore_meta_header_v3_t *)bs->meta_superblock;
hdr->zero = 0; hdr->zero = 0;
@@ -140,7 +141,7 @@ resume_1:
hdr->bitmap_granularity != bs->dsk.bitmap_granularity || hdr->bitmap_granularity != bs->dsk.bitmap_granularity ||
hdr->data_csum_type != bs->dsk.data_csum_type || hdr->data_csum_type != bs->dsk.data_csum_type ||
hdr->csum_block_size != bs->dsk.csum_block_size || hdr->csum_block_size != bs->dsk.csum_block_size ||
hdr->meta_area_size != bs->dsk.meta_area_size) hdr->meta_area_size > bs->dsk.meta_area_size)
{ {
printf( printf(
"Configuration stored in metadata superblock" "Configuration stored in metadata superblock"
@@ -153,7 +154,15 @@ resume_1:
); );
exit(1); exit(1);
} }
bs->dsk.meta_area_size = hdr->meta_area_size;
if (bs->dsk.meta_format != hdr->version)
{
bs->dsk.meta_format = hdr->version;
bs->dsk.calc_lengths();
}
bs->dsk.check_lengths();
} }
bs->init();
bs->heap->start_load(((blockstore_meta_header_v3_t *)bs->meta_superblock)->completed_lsn); bs->heap->start_load(((blockstore_meta_header_v3_t *)bs->meta_superblock)->completed_lsn);
if (bs->dsk.inmemory_journal) if (bs->dsk.inmemory_journal)
{ {
+13 -29
View File
@@ -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)
+16 -75
View File
@@ -407,88 +407,32 @@ blockstore_clean_db_t& blockstore_impl_t::clean_db_shard(object_id oid)
return clean_db_shards[(pool_id << (64-POOL_ID_BITS)) | pg_num]; return clean_db_shards[(pool_id << (64-POOL_ID_BITS)) | pg_num];
} }
struct bs_reshard_state_t void blockstore_impl_t::reshard_clean_db(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size)
{ {
int state = 0; uint64_t pool_id = (uint64_t)pool;
uint64_t pool_id = 0;
uint32_t pg_count = 0;
uint32_t pg_stripe_size = 0;
uint64_t chunk_size = 0;
std::map<pool_pg_id_t, blockstore_clean_db_t> old_shards;
std::map<pool_pg_id_t, blockstore_clean_db_t> new_shards; std::map<pool_pg_id_t, blockstore_clean_db_t> new_shards;
std::map<pool_pg_id_t, blockstore_clean_db_t>::iterator sh_it; auto sh_it = clean_db_shards.lower_bound((pool_id << (64-POOL_ID_BITS)));
blockstore_clean_db_t::iterator obj_it;
};
void* blockstore_impl_t::reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit)
{
auto & settings = clean_db_settings[pool];
if (settings.pg_count == pg_count && settings.pg_stripe_size == pg_stripe_size)
{
return NULL;
}
bs_reshard_state_t *st = new bs_reshard_state_t;
st->state = 0;
st->pool_id = pool;
st->pg_count = pg_count;
st->pg_stripe_size = pg_stripe_size;
auto sh_it = clean_db_shards.lower_bound((st->pool_id << (64-POOL_ID_BITS)));
while (sh_it != clean_db_shards.end() && while (sh_it != clean_db_shards.end() &&
(sh_it->first >> (64-POOL_ID_BITS)) == st->pool_id) (sh_it->first >> (64-POOL_ID_BITS)) == pool_id)
{ {
st->old_shards[sh_it->first] = std::move(sh_it->second); for (auto & pair: sh_it->second)
{
// like map_to_pg()
uint64_t pg_num = (pair.first.stripe / pg_stripe_size) % pg_count + 1;
uint64_t shard_id = (pool_id << (64-POOL_ID_BITS)) | pg_num;
new_shards[shard_id][pair.first] = pair.second;
}
clean_db_shards.erase(sh_it++); clean_db_shards.erase(sh_it++);
} }
bool finished = reshard_continue(st, chunk_limit); for (sh_it = new_shards.begin(); sh_it != new_shards.end(); sh_it++)
return finished ? NULL : st;
}
bool blockstore_impl_t::reshard_continue(void *reshard_state, uint64_t chunk_limit)
{
bs_reshard_state_t *st = (bs_reshard_state_t*)reshard_state;
uint64_t chunk_size = 0;
if (st->state == 1)
goto resume_1;
for (st->sh_it = st->old_shards.begin(); st->sh_it != st->old_shards.end(); )
{
for (st->obj_it = st->sh_it->second.begin(); st->obj_it != st->sh_it->second.end(); st->obj_it++)
{
if (chunk_limit > 0 && chunk_size >= chunk_limit)
{
st->state = 1;
return false;
}
resume_1:
// like map_to_pg()
uint64_t pg_num = (st->obj_it->first.stripe / st->pg_stripe_size) % st->pg_count + 1;
uint64_t shard_id = (st->pool_id << (64-POOL_ID_BITS)) | pg_num;
st->new_shards[shard_id][st->obj_it->first] = st->obj_it->second;
chunk_size++;
}
st->old_shards.erase(st->sh_it++);
}
for (auto sh_it = st->new_shards.begin(); sh_it != st->new_shards.end(); sh_it++)
{ {
auto & to = clean_db_shards[sh_it->first]; auto & to = clean_db_shards[sh_it->first];
to.swap(sh_it->second); to.swap(sh_it->second);
} }
clean_db_settings[st->pool_id] = (pool_shard_settings_t){ clean_db_settings[pool_id] = (pool_shard_settings_t){
.pg_count = st->pg_count, .pg_count = pg_count,
.pg_stripe_size = st->pg_stripe_size, .pg_stripe_size = pg_stripe_size,
}; };
delete st;
return true;
}
void blockstore_impl_t::reshard_abort(void *reshard_state)
{
bs_reshard_state_t *st = (bs_reshard_state_t*)reshard_state;
for (auto sh_it = st->old_shards.begin(); sh_it != st->old_shards.end(); sh_it++)
{
auto & to = clean_db_shards[sh_it->first];
to.swap(sh_it->second);
}
delete st;
} }
void blockstore_impl_t::process_list(blockstore_op_t *op) void blockstore_impl_t::process_list(blockstore_op_t *op)
@@ -521,10 +465,7 @@ void blockstore_impl_t::process_list(blockstore_op_t *op)
sh_it->second.pg_count != pg_count || sh_it->second.pg_count != pg_count ||
sh_it->second.pg_stripe_size != pg_stripe_size) sh_it->second.pg_stripe_size != pg_stripe_size)
{ {
// Sharding mismatch reshard_clean_db(pool_id, pg_count, pg_stripe_size);
op->retval = -EAGAIN;
FINISH_OP(op);
return;
} }
first_shard = last_shard = ((uint64_t)pool_id << (64-POOL_ID_BITS)) | list_pg; first_shard = last_shard = ((uint64_t)pool_id << (64-POOL_ID_BITS)) | list_pg;
} }
+1 -5
View File
@@ -202,6 +202,7 @@ class blockstore_impl_t: public blockstore_i
uint8_t* get_clean_entry_bitmap(uint64_t block_loc, int offset); uint8_t* get_clean_entry_bitmap(uint64_t block_loc, int offset);
blockstore_clean_db_t& clean_db_shard(object_id oid); blockstore_clean_db_t& clean_db_shard(object_id oid);
void reshard_clean_db(pool_id_t pool_id, uint32_t pg_count, uint32_t pg_stripe_size);
void recalc_inode_space_stats(uint64_t pool_id, bool per_inode); void recalc_inode_space_stats(uint64_t pool_id, bool per_inode);
// Journaling // Journaling
@@ -287,11 +288,6 @@ public:
void parse_config(blockstore_config_t & config); void parse_config(blockstore_config_t & config);
void parse_config(blockstore_config_t & config, bool init); void parse_config(blockstore_config_t & config, bool init);
// Reshard database for a pool
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
bool reshard_continue(void *reshard_state, uint64_t chunk_limit);
void reshard_abort(void *reshard_state);
// Event loop // Event loop
void loop(); void loop();
+1 -1
View File
@@ -183,7 +183,7 @@ bool blockstore_impl_t::enqueue_write(blockstore_op_t *op)
uint32_t end = (op->offset+op->len-1) / dsk.csum_block_size; uint32_t end = (op->offset+op->len-1) / dsk.csum_block_size;
auto fn = state & BS_ST_BIG_WRITE ? crc32c_pad : crc32c_nopad; auto fn = state & BS_ST_BIG_WRITE ? crc32c_pad : crc32c_nopad;
if (start == end) if (start == end)
data_csums[0] = fn(0, op->buf, op->len, op->offset - start*dsk.csum_block_size, (end+1)*dsk.csum_block_size - (op->offset+op->len)); data_csums[0] = fn(0, op->buf, op->len, op->offset - start*dsk.csum_block_size, end*dsk.csum_block_size - (op->offset+op->len));
else else
{ {
// First block // First block
+12 -20
View File
@@ -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
-1
View File
@@ -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
+7 -28
View File
@@ -568,19 +568,9 @@ void etcd_state_client_t::start_ws_keepalive()
void etcd_state_client_t::load_global_config() void etcd_state_client_t::load_global_config()
{ {
json11::Json::object req = { { "success", json11::Json::array { etcd_call("/kv/range", json11::Json::object {
json11::Json::object { { "key", base64_encode(etcd_prefix+"/config/global") }
{ "request_range", json11::Json::object { }, etcd_quick_timeout, max_etcd_attempts, 0, [this](std::string err, json11::Json data)
{ "key", base64_encode(etcd_prefix+"/config/global") },
} }
},
json11::Json::object {
{ "request_range", json11::Json::object {
{ "key", base64_encode(etcd_prefix+"/config/pools") },
} }
},
} } };
etcd_txn(req, etcd_quick_timeout, max_etcd_attempts, 0, [this](std::string err, json11::Json data)
{ {
if (err != "") if (err != "")
{ {
@@ -598,12 +588,10 @@ void etcd_state_client_t::load_global_config()
} }
return; return;
} }
json11::Json config_kv = data["responses"][0]["response_range"]["kvs"][0];
json11::Json pools_kv = data["responses"][1]["response_range"]["kvs"][0];
json11::Json::object global_config; json11::Json::object global_config;
if (!config_kv.is_null()) if (data["kvs"].array_items().size() > 0)
{ {
auto kv = parse_etcd_kv(config_kv); auto kv = parse_etcd_kv(data["kvs"][0]);
if (kv.value.is_object()) if (kv.value.is_object())
{ {
global_config = kv.value.object_items(); global_config = kv.value.object_items();
@@ -620,11 +608,6 @@ void etcd_state_client_t::load_global_config()
global_bitmap_granularity = DEFAULT_BITMAP_GRANULARITY; global_bitmap_granularity = DEFAULT_BITMAP_GRANULARITY;
} }
global_immediate_commit = parse_immediate_commit(global_config["immediate_commit"].string_value(), IMMEDIATE_ALL); global_immediate_commit = parse_immediate_commit(global_config["immediate_commit"].string_value(), IMMEDIATE_ALL);
if (!pools_kv.is_null())
{
auto kv = parse_etcd_kv(pools_kv);
parse_state(kv);
}
on_load_config_hook(global_config); on_load_config_hook(global_config);
}); });
} }
@@ -962,12 +945,8 @@ void etcd_state_client_t::parse_state(const etcd_kv_t & kv)
if (pc.pg_stripe_size < min_stripe_size) if (pc.pg_stripe_size < min_stripe_size)
pc.pg_stripe_size = min_stripe_size; pc.pg_stripe_size = min_stripe_size;
// Save // Save
auto & old_pc = this->pool_config[pool_id]; pc.real_pg_count = this->pool_config[pool_id].real_pg_count;
pc.real_pg_count = old_pc.real_pg_count; std::swap(pc.pg_config, this->pool_config[pool_id].pg_config);
pc.applied_pg_count = old_pc.applied_pg_count;
pc.applied_pg_stripe_size = old_pc.applied_pg_stripe_size;
pc.reshard_state = old_pc.reshard_state;
std::swap(pc.pg_config, old_pc.pg_config);
std::swap(this->pool_config[pool_id], pc); std::swap(this->pool_config[pool_id], pc);
auto & parsed_cfg = this->pool_config[pool_id]; auto & parsed_cfg = this->pool_config[pool_id];
parsed_cfg.exists = true; parsed_cfg.exists = true;
-5
View File
@@ -68,11 +68,6 @@ struct pool_config_t
std::string used_for_app; std::string used_for_app;
int backfillfull = 0; int backfillfull = 0;
int local_reads = 0; int local_reads = 0;
// runtime data, used only by OSD:
uint64_t applied_pg_count = 0;
uint64_t applied_pg_stripe_size = 0;
void *reshard_state = NULL;
}; };
struct inode_config_t struct inode_config_t
+24 -4
View File
@@ -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--;
+2
View File
@@ -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);
+2 -4
View File
@@ -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
} }
-7
View File
@@ -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)
+1 -1
View File
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: Vitastor Name: Vitastor
Description: Vitastor client library Description: Vitastor client library
Version: 3.0.2 Version: 3.0.0
Libs: -L${libdir} -lvitastor_client Libs: -L${libdir} -lvitastor_client
Cflags: -I${includedir} Cflags: -I${includedir}
+1 -1
View File
@@ -245,7 +245,7 @@ static json11::Json::object parse_args(int narg, const char *args[])
cfg["progress"] = "1"; cfg["progress"] = "1";
for (int i = 1; i < narg; i++) for (int i = 1; i < narg; i++)
{ {
bool argHasValue = (i < narg-1); bool argHasValue = (!(i == narg-1) && (args[i+1][0] != '-'));
if (args[i][0] == '-' && args[i][1] == 'h' && args[i][2] == 0) if (args[i][0] == '-' && args[i][1] == 'h' && args[i][2] == 0)
{ {
cfg["help"] = "1"; cfg["help"] = "1";
+3 -4
View File
@@ -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;
} }
}; };
+6 -17
View File
@@ -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 {
-2
View File
@@ -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"
-1
View File
@@ -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;
+15 -46
View File
@@ -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
View File
@@ -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
View File
@@ -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--;
+19 -44
View File
@@ -31,6 +31,25 @@ osd_t::osd_t(const json11::Json & config, ring_loop_t *ringloop)
// FIXME: Use timerfd_interval based directly on io_uring // FIXME: Use timerfd_interval based directly on io_uring
this->tfd = epmgr->tfd; this->tfd = epmgr->tfd;
if (!json_is_true(this->config["disable_blockstore"]))
{
auto bs_cfg = json_to_string_map(this->config);
this->bs = blockstore_i::create(bs_cfg, ringloop, tfd);
// Wait for blockstore initialisation before actually starting OSD logic
// to prevent peering timeouts during restart with filled databases
while (!bs->is_started())
{
ringloop->loop();
if (bs->is_started())
break;
ringloop->wait();
}
// Autosync based on the number of unstable writes to prevent stalls due to insufficient journal space
uint64_t max_autosync = bs->get_journal_size() / bs->get_block_size() / 2;
if (autosync_writes > max_autosync)
autosync_writes = max_autosync;
}
if (json_is_true(this->config["osd_memlock"])) if (json_is_true(this->config["osd_memlock"]))
{ {
// Lock all OSD memory if requested // Lock all OSD memory if requested
@@ -98,7 +117,6 @@ osd_t::~osd_t()
autosync_timer_id = -1; autosync_timer_id = -1;
} }
ringloop->unregister_consumer(&consumer); ringloop->unregister_consumer(&consumer);
ringloop->unregister_consumer(&init_consumer);
delete epmgr; delete epmgr;
if (bs) if (bs)
delete bs; delete bs;
@@ -113,43 +131,6 @@ osd_t::~osd_t()
free(zero_buffer); free(zero_buffer);
} }
void osd_t::init_blockstore(std::function<void()> on_init)
{
if (!json_is_true(this->config["disable_blockstore"]))
{
auto bs_cfg = json_to_string_map(this->config);
this->bs = blockstore_i::create(bs_cfg, ringloop, tfd);
// Pre-configure pool PG shards
for (auto & pool_item: st_cli.pool_config)
{
auto st = bs->reshard_start(pool_item.first, pool_item.second.pg_count, pool_item.second.pg_stripe_size, 0);
assert(!st);
}
// Autosync based on the number of unstable writes to prevent stalls due to insufficient journal space
uint64_t max_autosync = bs->get_journal_size() / bs->get_block_size() / 2;
if (autosync_writes > max_autosync)
autosync_writes = max_autosync;
if (on_init)
{
init_consumer.loop = [this, on_init]()
{
// Wait for blockstore initialisation before actually starting OSD logic
// to prevent peering timeouts during restart with filled databases
if (bs->is_started())
{
ringloop->set_immediate([this, on_init] { init_consumer.loop = NULL; on_init(); });
ringloop->unregister_consumer(&init_consumer);
}
};
ringloop->register_consumer(&init_consumer);
}
}
else if (on_init)
{
on_init();
}
}
void osd_t::parse_config(bool init) void osd_t::parse_config(bool init)
{ {
config = msgr.merge_configs(cli_config, file_config, etcd_global_config, etcd_osd_config); config = msgr.merge_configs(cli_config, file_config, etcd_global_config, etcd_osd_config);
@@ -311,12 +292,6 @@ void osd_t::parse_config(bool init)
scrub_list_limit = config["scrub_list_limit"].uint64_value(); scrub_list_limit = config["scrub_list_limit"].uint64_value();
if (!scrub_list_limit) if (!scrub_list_limit)
scrub_list_limit = 262144; scrub_list_limit = 262144;
pg_reshard_chunk_size = config["pg_reshard_chunk_size"].uint64_value();
if (!pg_reshard_chunk_size)
pg_reshard_chunk_size = 100000;
pg_reshard_chunk_pause_ms = config["pg_reshard_chunk_pause_ms"].uint64_value();
if (!pg_reshard_chunk_pause_ms)
pg_reshard_chunk_pause_ms = 100;
if (!old_auto_scrub && auto_scrub) if (!old_auto_scrub && auto_scrub)
{ {
// Schedule scrubbing // Schedule scrubbing
+8 -15
View File
@@ -148,8 +148,6 @@ class osd_t
bool enable_pg_locks = false; bool enable_pg_locks = false;
bool pg_locks_localize_only = false; bool pg_locks_localize_only = false;
uint64_t pg_lock_retry_interval_ms = 100; uint64_t pg_lock_retry_interval_ms = 100;
uint64_t pg_reshard_chunk_size = 100000;
uint64_t pg_reshard_chunk_pause_ms = 100;
// cluster state // cluster state
@@ -160,7 +158,6 @@ class osd_t
json11::Json self_state; json11::Json self_state;
bool loading_peer_config = false; bool loading_peer_config = false;
std::set<pool_pg_num_t> pg_state_dirty; std::set<pool_pg_num_t> pg_state_dirty;
bool etcd_global_config_loaded = false;
bool pg_config_applied = false; bool pg_config_applied = false;
bool etcd_reporting_pg_state = false; bool etcd_reporting_pg_state = false;
bool etcd_reporting_stats = false; bool etcd_reporting_stats = false;
@@ -171,11 +168,10 @@ class osd_t
// peers and PGs // peers and PGs
std::map<pool_pg_num_t, osd_pg_lock_t> pg_locks; std::map<pool_pg_num_t, osd_pg_lock_t> pg_locks;
std::map<pool_id_t, pg_num_t> pg_counts;
std::map<pool_pg_num_t, pg_t> pgs; std::map<pool_pg_num_t, pg_t> pgs;
std::set<pool_pg_num_t> dirty_pgs; std::set<pool_pg_num_t> dirty_pgs;
std::set<osd_num_t> dirty_osds; std::set<osd_num_t> dirty_osds;
std::vector<pool_id_t> reshard_pools;
int reshard_timer_id = -1;
int copies_to_delete_after_sync_count = 0; int copies_to_delete_after_sync_count = 0;
uint64_t misplaced_objects = 0, degraded_objects = 0, incomplete_objects = 0, inconsistent_objects = 0, corrupted_objects = 0; uint64_t misplaced_objects = 0, degraded_objects = 0, incomplete_objects = 0, inconsistent_objects = 0, corrupted_objects = 0;
int peering_state = 0; int peering_state = 0;
@@ -210,7 +206,7 @@ class osd_t
void *zero_buffer = NULL; void *zero_buffer = NULL;
uint64_t zero_buffer_size = 0; uint64_t zero_buffer_size = 0;
uint32_t bs_block_size, bs_bitmap_granularity, clean_entry_bitmap_size; uint32_t bs_block_size, bs_bitmap_granularity, clean_entry_bitmap_size;
ring_loop_t *ringloop = NULL; ring_loop_t *ringloop;
timerfd_manager_t *tfd = NULL; timerfd_manager_t *tfd = NULL;
epoll_manager_t *epmgr = NULL; epoll_manager_t *epmgr = NULL;
@@ -222,7 +218,6 @@ class osd_t
int rdmacm_port = 0; int rdmacm_port = 0;
#endif #endif
ring_consumer_t consumer; ring_consumer_t consumer;
ring_consumer_t init_consumer;
// op statistics // op statistics
osd_op_stats_t prev_stats, prev_report_stats; osd_op_stats_t prev_stats, prev_report_stats;
@@ -246,7 +241,6 @@ class osd_t
// cluster connection // cluster connection
void parse_config(bool init); void parse_config(bool init);
void init_blockstore(std::function<void()> on_init);
void init_cluster(); void init_cluster();
void on_change_osd_state_hook(osd_num_t peer_osd); void on_change_osd_state_hook(osd_num_t peer_osd);
void on_change_backfillfull_hook(pool_id_t pool_id); void on_change_backfillfull_hook(pool_id_t pool_id);
@@ -274,7 +268,6 @@ class osd_t
void apply_no_inode_stats(); void apply_no_inode_stats();
void apply_pg_count(); void apply_pg_count();
void apply_pg_config(); void apply_pg_config();
void reshard_continue();
// event loop, socket read/write // event loop, socket read/write
void loop(); void loop();
@@ -324,7 +317,7 @@ class osd_t
void finish_op(osd_op_t *cur_op, int retval); void finish_op(osd_op_t *cur_op, int retval);
// secondary ops // secondary ops
bool sec_check_pg_lock(osd_num_t primary_osd, const object_id & oid, uint32_t flags); bool sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid);
void exec_show_config(osd_op_t *cur_op); void exec_show_config(osd_op_t *cur_op);
void exec_secondary(osd_op_t *cur_op); void exec_secondary(osd_op_t *cur_op);
void exec_secondary_real(osd_op_t *cur_op); void exec_secondary_real(osd_op_t *cur_op);
@@ -383,12 +376,12 @@ class osd_t
int submit_bitmap_subops(osd_op_t *cur_op, pg_t & pg); int submit_bitmap_subops(osd_op_t *cur_op, pg_t & pg);
int read_bitmaps(osd_op_t *cur_op, pg_t *pg, int base_state); int read_bitmaps(osd_op_t *cur_op, pg_t *pg, int base_state);
inline pg_num_t map_to_pg(object_id oid) inline pg_num_t map_to_pg(object_id oid, uint64_t pg_stripe_size)
{ {
auto pool_it = st_cli.pool_config.find(INODE_POOL(oid.inode)); uint64_t pg_count = pg_counts[INODE_POOL(oid.inode)];
if (pool_it == st_cli.pool_config.end()) if (!pg_count)
return 1; pg_count = 1;
return (oid.stripe / pool_it->second.applied_pg_stripe_size) % pool_it->second.applied_pg_count + 1; return (oid.stripe / pg_stripe_size) % pg_count + 1;
} }
public: public:
+24 -118
View File
@@ -18,7 +18,6 @@ void osd_t::init_cluster()
{ {
if (!st_cli.address_count()) if (!st_cli.address_count())
{ {
init_blockstore(NULL);
if (run_primary) if (run_primary)
{ {
// Test version of clustering code with 1 pool, 1 PG and 2 peers // Test version of clustering code with 1 pool, 1 PG and 2 peers
@@ -55,10 +54,9 @@ void osd_t::init_cluster()
.pg_minsize = 2, .pg_minsize = 2,
.pg_count = 1, .pg_count = 1,
.real_pg_count = 1, .real_pg_count = 1,
.applied_pg_count = 1,
.applied_pg_stripe_size = bs_block_size*2,
}; };
report_pg_state(pgs[{ 1, 1 }]); report_pg_state(pgs[{ 1, 1 }]);
pg_counts[1] = 1;
} }
bind_socket(); bind_socket();
} }
@@ -424,10 +422,7 @@ void osd_t::on_change_osd_state_hook(osd_num_t peer_osd)
void osd_t::on_change_pool_config_hook() void osd_t::on_change_pool_config_hook()
{ {
if (etcd_global_config_loaded) apply_pg_locks_localize_only();
{
apply_pg_locks_localize_only();
}
} }
void osd_t::apply_pg_locks_localize_only() void osd_t::apply_pg_locks_localize_only()
@@ -489,13 +484,9 @@ void osd_t::on_load_config_hook(json11::Json::object & global_config)
{ {
etcd_global_config = global_config; etcd_global_config = global_config;
parse_config(true); parse_config(true);
bind_socket();
acquire_lease();
st_cli.on_load_config_hook = [this](json11::Json::object & cfg) { on_reload_config_hook(cfg); }; st_cli.on_load_config_hook = [this](json11::Json::object & cfg) { on_reload_config_hook(cfg); };
etcd_global_config_loaded = true;
init_blockstore([this]()
{
bind_socket();
acquire_lease();
});
} }
void osd_t::on_reload_config_hook(json11::Json::object & global_config) void osd_t::on_reload_config_hook(json11::Json::object & global_config)
@@ -728,13 +719,8 @@ void osd_t::apply_pg_count()
{ {
for (auto & pool_item: st_cli.pool_config) for (auto & pool_item: st_cli.pool_config)
{ {
auto & pool_cfg = pool_item.second; if (pool_item.second.real_pg_count != 0 &&
if (pool_cfg.real_pg_count == 0) pool_item.second.real_pg_count != pg_counts[pool_item.first])
{
continue;
}
if (pool_cfg.real_pg_count != pool_cfg.applied_pg_count ||
pool_cfg.pg_stripe_size != pool_cfg.applied_pg_stripe_size)
{ {
// Check that all pool PGs are offline. It is not allowed to change PG count when any PGs are online // Check that all pool PGs are offline. It is not allowed to change PG count when any PGs are online
// The external tool must wait for all PGs to come down before changing PG count // The external tool must wait for all PGs to come down before changing PG count
@@ -756,91 +742,17 @@ void osd_t::apply_pg_count()
} }
if (still_active_primary > 0 || still_active_secondary > 0) if (still_active_primary > 0 || still_active_secondary > 0)
{ {
if (pool_cfg.real_pg_count != pool_cfg.applied_pg_count) printf(
{ "[OSD %ju] PG count change detected for pool %u (new is %ju, old is %u),"
printf( " but %u PG(s) are still active as primary and %u as secondary. This is not allowed. Exiting\n",
"[OSD %ju] PG count change detected for pool %u (new is %ju, old is %ju)," this->osd_num, pool_item.first, pool_item.second.real_pg_count, pg_counts[pool_item.first],
" but %u PG(s) are still active as primary and %u as secondary. This is not allowed. Exiting\n", still_active_primary, still_active_secondary
this->osd_num, pool_item.first, pool_cfg.real_pg_count, pool_cfg.applied_pg_count, );
still_active_primary, still_active_secondary
);
}
else
{
printf(
"[OSD %ju] PG stripe change detected for pool %u (new is %ju, old is %ju),"
" but %u PG(s) are still active as primary and %u as secondary. This is not allowed. Exiting\n",
this->osd_num, pool_item.first, pool_cfg.pg_stripe_size, pool_cfg.applied_pg_stripe_size,
still_active_primary, still_active_secondary
);
}
force_stop(1); force_stop(1);
return; return;
} }
pool_cfg.applied_pg_count = pool_cfg.real_pg_count;
pool_cfg.applied_pg_stripe_size = pool_cfg.pg_stripe_size;
if (bs && !pool_cfg.reshard_state)
{
pool_cfg.reshard_state = bs->reshard_start(pool_item.first, pool_cfg.real_pg_count, pool_cfg.pg_stripe_size, pg_reshard_chunk_size);
if (pool_cfg.reshard_state)
{
reshard_pools.push_back(pool_item.first);
}
}
} }
} this->pg_counts[pool_item.first] = pool_item.second.real_pg_count;
if (reshard_pools.size() && reshard_timer_id < 0)
{
reshard_timer_id = tfd->set_timer(pg_reshard_chunk_pause_ms, false, [this](int)
{
reshard_continue();
});
}
}
void osd_t::reshard_continue()
{
again:
auto pool_id = reshard_pools[0];
auto pool_it = st_cli.pool_config.find(pool_id);
if (pool_it == st_cli.pool_config.end() || !pool_it->second.reshard_state)
{
reshard_pools.erase(reshard_pools.begin());
goto again;
}
auto & pool_cfg = pool_it->second;
bool done = false;
if (pool_cfg.real_pg_count != pool_cfg.applied_pg_count ||
pool_cfg.pg_stripe_size != pool_cfg.applied_pg_stripe_size)
{
// PG count changed again, reshard again
bs->reshard_abort(pool_cfg.reshard_state);
pool_cfg.applied_pg_count = pool_cfg.real_pg_count;
pool_cfg.applied_pg_stripe_size = pool_cfg.pg_stripe_size;
pool_cfg.reshard_state = bs->reshard_start(pool_id, pool_cfg.real_pg_count, pool_cfg.pg_stripe_size, pg_reshard_chunk_size);
done = !pool_cfg.reshard_state;
}
else
{
done = bs->reshard_continue(pool_cfg.reshard_state, pg_reshard_chunk_size);
}
if (done)
{
// Pool is resharded
pool_cfg.reshard_state = NULL;
reshard_pools.erase(reshard_pools.begin());
apply_pg_config();
}
if (reshard_pools.size())
{
reshard_timer_id = tfd->set_timer(pg_reshard_chunk_pause_ms, false, [this](int)
{
reshard_continue();
});
}
else
{
reshard_timer_id = -1;
} }
} }
@@ -849,15 +761,9 @@ void osd_t::apply_pg_config()
bool all_applied = true; bool all_applied = true;
for (auto & pool_item: st_cli.pool_config) for (auto & pool_item: st_cli.pool_config)
{ {
auto & pool_cfg = pool_item.second;
if (pool_cfg.reshard_state)
{
// Can't apply anything for pools being resharded
continue;
}
bool warned_block_size = false; bool warned_block_size = false;
auto pool_id = pool_item.first; auto pool_id = pool_item.first;
for (auto & kv: pool_cfg.pg_config) for (auto & kv: pool_item.second.pg_config)
{ {
pg_num_t pg_num = kv.first; pg_num_t pg_num = kv.first;
auto & pg_cfg = kv.second; auto & pg_cfg = kv.second;
@@ -866,8 +772,8 @@ void osd_t::apply_pg_config()
auto pg_it = this->pgs.find({ .pool_id = pool_id, .pg_num = pg_num }); auto pg_it = this->pgs.find({ .pool_id = pool_id, .pg_num = pg_num });
bool currently_taken = pg_it != this->pgs.end() && pg_it->second.state != PG_OFFLINE; bool currently_taken = pg_it != this->pgs.end() && pg_it->second.state != PG_OFFLINE;
// Check pool block size and bitmap granularity // Check pool block size and bitmap granularity
if (take && this->bs_block_size != pool_cfg.data_block_size || if (take && this->bs_block_size != pool_item.second.data_block_size ||
this->bs_bitmap_granularity != pool_cfg.bitmap_granularity) this->bs_bitmap_granularity != pool_item.second.bitmap_granularity)
{ {
if (!warned_block_size) if (!warned_block_size)
{ {
@@ -875,7 +781,7 @@ void osd_t::apply_pg_config()
"[OSD %ju] My block_size and bitmap_granularity are %u/%u" "[OSD %ju] My block_size and bitmap_granularity are %u/%u"
", but pool %u has %u/%u. Refusing to start PGs of this pool\n", ", but pool %u has %u/%u. Refusing to start PGs of this pool\n",
this->osd_num, bs_block_size, bs_bitmap_granularity, this->osd_num, bs_block_size, bs_bitmap_granularity,
pool_id, pool_cfg.data_block_size, pool_cfg.bitmap_granularity pool_id, pool_item.second.data_block_size, pool_item.second.bitmap_granularity
); );
} }
warned_block_size = true; warned_block_size = true;
@@ -968,12 +874,12 @@ void osd_t::apply_pg_config()
} }
auto & pg = this->pgs[{ .pool_id = pool_id, .pg_num = pg_num }]; auto & pg = this->pgs[{ .pool_id = pool_id, .pg_num = pg_num }];
pg.state = pg_cfg.cur_primary == this->osd_num ? PG_PEERING : PG_STARTING; pg.state = pg_cfg.cur_primary == this->osd_num ? PG_PEERING : PG_STARTING;
pg.scheme = pool_cfg.scheme; pg.scheme = pool_item.second.scheme;
pg.pg_cursize = 0; pg.pg_cursize = 0;
pg.pg_size = pool_cfg.pg_size; pg.pg_size = pool_item.second.pg_size;
pg.pg_minsize = pool_cfg.pg_minsize; pg.pg_minsize = pool_item.second.pg_minsize;
pg.pg_data_size = pool_cfg.scheme == POOL_SCHEME_REPLICATED pg.pg_data_size = pool_item.second.scheme == POOL_SCHEME_REPLICATED
? 1 : pool_cfg.pg_size - pool_cfg.parity_chunks; ? 1 : pool_item.second.pg_size - pool_item.second.parity_chunks;
pg.pool_id = pool_id; pg.pool_id = pool_id;
pg.pg_num = pg_num; pg.pg_num = pg_num;
pg.reported_epoch = pg_cfg.epoch; pg.reported_epoch = pg_cfg.epoch;
@@ -982,8 +888,8 @@ void osd_t::apply_pg_config()
pg.next_scrub = pg_cfg.next_scrub; pg.next_scrub = pg_cfg.next_scrub;
pg.target_set = pg_cfg.target_set; pg.target_set = pg_cfg.target_set;
pg.disable_pg_locks = pg_locks_localize_only && pg.disable_pg_locks = pg_locks_localize_only &&
(pool_cfg.scheme != POOL_SCHEME_REPLICATED || (pool_item.second.scheme != POOL_SCHEME_REPLICATED ||
pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY); pool_item.second.local_reads == POOL_LOCAL_READ_PRIMARY);
if (pg.scheme == POOL_SCHEME_EC) if (pg.scheme == POOL_SCHEME_EC)
{ {
use_ec(pg.pg_size, pg.pg_data_size, true); use_ec(pg.pg_size, pg.pg_data_size, true);
+2 -1
View File
@@ -318,7 +318,8 @@ void osd_t::submit_recovery_op(osd_recovery_op_t *op)
// EPIPE is totally harmless (peer is gone), others like EIO/EDOM may be not // EPIPE is totally harmless (peer is gone), others like EIO/EDOM may be not
printf( printf(
"[PG %u/%u] Recovery operation failed with object %jx:%jx: error %jd\n", "[PG %u/%u] Recovery operation failed with object %jx:%jx: error %jd\n",
INODE_POOL(op->oid.inode), map_to_pg(op->oid), INODE_POOL(op->oid.inode),
map_to_pg(op->oid, st_cli.pool_config.at(INODE_POOL(op->oid.inode)).pg_stripe_size),
op->oid.inode, op->oid.stripe, op->osd_op->reply.hdr.retval op->oid.inode, op->oid.stripe, op->osd_op->reply.hdr.retval
); );
} }
+6 -6
View File
@@ -159,10 +159,11 @@ void osd_t::reset_pg(pg_t & pg)
cancel_primary_write(p.second); cancel_primary_write(p.second);
} }
pg.write_queue.clear(); pg.write_queue.clear();
uint64_t pg_stripe_size = st_cli.pool_config[pg.pool_id].pg_stripe_size;
for (auto it = unstable_writes.begin(); it != unstable_writes.end(); ) for (auto it = unstable_writes.begin(); it != unstable_writes.end(); )
{ {
// Forget this PG's unstable writes // Forget this PG's unstable writes
if (INODE_POOL(it->first.oid.inode) == pg.pool_id && map_to_pg(it->first.oid) == pg.pg_num) if (INODE_POOL(it->first.oid.inode) == pg.pool_id && map_to_pg(it->first.oid, pg_stripe_size) == pg.pg_num)
unstable_writes.erase(it++); unstable_writes.erase(it++);
else else
it++; it++;
@@ -523,7 +524,6 @@ void osd_t::relock_pg(pg_t & pg)
void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps) void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
{ {
auto & pool_cfg = st_cli.pool_config.at(ps->pool_id);
if (role_osd == this->osd_num) if (role_osd == this->osd_num)
{ {
// Self // Self
@@ -533,11 +533,11 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
clock_gettime(CLOCK_REALTIME, &op->tv_begin); clock_gettime(CLOCK_REALTIME, &op->tv_begin);
op->bs_op = new blockstore_op_t(); op->bs_op = new blockstore_op_t();
op->bs_op->opcode = BS_OP_LIST; op->bs_op->opcode = BS_OP_LIST;
op->bs_op->pg_alignment = pool_cfg.applied_pg_stripe_size; op->bs_op->pg_alignment = st_cli.pool_config[ps->pool_id].pg_stripe_size;
op->bs_op->min_oid.inode = ((uint64_t)ps->pool_id << (64 - POOL_ID_BITS)); op->bs_op->min_oid.inode = ((uint64_t)ps->pool_id << (64 - POOL_ID_BITS));
op->bs_op->max_oid.inode = ((uint64_t)(ps->pool_id+1) << (64 - POOL_ID_BITS)) - 1; op->bs_op->max_oid.inode = ((uint64_t)(ps->pool_id+1) << (64 - POOL_ID_BITS)) - 1;
op->bs_op->max_oid.stripe = UINT64_MAX; op->bs_op->max_oid.stripe = UINT64_MAX;
op->bs_op->pg_count = pool_cfg.applied_pg_count; op->bs_op->pg_count = pg_counts[ps->pool_id];
op->bs_op->pg_number = ps->pg_num-1; op->bs_op->pg_number = ps->pg_num-1;
op->bs_op->callback = [this, ps, op, role_osd](blockstore_op_t *bs_op) op->bs_op->callback = [this, ps, op, role_osd](blockstore_op_t *bs_op)
{ {
@@ -584,8 +584,8 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
.opcode = OSD_OP_SEC_LIST, .opcode = OSD_OP_SEC_LIST,
}, },
.list_pg = ps->pg_num, .list_pg = ps->pg_num,
.pg_count = pool_cfg.applied_pg_count, .pg_count = pg_counts[ps->pool_id],
.pg_stripe_size = pool_cfg.applied_pg_stripe_size, .pg_stripe_size = st_cli.pool_config[ps->pool_id].pg_stripe_size,
.min_inode = ((uint64_t)(ps->pool_id) << (64 - POOL_ID_BITS)), .min_inode = ((uint64_t)(ps->pool_id) << (64 - POOL_ID_BITS)),
.max_inode = ((uint64_t)(ps->pool_id+1) << (64 - POOL_ID_BITS)) - 1, .max_inode = ((uint64_t)(ps->pool_id+1) << (64 - POOL_ID_BITS)) - 1,
}, },
+1 -8
View File
@@ -35,14 +35,7 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
// oid.stripe = starting offset of the parity stripe // oid.stripe = starting offset of the parity stripe
.stripe = (cur_op->req.rw.offset/pg_block_size)*pg_block_size, .stripe = (cur_op->req.rw.offset/pg_block_size)*pg_block_size,
}; };
auto pg_count = pool_cfg.applied_pg_count; pg_num_t pg_num = (oid.stripe/pool_cfg.pg_stripe_size) % pg_counts[pool_id] + 1; // like map_to_pg()
if (!pg_count)
{
// Pool config is not loaded yet
finish_op(cur_op, -EPIPE);
return false;
}
pg_num_t pg_num = (oid.stripe/pool_cfg.applied_pg_stripe_size) % pg_count + 1; // like map_to_pg()
auto pg_it = pgs.find({ .pool_id = pool_id, .pg_num = pg_num }); auto pg_it = pgs.find({ .pool_id = pool_id, .pg_num = pg_num });
if (pg_it == pgs.end() || pg_it->second.state == PG_OFFLINE) if (pg_it == pgs.end() || pg_it->second.state == PG_OFFLINE)
{ {
+1 -1
View File
@@ -171,7 +171,7 @@ resume_6:
auto & w = op_data->unstable_writes[unstable_osd.start + i]; auto & w = op_data->unstable_writes[unstable_osd.start + i];
pool_pg_num_t wpg = { pool_pg_num_t wpg = {
.pool_id = INODE_POOL(w.oid.inode), .pool_id = INODE_POOL(w.oid.inode),
.pg_num = map_to_pg(w.oid), .pg_num = map_to_pg(w.oid, st_cli.pool_config.at(INODE_POOL(w.oid.inode)).pg_stripe_size),
}; };
if (pgs.at(wpg).state & PG_ACTIVE) if (pgs.at(wpg).state & PG_ACTIVE)
{ {
+5 -6
View File
@@ -9,7 +9,6 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
{ {
pool_id_t pool_id = pg_id.pool_id; pool_id_t pool_id = pg_id.pool_id;
pg_num_t pg_num = pg_id.pg_num; pg_num_t pg_num = pg_id.pg_num;
auto & pool_cfg = st_cli.pool_config.at(pool_id);
assert(!scrub_list_op); assert(!scrub_list_op);
if (role_osd == this->osd_num) if (role_osd == this->osd_num)
{ {
@@ -20,7 +19,7 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
clock_gettime(CLOCK_REALTIME, &op->tv_begin); clock_gettime(CLOCK_REALTIME, &op->tv_begin);
op->bs_op = new blockstore_op_t(); op->bs_op = new blockstore_op_t();
op->bs_op->opcode = BS_OP_LIST; op->bs_op->opcode = BS_OP_LIST;
op->bs_op->pg_alignment = pool_cfg.applied_pg_stripe_size; op->bs_op->pg_alignment = st_cli.pool_config[pool_id].pg_stripe_size;
if (min_oid.inode != 0 || min_oid.stripe != 0) if (min_oid.inode != 0 || min_oid.stripe != 0)
op->bs_op->min_oid = min_oid; op->bs_op->min_oid = min_oid;
else else
@@ -31,7 +30,7 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
op->bs_op->max_oid.inode = ((uint64_t)(pool_id+1) << (64 - POOL_ID_BITS)) - 1; op->bs_op->max_oid.inode = ((uint64_t)(pool_id+1) << (64 - POOL_ID_BITS)) - 1;
op->bs_op->max_oid.stripe = UINT64_MAX; op->bs_op->max_oid.stripe = UINT64_MAX;
op->bs_op->list_stable_limit = scrub_list_limit; op->bs_op->list_stable_limit = scrub_list_limit;
op->bs_op->pg_count = pool_cfg.applied_pg_count; op->bs_op->pg_count = pg_counts[pool_id];
op->bs_op->pg_number = pg_num-1; op->bs_op->pg_number = pg_num-1;
op->bs_op->callback = [this, op](blockstore_op_t *bs_op) op->bs_op->callback = [this, op](blockstore_op_t *bs_op)
{ {
@@ -69,8 +68,8 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
.opcode = OSD_OP_SEC_LIST, .opcode = OSD_OP_SEC_LIST,
}, },
.list_pg = pg_num, .list_pg = pg_num,
.pg_count = (uint32_t)pool_cfg.applied_pg_count, .pg_count = pg_counts[pool_id],
.pg_stripe_size = pool_cfg.applied_pg_stripe_size, .pg_stripe_size = st_cli.pool_config[pool_id].pg_stripe_size,
.min_inode = min_oid.inode ? min_oid.inode : ((uint64_t)(pool_id) << (64 - POOL_ID_BITS)), .min_inode = min_oid.inode ? min_oid.inode : ((uint64_t)(pool_id) << (64 - POOL_ID_BITS)),
.max_inode = ((uint64_t)(pool_id+1) << (64 - POOL_ID_BITS)) - 1, .max_inode = ((uint64_t)(pool_id+1) << (64 - POOL_ID_BITS)) - 1,
.min_stripe = min_oid.stripe, .min_stripe = min_oid.stripe,
@@ -250,7 +249,7 @@ void osd_t::submit_scrub_op(object_id oid)
printf( printf(
"Scrub failed with object %jx:%jx (PG %u/%u): error %jd\n", "Scrub failed with object %jx:%jx (PG %u/%u): error %jd\n",
oid.inode, oid.stripe, INODE_POOL(oid.inode), oid.inode, oid.stripe, INODE_POOL(oid.inode),
map_to_pg(oid), map_to_pg(oid, st_cli.pool_config.at(INODE_POOL(oid.inode)).pg_stripe_size),
osd_op->reply.hdr.retval osd_op->reply.hdr.retval
); );
} }
+14 -23
View File
@@ -79,8 +79,12 @@ void osd_t::exec_secondary(osd_op_t *op)
} }
} }
bool osd_t::sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid, uint32_t flags) bool osd_t::sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid)
{ {
if (!enable_pg_locks)
{
return true;
}
pool_id_t pool_id = INODE_POOL(oid.inode); pool_id_t pool_id = INODE_POOL(oid.inode);
auto pool_cfg_it = st_cli.pool_config.find(pool_id); auto pool_cfg_it = st_cli.pool_config.find(pool_id);
if (pool_cfg_it == st_cli.pool_config.end()) if (pool_cfg_it == st_cli.pool_config.end())
@@ -88,19 +92,11 @@ bool osd_t::sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid, uint3
return false; return false;
} }
auto & pool_cfg = pool_cfg_it->second; auto & pool_cfg = pool_cfg_it->second;
if (pool_cfg.reshard_state)
{
return false;
}
if (!enable_pg_locks || (flags & OSD_OP_IGNORE_PG_LOCK))
{
return true;
}
if (pg_locks_localize_only && (pool_cfg.scheme != POOL_SCHEME_REPLICATED || pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY)) if (pg_locks_localize_only && (pool_cfg.scheme != POOL_SCHEME_REPLICATED || pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY))
{ {
return true; return true;
} }
auto ppg = (pool_pg_num_t){ .pool_id = pool_id, .pg_num = map_to_pg(oid) }; auto ppg = (pool_pg_num_t){ .pool_id = pool_id, .pg_num = map_to_pg(oid, pool_cfg_it->second.pg_stripe_size) };
auto pg_it = pgs.find(ppg); auto pg_it = pgs.find(ppg);
if (pg_it != pgs.end() && pg_it->second.state != PG_OFFLINE) if (pg_it != pgs.end() && pg_it->second.state != PG_OFFLINE)
{ {
@@ -144,7 +140,8 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE || cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE ||
cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE) cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE)
{ {
if (!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_rw.oid, cur_op->req.sec_rw.flags)) if (!(cur_op->req.sec_rw.flags & OSD_OP_IGNORE_PG_LOCK) &&
!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_rw.oid))
{ {
cur_op->bs_op->retval = -EPIPE; cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op); secondary_op_callback(cur_op);
@@ -172,7 +169,8 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
} }
else if (cur_op->req.hdr.opcode == OSD_OP_SEC_DELETE) else if (cur_op->req.hdr.opcode == OSD_OP_SEC_DELETE)
{ {
if (!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_del.oid, cur_op->req.sec_del.flags)) if (!(cur_op->req.sec_del.flags & OSD_OP_IGNORE_PG_LOCK) &&
!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_del.oid))
{ {
cur_op->bs_op->retval = -EPIPE; cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op); secondary_op_callback(cur_op);
@@ -192,11 +190,11 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
#ifdef OSD_STUB #ifdef OSD_STUB
cur_op->bs_op->retval = 0; cur_op->bs_op->retval = 0;
#endif #endif
if (enable_pg_locks) if (enable_pg_locks && !(cur_op->req.sec_stab.flags & OSD_OP_IGNORE_PG_LOCK))
{ {
for (int i = 0; i < cur_op->bs_op->len; i++) for (int i = 0; i < cur_op->bs_op->len; i++)
{ {
if (!sec_check_pg_lock(cl->in_osd_num, ((obj_ver_id*)cur_op->buf)[i].oid, cur_op->req.sec_stab.flags)) if (!sec_check_pg_lock(cl->in_osd_num, ((obj_ver_id*)cur_op->buf)[i].oid))
{ {
cur_op->bs_op->retval = -EPIPE; cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op); secondary_op_callback(cur_op);
@@ -215,14 +213,6 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
secondary_op_callback(cur_op); secondary_op_callback(cur_op);
return; return;
} }
auto pool_id = INODE_POOL(cur_op->bs_op->min_oid.inode);
if (pool_id && !sec_check_pg_lock(0, (object_id){ .inode = cur_op->bs_op->min_oid.inode }, OSD_OP_IGNORE_PG_LOCK))
{
// Check resharding state of the pool
cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op);
return;
}
cur_op->bs_op->pg_alignment = cur_op->req.sec_list.pg_stripe_size; cur_op->bs_op->pg_alignment = cur_op->req.sec_list.pg_stripe_size;
cur_op->bs_op->pg_count = cur_op->req.sec_list.pg_count; cur_op->bs_op->pg_count = cur_op->req.sec_list.pg_count;
cur_op->bs_op->pg_number = cur_op->req.sec_list.list_pg - 1; cur_op->bs_op->pg_number = cur_op->req.sec_list.list_pg - 1;
@@ -258,7 +248,8 @@ void osd_t::exec_sec_read_bmp(osd_op_t *cur_op)
void *cur_buf = reply_buf; void *cur_buf = reply_buf;
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
if (!sec_check_pg_lock(cl->in_osd_num, ov[i].oid, cur_op->req.sec_read_bmp.flags)) if (!sec_check_pg_lock(cl->in_osd_num, ov[i].oid) &&
!(cur_op->req.sec_read_bmp.flags & OSD_OP_IGNORE_PG_LOCK))
{ {
free(reply_buf); free(reply_buf);
cur_op->bs_op->retval = -EPIPE; cur_op->bs_op->retval = -EPIPE;
+1 -2
View File
@@ -899,8 +899,7 @@ void test_reshard_list()
free(listing); free(listing);
listing = NULL; listing = NULL;
void *st = heap.reshard_start(1, 2, 0x20000, 0); heap.reshard(1, 2, 0x20000);
assert(st == NULL);
assert(heap.read_entry((object_id){ .inode = INODE_WITH_POOL(1, 1), .stripe = 0 })); assert(heap.read_entry((object_id){ .inode = INODE_WITH_POOL(1, 1), .stripe = 0 }));
assert(heap.read_entry((object_id){ .inode = INODE_WITH_POOL(1, 1), .stripe = 0x20000 })); assert(heap.read_entry((object_id){ .inode = INODE_WITH_POOL(1, 1), .stripe = 0x20000 }));
-2
View File
@@ -37,7 +37,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include "crc32c.h" #include "crc32c.h"
#ifdef WITH_ISAL #ifdef WITH_ISAL
@@ -395,7 +394,6 @@ static uint8_t zero_page[4096] = {};
uint32_t crc32c_pad(uint32_t prev_crc, const void *buf, size_t len, size_t left_pad, size_t right_pad) uint32_t crc32c_pad(uint32_t prev_crc, const void *buf, size_t len, size_t left_pad, size_t right_pad)
{ {
assert(left_pad < 0x10000000 && right_pad < 0x10000000);
uint32_t r = prev_crc; uint32_t r = prev_crc;
while (left_pad >= 4096) while (left_pad >= 4096)
{ {
+2 -10
View File
@@ -65,7 +65,7 @@ start_etcd()
--max-txn-ops=100000 --auto-compaction-retention=10 --auto-compaction-mode=revision &>./testdata/etcd$i.log & --max-txn-ops=100000 --auto-compaction-retention=10 --auto-compaction-mode=revision &>./testdata/etcd$i.log &
eval ETCD${i}_PID=$! eval ETCD${i}_PID=$!
else else
node mon/mon-main.js $MON_PARAMS --antietcd_port $((ETCD_PORT+2*i-2)) --verbose 1 >>./testdata/mon$i.log 2>&1 & node mon/mon-main.js $MON_PARAMS --antietcd_port $((ETCD_PORT+2*i-2)) --etcd_address $ETCD_URL --etcd_prefix "/vitastor" --verbose 1 >>./testdata/mon$i.log 2>&1 &
eval ETCD${i}_PID=$! eval ETCD${i}_PID=$!
fi fi
} }
@@ -108,20 +108,12 @@ wait_condition()
done done
} }
VITASTOR_CFG='"etcd_address":"'$ETCD_URL'"'
echo "{$VITASTOR_CFG}" > ./testdata/vitastor.conf
VITASTOR_CFG=./testdata/vitastor.conf
VITASTOR_CLI="build/src/cmd/vitastor-cli --config_path $VITASTOR_CFG"
# Preload build/src/client/libfio_vitastor.so so libasan detects all symbols
VITASTOR_FIO="env LD_PRELOAD=build/src/client/libfio_vitastor.so fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -conf $VITASTOR_CFG"
OSD_ARGS="$OSD_ARGS --config_path $VITASTOR_CFG"
MON_PARAMS="$MON_PARAMS --config_path $VITASTOR_CFG"
if [[ -n "$ANTIETCD" ]]; then if [[ -n "$ANTIETCD" ]]; then
ETCDCTL="node mon/node_modules/.bin/anticli -e $ETCD_URL" ETCDCTL="node mon/node_modules/.bin/anticli -e $ETCD_URL"
MON_PARAMS="--use_antietcd 1 --antietcd_data_dir ./testdata --antietcd_persist_interval 500 $MON_PARAMS" MON_PARAMS="--use_antietcd 1 --antietcd_data_dir ./testdata --antietcd_persist_interval 500 $MON_PARAMS"
else else
ETCDCTL="${ETCD}ctl --endpoints=$ETCD_URL --dial-timeout=5s --command-timeout=10s" ETCDCTL="${ETCD}ctl --endpoints=$ETCD_URL --dial-timeout=5s --command-timeout=10s"
MON_PARAMS="$MON_PARAMS"
start_etcd_cluster start_etcd_cluster
fi fi
+2 -2
View File
@@ -23,7 +23,7 @@ if [[ -n "$ANTIETCD" ]]; then
start_etcd $i start_etcd $i
done done
else else
node mon/mon-main.js $MON_PARAMS --verbose 1 >>./testdata/mon.log 2>&1 & node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" --verbose 1 >>./testdata/mon.log 2>&1 &
MON_PID=$! MON_PID=$!
fi fi
wait_etcd wait_etcd
@@ -40,7 +40,7 @@ start_osd_on()
{ {
local i=$1 local i=$1
local dev=$2 local dev=$2
build/src/osd/vitastor-osd --osd_num $i --bind_address $ETCD_IP $NO_SAME $OSD_ARGS \ build/src/osd/vitastor-osd --osd_num $i --bind_address $ETCD_IP $NO_SAME $OSD_ARGS --etcd_address $ETCD_URL \
$(build/src/disk_tool/vitastor-disk simple-offsets --format options $OFFSET_ARGS $dev $OFFSET_ARGS 2>/dev/null) \ $(build/src/disk_tool/vitastor-disk simple-offsets --format options $OFFSET_ARGS $dev $OFFSET_ARGS 2>/dev/null) \
>>./testdata/osd$i.log 2>&1 & >>./testdata/osd$i.log 2>&1 &
eval OSD${i}_PID=$! eval OSD${i}_PID=$!
-4
View File
@@ -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
@@ -138,7 +136,6 @@ OLD=1 SCHEME=xor ./test_scrub.sh
OLD=1 PG_SIZE=3 ./test_scrub.sh OLD=1 PG_SIZE=3 ./test_scrub.sh
OLD=1 PG_SIZE=6 PG_MINSIZE=4 OSD_COUNT=6 SCHEME=ec ./test_scrub.sh OLD=1 PG_SIZE=6 PG_MINSIZE=4 OSD_COUNT=6 SCHEME=ec ./test_scrub.sh
OLD=1 SCHEME=ec ./test_scrub.sh OLD=1 SCHEME=ec ./test_scrub.sh
OLD=1 ./test_partwr_csum.sh
TEST_NAME=old_csum_32k_dmj OLD=1 OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_metadata false --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh TEST_NAME=old_csum_32k_dmj OLD=1 OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_metadata false --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh
TEST_NAME=old_csum_32k_dj OLD=1 OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh TEST_NAME=old_csum_32k_dj OLD=1 OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh
@@ -148,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
+4 -3
View File
@@ -4,8 +4,9 @@ PG_COUNT=2048
GLOBAL_CONFIG=',"osd_out_time":1' GLOBAL_CONFIG=',"osd_out_time":1'
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -end_fsync=1 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-rw=write -pool=1 -inode=1 -size=128M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -end_fsync=1 \
-rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10
start_osd 4 start_osd 4
@@ -29,7 +30,7 @@ wait_finish_rebalance 60
sleep 1 sleep 1
kill -9 $OSD4_PID kill -9 $OSD4_PID
sleep 1 sleep 1
$VITASTOR_CLI rm-osd --force 4 build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm-osd --force 4
sleep 2 sleep 2
+1 -1
View File
@@ -2,6 +2,6 @@
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
build/src/test/test_cas --pool_id 1 --inode_id 1 --config_path $VITASTOR_CFG build/src/test/test_cas --pool_id 1 --inode_id 1 --etcd_address $ETCD_URL
format_green OK format_green OK
+3 -3
View File
@@ -1,6 +1,5 @@
#!/bin/bash -ex #!/bin/bash -ex
GLOBAL_CONFIG=',"pg_reshard_chunk_size":100'
OSD_COUNT=${OSD_COUNT:-6} OSD_COUNT=${OSD_COUNT:-6}
PG_COUNT=16 PG_COUNT=16
@@ -8,8 +7,9 @@ PG_COUNT=16
NOBJ=$(((128*8+PG_DATA_SIZE-1)/PG_DATA_SIZE)) NOBJ=$(((128*8+PG_DATA_SIZE-1)/PG_DATA_SIZE))
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-pool=1 -inode=2 -size=128M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M -cluster_log_level=10
try_change() try_change()
{ {
+6 -3
View File
@@ -6,10 +6,13 @@ GLOBAL_CONFIG=',"client_retry_interval":1000'
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write -pool=1 -inode=2 -size=128M LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 -rw=randrw -pool=1 -inode=2 -size=128M -loops=100 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-cluster_log_level=3 -runtime=60 &>./testdata/fio.log & fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -rw=randrw \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M -loops=100 -cluster_log_level=3 -runtime=60 &>./testdata/fio.log &
FIO_PID=$! FIO_PID=$!
try_change() try_change()
+4 -3
View File
@@ -11,8 +11,9 @@ IMG_SIZE=128
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
# Write # Write
$VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-mirror_file=./testdata/bin/mirror.bin -end_fsync=1 -rw=write -image=testimg -runtime=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 \
-mirror_file=./testdata/bin/mirror.bin -end_fsync=1 -rw=write -etcd=$ETCD_URL -image=testimg -runtime=10
# Intentionally corrupt OSD data and restart it # Intentionally corrupt OSD data and restart it
kill $OSD1_PID kill $OSD1_PID
@@ -28,7 +29,7 @@ wait_up 10
# Read everything back # Read everything back
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-O raw ./testdata/bin/read.bin -O raw ./testdata/bin/read.bin
diff ./testdata/bin/read.bin ./testdata/bin/mirror.bin diff ./testdata/bin/read.bin ./testdata/bin/mirror.bin
+3 -3
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh . `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 & node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
MON_PID=$! MON_PID=$!
wait_etcd wait_etcd
@@ -28,8 +28,8 @@ $ETCDCTL put /vitastor/osd/stats/3 '{"host":"host2","size":1073741824,"time":"'$
$ETCDCTL put /vitastor/osd/stats/4 '{"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/5 '{"host":"host3","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/6 '{"host":"host3","size":1073741824,"time":"'$TIME'"}' $ETCDCTL put /vitastor/osd/stats/6 '{"host":"host3","size":1073741824,"time":"'$TIME'"}'
$VITASTOR_CLI osd-tree build/src/cmd/vitastor-cli --etcd_address $ETCD_URL osd-tree
# check that it doesn't fail # check that it doesn't fail
$VITASTOR_CLI create-pool testpool --ec 2+1 -n 32 build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool --ec 2+1 -n 32
format_green OK format_green OK
+1 -1
View File
@@ -6,7 +6,7 @@
$ETCDCTL put /vitastor/config/inode/1/120 '{"name":"testimg","size":'$((1024*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/120 '{"name":"testimg","size":'$((1024*1024*1024))'}'
$VITASTOR_CLI create -s 1G testimg2 build/src/cmd/vitastor-cli create --etcd_address $ETCD_URL -s 1G testimg2
t=$($ETCDCTL get --print-value-only /vitastor/config/inode/1/121 | jq -r .name) t=$($ETCDCTL get --print-value-only /vitastor/config/inode/1/121 | jq -r .name)
if [[ "$t" != "testimg2" ]]; then if [[ "$t" != "testimg2" ]]; then
+5 -5
View File
@@ -4,17 +4,17 @@
# pipe in - pipe out # pipe in - pipe out
dd if=/dev/urandom of=./testdata/testfile bs=1M count=128 dd if=/dev/urandom of=./testdata/testfile bs=1M count=128
$VITASTOR_CLI dd oimg=testimg iodepth=4 bs=1M count=128 < ./testdata/testfile build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd oimg=testimg iodepth=4 bs=1M count=128 < ./testdata/testfile
$VITASTOR_CLI dd iimg=testimg iodepth=4 bs=1M count=128 > ./testdata/testfile1 build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testimg iodepth=4 bs=1M count=128 > ./testdata/testfile1
diff ./testdata/testfile ./testdata/testfile1 diff ./testdata/testfile ./testdata/testfile1
rm ./testdata/testfile1 rm ./testdata/testfile1
# snapshot # snapshot
dd if=/dev/urandom of=./testdata/over bs=1M count=4 dd if=/dev/urandom of=./testdata/over bs=1M count=4
dd if=./testdata/over of=./testdata/testfile bs=1M seek=17 conv=notrunc dd if=./testdata/over of=./testdata/testfile bs=1M seek=17 conv=notrunc
$VITASTOR_CLI snap-create testimg@snap1 build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testimg@snap1
$VITASTOR_CLI dd iodepth=4 if=./testdata/over oimg=testimg bs=1M seek=17 build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iodepth=4 if=./testdata/over oimg=testimg bs=1M seek=17
$VITASTOR_CLI dd iodepth=4 iimg=testimg of=./testdata/testfile1 build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iodepth=4 iimg=testimg of=./testdata/testfile1
diff ./testdata/testfile ./testdata/testfile1 diff ./testdata/testfile ./testdata/testfile1
format_green OK format_green OK
+3 -2
View File
@@ -15,8 +15,9 @@ for i in $(seq 1 $OSD_COUNT); do
done done
wait_up 120 wait_up 120
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 -rw=randwrite -loops=1000 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-pool=1 -inode=2 -size=256M -cluster_log_level=10 -runtime=5 & fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -rw=randwrite -loops=1000 \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=256M -cluster_log_level=10 -runtime=5 &
FIO_PID=$! FIO_PID=$!
sleep 15 sleep 15
+8 -6
View File
@@ -5,21 +5,23 @@ GLOBAL_CONFIG=',"client_retry_enospc":false'
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
export LD_PRELOAD="build/src/client/libfio_vitastor.so"
# Should fail with ENOSPC # Should fail with ENOSPC
if $VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 \ if fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 \
-rw=write -pool=1 -inode=1 -size=500M -cluster_log_level=10; then -rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=500M -cluster_log_level=10; then
format_error "Should get ENOSPC, but didn't" format_error "Should get ENOSPC, but didn't"
fi fi
# Should fail with ENOSPC too (the idea is to try to overwrite first objects to check their rollback) # Should fail with ENOSPC too (the idea is to try to overwrite first objects to check their rollback)
if $VITASTOR_FIO -bs=1M -direct=1 -iodepth=32 \ if fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=32 \
-rw=write -pool=1 -inode=1 -size=500M -cluster_log_level=10; then -rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=500M -cluster_log_level=10; then
format_error "Should get ENOSPC, but didn't" format_error "Should get ENOSPC, but didn't"
fi fi
# Should complete OK # Should complete OK
if ! $VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 \ if ! fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 \
-rw=randwrite -pool=1 -inode=1 -size=100M -cluster_log_level=10 -number_ios=4096; then -rw=randwrite -etcd=$ETCD_URL -pool=1 -inode=1 -size=100M -cluster_log_level=10 -number_ios=4096; then
format_error "Should do random writes over ENOSPC correctly, but got an error" format_error "Should do random writes over ENOSPC correctly, but got an error"
fi fi
+6 -4
View File
@@ -5,8 +5,9 @@ ETCD_COUNT=5
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=randwrite \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-pool=1 -inode=1 -size=128M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=randwrite \
-etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10
kill_etcds() kill_etcds()
{ {
@@ -25,7 +26,8 @@ kill_etcds()
kill_etcds & kill_etcds &
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=1 -rw=randwrite \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-pool=1 -inode=1 -size=128M -cluster_log_level=10 -runtime=30 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=1 -rw=randwrite \
-etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10 -runtime=30
format_green OK format_green OK
+7 -7
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh . `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 & node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
MON_PID=$! MON_PID=$!
wait_etcd wait_etcd
@@ -17,13 +17,13 @@ $ETCDCTL put /vitastor/osd/stats/5 '{"host":"host3","size":1073741824,"time":"'$
$ETCDCTL put /vitastor/osd/stats/6 '{"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/7 '{"host":"host4","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/8 '{"host":"host4","size":1073741824,"time":"'$TIME'"}' $ETCDCTL put /vitastor/osd/stats/8 '{"host":"host4","size":1073741824,"time":"'$TIME'"}'
$VITASTOR_CLI create-pool testpool --ec 3+2 -n 32 --failure_domain rack --force build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool --ec 3+2 -n 32 --failure_domain rack --force
$ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1": {"failure_domain": "rack", "name": "testpool", "parity_chunks": 2, "pg_count": 32, "pg_minsize": 4, "pg_size": 5, "scheme": "ec"}}]' $ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1": {"failure_domain": "rack", "name": "testpool", "parity_chunks": 2, "pg_count": 32, "pg_minsize": 4, "pg_size": 5, "scheme": "ec"}}]'
$VITASTOR_CLI modify-pool testpool --ec 3+3 --failure_domain host build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool testpool --ec 3+3 --failure_domain host
$ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1": {"failure_domain": "host", "name": "testpool", "parity_chunks": 3, "pg_count": 32, "pg_minsize": 4, "pg_size": 6, "scheme": "ec"}}]' $ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1": {"failure_domain": "host", "name": "testpool", "parity_chunks": 3, "pg_count": 32, "pg_minsize": 4, "pg_size": 6, "scheme": "ec"}}]'
$VITASTOR_CLI rm-pool testpool build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm-pool testpool
$ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{}]' $ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{}]'
$VITASTOR_CLI create-pool testpool -s 2 -n 4 --failure_domain rack --force build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool -s 2 -n 4 --failure_domain rack --force
$ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1":{"name":"testpool","scheme":"replicated","pg_size":2,"pg_minsize":1,"pg_count":4,"failure_domain":"rack"}}]' $ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1":{"name":"testpool","scheme":"replicated","pg_size":2,"pg_minsize":1,"pg_count":4,"failure_domain":"rack"}}]'
sleep 2 sleep 2
@@ -32,9 +32,9 @@ $ETCDCTL get --prefix /vitastor/pg/config --print-value-only | \
jq -s -e '([ .[0].items["1"] | .[].osd_set | map_values(. | tonumber) | select((.[0] <= 4) != (.[1] <= 4)) ] | length) == 4' jq -s -e '([ .[0].items["1"] | .[].osd_set | map_values(. | tonumber) | select((.[0] <= 4) != (.[1] <= 4)) ] | length) == 4'
# test pool with size 1 # test pool with size 1
$VITASTOR_CLI create-pool size1pool -s 1 -n 1 --force build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool size1pool -s 1 -n 1 --force
wait_condition 10 "$ETCDCTL get --prefix /vitastor/pg/config --print-value-only | jq -s -e '.[0].items["'"'"2"'"'"]'" wait_condition 10 "$ETCDCTL get --prefix /vitastor/pg/config --print-value-only | jq -s -e '.[0].items["'"'"2"'"'"]'"
$VITASTOR_CLI modify-pool size1pool -s 2 --force build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool size1pool -s 2 --force
format_green OK format_green OK
+7 -5
View File
@@ -18,8 +18,9 @@ IMG_SIZE=960
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-mirror_file=./testdata/bin/mirror.bin -image=testimg -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-mirror_file=./testdata/bin/mirror.bin -etcd=$ETCD_URL -image=testimg -cluster_log_level=10
kill_osds() kill_osds()
{ {
@@ -50,11 +51,12 @@ kill_osds()
kill_osds & kill_osds &
$VITASTOR_FIO -bsrange=4k-128k -blockalign=4k -direct=1 -iodepth=32 -fsync=256 -rw=randrw \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-serialize_overlap=1 -randrepeat=0 -refill_buffers=1 -mirror_file=./testdata/bin/mirror.bin -image=testimg -loops=10 -runtime=120 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bsrange=4k-128k -blockalign=4k -direct=1 -iodepth=32 -fsync=256 -rw=randrw \
-serialize_overlap=1 -randrepeat=0 -refill_buffers=1 -mirror_file=./testdata/bin/mirror.bin -etcd=$ETCD_URL -image=testimg -loops=10 -runtime=120
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-O raw ./testdata/bin/read.bin -O raw ./testdata/bin/read.bin
if ! diff -q ./testdata/bin/read.bin ./testdata/bin/mirror.bin; then if ! diff -q ./testdata/bin/read.bin ./testdata/bin/mirror.bin; then
+3 -2
View File
@@ -6,8 +6,9 @@ PG_COUNT=32
IMG_SIZE=960 IMG_SIZE=960
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=16 -fsync=16 -rw=write \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-pool=1 -inode=2 -size=${IMG_SIZE}M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=16 -fsync=16 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=${IMG_SIZE}M -cluster_log_level=10
try_reweight 1 0 try_reweight 1 0
+1 -1
View File
@@ -3,6 +3,6 @@
PG_COUNT=16 PG_COUNT=16
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
build/src/kv/vitastor-kv-stress --config_path $VITASTOR_CFG --pool_id 1 --inode_id 1 --runtime 30 build/src/kv/vitastor-kv-stress --etcd_address $ETCD_URL --pool_id 1 --inode_id 1 --runtime 30
format_green OK format_green OK
-39
View File
@@ -1,39 +0,0 @@
#!/bin/bash -ex
. `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS >>./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'"}'
$VITASTOR_CLI 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
+7 -5
View File
@@ -10,7 +10,7 @@ OSD_ARGS="$OSD_ARGS"
for i in $(seq 1 $OSD_COUNT); do for i in $(seq 1 $OSD_COUNT); do
dd if=/dev/zero of=./testdata/bin/test_osd$i.bin bs=1024 count=1 seek=$((OSD_SIZE*1024-1)) dd if=/dev/zero of=./testdata/bin/test_osd$i.bin bs=1024 count=1 seek=$((OSD_SIZE*1024-1))
build/src/osd/vitastor-osd --log_level 10 --osd_num $i --bind_address 127.0.0.1 --etcd_stats_interval 5 $OSD_ARGS \ build/src/osd/vitastor-osd --log_level 10 --osd_num $i --bind_address 127.0.0.1 --etcd_stats_interval 5 $OSD_ARGS \
$(build/src/disk_tool/vitastor-disk simple-offsets --format options ./testdata/bin/test_osd$i.bin $OFFSET_ARGS 2>/dev/null) >>./testdata/osd$i.log 2>&1 & --etcd_address $ETCD_URL $(build/src/disk_tool/vitastor-disk simple-offsets --format options ./testdata/bin/test_osd$i.bin $OFFSET_ARGS 2>/dev/null) >>./testdata/osd$i.log 2>&1 &
eval OSD${i}_PID=$! eval OSD${i}_PID=$!
done done
@@ -27,8 +27,9 @@ for i in {1..30}; do
fi fi
done done
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-pool=1 -inode=2 -size=32M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=32M -cluster_log_level=10
$ETCDCTL put /vitastor/pg/config '{"items":{"1":{"1":{"osd_set":[1,0],"primary":0}}}}' $ETCDCTL put /vitastor/pg/config '{"items":{"1":{"1":{"osd_set":[1,0],"primary":0}}}}'
@@ -56,8 +57,9 @@ for i in {1..30}; do
done done
# Sync so all moved objects are removed from OSD 1 (they aren't removed without a sync) # Sync so all moved objects are removed from OSD 1 (they aren't removed without a sync)
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=1 -number_ios=2 -rw=write \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-pool=1 -inode=2 -size=32M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=1 -number_ios=2 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=32M -cluster_log_level=10
$ETCDCTL put /vitastor/pg/config '{"items":{"1":{"1":{"osd_set":[4,5],"primary":0}}}}' $ETCDCTL put /vitastor/pg/config '{"items":{"1":{"1":{"osd_set":[4,5],"primary":0}}}}'
+7 -7
View File
@@ -5,9 +5,9 @@ IMMEDIATE_COMMIT=1
PG_COUNT=16 PG_COUNT=16
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
$VITASTOR_CLI create -s 10G fsmeta build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 10G fsmeta
$VITASTOR_CLI modify-pool --used-for-app fs:fsmeta testpool build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool --used-for-app fs:fsmeta testpool
build/src/nfs/vitastor-nfs --config_path $VITASTOR_CFG start --fs fsmeta --portmap 0 --port 2050 --foreground 1 --trace 1 >>./testdata/nfs.log 2>&1 & 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=$! NFS_PID=$!
mkdir -p testdata/nfs mkdir -p testdata/nfs
@@ -175,22 +175,22 @@ format_green "rename over existing file ok"
# check listing and removal of a bad direntry # check listing and removal of a bad direntry
sudo umount ./testdata/nfs/ sudo umount ./testdata/nfs/
build/src/kv/vitastor-kv --config_path $VITASTOR_CFG fsmeta set d11/settings.jsonLGNmGn '{"ino": 123}' build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta set d11/settings.jsonLGNmGn '{"ino": 123}'
sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp
ls -l ./testdata/nfs ls -l ./testdata/nfs
ls -l ./testdata/nfs/settings.jsonLGNmGn ls -l ./testdata/nfs/settings.jsonLGNmGn
sudo rm ./testdata/nfs/settings.jsonLGNmGn sudo rm ./testdata/nfs/settings.jsonLGNmGn
build/src/kv/vitastor-kv --config_path $VITASTOR_CFG fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)' build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)'
ls -l ./testdata/nfs ls -l ./testdata/nfs
# repeat with ino=0 # repeat with ino=0
sudo umount ./testdata/nfs/ sudo umount ./testdata/nfs/
build/src/kv/vitastor-kv --config_path $VITASTOR_CFG fsmeta set d11/settings.jsonLGNmGn '{"ino": 0}' build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta set d11/settings.jsonLGNmGn '{"ino": 0}'
sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp
ls -l ./testdata/nfs ls -l ./testdata/nfs
ls -l ./testdata/nfs/settings.jsonLGNmGn ls -l ./testdata/nfs/settings.jsonLGNmGn
sudo rm ./testdata/nfs/settings.jsonLGNmGn sudo rm ./testdata/nfs/settings.jsonLGNmGn
build/src/kv/vitastor-kv --config_path $VITASTOR_CFG fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)' build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)'
ls -l ./testdata/nfs ls -l ./testdata/nfs
format_green OK format_green OK
-34
View File
@@ -1,34 +0,0 @@
#!/bin/bash -ex
GLOBAL_CONFIG=',"client_enable_writeback":false'
IMMEDIATE_COMMIT=1
PG_COUNT=16
. `dirname $0`/run_3osds.sh
$VITASTOR_CLI create -s 10G fsmeta
$VITASTOR_CLI modify-pool --used-for-app fs:fsmeta testpool
build/src/nfs/vitastor-nfs --config_path $VITASTOR_CFG start --fs fsmeta --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
$VITASTOR_CLI dd if=/dev/urandom of=./testdata/ref_data.bin bs=1M count=32 seek=1024B
$VITASTOR_CLI 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
$VITASTOR_CLI dd if=/dev/urandom of=./testdata/ref_small.bin bs=10 count=500 seek=15B
$VITASTOR_CLI 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
+1 -1
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh . `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 & node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
MON_PID=$! MON_PID=$!
wait_etcd wait_etcd
+3 -1
View File
@@ -39,7 +39,9 @@ try_change()
fi fi
} }
$VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 -rw=write -pool=1 -inode=1 -size=128M -runtime=10 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 \
-rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -runtime=10
PG_SIZE=7 PG_SIZE=7
POOLCFG='"name":"testpool","failure_domain":"osd","scheme":"ec","parity_chunks":'$((PG_SIZE-PG_DATA_SIZE)) POOLCFG='"name":"testpool","failure_domain":"osd","scheme":"ec","parity_chunks":'$((PG_SIZE-PG_DATA_SIZE))
-18
View File
@@ -1,18 +0,0 @@
#!/bin/bash -ex
OSD_ARGS="--data_csum_type crc32c"
OFFSET_ARGS=$OSD_ARGS
GLOBAL_CONFIG=',"client_eio_retry_interval":0'
. `dirname $0`/run_3osds.sh
$VITASTOR_CLI create -s 32M testimg
$VITASTOR_FIO -bs=4k -blockalign=128k -direct=1 -iodepth=16 -end_fsync=1 -rw=write -image=testimg
$VITASTOR_CLI dd iimg=testimg of=/dev/null
if grep -q 'Checksum mismatch' ./testdata/osd*.log; then
format_error Checksum mismatches detected during test
fi
format_green OK
+1 -1
View File
@@ -10,7 +10,7 @@ IMG_SIZE=256
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
NBD_DEV=$(sudo build/src/client/vitastor-nbd map --nbd_timeout 180 --config_path $VITASTOR_CFG --image testimg --logfile ./testdata/nbd.log &) NBD_DEV=$(sudo build/src/client/vitastor-nbd map --nbd_timeout 180 --etcd_address $ETCD_URL --image testimg --logfile ./testdata/nbd.log &)
trap "sudo build/src/client/vitastor-nbd unmap $NBD_DEV"' || true; kill -9 $(jobs -p)' EXIT trap "sudo build/src/client/vitastor-nbd unmap $NBD_DEV"' || true; kill -9 $(jobs -p)' EXIT
+9 -7
View File
@@ -5,14 +5,16 @@ PG_COUNT=${PG_COUNT:-32}
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
check_qemu check_qemu
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=4 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-rw=write -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=4 \
-rw=write -etcd=$ETCD_URL -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=32 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-rw=randwrite -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10 -number_ios=1024 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=32 \
-rw=randwrite -etcd=$ETCD_URL -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10 -number_ios=1024
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=1:size=$((256*1024*1024))" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=1:size=$((256*1024*1024))" \
-O raw ./testdata/bin/before.bin -O raw ./testdata/bin/before.bin
for i in $(seq 1 $OSD_COUNT); do for i in $(seq 1 $OSD_COUNT); do
@@ -70,7 +72,7 @@ done
$ETCDCTL del --prefix /vitastor/osd/state/ $ETCDCTL del --prefix /vitastor/osd/state/
for i in $(seq 1 $OSD_COUNT); do for i in $(seq 1 $OSD_COUNT); do
build/src/osd/vitastor-osd --osd_num $i --bind_address 127.0.0.1 $NO_SAME $OSD_ARGS \ build/src/osd/vitastor-osd --osd_num $i --bind_address 127.0.0.1 $NO_SAME $OSD_ARGS --etcd_address $ETCD_URL \
--meta_format $meta_format \ --meta_format $meta_format \
--data_device ./testdata/bin/test_osd$i.bin \ --data_device ./testdata/bin/test_osd$i.bin \
--meta_offset 0 \ --meta_offset 0 \
@@ -80,7 +82,7 @@ for i in $(seq 1 $OSD_COUNT); do
done done
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=1:size=$((256*1024*1024))" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=1:size=$((256*1024*1024))" \
-O raw ./testdata/bin/after.bin -O raw ./testdata/bin/after.bin
if ! cmp ./testdata/bin/before.bin ./testdata/bin/after.bin; then if ! cmp ./testdata/bin/before.bin ./testdata/bin/after.bin; then
+3 -3
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh . `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 & node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
MON_PID=$! MON_PID=$!
wait_etcd wait_etcd
@@ -11,7 +11,7 @@ $ETCDCTL put /vitastor/osd/stats/1 '{"host":"host1","size":1073741824,"time":"'$
$ETCDCTL put /vitastor/osd/stats/2 '{"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/3 '{"host":"host2","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/4 '{"host":"host2","size":1073741824,"time":"'$TIME'"}' $ETCDCTL put /vitastor/osd/stats/4 '{"host":"host2","size":1073741824,"time":"'$TIME'"}'
$VITASTOR_CLI create-pool testpool -s 2 -n 16 --force build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool -s 2 -n 16 --force
sleep 2 sleep 2
@@ -25,7 +25,7 @@ $ETCDCTL get /vitastor/pg/config --print-value-only | \
$ETCDCTL get /vitastor/pg/config --print-value-only | \ $ETCDCTL get /vitastor/pg/config --print-value-only | \
jq -s -e '([ .[0].items["1"] | .[].osd_set | map_values(. | tonumber) | select(.[0] == 4 or .[1] == 4) ] | length) == 8' jq -s -e '([ .[0].items["1"] | .[].osd_set | map_values(. | tonumber) | select(.[0] == 4 or .[1] == 4) ] | length) == 8'
$VITASTOR_CLI modify-osd --reweight 0.5 3 build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-osd --reweight 0.5 3
sleep 2 sleep 2
+4 -3
View File
@@ -3,11 +3,12 @@
PG_COUNT=16 PG_COUNT=16
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-end_fsync=1 -fsync=1 -rw=write -pool=1 -inode=1 -size=128M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10
$ETCDCTL get --prefix '/vitastor/pg/state' $ETCDCTL get --prefix '/vitastor/pg/state'
$VITASTOR_CLI rm-data --pool 1 --inode 1 build/src/cmd/vitastor-cli rm-data --etcd_address $ETCD_URL --pool 1 --inode 1
format_green OK format_green OK
+11 -9
View File
@@ -5,19 +5,20 @@ PG_COUNT=16
PG_MINSIZE=2 PG_MINSIZE=2
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
$VITASTOR_CLI create -s 128M testimg build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 128M testimg
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-end_fsync=1 -fsync=1 -rw=write -image=testimg -size=128M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -etcd=$ETCD_URL -image=testimg -size=128M -cluster_log_level=10
kill -9 $OSD3_PID kill -9 $OSD3_PID
$ETCDCTL del /vitastor/osd/state/3 $ETCDCTL del /vitastor/osd/state/3
if $VITASTOR_CLI rm testimg --log_level 10 ; then if build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm testimg --log_level 10 ; then
format_error "Delete should not be successful with inactive OSDs" format_error "Delete should not be successful with inactive OSDs"
fi fi
if ! ( $VITASTOR_CLI ls | grep testimg | grep DEL ) ; then if ! ( build/src/cmd/vitastor-cli --etcd_address $ETCD_URL ls | grep testimg | grep DEL ) ; then
format_error "Image should be marked as partially deleted" format_error "Image should be marked as partially deleted"
fi fi
@@ -26,16 +27,17 @@ sleep 5
# Now do the same but without del /vitastor/osd/state # Now do the same but without del /vitastor/osd/state
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-end_fsync=1 -fsync=1 -rw=write -image=testimg -size=128M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -etcd=$ETCD_URL -image=testimg -size=128M -cluster_log_level=10
kill -9 $OSD3_PID kill -9 $OSD3_PID
if $VITASTOR_CLI rm testimg --log_level 10 ; then if build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm testimg --log_level 10 ; then
format_error "Delete should not be successful with inactive OSDs" format_error "Delete should not be successful with inactive OSDs"
fi fi
if ! ( $VITASTOR_CLI ls | grep testimg | grep DEL ) ; then if ! ( build/src/cmd/vitastor-cli --etcd_address $ETCD_URL ls | grep testimg | grep DEL ) ; then
format_error "Image should be marked as partially deleted" format_error "Image should be marked as partially deleted"
fi fi
+1 -1
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh . `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 & node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
MON_PID=$! MON_PID=$!
wait_etcd wait_etcd
+9 -8
View File
@@ -20,8 +20,9 @@ check_qemu
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
# Write # Write
$VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-mirror_file=./testdata/bin/mirror.bin -end_fsync=1 -rw=write -image=testimg fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 \
-mirror_file=./testdata/bin/mirror.bin -end_fsync=1 -rw=write -etcd=$ETCD_URL -image=testimg
sleep 1 sleep 1
@@ -54,23 +55,23 @@ wait_condition 300 "$ETCDCTL get --prefix /vitastor/pg/history/ --print-value-on
if [[ ($SCHEME = replicated && $PG_SIZE < 3) || ($SCHEME != replicated && $((PG_SIZE-PG_DATA_SIZE)) < 2) ]]; then if [[ ($SCHEME = replicated && $PG_SIZE < 3) || ($SCHEME != replicated && $((PG_SIZE-PG_DATA_SIZE)) < 2) ]]; then
# Check that objects are marked as inconsistent if 2 replicas or EC/XOR 2+1 # Check that objects are marked as inconsistent if 2 replicas or EC/XOR 2+1
$VITASTOR_CLI describe --json &>./testdata/describe.log build/src/cmd/vitastor-cli describe --etcd_address $ETCD_URL --json &>./testdata/describe.log
$VITASTOR_CLI describe --json | jq -e '[ .[] | select(.inconsistent) ] | length == '$((IMG_SIZE * 8 * PG_SIZE / (SCHEME = replicated ? 1 : PG_DATA_SIZE))) build/src/cmd/vitastor-cli describe --etcd_address $ETCD_URL --json | jq -e '[ .[] | select(.inconsistent) ] | length == '$((IMG_SIZE * 8 * PG_SIZE / (SCHEME = replicated ? 1 : PG_DATA_SIZE)))
# Fix objects using vitastor-cli fix # Fix objects using vitastor-cli fix
$VITASTOR_CLI describe --json | \ build/src/cmd/vitastor-cli describe --etcd_address $ETCD_URL --json | \
jq -s '[ .[0][] | select(.inconsistent and .osd_num == '$ZERO_OSD') ]' | \ jq -s '[ .[0][] | select(.inconsistent and .osd_num == '$ZERO_OSD') ]' | \
$VITASTOR_CLI fix --bad_osds $ZERO_OSD build/src/cmd/vitastor-cli fix --etcd_address $ETCD_URL --bad_osds $ZERO_OSD
elif [[ ($SCHEME = replicated && $PG_SIZE > 2) || ($SCHEME != replicated && $((PG_SIZE-PG_DATA_SIZE)) > 1) ]]; then elif [[ ($SCHEME = replicated && $PG_SIZE > 2) || ($SCHEME != replicated && $((PG_SIZE-PG_DATA_SIZE)) > 1) ]]; then
# Check that everything heals # Check that everything heals
wait_finish_rebalance 300 wait_finish_rebalance 300
$VITASTOR_CLI describe --json | jq -e '. | length == 0' build/src/cmd/vitastor-cli describe --etcd_address $ETCD_URL --json | jq -e '. | length == 0'
fi fi
# Read everything back # Read everything back
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-O raw ./testdata/bin/read.bin -O raw ./testdata/bin/read.bin
diff ./testdata/bin/read.bin ./testdata/bin/mirror.bin diff ./testdata/bin/read.bin ./testdata/bin/mirror.bin
+16 -12
View File
@@ -7,39 +7,43 @@ check_qemu
$ETCDCTL put /vitastor/config/inode/1/2 '{"name":"testimg","size":'$((32*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/2 '{"name":"testimg","size":'$((32*1024*1024))'}'
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-pool=1 -inode=2 -size=32M -cluster_log_level=10 fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=32M -cluster_log_level=10
$ETCDCTL put /vitastor/config/inode/1/2 '{"name":"testimg@0","size":'$((32*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/2 '{"name":"testimg@0","size":'$((32*1024*1024))'}'
$ETCDCTL put /vitastor/config/inode/1/3 '{"parent_id":2,"name":"testimg","size":'$((32*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/3 '{"parent_id":2,"name":"testimg","size":'$((32*1024*1024))'}'
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=32 -buffer_pattern=0xdeadface \ # Preload build/src/client/libfio_vitastor.so so libasan detects all symbols
-rw=randwrite -image=testimg -number_ios=1024 LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=32 -buffer_pattern=0xdeadface \
-rw=randwrite -etcd=$ETCD_URL -image=testimg -number_ios=1024
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -rw=read -pool=1 -inode=3 -size=32M LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -rw=read -etcd=$ETCD_URL -pool=1 -inode=3 -size=32M
qemu-img convert -p \ qemu-img convert -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=2:size=$((32*1024*1024)):skip-parents=1" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=2:size=$((32*1024*1024)):skip-parents=1" \
-O qcow2 ./testdata/layer0.qcow2 -O qcow2 ./testdata/layer0.qcow2
qemu-img create -f qcow2 ./testdata/empty.qcow2 32M qemu-img create -f qcow2 ./testdata/empty.qcow2 32M
qemu-img convert -p \ qemu-img convert -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=3:size=$((32*1024*1024)):skip-parents=1" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=3:size=$((32*1024*1024)):skip-parents=1" \
-O qcow2 -o 'cluster_size=4k,backing_fmt=qcow2' -B empty.qcow2 ./testdata/layer1.qcow2 -O qcow2 -o 'cluster_size=4k,backing_fmt=qcow2' -B empty.qcow2 ./testdata/layer1.qcow2
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=3:size=$((32*1024*1024))" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=3:size=$((32*1024*1024))" \
-O raw ./testdata/bin/merged.bin -O raw ./testdata/bin/merged.bin
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg@0" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg@0" \
-O raw ./testdata/bin/layer0.bin -O raw ./testdata/bin/layer0.bin
$ETCDCTL put /vitastor/config/inode/1/3 '{"name":"testimg","size":'$((32*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/3 '{"name":"testimg","size":'$((32*1024*1024))'}'
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-O raw ./testdata/bin/layer1.bin -O raw ./testdata/bin/layer1.bin
node tests/merge.js ./testdata/bin/layer0.bin ./testdata/bin/layer1.bin ./testdata/bin/check.bin node tests/merge.js ./testdata/bin/layer0.bin ./testdata/bin/layer1.bin ./testdata/bin/check.bin
@@ -50,10 +54,10 @@ cmp ./testdata/bin/merged.bin ./testdata/bin/check.bin
$ETCDCTL put /vitastor/config/inode/1/3 '{"parent_id":2,"name":"testimg","size":'$((32*1024*1024))'}' $ETCDCTL put /vitastor/config/inode/1/3 '{"parent_id":2,"name":"testimg","size":'$((32*1024*1024))'}'
$VITASTOR_CLI rm testimg@0 build/src/cmd/vitastor-cli rm --etcd_address $ETCD_URL testimg@0
qemu-img convert -S 4096 -p \ qemu-img convert -S 4096 -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-O raw ./testdata/bin/merged-by-tool.bin -O raw ./testdata/bin/merged-by-tool.bin
cmp ./testdata/bin/merged.bin ./testdata/bin/merged-by-tool.bin cmp ./testdata/bin/merged.bin ./testdata/bin/merged-by-tool.bin
+13 -11
View File
@@ -5,41 +5,43 @@ check_qemu
# Test multiple snapshots # Test multiple snapshots
$VITASTOR_CLI create -s 32M testchain build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 32M testchain
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
-image=testchain -mirror_file=./testdata/bin/mirror.bin fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin
for i in {1..10}; do for i in {1..10}; do
# Create a snapshot # Create a snapshot
$VITASTOR_CLI snap-create testchain@$i build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@$i
# Check that the new snapshot is see-through # Check that the new snapshot is see-through
qemu-img convert -p \ qemu-img convert -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-O raw ./testdata/bin/check.bin -O raw ./testdata/bin/check.bin
cmp ./testdata/bin/check.bin ./testdata/bin/mirror.bin cmp ./testdata/bin/check.bin ./testdata/bin/mirror.bin
# Write something to it # Write something to it
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=32 -rw=randwrite \ LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=32 -rw=randwrite \
-randrepeat=$((i <= 2)) -buffer_pattern=0x$((10+i))$((10+i))$((10+i))$((10+i)) \ -randrepeat=$((i <= 2)) -buffer_pattern=0x$((10+i))$((10+i))$((10+i))$((10+i)) \
-image=testchain -number_ios=1024 -mirror_file=./testdata/bin/mirror.bin -etcd=$ETCD_URL -image=testchain -number_ios=1024 -mirror_file=./testdata/bin/mirror.bin
# Check the new content # Check the new content
qemu-img convert -p \ qemu-img convert -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-O raw ./testdata/bin/layer1.bin -O raw ./testdata/bin/layer1.bin
cmp ./testdata/bin/layer1.bin ./testdata/bin/mirror.bin cmp ./testdata/bin/layer1.bin ./testdata/bin/mirror.bin
done done
$VITASTOR_CLI rm testchain@1 testchain@9 build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm testchain@1 testchain@9
# Check the final image # Check the final image
qemu-img convert -p \ qemu-img convert -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-O raw ./testdata/bin/layer1.bin -O raw ./testdata/bin/layer1.bin
cmp ./testdata/bin/layer1.bin ./testdata/bin/mirror.bin cmp ./testdata/bin/layer1.bin ./testdata/bin/mirror.bin
# Check the last remaining snapshot # Check the last remaining snapshot
qemu-img convert -p \ qemu-img convert -p \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain@10" \ -f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain@10" \
-O raw ./testdata/bin/layer0.bin -O raw ./testdata/bin/layer0.bin
cmp ./testdata/bin/layer0.bin ./testdata/bin/check.bin cmp ./testdata/bin/layer0.bin ./testdata/bin/check.bin

Some files were not shown because too many files have changed in this diff Show More