Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
041185c673 | ||
|
|
b03ac80a57 | ||
|
|
2ba56074f9 | ||
|
|
4acfe149cb | ||
|
|
008ed5b269 | ||
|
|
4fffe0f032 | ||
|
|
a76d5ccc0d | ||
|
|
8ed1e180e0 | ||
|
|
8832fc3b14 | ||
|
|
0134934c99 | ||
|
|
2e36f292bd | ||
|
|
bcc6419760 | ||
|
|
dd5941b9a4 | ||
|
|
4005b88865 | ||
|
|
280b5cd675 | ||
|
|
e5c505eaf4 | ||
|
|
c1d244d4f0 | ||
|
|
9b264a212f | ||
|
|
ff7f5cb4f4 | ||
|
|
25ecca7625 | ||
|
|
99c4244004 | ||
|
|
9949b9fb4e | ||
|
|
e6881ad1d5 | ||
|
|
b30635b932 | ||
|
|
0c1154833c | ||
|
|
c227bb05b6 | ||
|
|
dd85315f22 | ||
|
|
47d2f4e0be | ||
|
|
2a5028d17f | ||
|
|
07915c2881 | ||
|
|
79141eb383 | ||
|
|
f7cbb6ed56 | ||
|
|
8f8172db99 | ||
|
|
94be147e80 | ||
|
|
538620b400 |
@@ -63,7 +63,7 @@ jobs:
|
|||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
steps:
|
steps:
|
||||||
# leak sanitizer sometimes crashes
|
# leak sanitizer sometimes crashes
|
||||||
- run: cd /root/vitastor/build && ASAN_OPTIONS=detect_leaks=0 make -j16 test
|
- run: cd /root/vitastor/build && ASAN_OPTIONS=detect_leaks=0 make -j16 build_tests test
|
||||||
|
|
||||||
npm_lint:
|
npm_lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
+7
-7
@@ -1,20 +1,20 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
set(VITASTOR_VERSION "3.0.5")
|
set(VITASTOR_VERSION "3.0.11")
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
add_custom_target(build_tests)
|
add_custom_target(build_tests)
|
||||||
add_custom_target(test
|
set_property(TEST PROPERTY ENVIRONMENT LSAN_OPTIONS=suppressions=${CMAKE_CURRENT_BINARY_DIR}/lsan-suppress.txt)
|
||||||
COMMAND
|
add_test(gen_lsan_suppress
|
||||||
echo leak:tcmalloc > ${CMAKE_CURRENT_BINARY_DIR}/lsan-suppress.txt &&
|
${CMAKE_COMMAND} -E echo leak:tcmalloc > "${CMAKE_CURRENT_BINARY_DIR}/lsan-suppress.txt"
|
||||||
env LSAN_OPTIONS=suppressions=${CMAKE_CURRENT_BINARY_DIR}/lsan-suppress.txt ${CMAKE_CTEST_COMMAND}
|
|
||||||
)
|
)
|
||||||
|
set_tests_properties(gen_lsan_suppress PROPERTIES FIXTURES_SETUP f_lsan_suppress)
|
||||||
|
set_property(TEST PROPERTY FIXTURES_REQUIRED f_lsan_suppress)
|
||||||
# make -j16 -C ../../build test_heap && ../../build/src/test/test_heap
|
# make -j16 -C ../../build test_heap && ../../build/src/test/test_heap
|
||||||
# make -j16 -C ../../build test_heap && rm -f $(find ../../build -name '*.gcda') && ctest -V -T test -T coverage -R heap --test-dir ../../build && (cd ../../build; gcovr -f ../src --html --html-nested -o coverage/index.html; cd ../src/test)
|
# make -j16 -C ../../build test_heap && rm -f $(find ../../build -name '*.gcda') && ctest -V -T test -T coverage -R heap --test-dir ../../build && (cd ../../build; gcovr -f ../src --html --html-nested -o coverage/index.html; cd ../src/test)
|
||||||
# make -j16 -C ../../build test_blockstore && rm -f $(find ../../build -name '*.gcda') && ctest -V -T test -T coverage -R blockstore --test-dir ../../build && (cd ../../build; gcovr -f ../src --html --html-nested -o coverage/index.html; cd ../src/test)
|
# make -j16 -C ../../build test_blockstore && rm -f $(find ../../build -name '*.gcda') && ctest -V -T test -T coverage -R blockstore --test-dir ../../build && (cd ../../build; gcovr -f ../src --html --html-nested -o coverage/index.html; cd ../src/test)
|
||||||
# kcov --include-path=../../../src ../../kcov ./test_blockstore
|
# kcov --include-path=../../../src ../../kcov ./test_blockstore
|
||||||
add_dependencies(test build_tests)
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|||||||
+1
-1
Submodule cpp-btree updated: 8de8b467ac...ebe44c9b66
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
VITASTOR_VERSION ?= v3.0.5
|
VITASTOR_VERSION ?= v3.0.11
|
||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ spec:
|
|||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
allowPrivilegeEscalation: true
|
allowPrivilegeEscalation: true
|
||||||
image: vitalif/vitastor-csi:v3.0.5
|
image: vitalif/vitastor-csi:v3.0.11
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ spec:
|
|||||||
privileged: true
|
privileged: true
|
||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
image: vitalif/vitastor-csi:v3.0.5
|
image: vitalif/vitastor-csi:v3.0.11
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ package vitastor
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
vitastorCSIDriverName = "csi.vitastor.io"
|
vitastorCSIDriverName = "csi.vitastor.io"
|
||||||
vitastorCSIDriverVersion = "3.0.5"
|
vitastorCSIDriverVersion = "3.0.11"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct fills the parameters of request or user input
|
// Config struct fills the parameters of request or user input
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
vitastor (3.0.5-1) unstable; urgency=medium
|
vitastor (3.0.11-1) unstable; urgency=medium
|
||||||
|
|
||||||
* Bugfixes
|
* Bugfixes
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -44,7 +44,7 @@ curl -s https://git.yourcmc.ru/vitalif/antietcd/archive/master.tar.gz | tar -zx
|
|||||||
curl -s https://git.yourcmc.ru/vitalif/tinyraft/archive/master.tar.gz | tar -zx
|
curl -s https://git.yourcmc.ru/vitalif/tinyraft/archive/master.tar.gz | tar -zx
|
||||||
|
|
||||||
cd /root/vitastor/packages/vitastor-$REL
|
cd /root/vitastor/packages/vitastor-$REL
|
||||||
if [[ "$REL" = "trixie" && -e ../vitastor-bookworm/vitastor_$VER.orig.tar.xz ]]; then
|
if [[ ( "$REL" = "trixie" || "$REL" = "resolute" ) && -e ../vitastor-bookworm/vitastor_$VER.orig.tar.xz ]]; then
|
||||||
# Fucking shit, archives differ between bookworm (xz 5.4.1) and trixie (xz 5.8.1)
|
# Fucking shit, archives differ between bookworm (xz 5.4.1) and trixie (xz 5.8.1)
|
||||||
cp ../vitastor-bookworm/vitastor_$VER.orig.tar.xz .
|
cp ../vitastor-bookworm/vitastor_$VER.orig.tar.xz .
|
||||||
else
|
else
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
VITASTOR_VERSION ?= v3.0.5
|
VITASTOR_VERSION ?= v3.0.11
|
||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Desired Vitastor version
|
# Desired Vitastor version
|
||||||
VITASTOR_VERSION=v3.0.5
|
VITASTOR_VERSION=v3.0.11
|
||||||
|
|
||||||
# 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
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ with an OSD restart or, for some of them, even without restarting by updating co
|
|||||||
- [use_atomic_flag](#use_atomic_flag)
|
- [use_atomic_flag](#use_atomic_flag)
|
||||||
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
|
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
|
||||||
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
|
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
|
||||||
|
- [gc_on_start](#gc_on_start)
|
||||||
|
|
||||||
## bind_address
|
## bind_address
|
||||||
|
|
||||||
@@ -753,3 +754,9 @@ This option sets the maximum number of object is a chunk. Moving 100k objects us
|
|||||||
- Default: 100
|
- Default: 100
|
||||||
|
|
||||||
This option sets the interval between handling two PG count change chunks.
|
This option sets the interval between handling two PG count change chunks.
|
||||||
|
|
||||||
|
## gc_on_start
|
||||||
|
|
||||||
|
- Type: boolean
|
||||||
|
|
||||||
|
Forcibly clean all garbage entries in the new store on every OSD restart.
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
- [use_atomic_flag](#use_atomic_flag)
|
- [use_atomic_flag](#use_atomic_flag)
|
||||||
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
|
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
|
||||||
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
|
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
|
||||||
|
- [gc_on_start](#gc_on_start)
|
||||||
|
|
||||||
## bind_address
|
## bind_address
|
||||||
|
|
||||||
@@ -793,3 +794,9 @@ pg_minsize OSD во время переключений, что может по
|
|||||||
- Значение по умолчанию: 100
|
- Значение по умолчанию: 100
|
||||||
|
|
||||||
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
|
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
|
||||||
|
|
||||||
|
## gc_on_start
|
||||||
|
|
||||||
|
- Тип: булево (да/нет)
|
||||||
|
|
||||||
|
Принудительно очищать все мусорные записи в новом хранилище при каждом запуске OSD.
|
||||||
|
|||||||
@@ -938,3 +938,7 @@
|
|||||||
This option sets the interval between handling two PG count change chunks.
|
This option sets the interval between handling two PG count change chunks.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
|
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
|
||||||
|
- name: gc_on_start
|
||||||
|
type: bool
|
||||||
|
info: Forcibly clean all garbage entries in the new store on every OSD restart.
|
||||||
|
info_ru: Принудительно очищать все мусорные записи в новом хранилище при каждом запуске OSD.
|
||||||
|
|||||||
@@ -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.5`
|
`docker pull vitalif/vitastor:v3.0.11`
|
||||||
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.5 install.sh`
|
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.11 install.sh`
|
||||||
3. Reload udev rules: \
|
3. Reload udev rules: \
|
||||||
`udevadm control --reload-rules`
|
`udevadm control --reload-rules`
|
||||||
4. Enable the vitastor-host service: \
|
4. Enable the vitastor-host service: \
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ Vitastor можно установить в Docker/Podman. При этом etcd,
|
|||||||
Инструкция по установке максимально простая.
|
Инструкция по установке максимально простая.
|
||||||
|
|
||||||
1. Скачайте Docker-образ желаемой версии: \
|
1. Скачайте Docker-образ желаемой версии: \
|
||||||
`docker pull vitalif/vitastor:v3.0.5`
|
`docker pull vitalif/vitastor:v3.0.11`
|
||||||
2. Установите скрипты в хост-систему командой: \
|
2. Установите скрипты в хост-систему командой: \
|
||||||
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.5 install.sh`
|
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.11 install.sh`
|
||||||
3. Перезагрузите правила udev: \
|
3. Перезагрузите правила udev: \
|
||||||
`udevadm control --reload-rules`
|
`udevadm control --reload-rules`
|
||||||
4. Включите сервис vitastor-host: \
|
4. Включите сервис vitastor-host: \
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
|
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
|
||||||
- Ubuntu 22.04 (Jammy): `deb https://vitastor.io/debian jammy main`
|
- Ubuntu 22.04 (Jammy): `deb https://vitastor.io/debian jammy main`
|
||||||
- Ubuntu 24.04 (Noble): `deb https://vitastor.io/debian noble main`
|
- Ubuntu 24.04 (Noble): `deb https://vitastor.io/debian noble main`
|
||||||
|
- Ubuntu 26.04 (Resolute): `deb https://vitastor.io/debian resolute main`
|
||||||
- Add `-oldstable` to bookworm/bullseye/buster in this line to install the last
|
- Add `-oldstable` to bookworm/bullseye/buster in this line to install the last
|
||||||
stable version from 0.9.x branch instead of 1.x
|
stable version from 0.9.x branch instead of 1.x
|
||||||
- To always prefer vitastor-patched QEMU and Libvirt versions, add the following to `/etc/apt/preferences`:
|
- To always prefer vitastor-patched QEMU and Libvirt versions, add the following to `/etc/apt/preferences`:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
|
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
|
||||||
- Ubuntu 22.04 (Jammy): `deb https://vitastor.io/debian jammy main`
|
- Ubuntu 22.04 (Jammy): `deb https://vitastor.io/debian jammy main`
|
||||||
- Ubuntu 24.04 (Noble): `deb https://vitastor.io/debian noble main`
|
- Ubuntu 24.04 (Noble): `deb https://vitastor.io/debian noble main`
|
||||||
|
- Ubuntu 26.04 (Resolute): `deb https://vitastor.io/debian resolute main`
|
||||||
- Добавьте `-oldstable` к слову bookworm/bullseye/buster в этой строке, чтобы
|
- Добавьте `-oldstable` к слову bookworm/bullseye/buster в этой строке, чтобы
|
||||||
установить последнюю стабильную версию из ветки 0.9.x вместо 1.x
|
установить последнюю стабильную версию из ветки 0.9.x вместо 1.x
|
||||||
- Чтобы всегда предпочитались версии пакетов QEMU и Libvirt с патчами Vitastor, добавьте в `/etc/apt/preferences`:
|
- Чтобы всегда предпочитались версии пакетов QEMU и Libvirt с патчами Vitastor, добавьте в `/etc/apt/preferences`:
|
||||||
|
|||||||
@@ -262,3 +262,4 @@ Options:
|
|||||||
| `--logfile <FILE>` | log to the specified file |
|
| `--logfile <FILE>` | log to the specified file |
|
||||||
| `--enforce 1` | enforce permissions at the server side (no by default) |
|
| `--enforce 1` | enforce permissions at the server side (no by default) |
|
||||||
| `--foreground 1` | stay in foreground, do not daemonize |
|
| `--foreground 1` | stay in foreground, do not daemonize |
|
||||||
|
| `--trace` | trace all NFS requests |
|
||||||
|
|||||||
@@ -274,3 +274,4 @@ VitastorFS из GPUDirect.
|
|||||||
| `--logfile <FILE>` | записывать логи в заданный файл |
|
| `--logfile <FILE>` | записывать логи в заданный файл |
|
||||||
| `--enforce 1` | проверять права доступа на стороне сервера (по умолчанию нет) |
|
| `--enforce 1` | проверять права доступа на стороне сервера (по умолчанию нет) |
|
||||||
| `--foreground 1` | не уходить в фон после запуска |
|
| `--foreground 1` | не уходить в фон после запуска |
|
||||||
|
| `--trace` | логгировать все запросы NFS |
|
||||||
|
|||||||
+1
-1
Submodule json11 updated: fd37016cf8...edcd85b8bd
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vitastor-mon",
|
"name": "vitastor-mon",
|
||||||
"version": "3.0.5",
|
"version": "3.0.11",
|
||||||
"description": "Vitastor SDS monitor service",
|
"description": "Vitastor SDS monitor service",
|
||||||
"main": "mon-main.js",
|
"main": "mon-main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ function derive_osd_stats(st, prev, prev_diff)
|
|||||||
const n = c.count - BigInt(pr && pr.count||0);
|
const n = c.count - BigInt(pr && pr.count||0);
|
||||||
diff.recovery_stats[op] = { ...c, bps: n > 0 ? b*1000n/timediff : 0n, iops: n > 0 ? n*1000n/timediff : 0n };
|
diff.recovery_stats[op] = { ...c, bps: n > 0 ? b*1000n/timediff : 0n, iops: n > 0 ? n*1000n/timediff : 0n };
|
||||||
}
|
}
|
||||||
|
diff.inode_stats = {};
|
||||||
for (const pool_id in st.inode_stats||{})
|
for (const pool_id in st.inode_stats||{})
|
||||||
{
|
{
|
||||||
diff.inode_stats[pool_id] = {};
|
diff.inode_stats[pool_id] = {};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vitastor",
|
"name": "vitastor",
|
||||||
"version": "3.0.5",
|
"version": "3.0.11",
|
||||||
"description": "Low-level native bindings to Vitastor client library",
|
"description": "Low-level native bindings to Vitastor client library",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ from cinder.volume import configuration
|
|||||||
from cinder.volume import driver
|
from cinder.volume import driver
|
||||||
from cinder.volume import volume_utils
|
from cinder.volume import volume_utils
|
||||||
|
|
||||||
VITASTOR_VERSION = '3.0.5'
|
VITASTOR_VERSION = '3.0.11'
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,637 @@
|
|||||||
|
diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h
|
||||||
|
index aaad4a3da1..5f5daa8341 100644
|
||||||
|
--- a/include/libvirt/libvirt-storage.h
|
||||||
|
+++ b/include/libvirt/libvirt-storage.h
|
||||||
|
@@ -326,6 +326,7 @@ typedef enum {
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_ZFS = 1 << 17, /* (Since: 1.2.8) */
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE = 1 << 18, /* (Since: 3.1.0) */
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI_DIRECT = 1 << 19, /* (Since: 5.6.0) */
|
||||||
|
+ VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR = 1 << 20, /* (Since: 5.0.0) */
|
||||||
|
} virConnectListAllStoragePoolsFlags;
|
||||||
|
|
||||||
|
int virConnectListAllStoragePools(virConnectPtr conn,
|
||||||
|
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
||||||
|
index 9ca5c2450c..cc52f00c0c 100644
|
||||||
|
--- a/src/conf/domain_conf.c
|
||||||
|
+++ b/src/conf/domain_conf.c
|
||||||
|
@@ -7453,7 +7453,8 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node,
|
||||||
|
src->configFile = virXPathString("string(./config/@file)", ctxt);
|
||||||
|
|
||||||
|
if (src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
|
||||||
|
- src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS)
|
||||||
|
+ src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS ||
|
||||||
|
+ src->protocol == VIR_STORAGE_NET_PROTOCOL_VITASTOR)
|
||||||
|
src->query = virXMLPropString(node, "query");
|
||||||
|
|
||||||
|
if (virDomainStorageNetworkParseHosts(node, ctxt, &src->hosts, &src->nhosts) < 0)
|
||||||
|
@@ -32187,6 +32188,7 @@ virDomainStorageSourceTranslateSourcePool(virStorageSource *src,
|
||||||
|
|
||||||
|
case VIR_STORAGE_POOL_MPATH:
|
||||||
|
case VIR_STORAGE_POOL_RBD:
|
||||||
|
+ case VIR_STORAGE_POOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_POOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_POOL_GLUSTER:
|
||||||
|
case VIR_STORAGE_POOL_LAST:
|
||||||
|
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
|
||||||
|
index 7346a61731..83e94d762e 100644
|
||||||
|
--- a/src/conf/domain_validate.c
|
||||||
|
+++ b/src/conf/domain_validate.c
|
||||||
|
@@ -520,6 +520,7 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
||||||
|
@@ -592,7 +593,7 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* internal snapshots and config files are currently supported only with rbd: */
|
||||||
|
+ /* internal snapshots are currently supported only with rbd: */
|
||||||
|
if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK &&
|
||||||
|
src->protocol != VIR_STORAGE_NET_PROTOCOL_RBD) {
|
||||||
|
if (src->snapshot) {
|
||||||
|
@@ -600,10 +601,14 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
|
||||||
|
_("<snapshot> element is currently supported only with 'rbd' disks"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ }
|
||||||
|
+ /* config files are currently supported only with rbd and vitastor: */
|
||||||
|
+ if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK &&
|
||||||
|
+ src->protocol != VIR_STORAGE_NET_PROTOCOL_RBD &&
|
||||||
|
+ src->protocol != VIR_STORAGE_NET_PROTOCOL_VITASTOR) {
|
||||||
|
if (src->configFile) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
- _("<config> element is currently supported only with 'rbd' disks"));
|
||||||
|
+ _("<config> element is currently supported only with 'rbd' and 'vitastor' disks"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
|
||||||
|
index 114dd3f96f..c71f9a3277 100644
|
||||||
|
--- a/src/conf/schemas/domaincommon.rng
|
||||||
|
+++ b/src/conf/schemas/domaincommon.rng
|
||||||
|
@@ -2093,6 +2093,35 @@
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
+ <define name="diskSourceNetworkProtocolVitastor">
|
||||||
|
+ <element name="source">
|
||||||
|
+ <interleave>
|
||||||
|
+ <attribute name="protocol">
|
||||||
|
+ <value>vitastor</value>
|
||||||
|
+ </attribute>
|
||||||
|
+ <ref name="diskSourceCommon"/>
|
||||||
|
+ <optional>
|
||||||
|
+ <attribute name="name"/>
|
||||||
|
+ </optional>
|
||||||
|
+ <optional>
|
||||||
|
+ <attribute name="query"/>
|
||||||
|
+ </optional>
|
||||||
|
+ <zeroOrMore>
|
||||||
|
+ <ref name="diskSourceNetworkHost"/>
|
||||||
|
+ </zeroOrMore>
|
||||||
|
+ <optional>
|
||||||
|
+ <element name="config">
|
||||||
|
+ <attribute name="file">
|
||||||
|
+ <ref name="absFilePath"/>
|
||||||
|
+ </attribute>
|
||||||
|
+ <empty/>
|
||||||
|
+ </element>
|
||||||
|
+ </optional>
|
||||||
|
+ <empty/>
|
||||||
|
+ </interleave>
|
||||||
|
+ </element>
|
||||||
|
+ </define>
|
||||||
|
+
|
||||||
|
<define name="diskSourceNetworkProtocolISCSI">
|
||||||
|
<element name="source">
|
||||||
|
<attribute name="protocol">
|
||||||
|
@@ -2443,6 +2472,7 @@
|
||||||
|
<ref name="diskSourceNetworkProtocolSimple"/>
|
||||||
|
<ref name="diskSourceNetworkProtocolVxHS"/>
|
||||||
|
<ref name="diskSourceNetworkProtocolNFS"/>
|
||||||
|
+ <ref name="diskSourceNetworkProtocolVitastor"/>
|
||||||
|
</choice>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
|
||||||
|
index 1dc9365bf2..a8a736be81 100644
|
||||||
|
--- a/src/conf/storage_conf.c
|
||||||
|
+++ b/src/conf/storage_conf.c
|
||||||
|
@@ -56,7 +56,7 @@ VIR_ENUM_IMPL(virStoragePool,
|
||||||
|
"logical", "disk", "iscsi",
|
||||||
|
"iscsi-direct", "scsi", "mpath",
|
||||||
|
"rbd", "sheepdog", "gluster",
|
||||||
|
- "zfs", "vstorage",
|
||||||
|
+ "zfs", "vstorage", "vitastor",
|
||||||
|
);
|
||||||
|
|
||||||
|
VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
|
||||||
|
@@ -242,6 +242,18 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
|
||||||
|
.formatToString = virStorageFileFormatTypeToString,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
+ {.poolType = VIR_STORAGE_POOL_VITASTOR,
|
||||||
|
+ .poolOptions = {
|
||||||
|
+ .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
|
||||||
|
+ VIR_STORAGE_POOL_SOURCE_NETWORK |
|
||||||
|
+ VIR_STORAGE_POOL_SOURCE_NAME),
|
||||||
|
+ },
|
||||||
|
+ .volOptions = {
|
||||||
|
+ .defaultFormat = VIR_STORAGE_FILE_RAW,
|
||||||
|
+ .formatFromString = virStorageVolumeFormatFromString,
|
||||||
|
+ .formatToString = virStorageFileFormatTypeToString,
|
||||||
|
+ }
|
||||||
|
+ },
|
||||||
|
{.poolType = VIR_STORAGE_POOL_SHEEPDOG,
|
||||||
|
.poolOptions = {
|
||||||
|
.flags = (VIR_STORAGE_POOL_SOURCE_HOST |
|
||||||
|
@@ -538,6 +550,11 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
|
||||||
|
_("element 'name' is mandatory for RBD pool"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
+ if (pool_type == VIR_STORAGE_POOL_VITASTOR && source->name == NULL) {
|
||||||
|
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
+ _("element 'name' is mandatory for Vitastor pool"));
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (options->formatFromString) {
|
||||||
|
g_autofree char *format = NULL;
|
||||||
|
@@ -1127,6 +1144,7 @@ virStoragePoolDefFormatBuf(virBuffer *buf,
|
||||||
|
/* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
|
||||||
|
* files, so they don't have a target */
|
||||||
|
if (def->type != VIR_STORAGE_POOL_RBD &&
|
||||||
|
+ def->type != VIR_STORAGE_POOL_VITASTOR &&
|
||||||
|
def->type != VIR_STORAGE_POOL_SHEEPDOG &&
|
||||||
|
def->type != VIR_STORAGE_POOL_GLUSTER &&
|
||||||
|
def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
|
||||||
|
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
|
||||||
|
index fc67957cfe..720c07ef74 100644
|
||||||
|
--- a/src/conf/storage_conf.h
|
||||||
|
+++ b/src/conf/storage_conf.h
|
||||||
|
@@ -103,6 +103,7 @@ typedef enum {
|
||||||
|
VIR_STORAGE_POOL_GLUSTER, /* Gluster device */
|
||||||
|
VIR_STORAGE_POOL_ZFS, /* ZFS */
|
||||||
|
VIR_STORAGE_POOL_VSTORAGE, /* Virtuozzo Storage */
|
||||||
|
+ VIR_STORAGE_POOL_VITASTOR, /* Vitastor */
|
||||||
|
|
||||||
|
VIR_STORAGE_POOL_LAST,
|
||||||
|
} virStoragePoolType;
|
||||||
|
@@ -454,6 +455,7 @@ VIR_ENUM_DECL(virStoragePartedFs);
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_SCSI | \
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_MPATH | \
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_RBD | \
|
||||||
|
+ VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR | \
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG | \
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER | \
|
||||||
|
VIR_CONNECT_LIST_STORAGE_POOLS_ZFS | \
|
||||||
|
diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
|
||||||
|
index d7b9bdfecb..38aefd0dd4 100644
|
||||||
|
--- a/src/conf/storage_source_conf.c
|
||||||
|
+++ b/src/conf/storage_source_conf.c
|
||||||
|
@@ -90,6 +90,7 @@ VIR_ENUM_IMPL(virStorageNetProtocol,
|
||||||
|
"ssh",
|
||||||
|
"vxhs",
|
||||||
|
"nfs",
|
||||||
|
+ "vitastor",
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1317,6 +1318,7 @@ virStorageSourceNetworkDefaultPort(virStorageNetProtocol protocol)
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
||||||
|
return 24007;
|
||||||
|
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
||||||
|
/* we don't provide a default for RBD */
|
||||||
|
return 0;
|
||||||
|
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
|
||||||
|
index 22c35d420d..f1e32ea83d 100644
|
||||||
|
--- a/src/conf/storage_source_conf.h
|
||||||
|
+++ b/src/conf/storage_source_conf.h
|
||||||
|
@@ -131,6 +131,7 @@ typedef enum {
|
||||||
|
VIR_STORAGE_NET_PROTOCOL_SSH,
|
||||||
|
VIR_STORAGE_NET_PROTOCOL_VXHS,
|
||||||
|
VIR_STORAGE_NET_PROTOCOL_NFS,
|
||||||
|
+ VIR_STORAGE_NET_PROTOCOL_VITASTOR,
|
||||||
|
|
||||||
|
VIR_STORAGE_NET_PROTOCOL_LAST
|
||||||
|
} virStorageNetProtocol;
|
||||||
|
diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c
|
||||||
|
index 59fa5da372..4739167f5f 100644
|
||||||
|
--- a/src/conf/virstorageobj.c
|
||||||
|
+++ b/src/conf/virstorageobj.c
|
||||||
|
@@ -1438,6 +1438,7 @@ virStoragePoolObjSourceFindDuplicateCb(const void *payload,
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case VIR_STORAGE_POOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_POOL_ISCSI_DIRECT:
|
||||||
|
case VIR_STORAGE_POOL_RBD:
|
||||||
|
case VIR_STORAGE_POOL_LAST:
|
||||||
|
@@ -1921,6 +1922,8 @@ virStoragePoolObjMatch(virStoragePoolObj *obj,
|
||||||
|
(obj->def->type == VIR_STORAGE_POOL_MPATH)) ||
|
||||||
|
(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_RBD) &&
|
||||||
|
(obj->def->type == VIR_STORAGE_POOL_RBD)) ||
|
||||||
|
+ (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR) &&
|
||||||
|
+ (obj->def->type == VIR_STORAGE_POOL_VITASTOR)) ||
|
||||||
|
(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG) &&
|
||||||
|
(obj->def->type == VIR_STORAGE_POOL_SHEEPDOG)) ||
|
||||||
|
(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER) &&
|
||||||
|
diff --git a/src/libvirt-storage.c b/src/libvirt-storage.c
|
||||||
|
index db7660aac4..561df34709 100644
|
||||||
|
--- a/src/libvirt-storage.c
|
||||||
|
+++ b/src/libvirt-storage.c
|
||||||
|
@@ -94,6 +94,7 @@ virStoragePoolGetConnect(virStoragePoolPtr pool)
|
||||||
|
* VIR_CONNECT_LIST_STORAGE_POOLS_SCSI
|
||||||
|
* VIR_CONNECT_LIST_STORAGE_POOLS_MPATH
|
||||||
|
* VIR_CONNECT_LIST_STORAGE_POOLS_RBD
|
||||||
|
+ * VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR
|
||||||
|
* VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG
|
||||||
|
* VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER
|
||||||
|
* VIR_CONNECT_LIST_STORAGE_POOLS_ZFS
|
||||||
|
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
|
||||||
|
index 2b988157fa..9d0eb47b25 100644
|
||||||
|
--- a/src/libxl/libxl_conf.c
|
||||||
|
+++ b/src/libxl/libxl_conf.c
|
||||||
|
@@ -1069,6 +1069,7 @@ libxlMakeNetworkDiskSrcStr(virStorageSource *src,
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SSH:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_VXHS:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NFS:
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT,
|
||||||
|
diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c
|
||||||
|
index e72e7d7f44..8482c21805 100644
|
||||||
|
--- a/src/libxl/xen_xl.c
|
||||||
|
+++ b/src/libxl/xen_xl.c
|
||||||
|
@@ -1461,6 +1461,7 @@ xenFormatXLDiskSrcNet(virStorageSource *src)
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SSH:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_VXHS:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NFS:
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT,
|
||||||
|
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
|
||||||
|
index 9b43279797..459d8e8a65 100644
|
||||||
|
--- a/src/qemu/qemu_block.c
|
||||||
|
+++ b/src/qemu/qemu_block.c
|
||||||
|
@@ -743,6 +743,38 @@ qemuBlockStorageSourceGetRBDProps(virStorageSource *src,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+static virJSONValue *
|
||||||
|
+qemuBlockStorageSourceGetVitastorProps(virStorageSource *src)
|
||||||
|
+{
|
||||||
|
+ virJSONValue *ret = NULL;
|
||||||
|
+ virStorageNetHostDef *host;
|
||||||
|
+ size_t i;
|
||||||
|
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
+ g_autofree char *etcd = NULL;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < src->nhosts; i++) {
|
||||||
|
+ host = src->hosts + i;
|
||||||
|
+ if ((virStorageNetHostTransport)host->transport != VIR_STORAGE_NET_HOST_TRANS_TCP) {
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ virBufferAsprintf(&buf, i > 0 ? ",%s:%u" : "%s:%u", host->name, host->port);
|
||||||
|
+ }
|
||||||
|
+ if (src->nhosts > 0) {
|
||||||
|
+ etcd = virBufferContentAndReset(&buf);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (virJSONValueObjectAdd(&ret,
|
||||||
|
+ "S:etcd-host", etcd,
|
||||||
|
+ "S:etcd-prefix", src->query,
|
||||||
|
+ "S:config-path", src->configFile,
|
||||||
|
+ "s:image", src->path,
|
||||||
|
+ NULL) < 0)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static virJSONValue *
|
||||||
|
qemuBlockStorageSourceGetSshProps(virStorageSource *src)
|
||||||
|
{
|
||||||
|
@@ -1094,6 +1126,12 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource *src,
|
||||||
|
return NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
+ driver = "vitastor";
|
||||||
|
+ if (!(fileprops = qemuBlockStorageSourceGetVitastorProps(src)))
|
||||||
|
+ return NULL;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SSH:
|
||||||
|
driver = "ssh";
|
||||||
|
if (!(fileprops = qemuBlockStorageSourceGetSshProps(src)))
|
||||||
|
@@ -1997,6 +2035,7 @@ qemuBlockGetBackingStoreString(virStorageSource *src,
|
||||||
|
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_VXHS:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NFS:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SSH:
|
||||||
|
@@ -2377,6 +2416,12 @@ qemuBlockStorageSourceCreateGetStorageProps(virStorageSource *src,
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
+ driver = "vitastor";
|
||||||
|
+ if (!(location = qemuBlockStorageSourceGetVitastorProps(src)))
|
||||||
|
+ return -1;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SSH:
|
||||||
|
if (srcPriv->nbdkitProcess) {
|
||||||
|
/* disk creation not yet supported with nbdkit, and even if it
|
||||||
|
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
||||||
|
index ac56fc7cb4..9e407b4aab 100644
|
||||||
|
--- a/src/qemu/qemu_domain.c
|
||||||
|
+++ b/src/qemu/qemu_domain.c
|
||||||
|
@@ -4677,7 +4677,8 @@ qemuDomainValidateStorageSource(virStorageSource *src,
|
||||||
|
if (src->query &&
|
||||||
|
(actualType != VIR_STORAGE_TYPE_NETWORK ||
|
||||||
|
(src->protocol != VIR_STORAGE_NET_PROTOCOL_HTTPS &&
|
||||||
|
- src->protocol != VIR_STORAGE_NET_PROTOCOL_HTTP))) {
|
||||||
|
+ src->protocol != VIR_STORAGE_NET_PROTOCOL_HTTP &&
|
||||||
|
+ src->protocol != VIR_STORAGE_NET_PROTOCOL_VITASTOR))) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("query is supported only with HTTP(S) protocols"));
|
||||||
|
return -1;
|
||||||
|
@@ -9103,6 +9104,7 @@ qemuDomainPrepareStorageSourceTLS(virStorageSource *src,
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
||||||
|
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
|
||||||
|
index e738afffc3..37d64f469b 100644
|
||||||
|
--- a/src/qemu/qemu_snapshot.c
|
||||||
|
+++ b/src/qemu/qemu_snapshot.c
|
||||||
|
@@ -665,6 +665,7 @@ qemuSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDef *snapdisk,
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
||||||
|
@@ -893,6 +894,7 @@ qemuSnapshotPrepareDiskInternal(virDomainDiskDef *disk,
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
||||||
|
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
|
||||||
|
index e19e032427..59f91f4710 100644
|
||||||
|
--- a/src/storage/storage_driver.c
|
||||||
|
+++ b/src/storage/storage_driver.c
|
||||||
|
@@ -1626,6 +1626,7 @@ storageVolLookupByPathCallback(virStoragePoolObj *obj,
|
||||||
|
|
||||||
|
case VIR_STORAGE_POOL_GLUSTER:
|
||||||
|
case VIR_STORAGE_POOL_RBD:
|
||||||
|
+ case VIR_STORAGE_POOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_POOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_POOL_ZFS:
|
||||||
|
case VIR_STORAGE_POOL_LAST:
|
||||||
|
diff --git a/src/storage_file/storage_source_backingstore.c b/src/storage_file/storage_source_backingstore.c
|
||||||
|
index 821378883c..2211f6891b 100644
|
||||||
|
--- a/src/storage_file/storage_source_backingstore.c
|
||||||
|
+++ b/src/storage_file/storage_source_backingstore.c
|
||||||
|
@@ -264,6 +264,75 @@ virStorageSourceParseRBDColonString(const char *rbdstr,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+virStorageSourceParseVitastorColonString(const char *colonstr,
|
||||||
|
+ virStorageSource *src)
|
||||||
|
+{
|
||||||
|
+ char *p, *e, *next;
|
||||||
|
+ g_autofree char *options = NULL;
|
||||||
|
+
|
||||||
|
+ /* optionally skip the "vitastor:" prefix if provided */
|
||||||
|
+ if (STRPREFIX(colonstr, "vitastor:"))
|
||||||
|
+ colonstr += strlen("vitastor:");
|
||||||
|
+
|
||||||
|
+ options = g_strdup(colonstr);
|
||||||
|
+
|
||||||
|
+ p = options;
|
||||||
|
+ while (*p) {
|
||||||
|
+ /* find : delimiter or end of string */
|
||||||
|
+ for (e = p; *e && *e != ':'; ++e) {
|
||||||
|
+ if (*e == '\\') {
|
||||||
|
+ e++;
|
||||||
|
+ if (*e == '\0')
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (*e == '\0') {
|
||||||
|
+ next = e; /* last kv pair */
|
||||||
|
+ } else {
|
||||||
|
+ next = e + 1;
|
||||||
|
+ *e = '\0';
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (STRPREFIX(p, "image=")) {
|
||||||
|
+ src->path = g_strdup(p + strlen("image="));
|
||||||
|
+ } else if (STRPREFIX(p, "etcd-prefix=")) {
|
||||||
|
+ src->query = g_strdup(p + strlen("etcd-prefix="));
|
||||||
|
+ } else if (STRPREFIX(p, "config-path=")) {
|
||||||
|
+ src->configFile = g_strdup(p + strlen("config-path="));
|
||||||
|
+ } else if (STRPREFIX(p, "etcd-host=")) {
|
||||||
|
+ char *h, *sep;
|
||||||
|
+
|
||||||
|
+ h = p + strlen("etcd-host=");
|
||||||
|
+ while (h < e) {
|
||||||
|
+ for (sep = h; sep < e; ++sep) {
|
||||||
|
+ if (*sep == '\\' && (sep[1] == ',' ||
|
||||||
|
+ sep[1] == ';' ||
|
||||||
|
+ sep[1] == ' ')) {
|
||||||
|
+ *sep = '\0';
|
||||||
|
+ sep += 2;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (virStorageSourceRBDAddHost(src, h) < 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ h = sep;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ p = next;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!src->path) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
virStorageSourceParseNBDColonString(const char *nbdstr,
|
||||||
|
virStorageSource *src)
|
||||||
|
@@ -379,6 +448,11 @@ virStorageSourceParseBackingColon(virStorageSource *src,
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
|
||||||
|
+ if (virStorageSourceParseVitastorColonString(path, src) < 0)
|
||||||
|
+ return -1;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
||||||
|
@@ -953,6 +1027,54 @@ virStorageSourceParseBackingJSONRBD(virStorageSource *src,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+virStorageSourceParseBackingJSONVitastor(virStorageSource *src,
|
||||||
|
+ virJSONValue *json,
|
||||||
|
+ const char *jsonstr G_GNUC_UNUSED,
|
||||||
|
+ int opaque G_GNUC_UNUSED)
|
||||||
|
+{
|
||||||
|
+ const char *filename;
|
||||||
|
+ const char *image = virJSONValueObjectGetString(json, "image");
|
||||||
|
+ const char *conf = virJSONValueObjectGetString(json, "config-path");
|
||||||
|
+ const char *etcd_prefix = virJSONValueObjectGetString(json, "etcd-prefix");
|
||||||
|
+ virJSONValue *servers = virJSONValueObjectGetArray(json, "server");
|
||||||
|
+ size_t nservers;
|
||||||
|
+ size_t i;
|
||||||
|
+
|
||||||
|
+ src->type = VIR_STORAGE_TYPE_NETWORK;
|
||||||
|
+ src->protocol = VIR_STORAGE_NET_PROTOCOL_VITASTOR;
|
||||||
|
+
|
||||||
|
+ /* legacy syntax passed via 'filename' option */
|
||||||
|
+ if ((filename = virJSONValueObjectGetString(json, "filename")))
|
||||||
|
+ return virStorageSourceParseVitastorColonString(filename, src);
|
||||||
|
+
|
||||||
|
+ if (!image) {
|
||||||
|
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||||
|
+ _("missing image name in Vitastor backing volume "
|
||||||
|
+ "JSON specification"));
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ src->path = g_strdup(image);
|
||||||
|
+ src->configFile = g_strdup(conf);
|
||||||
|
+ src->query = g_strdup(etcd_prefix);
|
||||||
|
+
|
||||||
|
+ if (servers) {
|
||||||
|
+ nservers = virJSONValueArraySize(servers);
|
||||||
|
+
|
||||||
|
+ src->hosts = g_new0(virStorageNetHostDef, nservers);
|
||||||
|
+ src->nhosts = nservers;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < nservers; i++) {
|
||||||
|
+ if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts + i,
|
||||||
|
+ virJSONValueArrayGet(servers, i)) < 0)
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
virStorageSourceParseBackingJSONRaw(virStorageSource *src,
|
||||||
|
virJSONValue *json,
|
||||||
|
@@ -1130,6 +1252,7 @@ static const struct virStorageSourceJSONDriverParser jsonParsers[] = {
|
||||||
|
{"sheepdog", false, virStorageSourceParseBackingJSONSheepdog, 0},
|
||||||
|
{"ssh", false, virStorageSourceParseBackingJSONSSH, 0},
|
||||||
|
{"rbd", false, virStorageSourceParseBackingJSONRBD, 0},
|
||||||
|
+ {"vitastor", false, virStorageSourceParseBackingJSONVitastor, 0},
|
||||||
|
{"raw", true, virStorageSourceParseBackingJSONRaw, 0},
|
||||||
|
{"nfs", false, virStorageSourceParseBackingJSONNFS, 0},
|
||||||
|
{"vxhs", false, virStorageSourceParseBackingJSONVxHS, 0},
|
||||||
|
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
|
||||||
|
index 1165689de7..bba846351c 100644
|
||||||
|
--- a/src/test/test_driver.c
|
||||||
|
+++ b/src/test/test_driver.c
|
||||||
|
@@ -7345,6 +7345,7 @@ testStorageVolumeTypeForPool(int pooltype)
|
||||||
|
case VIR_STORAGE_POOL_ISCSI_DIRECT:
|
||||||
|
case VIR_STORAGE_POOL_GLUSTER:
|
||||||
|
case VIR_STORAGE_POOL_RBD:
|
||||||
|
+ case VIR_STORAGE_POOL_VITASTOR:
|
||||||
|
return VIR_STORAGE_VOL_NETWORK;
|
||||||
|
case VIR_STORAGE_POOL_LOGICAL:
|
||||||
|
case VIR_STORAGE_POOL_DISK:
|
||||||
|
diff --git a/tests/storagepoolcapsschemadata/poolcaps-fs.xml b/tests/storagepoolcapsschemadata/poolcaps-fs.xml
|
||||||
|
index eee75af746..8bd0a57bdd 100644
|
||||||
|
--- a/tests/storagepoolcapsschemadata/poolcaps-fs.xml
|
||||||
|
+++ b/tests/storagepoolcapsschemadata/poolcaps-fs.xml
|
||||||
|
@@ -204,4 +204,11 @@
|
||||||
|
</enum>
|
||||||
|
</volOptions>
|
||||||
|
</pool>
|
||||||
|
+ <pool type='vitastor' supported='no'>
|
||||||
|
+ <volOptions>
|
||||||
|
+ <defaultFormat type='raw'/>
|
||||||
|
+ <enum name='targetFormatType'>
|
||||||
|
+ </enum>
|
||||||
|
+ </volOptions>
|
||||||
|
+ </pool>
|
||||||
|
</storagepoolCapabilities>
|
||||||
|
diff --git a/tests/storagepoolcapsschemadata/poolcaps-full.xml b/tests/storagepoolcapsschemadata/poolcaps-full.xml
|
||||||
|
index 805950a937..852df0de16 100644
|
||||||
|
--- a/tests/storagepoolcapsschemadata/poolcaps-full.xml
|
||||||
|
+++ b/tests/storagepoolcapsschemadata/poolcaps-full.xml
|
||||||
|
@@ -204,4 +204,11 @@
|
||||||
|
</enum>
|
||||||
|
</volOptions>
|
||||||
|
</pool>
|
||||||
|
+ <pool type='vitastor' supported='yes'>
|
||||||
|
+ <volOptions>
|
||||||
|
+ <defaultFormat type='raw'/>
|
||||||
|
+ <enum name='targetFormatType'>
|
||||||
|
+ </enum>
|
||||||
|
+ </volOptions>
|
||||||
|
+ </pool>
|
||||||
|
</storagepoolCapabilities>
|
||||||
|
diff --git a/tests/storagepoolxml2argvtest.c b/tests/storagepoolxml2argvtest.c
|
||||||
|
index d5c2531ab8..b19308ac38 100644
|
||||||
|
--- a/tests/storagepoolxml2argvtest.c
|
||||||
|
+++ b/tests/storagepoolxml2argvtest.c
|
||||||
|
@@ -57,6 +57,7 @@ testCompareXMLToArgvFiles(bool shouldFail,
|
||||||
|
case VIR_STORAGE_POOL_GLUSTER:
|
||||||
|
case VIR_STORAGE_POOL_ZFS:
|
||||||
|
case VIR_STORAGE_POOL_VSTORAGE:
|
||||||
|
+ case VIR_STORAGE_POOL_VITASTOR:
|
||||||
|
case VIR_STORAGE_POOL_LAST:
|
||||||
|
default:
|
||||||
|
VIR_TEST_DEBUG("pool type '%s' has no xml2argv test", defTypeStr);
|
||||||
|
diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c
|
||||||
|
index 2010ef1356..072e2ff9e8 100644
|
||||||
|
--- a/tools/virsh-pool.c
|
||||||
|
+++ b/tools/virsh-pool.c
|
||||||
|
@@ -1187,6 +1187,9 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
|
||||||
|
case VIR_STORAGE_POOL_VSTORAGE:
|
||||||
|
flags |= VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE;
|
||||||
|
break;
|
||||||
|
+ case VIR_STORAGE_POOL_VITASTOR:
|
||||||
|
+ flags |= VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR;
|
||||||
|
+ break;
|
||||||
|
case VIR_STORAGE_POOL_LAST:
|
||||||
|
break;
|
||||||
|
}
|
||||||
@@ -1,29 +1,172 @@
|
|||||||
diff --git a/src/client/qemu_driver.c b/src/client/qemu_driver.c
|
diff --git a/block/meson.build b/block/meson.build
|
||||||
index d8356dab..5f4cd50d 100644
|
index 34b1b2a306..24ca0f1e52 100644
|
||||||
--- a/src/client/qemu_driver.c
|
--- a/block/meson.build
|
||||||
+++ b/src/client/qemu_driver.c
|
+++ b/block/meson.build
|
||||||
@@ -974,14 +974,21 @@ static void vitastor_co_read_bitmap_cb(void *opaque, long retval, uint8_t *bitma
|
@@ -114,6 +114,7 @@ foreach m : [
|
||||||
#endif
|
[libnfs, 'nfs', files('nfs.c')],
|
||||||
}
|
[libssh, 'ssh', files('ssh.c')],
|
||||||
|
[rbd, 'rbd', files('rbd.c')],
|
||||||
|
+ [vitastor, 'vitastor', files('vitastor.c')],
|
||||||
|
]
|
||||||
|
if m[0].found()
|
||||||
|
module_ss = ss.source_set()
|
||||||
|
diff --git a/meson.build b/meson.build
|
||||||
|
index 50c774a195..e5c7a3a4b1 100644
|
||||||
|
--- a/meson.build
|
||||||
|
+++ b/meson.build
|
||||||
|
@@ -1652,6 +1652,26 @@ if not get_option('rbd').auto() or have_block
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
-static int coroutine_fn vitastor_co_block_status(
|
+vitastor = not_found
|
||||||
- BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
|
+if not get_option('vitastor').auto() or have_block
|
||||||
- int64_t *pnum, int64_t *map, BlockDriverState **file)
|
+ libvitastor_client = cc.find_library('vitastor_client', has_headers: ['vitastor_c.h'],
|
||||||
+static int coroutine_fn vitastor_co_block_status(BlockDriverState *bs,
|
+ required: get_option('vitastor'))
|
||||||
+#if QEMU_VERSION_MAJOR > 10 || QEMU_VERSION_MAJOR == 10 && QEMU_VERSION_MINOR >= 1
|
+ if libvitastor_client.found()
|
||||||
+ unsigned int mode,
|
+ if cc.links('''
|
||||||
+#else
|
+ #include <vitastor_c.h>
|
||||||
+ bool want_zero,
|
+ int main(void) {
|
||||||
+#endif
|
+ vitastor_c_create_qemu(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
+ int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file)
|
+ return 0;
|
||||||
{
|
+ }''', dependencies: libvitastor_client)
|
||||||
// Allocated => return BDRV_BLOCK_DATA|BDRV_BLOCK_OFFSET_VALID
|
+ vitastor = declare_dependency(dependencies: libvitastor_client)
|
||||||
// Not allocated => return 0
|
+ elif get_option('vitastor').enabled()
|
||||||
// Error => return -errno
|
+ error('could not link libvitastor_client')
|
||||||
// Set pnum to length of the extent, `*map` = `offset`, `*file` = `bs`
|
+ else
|
||||||
+#if QEMU_VERSION_MAJOR > 10 || QEMU_VERSION_MAJOR == 10 && QEMU_VERSION_MINOR >= 1
|
+ warning('could not link libvitastor_client, disabling')
|
||||||
+ int want_zero = (mode == BDRV_WANT_PRECISE);
|
+ endif
|
||||||
+#endif
|
+ endif
|
||||||
VitastorRPC task;
|
+endif
|
||||||
VitastorClient *client = bs->opaque;
|
+
|
||||||
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
glusterfs = not_found
|
||||||
|
glusterfs_ftruncate_has_stat = false
|
||||||
|
glusterfs_iocb_has_stat = false
|
||||||
|
@@ -2547,6 +2567,7 @@ endif
|
||||||
|
config_host_data.set('CONFIG_OPENGL', opengl.found())
|
||||||
|
config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
|
||||||
|
config_host_data.set('CONFIG_RBD', rbd.found())
|
||||||
|
+config_host_data.set('CONFIG_VITASTOR', vitastor.found())
|
||||||
|
config_host_data.set('CONFIG_RDMA', rdma.found())
|
||||||
|
config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
|
||||||
|
config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
|
||||||
|
@@ -4972,6 +4993,7 @@ summary_info += {'fdt support': fdt_opt == 'internal' ? 'internal' : fdt}
|
||||||
|
summary_info += {'libcap-ng support': libcap_ng}
|
||||||
|
summary_info += {'bpf support': libbpf}
|
||||||
|
summary_info += {'rbd support': rbd}
|
||||||
|
+summary_info += {'vitastor support': vitastor}
|
||||||
|
summary_info += {'smartcard support': cacard}
|
||||||
|
summary_info += {'U2F support': u2f}
|
||||||
|
summary_info += {'libusb': libusb}
|
||||||
|
diff --git a/meson_options.txt b/meson_options.txt
|
||||||
|
index fff1521e58..f0844c0e00 100644
|
||||||
|
--- a/meson_options.txt
|
||||||
|
+++ b/meson_options.txt
|
||||||
|
@@ -202,6 +202,8 @@ option('pvg', type: 'feature', value: 'auto',
|
||||||
|
description: 'macOS paravirtualized graphics support')
|
||||||
|
option('rbd', type : 'feature', value : 'auto',
|
||||||
|
description: 'Ceph block device driver')
|
||||||
|
+option('vitastor', type : 'feature', value : 'auto',
|
||||||
|
+ description: 'Vitastor block device driver')
|
||||||
|
option('opengl', type : 'feature', value : 'auto',
|
||||||
|
description: 'OpenGL support')
|
||||||
|
option('rdma', type : 'feature', value : 'auto',
|
||||||
|
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
||||||
|
index dc6eb4ae23..d043f4340e 100644
|
||||||
|
--- a/qapi/block-core.json
|
||||||
|
+++ b/qapi/block-core.json
|
||||||
|
@@ -3280,7 +3280,7 @@
|
||||||
|
'parallels', 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum',
|
||||||
|
'raw', 'rbd',
|
||||||
|
{ 'name': 'replication', 'if': 'CONFIG_REPLICATION' },
|
||||||
|
- 'ssh', 'throttle', 'vdi', 'vhdx',
|
||||||
|
+ 'ssh', 'throttle', 'vdi', 'vhdx', 'vitastor',
|
||||||
|
{ 'name': 'virtio-blk-vfio-pci', 'if': 'CONFIG_BLKIO' },
|
||||||
|
{ 'name': 'virtio-blk-vhost-user', 'if': 'CONFIG_BLKIO' },
|
||||||
|
{ 'name': 'virtio-blk-vhost-vdpa', 'if': 'CONFIG_BLKIO' },
|
||||||
|
@@ -4363,6 +4363,28 @@
|
||||||
|
'*key-secret': 'str',
|
||||||
|
'*server': ['InetSocketAddressBase'] } }
|
||||||
|
|
||||||
|
+##
|
||||||
|
+# @BlockdevOptionsVitastor:
|
||||||
|
+#
|
||||||
|
+# Driver specific block device options for vitastor
|
||||||
|
+#
|
||||||
|
+# @image: Image name
|
||||||
|
+# @inode: Inode number
|
||||||
|
+# @pool: Pool ID
|
||||||
|
+# @size: Desired image size in bytes
|
||||||
|
+# @config-path: Path to Vitastor configuration
|
||||||
|
+# @etcd-host: etcd connection address(es)
|
||||||
|
+# @etcd-prefix: etcd key/value prefix
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'BlockdevOptionsVitastor',
|
||||||
|
+ 'data': { '*inode': 'uint64',
|
||||||
|
+ '*pool': 'uint64',
|
||||||
|
+ '*size': 'uint64',
|
||||||
|
+ '*image': 'str',
|
||||||
|
+ '*config-path': 'str',
|
||||||
|
+ '*etcd-host': 'str',
|
||||||
|
+ '*etcd-prefix': 'str' } }
|
||||||
|
+
|
||||||
|
##
|
||||||
|
# @ReplicationMode:
|
||||||
|
#
|
||||||
|
@@ -4831,6 +4853,7 @@
|
||||||
|
'throttle': 'BlockdevOptionsThrottle',
|
||||||
|
'vdi': 'BlockdevOptionsGenericFormat',
|
||||||
|
'vhdx': 'BlockdevOptionsGenericFormat',
|
||||||
|
+ 'vitastor': 'BlockdevOptionsVitastor',
|
||||||
|
'virtio-blk-vfio-pci':
|
||||||
|
{ 'type': 'BlockdevOptionsVirtioBlkVfioPci',
|
||||||
|
'if': 'CONFIG_BLKIO' },
|
||||||
|
@@ -5304,6 +5327,20 @@
|
||||||
|
'*cluster-size' : 'size',
|
||||||
|
'*encrypt' : 'RbdEncryptionCreateOptions' } }
|
||||||
|
|
||||||
|
+##
|
||||||
|
+# @BlockdevCreateOptionsVitastor:
|
||||||
|
+#
|
||||||
|
+# Driver specific image creation options for Vitastor.
|
||||||
|
+#
|
||||||
|
+# @location: Where to store the new image file. This location cannot
|
||||||
|
+# point to a snapshot.
|
||||||
|
+#
|
||||||
|
+# @size: Size of the virtual disk in bytes
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'BlockdevCreateOptionsVitastor',
|
||||||
|
+ 'data': { 'location': 'BlockdevOptionsVitastor',
|
||||||
|
+ 'size': 'size' } }
|
||||||
|
+
|
||||||
|
##
|
||||||
|
# @BlockdevVmdkSubformat:
|
||||||
|
#
|
||||||
|
@@ -5526,6 +5563,7 @@
|
||||||
|
'ssh': 'BlockdevCreateOptionsSsh',
|
||||||
|
'vdi': 'BlockdevCreateOptionsVdi',
|
||||||
|
'vhdx': 'BlockdevCreateOptionsVhdx',
|
||||||
|
+ 'vitastor': 'BlockdevCreateOptionsVitastor',
|
||||||
|
'vmdk': 'BlockdevCreateOptionsVmdk',
|
||||||
|
'vpc': 'BlockdevCreateOptionsVpc'
|
||||||
|
} }
|
||||||
|
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
|
||||||
|
index 0ebe6bc52a..2c37ad3892 100644
|
||||||
|
--- a/scripts/meson-buildoptions.sh
|
||||||
|
+++ b/scripts/meson-buildoptions.sh
|
||||||
|
@@ -175,6 +175,7 @@ meson_options_help() {
|
||||||
|
printf "%s\n" ' qga-vss build QGA VSS support (broken with MinGW)'
|
||||||
|
printf "%s\n" ' qpl Query Processing Library support'
|
||||||
|
printf "%s\n" ' rbd Ceph block device driver'
|
||||||
|
+ printf "%s\n" ' vitastor Vitastor block device driver'
|
||||||
|
printf "%s\n" ' rdma Enable RDMA-based migration'
|
||||||
|
printf "%s\n" ' replication replication support'
|
||||||
|
printf "%s\n" ' rust Rust support'
|
||||||
|
@@ -459,6 +460,8 @@ _meson_option_parse() {
|
||||||
|
--disable-qpl) printf "%s" -Dqpl=disabled ;;
|
||||||
|
--enable-rbd) printf "%s" -Drbd=enabled ;;
|
||||||
|
--disable-rbd) printf "%s" -Drbd=disabled ;;
|
||||||
|
+ --enable-vitastor) printf "%s" -Dvitastor=enabled ;;
|
||||||
|
+ --disable-vitastor) printf "%s" -Dvitastor=disabled ;;
|
||||||
|
--enable-rdma) printf "%s" -Drdma=enabled ;;
|
||||||
|
--disable-rdma) printf "%s" -Drdma=disabled ;;
|
||||||
|
--enable-relocatable) printf "%s" -Drelocatable=true ;;
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
diff --git a/block/meson.build b/block/meson.build
|
||||||
|
index 34b1b2a306..24ca0f1e52 100644
|
||||||
|
--- a/block/meson.build
|
||||||
|
+++ b/block/meson.build
|
||||||
|
@@ -114,6 +114,7 @@ foreach m : [
|
||||||
|
[libnfs, 'nfs', files('nfs.c')],
|
||||||
|
[libssh, 'ssh', files('ssh.c')],
|
||||||
|
[rbd, 'rbd', files('rbd.c')],
|
||||||
|
+ [vitastor, 'vitastor', files('vitastor.c')],
|
||||||
|
]
|
||||||
|
if m[0].found()
|
||||||
|
module_ss = ss.source_set()
|
||||||
|
diff --git a/meson.build b/meson.build
|
||||||
|
index d9293294d8..776a5becc6 100644
|
||||||
|
--- a/meson.build
|
||||||
|
+++ b/meson.build
|
||||||
|
@@ -1665,6 +1665,26 @@ if not get_option('rbd').auto() or have_block
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
+vitastor = not_found
|
||||||
|
+if not get_option('vitastor').auto() or have_block
|
||||||
|
+ libvitastor_client = cc.find_library('vitastor_client', has_headers: ['vitastor_c.h'],
|
||||||
|
+ required: get_option('vitastor'))
|
||||||
|
+ if libvitastor_client.found()
|
||||||
|
+ if cc.links('''
|
||||||
|
+ #include <vitastor_c.h>
|
||||||
|
+ int main(void) {
|
||||||
|
+ vitastor_c_create_qemu(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
+ return 0;
|
||||||
|
+ }''', dependencies: libvitastor_client)
|
||||||
|
+ vitastor = declare_dependency(dependencies: libvitastor_client)
|
||||||
|
+ elif get_option('vitastor').enabled()
|
||||||
|
+ error('could not link libvitastor_client')
|
||||||
|
+ else
|
||||||
|
+ warning('could not link libvitastor_client, disabling')
|
||||||
|
+ endif
|
||||||
|
+ endif
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
glusterfs = not_found
|
||||||
|
glusterfs_ftruncate_has_stat = false
|
||||||
|
glusterfs_iocb_has_stat = false
|
||||||
|
@@ -2509,6 +2529,7 @@ endif
|
||||||
|
config_host_data.set('CONFIG_OPENGL', opengl.found())
|
||||||
|
config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
|
||||||
|
config_host_data.set('CONFIG_RBD', rbd.found())
|
||||||
|
+config_host_data.set('CONFIG_VITASTOR', vitastor.found())
|
||||||
|
config_host_data.set('CONFIG_RDMA', rdma.found())
|
||||||
|
config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
|
||||||
|
config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
|
||||||
|
@@ -4948,6 +4969,7 @@ summary_info += {'fdt support': fdt_opt == 'internal' ? 'internal' : fdt}
|
||||||
|
summary_info += {'libcap-ng support': libcap_ng}
|
||||||
|
summary_info += {'bpf support': libbpf}
|
||||||
|
summary_info += {'rbd support': rbd}
|
||||||
|
+summary_info += {'vitastor support': vitastor}
|
||||||
|
summary_info += {'smartcard support': cacard}
|
||||||
|
summary_info += {'U2F support': u2f}
|
||||||
|
summary_info += {'libusb': libusb}
|
||||||
|
diff --git a/meson_options.txt b/meson_options.txt
|
||||||
|
index 2836156257..148086cc6f 100644
|
||||||
|
--- a/meson_options.txt
|
||||||
|
+++ b/meson_options.txt
|
||||||
|
@@ -206,6 +206,8 @@ option('pvg', type: 'feature', value: 'auto',
|
||||||
|
description: 'macOS paravirtualized graphics support')
|
||||||
|
option('rbd', type : 'feature', value : 'auto',
|
||||||
|
description: 'Ceph block device driver')
|
||||||
|
+option('vitastor', type : 'feature', value : 'auto',
|
||||||
|
+ description: 'Vitastor block device driver')
|
||||||
|
option('opengl', type : 'feature', value : 'auto',
|
||||||
|
description: 'OpenGL support')
|
||||||
|
option('rdma', type : 'feature', value : 'auto',
|
||||||
|
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
||||||
|
index b82af74256..f25a6f5ce8 100644
|
||||||
|
--- a/qapi/block-core.json
|
||||||
|
+++ b/qapi/block-core.json
|
||||||
|
@@ -3351,7 +3351,7 @@
|
||||||
|
'parallels', 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum',
|
||||||
|
'raw', 'rbd',
|
||||||
|
{ 'name': 'replication', 'if': 'CONFIG_REPLICATION' },
|
||||||
|
- 'ssh', 'throttle', 'vdi', 'vhdx',
|
||||||
|
+ 'ssh', 'throttle', 'vdi', 'vhdx', 'vitastor',
|
||||||
|
{ 'name': 'virtio-blk-vfio-pci', 'if': 'CONFIG_BLKIO' },
|
||||||
|
{ 'name': 'virtio-blk-vhost-user', 'if': 'CONFIG_BLKIO' },
|
||||||
|
{ 'name': 'virtio-blk-vhost-vdpa', 'if': 'CONFIG_BLKIO' },
|
||||||
|
@@ -4434,6 +4434,28 @@
|
||||||
|
'*key-secret': 'str',
|
||||||
|
'*server': ['InetSocketAddressBase'] } }
|
||||||
|
|
||||||
|
+##
|
||||||
|
+# @BlockdevOptionsVitastor:
|
||||||
|
+#
|
||||||
|
+# Driver specific block device options for vitastor
|
||||||
|
+#
|
||||||
|
+# @image: Image name
|
||||||
|
+# @inode: Inode number
|
||||||
|
+# @pool: Pool ID
|
||||||
|
+# @size: Desired image size in bytes
|
||||||
|
+# @config-path: Path to Vitastor configuration
|
||||||
|
+# @etcd-host: etcd connection address(es)
|
||||||
|
+# @etcd-prefix: etcd key/value prefix
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'BlockdevOptionsVitastor',
|
||||||
|
+ 'data': { '*inode': 'uint64',
|
||||||
|
+ '*pool': 'uint64',
|
||||||
|
+ '*size': 'uint64',
|
||||||
|
+ '*image': 'str',
|
||||||
|
+ '*config-path': 'str',
|
||||||
|
+ '*etcd-host': 'str',
|
||||||
|
+ '*etcd-prefix': 'str' } }
|
||||||
|
+
|
||||||
|
##
|
||||||
|
# @ReplicationMode:
|
||||||
|
#
|
||||||
|
@@ -4902,6 +4924,7 @@
|
||||||
|
'throttle': 'BlockdevOptionsThrottle',
|
||||||
|
'vdi': 'BlockdevOptionsGenericFormat',
|
||||||
|
'vhdx': 'BlockdevOptionsGenericFormat',
|
||||||
|
+ 'vitastor': 'BlockdevOptionsVitastor',
|
||||||
|
'virtio-blk-vfio-pci':
|
||||||
|
{ 'type': 'BlockdevOptionsVirtioBlkVfioPci',
|
||||||
|
'if': 'CONFIG_BLKIO' },
|
||||||
|
@@ -5376,6 +5399,20 @@
|
||||||
|
'*cluster-size' : 'size',
|
||||||
|
'*encrypt' : 'RbdEncryptionCreateOptions' } }
|
||||||
|
|
||||||
|
+##
|
||||||
|
+# @BlockdevCreateOptionsVitastor:
|
||||||
|
+#
|
||||||
|
+# Driver specific image creation options for Vitastor.
|
||||||
|
+#
|
||||||
|
+# @location: Where to store the new image file. This location cannot
|
||||||
|
+# point to a snapshot.
|
||||||
|
+#
|
||||||
|
+# @size: Size of the virtual disk in bytes
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'BlockdevCreateOptionsVitastor',
|
||||||
|
+ 'data': { 'location': 'BlockdevOptionsVitastor',
|
||||||
|
+ 'size': 'size' } }
|
||||||
|
+
|
||||||
|
##
|
||||||
|
# @BlockdevVmdkSubformat:
|
||||||
|
#
|
||||||
|
@@ -5598,6 +5635,7 @@
|
||||||
|
'ssh': 'BlockdevCreateOptionsSsh',
|
||||||
|
'vdi': 'BlockdevCreateOptionsVdi',
|
||||||
|
'vhdx': 'BlockdevCreateOptionsVhdx',
|
||||||
|
+ 'vitastor': 'BlockdevCreateOptionsVitastor',
|
||||||
|
'vmdk': 'BlockdevCreateOptionsVmdk',
|
||||||
|
'vpc': 'BlockdevCreateOptionsVpc'
|
||||||
|
} }
|
||||||
|
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
|
||||||
|
index 3d0d132344..65ee8c855e 100644
|
||||||
|
--- a/scripts/meson-buildoptions.sh
|
||||||
|
+++ b/scripts/meson-buildoptions.sh
|
||||||
|
@@ -177,6 +177,7 @@ meson_options_help() {
|
||||||
|
printf "%s\n" ' qga-vss build QGA VSS support (broken with MinGW)'
|
||||||
|
printf "%s\n" ' qpl Query Processing Library support'
|
||||||
|
printf "%s\n" ' rbd Ceph block device driver'
|
||||||
|
+ printf "%s\n" ' vitastor Vitastor block device driver'
|
||||||
|
printf "%s\n" ' rdma Enable RDMA-based migration'
|
||||||
|
printf "%s\n" ' replication replication support'
|
||||||
|
printf "%s\n" ' rust Rust support'
|
||||||
|
@@ -464,6 +465,8 @@ _meson_option_parse() {
|
||||||
|
--disable-qpl) printf "%s" -Dqpl=disabled ;;
|
||||||
|
--enable-rbd) printf "%s" -Drbd=enabled ;;
|
||||||
|
--disable-rbd) printf "%s" -Drbd=disabled ;;
|
||||||
|
+ --enable-vitastor) printf "%s" -Dvitastor=enabled ;;
|
||||||
|
+ --disable-vitastor) printf "%s" -Dvitastor=disabled ;;
|
||||||
|
--enable-rdma) printf "%s" -Drdma=enabled ;;
|
||||||
|
--disable-rdma) printf "%s" -Drdma=disabled ;;
|
||||||
|
--enable-relocatable) printf "%s" -Drelocatable=true ;;
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 3.0.5
|
Version: 3.0.11
|
||||||
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.5.el10.tar.gz
|
Source0: vitastor-3.0.11.el10.tar.gz
|
||||||
|
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
BuildRequires: gcc-c++
|
BuildRequires: gcc-c++
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 3.0.5
|
Version: 3.0.11
|
||||||
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.5.el7.tar.gz
|
Source0: vitastor-3.0.11.el7.tar.gz
|
||||||
|
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
BuildRequires: devtoolset-9-gcc-c++
|
BuildRequires: devtoolset-9-gcc-c++
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 3.0.5
|
Version: 3.0.11
|
||||||
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.5.el8.tar.gz
|
Source0: vitastor-3.0.11.el8.tar.gz
|
||||||
|
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
BuildRequires: gcc-toolset-9-gcc-c++
|
BuildRequires: gcc-toolset-9-gcc-c++
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 3.0.5
|
Version: 3.0.11
|
||||||
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.5.el9.tar.gz
|
Source0: vitastor-3.0.11.el9.tar.gz
|
||||||
|
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
BuildRequires: gcc-c++
|
BuildRequires: gcc-c++
|
||||||
|
|||||||
+2
-3
@@ -1,9 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
include(CTest)
|
|
||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
|
|
||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
@@ -21,7 +20,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.5")
|
add_definitions(-DVITASTOR_VERSION="3.0.11")
|
||||||
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})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
@@ -228,4 +228,9 @@ public:
|
|||||||
virtual uint64_t get_journal_size() = 0;
|
virtual uint64_t get_journal_size() = 0;
|
||||||
|
|
||||||
virtual uint32_t get_bitmap_granularity() = 0;
|
virtual uint32_t get_bitmap_granularity() = 0;
|
||||||
|
|
||||||
|
virtual uint64_t get_live_entries() = 0;
|
||||||
|
virtual uint64_t get_live_memory() = 0;
|
||||||
|
virtual uint64_t get_garbage_entries() = 0;
|
||||||
|
virtual uint64_t get_garbage_memory() = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ void blockstore_disk_t::parse_config(std::map<std::string, std::string> & config
|
|||||||
csum_block_size = parse_size(config["csum_block_size"]);
|
csum_block_size = parse_size(config["csum_block_size"]);
|
||||||
discard_on_start = config.find("discard_on_start") != config.end() &&
|
discard_on_start = config.find("discard_on_start") != config.end() &&
|
||||||
(config["discard_on_start"] == "true" || config["discard_on_start"] == "1" || config["discard_on_start"] == "yes");
|
(config["discard_on_start"] == "true" || config["discard_on_start"] == "1" || config["discard_on_start"] == "yes");
|
||||||
|
gc_on_start = config.find("gc_on_start") == config.end() ||
|
||||||
|
(config["gc_on_start"] == "true" || config["gc_on_start"] == "1" || config["gc_on_start"] == "yes");
|
||||||
min_discard_size = parse_size(config["min_discard_size"]);
|
min_discard_size = parse_size(config["min_discard_size"]);
|
||||||
if (!min_discard_size)
|
if (!min_discard_size)
|
||||||
min_discard_size = 1024*1024;
|
min_discard_size = 1024*1024;
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ struct blockstore_disk_t
|
|||||||
bool inmemory_journal = true;
|
bool inmemory_journal = true;
|
||||||
// Data discard granularity and minimum size (for the sake of performance)
|
// Data discard granularity and minimum size (for the sake of performance)
|
||||||
bool discard_on_start = false;
|
bool discard_on_start = false;
|
||||||
|
// GC on start (new store)
|
||||||
|
bool gc_on_start = true;
|
||||||
uint64_t min_discard_size = 1024*1024;
|
uint64_t min_discard_size = 1024*1024;
|
||||||
uint64_t discard_granularity = 0;
|
uint64_t discard_granularity = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#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
|
||||||
|
|
||||||
|
#define list_item_overhead(a) (((a) + sizeof(heap_list_item_t) - sizeof(heap_entry_t) + sizeof(void*) + 15) & ~15)
|
||||||
|
|
||||||
void inode_map_put(void* & inode_idx, heap_list_item_t* li);
|
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_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_free(void* inode_idx);
|
||||||
@@ -244,7 +246,7 @@ blockstore_heap_t::blockstore_heap_t(blockstore_disk_t *dsk, uint8_t *buffer_are
|
|||||||
assert(dsk->meta_block_size < 32768);
|
assert(dsk->meta_block_size < 32768);
|
||||||
assert(dsk->meta_area_size > 0);
|
assert(dsk->meta_area_size > 0);
|
||||||
assert(dsk->journal_len > 0);
|
assert(dsk->journal_len > 0);
|
||||||
meta_alloc = new multilist_index_t(meta_block_count, META_ALLOC_LEVELS+1, 0);
|
meta_alloc = new multilist_index_t(meta_block_count, META_ALLOC_LEVELS+1, 2);
|
||||||
block_info.resize(meta_block_count);
|
block_info.resize(meta_block_count);
|
||||||
assert(dsk->block_count <= 0xFFFF0000);
|
assert(dsk->block_count <= 0xFFFF0000);
|
||||||
data_alloc = new allocator_t(dsk->block_count);
|
data_alloc = new allocator_t(dsk->block_count);
|
||||||
@@ -332,19 +334,12 @@ corrupted_block:
|
|||||||
block_num, block_offset, wr->size, sizeof(heap_entry_t));
|
block_num, block_offset, wr->size, sizeof(heap_entry_t));
|
||||||
goto corrupted_block;
|
goto corrupted_block;
|
||||||
}
|
}
|
||||||
if (wr->is_garbage())
|
// Garbage collection is only performed when writing new entries into the block
|
||||||
{
|
// because it needs a fake LSN and modified blocks require consecutive modified LSNs
|
||||||
// Garbage collection is only performed when writing new entries into the block
|
// At the same time, further modifications _after_ putting new entries into the block,
|
||||||
// because it needs a fake LSN and modified blocks require consecutive modified LSNs
|
// but _before_ writing it, may mark some entries in it as garbage. That's why garbage
|
||||||
// That's why garbage entries may persist on disk
|
// entries may still be present on disk.
|
||||||
if (log_level > 5)
|
wr->entry_type &= ~BS_HEAP_GARBAGE;
|
||||||
{
|
|
||||||
fprintf(stderr, "Notice: skipping garbage entry %jx:%jx v%ju l%ju in metadata block %u at %u\n",
|
|
||||||
wr->inode, wr->stripe, wr->version, wr->lsn, block_num, block_offset);
|
|
||||||
}
|
|
||||||
block_offset += wr->size;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((wr->entry_type & BS_HEAP_TYPE) < BS_HEAP_BIG_WRITE ||
|
if ((wr->entry_type & BS_HEAP_TYPE) < BS_HEAP_BIG_WRITE ||
|
||||||
(wr->entry_type & BS_HEAP_TYPE) > BS_HEAP_ROLLBACK ||
|
(wr->entry_type & BS_HEAP_TYPE) > BS_HEAP_ROLLBACK ||
|
||||||
(wr->entry_type & ~(BS_HEAP_TYPE|BS_HEAP_STABLE)) ||
|
(wr->entry_type & ~(BS_HEAP_TYPE|BS_HEAP_STABLE)) ||
|
||||||
@@ -426,7 +421,10 @@ int blockstore_heap_t::load_blocks(uint64_t disk_offset, uint64_t size, uint8_t
|
|||||||
entries_loaded = 0;
|
entries_loaded = 0;
|
||||||
return read_blocks(disk_offset, size, buf, allow_corrupted, [&](uint32_t block_num, heap_entry_t *wr_orig)
|
return read_blocks(disk_offset, size, buf, allow_corrupted, [&](uint32_t block_num, heap_entry_t *wr_orig)
|
||||||
{
|
{
|
||||||
heap_list_item_t *li = (heap_list_item_t*)malloc_or_die(wr_orig->size + sizeof(heap_list_item_t) - sizeof(heap_entry_t));
|
auto alloc_size = wr_orig->size + sizeof(heap_list_item_t) - sizeof(heap_entry_t);
|
||||||
|
heap_list_item_t *li = (heap_list_item_t*)malloc_or_die(alloc_size);
|
||||||
|
live_entries++;
|
||||||
|
live_memory += list_item_overhead(wr_orig->size);
|
||||||
li->block_num = block_num;
|
li->block_num = block_num;
|
||||||
li->prev = li->next = NULL;
|
li->prev = li->next = NULL;
|
||||||
memcpy(&li->entry, wr_orig, wr_orig->size);
|
memcpy(&li->entry, wr_orig, wr_orig->size);
|
||||||
@@ -611,10 +609,11 @@ int blockstore_heap_t::mark_used_blocks()
|
|||||||
if (wr->entry_type == (BS_HEAP_DELETE|BS_HEAP_STABLE) && !li->prev)
|
if (wr->entry_type == (BS_HEAP_DELETE|BS_HEAP_STABLE) && !li->prev)
|
||||||
{
|
{
|
||||||
wr->set_garbage();
|
wr->set_garbage();
|
||||||
|
garbage_entries++;
|
||||||
|
garbage_memory += list_item_overhead(wr->size);
|
||||||
modify_alloc(li->block_num, [&](heap_block_info_t & inf)
|
modify_alloc(li->block_num, [&](heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
inf.used_space -= wr->size;
|
inf.garbage_space += wr->size;
|
||||||
inf.has_garbage = true;
|
|
||||||
});
|
});
|
||||||
li = NULL;
|
li = NULL;
|
||||||
}
|
}
|
||||||
@@ -624,10 +623,11 @@ int blockstore_heap_t::mark_used_blocks()
|
|||||||
if (overwritten)
|
if (overwritten)
|
||||||
{
|
{
|
||||||
wr->set_garbage();
|
wr->set_garbage();
|
||||||
|
garbage_entries++;
|
||||||
|
garbage_memory += list_item_overhead(wr->size);
|
||||||
modify_alloc(li->block_num, [&](heap_block_info_t & inf)
|
modify_alloc(li->block_num, [&](heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
inf.used_space -= wr->size;
|
inf.garbage_space += wr->size;
|
||||||
inf.has_garbage = true;
|
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -666,15 +666,66 @@ int blockstore_heap_t::mark_used_blocks()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dsk->gc_on_start)
|
||||||
|
{
|
||||||
|
recheck_full_gc();
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void blockstore_heap_t::recheck_full_gc()
|
||||||
|
{
|
||||||
|
uint32_t block_num = 0;
|
||||||
|
for (auto & inf: block_info)
|
||||||
|
{
|
||||||
|
// Instantly collect all garbage on restart
|
||||||
|
if (inf.garbage_space > 0)
|
||||||
|
{
|
||||||
|
if (log_level > 5)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Clearing %u out of %u garbage bytes in block %u\n", inf.garbage_space, inf.used_space, block_num);
|
||||||
|
}
|
||||||
|
uint32_t collected_garbage = 0;
|
||||||
|
size_t i = 0, j = 0;
|
||||||
|
for (; i < inf.entries.size(); i++)
|
||||||
|
{
|
||||||
|
if (inf.entries[i]->entry.is_garbage())
|
||||||
|
{
|
||||||
|
collected_garbage += inf.entries[i]->entry.size;
|
||||||
|
remove_list_item(inf.entries[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (j != i)
|
||||||
|
inf.entries[j] = inf.entries[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inf.entries.resize(j);
|
||||||
|
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
||||||
|
{
|
||||||
|
inf.used_space -= collected_garbage;
|
||||||
|
inf.garbage_space -= collected_garbage;
|
||||||
|
});
|
||||||
|
recheck_modified_blocks.insert(block_num);
|
||||||
|
}
|
||||||
|
block_num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void blockstore_heap_t::recheck_buffer(heap_entry_t *cwr, uint8_t *buf)
|
void blockstore_heap_t::recheck_buffer(heap_entry_t *cwr, uint8_t *buf)
|
||||||
{
|
{
|
||||||
auto free_entry = [&](heap_list_item_t *li)
|
auto free_entry = [&](heap_list_item_t *li)
|
||||||
{
|
{
|
||||||
uint32_t block_num = li->block_num;
|
uint32_t block_num = li->block_num;
|
||||||
auto wr_size = li->entry.size;
|
auto wr_size = li->entry.size;
|
||||||
|
if (li->entry.is_garbage())
|
||||||
|
{
|
||||||
|
garbage_entries--;
|
||||||
|
garbage_memory -= list_item_overhead(wr_size);
|
||||||
|
}
|
||||||
|
live_entries--;
|
||||||
|
live_memory -= list_item_overhead(wr_size);
|
||||||
free(li);
|
free(li);
|
||||||
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
@@ -712,7 +763,12 @@ void blockstore_heap_t::recheck_buffer(heap_entry_t *cwr, uint8_t *buf)
|
|||||||
assert(li->entry.entry_type == cwr->entry_type);
|
assert(li->entry.entry_type == cwr->entry_type);
|
||||||
auto prev = li->prev;
|
auto prev = li->prev;
|
||||||
li->next = li->prev = NULL;
|
li->next = li->prev = NULL;
|
||||||
li->entry.set_garbage();
|
if (!li->entry.is_garbage())
|
||||||
|
{
|
||||||
|
garbage_entries++;
|
||||||
|
garbage_memory += list_item_overhead(li->entry.size);
|
||||||
|
li->entry.set_garbage();
|
||||||
|
}
|
||||||
li = prev;
|
li = prev;
|
||||||
rolled_back++;
|
rolled_back++;
|
||||||
}
|
}
|
||||||
@@ -1162,7 +1218,7 @@ heap_entry_t *blockstore_heap_t::read_entry(object_id oid)
|
|||||||
|
|
||||||
void blockstore_heap_t::gc_block(heap_block_info_t & inf)
|
void blockstore_heap_t::gc_block(heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
if (inf.has_garbage)
|
if (inf.garbage_space > 0)
|
||||||
{
|
{
|
||||||
size_t i = 0, j = 0;
|
size_t i = 0, j = 0;
|
||||||
for (; i < inf.entries.size(); i++)
|
for (; i < inf.entries.size(); i++)
|
||||||
@@ -1185,7 +1241,8 @@ void blockstore_heap_t::gc_block(heap_block_info_t & inf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
inf.entries.resize(j);
|
inf.entries.resize(j);
|
||||||
inf.has_garbage = false;
|
inf.used_space -= inf.garbage_space;
|
||||||
|
inf.garbage_space = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1195,11 +1252,12 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
{
|
{
|
||||||
// First try to write into the same block as the previous time
|
// First try to write into the same block as the previous time
|
||||||
auto & inf = block_info.at(last_allocated_block);
|
auto & inf = block_info.at(last_allocated_block);
|
||||||
auto free_space = dsk->meta_block_size - inf.used_space;
|
if (inf.is_writing ||
|
||||||
if (inf.is_writing || free_space < entry_size ||
|
inf.used_space - inf.garbage_space + entry_size > dsk->meta_block_size ||
|
||||||
// Do not allow to make the last non-nearfull block nearfull
|
// Do not allow to make the last non-nearfull block nearfull
|
||||||
!allow_last_free && meta_nearfull_blocks >= meta_block_count-1 &&
|
!allow_last_free && meta_nearfull_blocks >= meta_block_count-1 &&
|
||||||
free_space >= max_entry_size && free_space < max_entry_size+entry_size)
|
inf.used_space - inf.garbage_space <= dsk->meta_block_size-max_entry_size &&
|
||||||
|
inf.used_space - inf.garbage_space + entry_size > dsk->meta_block_size-max_entry_size)
|
||||||
{
|
{
|
||||||
last_allocated_block = UINT32_MAX;
|
last_allocated_block = UINT32_MAX;
|
||||||
}
|
}
|
||||||
@@ -1216,8 +1274,8 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
{
|
{
|
||||||
// Do not allow to make the last non-nearfull block nearfull
|
// Do not allow to make the last non-nearfull block nearfull
|
||||||
auto & inf = block_info.at(last_allocated_block);
|
auto & inf = block_info.at(last_allocated_block);
|
||||||
auto free_space = dsk->meta_block_size - inf.used_space;
|
if (inf.used_space - inf.garbage_space <= dsk->meta_block_size-max_entry_size &&
|
||||||
if (free_space >= max_entry_size && free_space < max_entry_size+entry_size)
|
inf.used_space - inf.garbage_space + entry_size > dsk->meta_block_size-max_entry_size)
|
||||||
{
|
{
|
||||||
last_allocated_block = UINT32_MAX;
|
last_allocated_block = UINT32_MAX;
|
||||||
}
|
}
|
||||||
@@ -1228,8 +1286,7 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
for (uint32_t b = meta_alloc->find(META_ALLOC_LEVELS-1); b != UINT32_MAX; b = meta_alloc->next(b))
|
for (uint32_t b = meta_alloc->find(META_ALLOC_LEVELS-1); b != UINT32_MAX; b = meta_alloc->next(b))
|
||||||
{
|
{
|
||||||
auto & inf = block_info.at(b);
|
auto & inf = block_info.at(b);
|
||||||
auto free_space = dsk->meta_block_size - inf.used_space;
|
if (inf.used_space - inf.garbage_space + entry_size <= dsk->meta_block_size)
|
||||||
if (free_space >= entry_size)
|
|
||||||
{
|
{
|
||||||
last_allocated_block = b;
|
last_allocated_block = b;
|
||||||
break;
|
break;
|
||||||
@@ -1246,20 +1303,27 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
{
|
{
|
||||||
// Do not allow to make the last non-nearfull block nearfull
|
// Do not allow to make the last non-nearfull block nearfull
|
||||||
auto & inf = block_info.at(last_allocated_block);
|
auto & inf = block_info.at(last_allocated_block);
|
||||||
if (dsk->meta_block_size-inf.used_space >= max_entry_size &&
|
if (inf.used_space - inf.garbage_space <= dsk->meta_block_size-max_entry_size &&
|
||||||
dsk->meta_block_size-inf.used_space+entry_size < max_entry_size)
|
inf.used_space - inf.garbage_space + entry_size > dsk->meta_block_size-max_entry_size)
|
||||||
{
|
{
|
||||||
last_allocated_block = UINT32_MAX;
|
last_allocated_block = UINT32_MAX;
|
||||||
return ENOSPC;
|
return ENOSPC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Write into the same block
|
// Write into the same block
|
||||||
auto & inf = block_info.at(last_allocated_block);
|
|
||||||
gc_block(inf);
|
|
||||||
*block_num = last_allocated_block;
|
*block_num = last_allocated_block;
|
||||||
modify_alloc(last_allocated_block, [&](heap_block_info_t & inf)
|
modify_alloc(last_allocated_block, [&](heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
|
// Write just 1 entry to the block to collect garbage
|
||||||
|
if (inf.garbage_space > (inf.used_space-inf.garbage_space)/2)
|
||||||
|
last_allocated_block = UINT32_MAX;
|
||||||
|
gc_block(inf);
|
||||||
inf.used_space += entry_size;
|
inf.used_space += entry_size;
|
||||||
|
assert(inf.used_space - inf.garbage_space <= dsk->meta_block_size);
|
||||||
|
assert(!inf.mod_lsn_to || inf.mod_lsn_to == next_lsn);
|
||||||
|
++next_lsn;
|
||||||
|
inf.mod_lsn = inf.mod_lsn ? inf.mod_lsn : next_lsn;
|
||||||
|
inf.mod_lsn_to = next_lsn;
|
||||||
});
|
});
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1318,16 +1382,15 @@ int blockstore_heap_t::add_entry(uint32_t wr_size, uint32_t *modified_block,
|
|||||||
*modified_block = block_num;
|
*modified_block = block_num;
|
||||||
}
|
}
|
||||||
auto li = (heap_list_item_t*)malloc_or_die(wr_size + sizeof(heap_list_item_t) - sizeof(heap_entry_t));
|
auto li = (heap_list_item_t*)malloc_or_die(wr_size + sizeof(heap_list_item_t) - sizeof(heap_entry_t));
|
||||||
|
live_entries++;
|
||||||
|
live_memory += list_item_overhead(wr_size);
|
||||||
auto new_wr = &li->entry;
|
auto new_wr = &li->entry;
|
||||||
auto & inf = block_info.at(block_num);
|
auto & inf = block_info.at(block_num);
|
||||||
if (!inf.entries.size())
|
if (!inf.entries.size())
|
||||||
inf.entries.reserve(dsk->meta_block_size / max_entry_size);
|
inf.entries.reserve(dsk->meta_block_size / max_entry_size);
|
||||||
inf.entries.push_back(li);
|
inf.entries.push_back(li);
|
||||||
assert(!inf.mod_lsn_to || inf.mod_lsn_to == next_lsn);
|
new_wr->lsn = next_lsn;
|
||||||
new_wr->lsn = ++next_lsn;
|
|
||||||
fill_entry(new_wr);
|
fill_entry(new_wr);
|
||||||
inf.mod_lsn = inf.mod_lsn ? inf.mod_lsn : next_lsn;
|
|
||||||
inf.mod_lsn_to = next_lsn;
|
|
||||||
// Remember the object as dirty and remove older entries when this block is written and fsynced
|
// Remember the object as dirty and remove older entries when this block is written and fsynced
|
||||||
push_inflight_lsn(next_lsn, new_wr,
|
push_inflight_lsn(next_lsn, new_wr,
|
||||||
(explicit_complete ? HEAP_INFLIGHT_EXPLICIT : 0) |
|
(explicit_complete ? HEAP_INFLIGHT_EXPLICIT : 0) |
|
||||||
@@ -1666,28 +1729,38 @@ int blockstore_heap_t::add_delete(heap_entry_t *obj, uint32_t *modified_block)
|
|||||||
|
|
||||||
uint32_t blockstore_heap_t::meta_alloc_pos(const heap_block_info_t & inf)
|
uint32_t blockstore_heap_t::meta_alloc_pos(const heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
if (inf.is_writing || inf.used_space > dsk->meta_block_size-sizeof(heap_entry_t))
|
auto real_used = (inf.used_space-inf.garbage_space);
|
||||||
|
if (inf.is_writing || inf.mod_lsn || real_used > dsk->meta_block_size-sizeof(heap_entry_t))
|
||||||
{
|
{
|
||||||
// 100% full - no entry can be written into this block at all
|
// 100% full - no entry can be written into this block at all
|
||||||
return META_ALLOC_LEVELS;
|
return META_ALLOC_LEVELS;
|
||||||
}
|
}
|
||||||
if (inf.used_space > dsk->meta_block_size-max_entry_size)
|
if (real_used > dsk->meta_block_size-max_entry_size)
|
||||||
{
|
{
|
||||||
// nearfull - big_entries won't fit into this block so it can't be used for compaction
|
// nearfull - big_entries won't fit into this block so it can't be used for compaction
|
||||||
return META_ALLOC_LEVELS-1;
|
return META_ALLOC_LEVELS-1;
|
||||||
}
|
}
|
||||||
// normal block
|
// First we want to write to blocks with most garbage:
|
||||||
return inf.used_space / ((dsk->meta_block_size-max_entry_size+META_ALLOC_LEVELS-2) / (META_ALLOC_LEVELS-1));
|
// >= 2*used, >= used/2
|
||||||
|
// (i.e. 66% garbage, 33% garbage)
|
||||||
|
// Then to mostly free blocks:
|
||||||
|
// >= 75% free, >= 50% free, >= 25% free
|
||||||
|
if (inf.garbage_space > real_used*2)
|
||||||
|
return 0;
|
||||||
|
if (inf.garbage_space > real_used/2)
|
||||||
|
return 1;
|
||||||
|
// META_ALLOC_LEVELS-3 levels left
|
||||||
|
return 2 + real_used / ((dsk->meta_block_size-max_entry_size+META_ALLOC_LEVELS-4) / (META_ALLOC_LEVELS-3));
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockstore_heap_t::modify_alloc(uint32_t block_num, std::function<void(heap_block_info_t &)> change_cb)
|
void blockstore_heap_t::modify_alloc(uint32_t block_num, std::function<void(heap_block_info_t &)> change_cb)
|
||||||
{
|
{
|
||||||
auto & inf = block_info.at(block_num);
|
auto & inf = block_info.at(block_num);
|
||||||
uint32_t old_pos = meta_alloc_pos(inf);
|
uint32_t old_pos = meta_alloc_pos(inf);
|
||||||
uint32_t old_used = inf.used_space;
|
uint32_t old_used = inf.used_space-inf.garbage_space;
|
||||||
change_cb(inf);
|
change_cb(inf);
|
||||||
uint32_t new_pos = meta_alloc_pos(inf);
|
uint32_t new_pos = meta_alloc_pos(inf);
|
||||||
uint32_t new_used = inf.used_space;
|
uint32_t new_used = inf.used_space-inf.garbage_space;
|
||||||
meta_alloc->change(block_num, old_pos, new_pos);
|
meta_alloc->change(block_num, old_pos, new_pos);
|
||||||
meta_used_space -= old_used;
|
meta_used_space -= old_used;
|
||||||
meta_used_space += new_used;
|
meta_used_space += new_used;
|
||||||
@@ -1699,11 +1772,19 @@ void blockstore_heap_t::modify_alloc(uint32_t block_num, std::function<void(heap
|
|||||||
|
|
||||||
void blockstore_heap_t::start_block_write(uint32_t block_num)
|
void blockstore_heap_t::start_block_write(uint32_t block_num)
|
||||||
{
|
{
|
||||||
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
auto & inf = block_info.at(block_num);
|
||||||
|
assert(!inf.is_writing);
|
||||||
|
if (!inf.mod_lsn)
|
||||||
|
{
|
||||||
|
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
||||||
|
{
|
||||||
|
inf.is_writing = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
assert(!inf.is_writing);
|
|
||||||
inf.is_writing = true;
|
inf.is_writing = true;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockstore_heap_t::complete_block_write(uint32_t block_num)
|
void blockstore_heap_t::complete_block_write(uint32_t block_num)
|
||||||
@@ -1768,6 +1849,8 @@ void blockstore_heap_t::mark_garbage_up_to(heap_entry_t *wr)
|
|||||||
void blockstore_heap_t::mark_garbage(uint32_t block_num, heap_entry_t *prev_wr, uint32_t used_big)
|
void blockstore_heap_t::mark_garbage(uint32_t block_num, heap_entry_t *prev_wr, uint32_t used_big)
|
||||||
{
|
{
|
||||||
prev_wr->set_garbage();
|
prev_wr->set_garbage();
|
||||||
|
garbage_entries++;
|
||||||
|
garbage_memory += list_item_overhead(prev_wr->size);
|
||||||
// And this is the moment when we can free the data reference
|
// And this is the moment when we can free the data reference
|
||||||
if (prev_wr->type() == BS_HEAP_SMALL_WRITE && prev_wr->small().len > 0)
|
if (prev_wr->type() == BS_HEAP_SMALL_WRITE && prev_wr->small().len > 0)
|
||||||
{
|
{
|
||||||
@@ -1783,8 +1866,7 @@ void blockstore_heap_t::mark_garbage(uint32_t block_num, heap_entry_t *prev_wr,
|
|||||||
}
|
}
|
||||||
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
inf.used_space -= prev_wr->size;
|
inf.garbage_space += prev_wr->size;
|
||||||
inf.has_garbage = true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2154,7 +2236,7 @@ void blockstore_heap_t::fill_block_empty_space(uint8_t *buffer, uint32_t pos)
|
|||||||
uint32_t blockstore_heap_t::get_meta_block_used_space(uint32_t block_num)
|
uint32_t blockstore_heap_t::get_meta_block_used_space(uint32_t block_num)
|
||||||
{
|
{
|
||||||
auto & inf = block_info.at(block_num);
|
auto & inf = block_info.at(block_num);
|
||||||
return inf.used_space;
|
return inf.used_space - inf.garbage_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t blockstore_heap_t::get_data_used_space()
|
uint64_t blockstore_heap_t::get_data_used_space()
|
||||||
@@ -2197,6 +2279,26 @@ uint64_t blockstore_heap_t::get_compacted_count()
|
|||||||
return compacted_count;
|
return compacted_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t blockstore_heap_t::get_live_entries()
|
||||||
|
{
|
||||||
|
return live_entries-garbage_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t blockstore_heap_t::get_live_memory()
|
||||||
|
{
|
||||||
|
return live_memory-garbage_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t blockstore_heap_t::get_garbage_entries()
|
||||||
|
{
|
||||||
|
return garbage_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t blockstore_heap_t::get_garbage_memory()
|
||||||
|
{
|
||||||
|
return garbage_memory;
|
||||||
|
}
|
||||||
|
|
||||||
void blockstore_heap_t::push_inflight_lsn(uint64_t lsn, heap_entry_t *wr, uint64_t flags)
|
void blockstore_heap_t::push_inflight_lsn(uint64_t lsn, heap_entry_t *wr, uint64_t flags)
|
||||||
{
|
{
|
||||||
uint64_t next_inf = first_inflight_lsn + inflight_lsn.size();
|
uint64_t next_inf = first_inflight_lsn + inflight_lsn.size();
|
||||||
@@ -2283,37 +2385,50 @@ void blockstore_heap_t::apply_inflight(heap_inflight_lsn_t & inflight)
|
|||||||
{
|
{
|
||||||
// Remove entry
|
// Remove entry
|
||||||
auto li = list_item(wr);
|
auto li = list_item(wr);
|
||||||
auto prev = li->prev;
|
remove_list_item(li);
|
||||||
auto next = li->next;
|
|
||||||
if (prev)
|
|
||||||
{
|
|
||||||
prev->next = next;
|
|
||||||
}
|
|
||||||
if (!next)
|
|
||||||
{
|
|
||||||
// The last freed entry must be a deletion
|
|
||||||
assert(!prev);
|
|
||||||
assert(wr->entry_type == BS_HEAP_DELETE|BS_HEAP_STABLE);
|
|
||||||
auto & pg_idx = block_index[get_pg_id(wr->inode, wr->stripe)];
|
|
||||||
auto & inode_idx = pg_idx[wr->inode];
|
|
||||||
heap_inode_map_t::iterator li_it;
|
|
||||||
heap_list_item_t *old_li = NULL;
|
|
||||||
inode_map_get(inode_idx, li_it, old_li, wr->stripe);
|
|
||||||
inode_map_erase(pg_idx, inode_idx, li_it, old_li);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
next->prev = prev;
|
|
||||||
if (!prev && next->entry.entry_type == (BS_HEAP_DELETE|BS_HEAP_STABLE))
|
|
||||||
{
|
|
||||||
// free BS_HEAP_DELETEs when all previous entries are also freed
|
|
||||||
mark_garbage(next->block_num, &next->entry, UINT32_MAX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(li);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void blockstore_heap_t::remove_list_item(heap_list_item_t *li)
|
||||||
|
{
|
||||||
|
auto prev = li->prev;
|
||||||
|
auto next = li->next;
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
if (!next)
|
||||||
|
{
|
||||||
|
// The last freed entry must be a deletion
|
||||||
|
assert(!prev);
|
||||||
|
auto wr = &li->entry;
|
||||||
|
assert(wr->entry_type == BS_HEAP_DELETE|BS_HEAP_STABLE);
|
||||||
|
auto & pg_idx = block_index[get_pg_id(wr->inode, wr->stripe)];
|
||||||
|
auto & inode_idx = pg_idx[wr->inode];
|
||||||
|
heap_inode_map_t::iterator li_it;
|
||||||
|
heap_list_item_t *old_li = NULL;
|
||||||
|
inode_map_get(inode_idx, li_it, old_li, wr->stripe);
|
||||||
|
inode_map_erase(pg_idx, inode_idx, li_it, old_li);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next->prev = prev;
|
||||||
|
if (!prev && next->entry.entry_type == (BS_HEAP_DELETE|BS_HEAP_STABLE))
|
||||||
|
{
|
||||||
|
// free BS_HEAP_DELETEs when all previous entries are also freed
|
||||||
|
mark_garbage(next->block_num, &next->entry, UINT32_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (li->entry.is_garbage())
|
||||||
|
{
|
||||||
|
garbage_entries--;
|
||||||
|
garbage_memory -= list_item_overhead(li->entry.size);
|
||||||
|
}
|
||||||
|
live_entries--;
|
||||||
|
live_memory -= list_item_overhead(li->entry.size);
|
||||||
|
free(li);
|
||||||
|
}
|
||||||
|
|
||||||
bool blockstore_heap_t::is_lsn_completed(uint64_t lsn)
|
bool blockstore_heap_t::is_lsn_completed(uint64_t lsn)
|
||||||
{
|
{
|
||||||
if (lsn <= completed_lsn)
|
if (lsn <= completed_lsn)
|
||||||
|
|||||||
@@ -117,10 +117,13 @@ struct heap_object_mvcc_t
|
|||||||
|
|
||||||
struct heap_block_info_t
|
struct heap_block_info_t
|
||||||
{
|
{
|
||||||
uint32_t used_space = 0;
|
struct __attribute__((__packed__))
|
||||||
|
{
|
||||||
|
uint32_t used_space = 0;
|
||||||
|
uint32_t garbage_space = 0;
|
||||||
|
};
|
||||||
uint64_t mod_lsn = 0, mod_lsn_to = 0; // only 1 block write of LSN sequence is allowed at a moment
|
uint64_t mod_lsn = 0, mod_lsn_to = 0; // only 1 block write of LSN sequence is allowed at a moment
|
||||||
bool is_writing: 1;
|
bool is_writing = false;
|
||||||
bool has_garbage: 1;
|
|
||||||
std::vector<heap_list_item_t*> entries;
|
std::vector<heap_list_item_t*> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -184,6 +187,11 @@ class blockstore_heap_t
|
|||||||
uint64_t buffer_area_used_space = 0;
|
uint64_t buffer_area_used_space = 0;
|
||||||
uint64_t data_used_space = 0;
|
uint64_t data_used_space = 0;
|
||||||
|
|
||||||
|
uint64_t live_entries = 0;
|
||||||
|
uint64_t live_memory = 0;
|
||||||
|
uint64_t garbage_entries = 0;
|
||||||
|
uint64_t garbage_memory = 0;
|
||||||
|
|
||||||
uint64_t next_lsn = 0;
|
uint64_t next_lsn = 0;
|
||||||
uint32_t last_allocated_block = UINT32_MAX;
|
uint32_t last_allocated_block = UINT32_MAX;
|
||||||
heap_mvcc_map_t object_mvcc;
|
heap_mvcc_map_t object_mvcc;
|
||||||
@@ -212,6 +220,7 @@ class blockstore_heap_t
|
|||||||
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_full_gc();
|
||||||
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);
|
void reshard_add(heap_reshard_state_t *st, heap_list_item_t *li);
|
||||||
@@ -219,6 +228,7 @@ class blockstore_heap_t
|
|||||||
void gc_block(heap_block_info_t & inf);
|
void gc_block(heap_block_info_t & inf);
|
||||||
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);
|
||||||
|
void remove_list_item(heap_list_item_t *li);
|
||||||
int add_entry(uint32_t wr_size, uint32_t *modified_block, bool allow_last_free,
|
int add_entry(uint32_t wr_size, uint32_t *modified_block, bool allow_last_free,
|
||||||
bool explicit_complete, std::function<void(heap_entry_t *wr)> fill_entry);
|
bool explicit_complete, std::function<void(heap_entry_t *wr)> fill_entry);
|
||||||
int add_simple(heap_entry_t *obj, uint64_t version, uint32_t *modified_block, uint32_t entry_type);
|
int add_simple(heap_entry_t *obj, uint64_t version, uint32_t *modified_block, uint32_t entry_type);
|
||||||
@@ -345,6 +355,10 @@ public:
|
|||||||
uint32_t get_compact_queue_size();
|
uint32_t get_compact_queue_size();
|
||||||
uint32_t get_to_compact_count();
|
uint32_t get_to_compact_count();
|
||||||
uint64_t get_compacted_count();
|
uint64_t get_compacted_count();
|
||||||
|
uint64_t get_live_entries();
|
||||||
|
uint64_t get_live_memory();
|
||||||
|
uint64_t get_garbage_entries();
|
||||||
|
uint64_t get_garbage_memory();
|
||||||
|
|
||||||
uint64_t entry_pos(uint32_t block_num, uint32_t offset);
|
uint64_t entry_pos(uint32_t block_num, uint32_t offset);
|
||||||
heap_entry_t *entry_from_pos(uint64_t entry_pos, bool allow_unallocated = false);
|
heap_entry_t *entry_from_pos(uint64_t entry_pos, bool allow_unallocated = false);
|
||||||
|
|||||||
@@ -229,4 +229,9 @@ public:
|
|||||||
uint64_t get_free_block_count();
|
uint64_t get_free_block_count();
|
||||||
inline uint32_t get_bitmap_granularity() { return dsk.bitmap_granularity; }
|
inline uint32_t get_bitmap_granularity() { return dsk.bitmap_granularity; }
|
||||||
inline uint64_t get_journal_size() { return dsk.journal_len; }
|
inline uint64_t get_journal_size() { return dsk.journal_len; }
|
||||||
|
|
||||||
|
inline uint64_t get_live_entries() { return heap->get_live_entries(); }
|
||||||
|
inline uint64_t get_live_memory() { return heap->get_live_memory(); }
|
||||||
|
inline uint64_t get_garbage_entries() { return heap->get_garbage_entries(); }
|
||||||
|
inline uint64_t get_garbage_memory() { return heap->get_garbage_memory(); }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ resume_4:
|
|||||||
}
|
}
|
||||||
// metadata read finished
|
// metadata read finished
|
||||||
bs->heap->finish_load();
|
bs->heap->finish_load();
|
||||||
printf("Metadata entries loaded: %ju, used blocks: %ju / %ju\n", entries_loaded, bs->heap->get_data_used_space() / bs->dsk.data_block_size, bs->dsk.block_count);
|
printf("Metadata entries loaded: %ju, rechecking unfinished writes and garbage entries\n", entries_loaded);
|
||||||
if (zero_on_init && !bs->dsk.disable_meta_fsync)
|
if (zero_on_init && !bs->dsk.disable_meta_fsync)
|
||||||
{
|
{
|
||||||
GET_SQE();
|
GET_SQE();
|
||||||
@@ -293,6 +293,11 @@ resume_7:
|
|||||||
if (bs->readonly)
|
if (bs->readonly)
|
||||||
{
|
{
|
||||||
recheck_mod.clear();
|
recheck_mod.clear();
|
||||||
|
printf("Actual metadata entries: %ju\n", bs->heap->get_live_entries());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Actual metadata entries: %ju, clearing garbage in %zu metadata blocks\n", bs->heap->get_live_entries(), recheck_mod.size());
|
||||||
}
|
}
|
||||||
for (i = 0; i < recheck_mod.size(); i++)
|
for (i = 0; i < recheck_mod.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -306,7 +311,7 @@ resume_8:
|
|||||||
uint32_t block_num = recheck_mod[i];
|
uint32_t block_num = recheck_mod[i];
|
||||||
uint64_t block_offset = bs->dsk.meta_offset + (uint64_t)(block_num+1) * bs->dsk.meta_block_size;
|
uint64_t block_offset = bs->dsk.meta_offset + (uint64_t)(block_num+1) * bs->dsk.meta_block_size;
|
||||||
data = ((ring_data_t*)sqe->user_data);
|
data = ((ring_data_t*)sqe->user_data);
|
||||||
uint8_t *buf = (uint8_t*)malloc_or_die(bs->dsk.meta_block_size);
|
uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, bs->dsk.meta_block_size);
|
||||||
bs->heap->get_meta_block(block_num, buf);
|
bs->heap->get_meta_block(block_num, buf);
|
||||||
data->iov = { buf, bs->dsk.meta_block_size };
|
data->iov = { buf, bs->dsk.meta_block_size };
|
||||||
data->callback = [this, buf, block_offset](ring_data_t *data)
|
data->callback = [this, buf, block_offset](ring_data_t *data)
|
||||||
@@ -332,5 +337,9 @@ resume_9:
|
|||||||
}
|
}
|
||||||
free(metadata_buffer);
|
free(metadata_buffer);
|
||||||
metadata_buffer = NULL;
|
metadata_buffer = NULL;
|
||||||
|
printf("Loading finished. Data used: %ju / %ju bytes (%s / %s)\n",
|
||||||
|
bs->heap->get_data_used_space(), bs->dsk.block_count * bs->dsk.data_block_size,
|
||||||
|
format_size(bs->heap->get_data_used_space()).c_str(),
|
||||||
|
format_size(bs->dsk.block_count * bs->dsk.data_block_size).c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -462,6 +462,10 @@ int blockstore_impl_t::read_bitmap(object_id oid, uint64_t target_version, void
|
|||||||
{
|
{
|
||||||
if (target_version >= wr->version)
|
if (target_version >= wr->version)
|
||||||
{
|
{
|
||||||
|
if (wr->type() == BS_HEAP_DELETE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
found = true;
|
found = true;
|
||||||
if (result_version)
|
if (result_version)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -855,4 +855,29 @@ std::string blockstore_impl_t::get_op_diag(blockstore_op_t *op)
|
|||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t blockstore_impl_t::get_live_entries()
|
||||||
|
{
|
||||||
|
return used_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t blockstore_impl_t::get_live_memory()
|
||||||
|
{
|
||||||
|
uint64_t used = 0;
|
||||||
|
for (auto & kv: clean_db_shards)
|
||||||
|
{
|
||||||
|
used += kv.second.size() * sizeof(blockstore_clean_db_t::value_type);
|
||||||
|
}
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t blockstore_impl_t::get_garbage_entries()
|
||||||
|
{
|
||||||
|
return dirty_db.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t blockstore_impl_t::get_garbage_memory()
|
||||||
|
{
|
||||||
|
return (sizeof(obj_ver_id) + sizeof(dirty_entry) + 32) * dirty_db.size();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace v1
|
} // namespace v1
|
||||||
|
|||||||
@@ -332,6 +332,10 @@ public:
|
|||||||
inline uint64_t get_free_block_count() { return dsk.block_count - used_blocks; }
|
inline uint64_t get_free_block_count() { return dsk.block_count - used_blocks; }
|
||||||
inline uint32_t get_bitmap_granularity() { return dsk.disk_alignment; }
|
inline uint32_t get_bitmap_granularity() { return dsk.disk_alignment; }
|
||||||
inline uint64_t get_journal_size() { return dsk.journal_len; }
|
inline uint64_t get_journal_size() { return dsk.journal_len; }
|
||||||
|
uint64_t get_live_entries();
|
||||||
|
uint64_t get_live_memory();
|
||||||
|
uint64_t get_garbage_entries();
|
||||||
|
uint64_t get_garbage_memory();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace v1
|
} // namespace v1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ cluster_client_t::cluster_client_t(ring_loop_t *ringloop, timerfd_manager_t *tfd
|
|||||||
msgr.ringloop = ringloop;
|
msgr.ringloop = ringloop;
|
||||||
msgr.repeer_pgs = [this](osd_num_t peer_osd)
|
msgr.repeer_pgs = [this](osd_num_t peer_osd)
|
||||||
{
|
{
|
||||||
if (msgr.osd_peer_fds.find(peer_osd) != msgr.osd_peer_fds.end())
|
if (msgr.osd_peers.find(peer_osd) != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
// peer_osd just connected
|
// peer_osd just connected
|
||||||
continue_ops();
|
continue_ops();
|
||||||
@@ -47,8 +47,8 @@ cluster_client_t::cluster_client_t(ring_loop_t *ringloop, timerfd_manager_t *tfd
|
|||||||
msgr.exec_op = [this](osd_op_t *op)
|
msgr.exec_op = [this](osd_op_t *op)
|
||||||
{
|
{
|
||||||
// Garbage in
|
// Garbage in
|
||||||
fprintf(stderr, "Incoming garbage from peer %d\n", op->peer_fd);
|
fprintf(stderr, "Can't handle incoming operation from client %lu\n", op->client_id);
|
||||||
msgr.stop_client(op->peer_fd);
|
msgr.stop_client(op->client_id);
|
||||||
delete op;
|
delete op;
|
||||||
};
|
};
|
||||||
msgr.parse_config(config);
|
msgr.parse_config(config);
|
||||||
@@ -156,7 +156,7 @@ void cluster_client_t::continue_raw_ops(osd_num_t peer_osd)
|
|||||||
{
|
{
|
||||||
auto op = it->second;
|
auto op = it->second;
|
||||||
op->op_type = OSD_OP_OUT;
|
op->op_type = OSD_OP_OUT;
|
||||||
op->peer_fd = msgr.osd_peer_fds.at(peer_osd);
|
op->client_id = msgr.osd_peers.at(peer_osd)->client_id;
|
||||||
msgr.outbox_push(op);
|
msgr.outbox_push(op);
|
||||||
raw_ops.erase(it++);
|
raw_ops.erase(it++);
|
||||||
}
|
}
|
||||||
@@ -590,7 +590,7 @@ void cluster_client_t::on_change_pool_config_hook()
|
|||||||
{
|
{
|
||||||
if (log_level > 2 && pg_counts[pool_item.first])
|
if (log_level > 2 && pg_counts[pool_item.first])
|
||||||
{
|
{
|
||||||
printf("Pool %u (%s) PG count changed from %lu to %lu\n", pool_item.first, pool_item.second.name.c_str(),
|
fprintf(stderr, "Pool %u (%s) PG count changed from %lu to %lu\n", pool_item.first, pool_item.second.name.c_str(),
|
||||||
pg_counts[pool_item.first], pool_item.second.real_pg_count);
|
pg_counts[pool_item.first], pool_item.second.real_pg_count);
|
||||||
}
|
}
|
||||||
// At this point, all pool operations should have been suspended
|
// At this point, all pool operations should have been suspended
|
||||||
@@ -871,13 +871,13 @@ void cluster_client_t::execute_cas(cluster_op_t *op)
|
|||||||
if (op->retval != expected && op->retval >= 0)
|
if (op->retval != expected && op->retval >= 0)
|
||||||
op->retval = -EIO;
|
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_peers.find(op->parts[0].osd_num);
|
||||||
if (op->retval != 0 || (op->flags & OP_IMMEDIATE_COMMIT))
|
if (op->retval != 0 || (op->flags & OP_IMMEDIATE_COMMIT))
|
||||||
{
|
{
|
||||||
auto cb = std::move(op->callback);
|
auto cb = std::move(op->callback);
|
||||||
cb(op);
|
cb(op);
|
||||||
}
|
}
|
||||||
else if (peer_it == msgr.osd_peer_fds.end())
|
else if (peer_it == msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
// Care must be taken to make sure that the client doesn't reconnect to the OSD
|
// Care must be taken to make sure that the client doesn't reconnect to the OSD
|
||||||
// before executing the previously completed operation callback (!)
|
// before executing the previously completed operation callback (!)
|
||||||
@@ -888,10 +888,10 @@ void cluster_client_t::execute_cas(cluster_op_t *op)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// CAS writes have a built-in sync
|
// CAS writes have a built-in sync
|
||||||
auto peer_fd = peer_it->second;
|
osd_client_t *cl = peer_it->second;
|
||||||
*part = (osd_op_t){
|
*part = (osd_op_t){
|
||||||
.op_type = OSD_OP_OUT,
|
.op_type = OSD_OP_OUT,
|
||||||
.peer_fd = peer_fd,
|
.client_id = cl->client_id,
|
||||||
.req = {
|
.req = {
|
||||||
.hdr = {
|
.hdr = {
|
||||||
.magic = SECONDARY_OSD_OP_MAGIC,
|
.magic = SECONDARY_OSD_OP_MAGIC,
|
||||||
@@ -1004,11 +1004,11 @@ bool cluster_client_t::check_rw(cluster_op_t *op)
|
|||||||
|
|
||||||
void cluster_client_t::execute_raw(osd_num_t osd_num, osd_op_t *op)
|
void cluster_client_t::execute_raw(osd_num_t osd_num, osd_op_t *op)
|
||||||
{
|
{
|
||||||
auto fd_it = msgr.osd_peer_fds.find(osd_num);
|
auto peer_it = msgr.osd_peers.find(osd_num);
|
||||||
if (fd_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
op->op_type = OSD_OP_OUT;
|
op->op_type = OSD_OP_OUT;
|
||||||
op->peer_fd = fd_it->second;
|
op->client_id = peer_it->second->client_id;
|
||||||
msgr.outbox_push(op);
|
msgr.outbox_push(op);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1119,6 +1119,13 @@ resume_2:
|
|||||||
// Finished successfully
|
// Finished successfully
|
||||||
// Even if the PG count has changed in meanwhile we treat it as success
|
// Even if the PG count has changed in meanwhile we treat it as success
|
||||||
// because if some operations were invalid for the new PG count we'd get errors
|
// because if some operations were invalid for the new PG count we'd get errors
|
||||||
|
if (op->opcode == OSD_OP_READ || op->opcode == OSD_OP_READ_BITMAP || op->opcode == OSD_OP_READ_CHAIN_BITMAP)
|
||||||
|
{
|
||||||
|
// Copy part bitmaps only after finishing all part reads
|
||||||
|
for (auto & part: op->parts)
|
||||||
|
if ((part.flags & (PART_SENT|PART_DONE|PART_VALID)) == (PART_SENT|PART_DONE|PART_VALID))
|
||||||
|
copy_part_bitmap(op, &part);
|
||||||
|
}
|
||||||
if (op->opcode == OSD_OP_READ || op->opcode == OSD_OP_READ_CHAIN_BITMAP)
|
if (op->opcode == OSD_OP_READ || op->opcode == OSD_OP_READ_CHAIN_BITMAP)
|
||||||
{
|
{
|
||||||
// Check parent inode
|
// Check parent inode
|
||||||
@@ -1401,10 +1408,10 @@ int cluster_client_t::try_send(cluster_op_t *op, int i, std::function<void(osd_o
|
|||||||
primary_osd = nearest_osd;
|
primary_osd = nearest_osd;
|
||||||
}
|
}
|
||||||
part->osd_num = primary_osd;
|
part->osd_num = primary_osd;
|
||||||
auto peer_it = msgr.osd_peer_fds.find(primary_osd);
|
auto peer_it = msgr.osd_peers.find(primary_osd);
|
||||||
if (peer_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
int peer_fd = peer_it->second;
|
osd_client_t *cl = peer_it->second;
|
||||||
part->flags |= PART_SENT|PART_VALID;
|
part->flags |= PART_SENT|PART_VALID;
|
||||||
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) * (
|
||||||
@@ -1419,7 +1426,7 @@ int cluster_client_t::try_send(cluster_op_t *op, int i, std::function<void(osd_o
|
|||||||
}
|
}
|
||||||
part->op = (osd_op_t){
|
part->op = (osd_op_t){
|
||||||
.op_type = OSD_OP_OUT,
|
.op_type = OSD_OP_OUT,
|
||||||
.peer_fd = peer_fd,
|
.client_id = cl->client_id,
|
||||||
.req = { .rw = {
|
.req = { .rw = {
|
||||||
.header = {
|
.header = {
|
||||||
.magic = SECONDARY_OSD_OP_MAGIC,
|
.magic = SECONDARY_OSD_OP_MAGIC,
|
||||||
@@ -1468,8 +1475,8 @@ int cluster_client_t::continue_sync(cluster_op_t *op)
|
|||||||
for (auto do_it = dirty_osds.begin(); do_it != dirty_osds.end(); )
|
for (auto do_it = dirty_osds.begin(); do_it != dirty_osds.end(); )
|
||||||
{
|
{
|
||||||
osd_num_t sync_osd = *do_it;
|
osd_num_t sync_osd = *do_it;
|
||||||
auto peer_it = msgr.osd_peer_fds.find(sync_osd);
|
auto peer_it = msgr.osd_peers.find(sync_osd);
|
||||||
if (peer_it == msgr.osd_peer_fds.end())
|
if (peer_it == msgr.osd_peers.end())
|
||||||
dirty_osds.erase(do_it++);
|
dirty_osds.erase(do_it++);
|
||||||
else
|
else
|
||||||
do_it++;
|
do_it++;
|
||||||
@@ -1522,12 +1529,12 @@ resume_1:
|
|||||||
|
|
||||||
void cluster_client_t::send_sync(cluster_op_t *op, cluster_op_part_t *part)
|
void cluster_client_t::send_sync(cluster_op_t *op, cluster_op_part_t *part)
|
||||||
{
|
{
|
||||||
auto peer_fd = msgr.osd_peer_fds.at(part->osd_num);
|
osd_client_t *cl = msgr.osd_peers.at(part->osd_num);
|
||||||
part->flags |= PART_SENT;
|
part->flags |= PART_SENT;
|
||||||
op->inflight_count++;
|
op->inflight_count++;
|
||||||
part->op = (osd_op_t){
|
part->op = (osd_op_t){
|
||||||
.op_type = OSD_OP_OUT,
|
.op_type = OSD_OP_OUT,
|
||||||
.peer_fd = peer_fd,
|
.client_id = cl->client_id,
|
||||||
.req = {
|
.req = {
|
||||||
.hdr = {
|
.hdr = {
|
||||||
.magic = SECONDARY_OSD_OP_MAGIC,
|
.magic = SECONDARY_OSD_OP_MAGIC,
|
||||||
@@ -1567,10 +1574,10 @@ void cluster_client_t::handle_op_part(cluster_op_part_t *part)
|
|||||||
// Error priority: EIO > ENOSPC > ETIMEDOUT > EPIPE
|
// Error priority: EIO > ENOSPC > ETIMEDOUT > EPIPE
|
||||||
op->retval = part->op.reply.hdr.retval;
|
op->retval = part->op.reply.hdr.retval;
|
||||||
}
|
}
|
||||||
int stop_fd = -1;
|
uint64_t stop_client_id = 0;
|
||||||
if (op->retval != -EINTR && op->retval != -EIO && op->retval != -ENOSPC)
|
if (op->retval != -EINTR && op->retval != -EIO && op->retval != -ENOSPC)
|
||||||
{
|
{
|
||||||
stop_fd = part->op.peer_fd;
|
stop_client_id = part->op.client_id;
|
||||||
if (op->retval != -EPIPE || log_level > 0)
|
if (op->retval != -EPIPE || log_level > 0)
|
||||||
{
|
{
|
||||||
fprintf(
|
fprintf(
|
||||||
@@ -1597,9 +1604,9 @@ void cluster_client_t::handle_op_part(cluster_op_part_t *part)
|
|||||||
op->retry_after = op->retval != -EPIPE ? client_eio_retry_interval : client_retry_interval;
|
op->retry_after = op->retval != -EPIPE ? client_eio_retry_interval : client_retry_interval;
|
||||||
}
|
}
|
||||||
reset_retry_timer(op->retry_after);
|
reset_retry_timer(op->retry_after);
|
||||||
if (stop_fd >= 0)
|
if (stop_client_id)
|
||||||
{
|
{
|
||||||
msgr.stop_client(stop_fd);
|
msgr.stop_client(stop_client_id);
|
||||||
}
|
}
|
||||||
op->inflight_count--;
|
op->inflight_count--;
|
||||||
if (op->inflight_count == 0 && !op->retry_after)
|
if (op->inflight_count == 0 && !op->retry_after)
|
||||||
@@ -1630,13 +1637,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
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ int cluster_client_t::start_pg_listing(inode_list_pg_t *pg)
|
|||||||
bool conn = true;
|
bool conn = true;
|
||||||
for (osd_num_t peer_osd: all_peers)
|
for (osd_num_t peer_osd: all_peers)
|
||||||
{
|
{
|
||||||
if (msgr.osd_peer_fds.find(peer_osd) == msgr.osd_peer_fds.end())
|
if (msgr.osd_peers.find(peer_osd) == msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
// Initiate connection
|
// Initiate connection
|
||||||
if (st_cli.peer_states[peer_osd].is_null())
|
if (st_cli.peer_states[peer_osd].is_null())
|
||||||
@@ -340,7 +340,7 @@ void cluster_client_t::send_list(inode_list_osd_t *cur_list)
|
|||||||
osd_op_t *op = new osd_op_t();
|
osd_op_t *op = new osd_op_t();
|
||||||
op->op_type = OSD_OP_OUT;
|
op->op_type = OSD_OP_OUT;
|
||||||
// Already checked that it exists above, but anyway
|
// Already checked that it exists above, but anyway
|
||||||
op->peer_fd = msgr.osd_peer_fds.at(cur_list->osd_num);
|
op->client_id = msgr.osd_peers.at(cur_list->osd_num)->client_id;
|
||||||
op->req = (osd_any_op_t){
|
op->req = (osd_any_op_t){
|
||||||
.sec_list = {
|
.sec_list = {
|
||||||
.header = {
|
.header = {
|
||||||
|
|||||||
+66
-53
@@ -182,12 +182,13 @@ void osd_messenger_t::init()
|
|||||||
}
|
}
|
||||||
keepalive_timer_id = tfd->set_timer(1000, true, [this](int)
|
keepalive_timer_id = tfd->set_timer(1000, true, [this](int)
|
||||||
{
|
{
|
||||||
|
std::vector<uint64_t> clients_to_stop;
|
||||||
|
std::vector<osd_op_t*> ops_to_send;
|
||||||
auto cl_it = clients.begin();
|
auto cl_it = clients.begin();
|
||||||
while (cl_it != clients.end())
|
while (cl_it != clients.end())
|
||||||
{
|
{
|
||||||
auto cl = cl_it->second;
|
auto cl = cl_it->second;
|
||||||
cl_it++;
|
cl_it++;
|
||||||
auto peer_fd = cl->peer_fd;
|
|
||||||
if (!cl->osd_num && !cl->in_osd_num || cl->peer_state != PEER_CONNECTED && cl->peer_state != PEER_RDMA)
|
if (!cl->osd_num && !cl->in_osd_num || cl->peer_state != PEER_CONNECTED && cl->peer_state != PEER_RDMA)
|
||||||
{
|
{
|
||||||
// Do not run keepalive on regular clients
|
// Do not run keepalive on regular clients
|
||||||
@@ -199,10 +200,9 @@ void osd_messenger_t::init()
|
|||||||
if (!cl->ping_time_remaining)
|
if (!cl->ping_time_remaining)
|
||||||
{
|
{
|
||||||
// Ping timed out, stop the client
|
// Ping timed out, stop the client
|
||||||
fprintf(stderr, "Ping timed out for OSD %ju (client %d), disconnecting peer\n", cl->in_osd_num ? cl->in_osd_num : cl->osd_num, cl->peer_fd);
|
fprintf(stderr, "Ping timed out for OSD %ju (client %ju), disconnecting peer\n",
|
||||||
stop_client(peer_fd, true);
|
cl->in_osd_num ? cl->in_osd_num : cl->osd_num, cl->client_id);
|
||||||
// Restart iterator because it may be invalidated
|
clients_to_stop.push_back(cl->client_id);
|
||||||
cl_it = clients.upper_bound(peer_fd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cl->idle_time_remaining > 0)
|
else if (cl->idle_time_remaining > 0)
|
||||||
@@ -213,7 +213,7 @@ void osd_messenger_t::init()
|
|||||||
// Connection is idle for <osd_idle_time>, send ping
|
// Connection is idle for <osd_idle_time>, send ping
|
||||||
osd_op_t *op = new osd_op_t();
|
osd_op_t *op = new osd_op_t();
|
||||||
op->op_type = OSD_OP_OUT;
|
op->op_type = OSD_OP_OUT;
|
||||||
op->peer_fd = cl->peer_fd;
|
op->client_id = cl->client_id;
|
||||||
op->req = (osd_any_op_t){
|
op->req = (osd_any_op_t){
|
||||||
.hdr = {
|
.hdr = {
|
||||||
.magic = SECONDARY_OSD_OP_MAGIC,
|
.magic = SECONDARY_OSD_OP_MAGIC,
|
||||||
@@ -222,28 +222,26 @@ void osd_messenger_t::init()
|
|||||||
};
|
};
|
||||||
op->callback = [this, cl](osd_op_t *op)
|
op->callback = [this, cl](osd_op_t *op)
|
||||||
{
|
{
|
||||||
auto cl_it = clients.find(op->peer_fd);
|
auto cl_it = clients.find(op->client_id);
|
||||||
if (cl_it == clients.end() || cl_it->second != cl)
|
if (cl_it == clients.end())
|
||||||
{
|
{
|
||||||
// client is already dropped
|
// client is already dropped
|
||||||
delete op;
|
delete op;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int fail_fd = (op->reply.hdr.retval != 0 ? op->peer_fd : -1);
|
uint64_t fail_client_id = (op->reply.hdr.retval != 0 ? op->client_id : 0);
|
||||||
auto fail_osd_num = cl->in_osd_num ? cl->in_osd_num : cl->osd_num;
|
auto fail_osd_num = cl->in_osd_num ? cl->in_osd_num : cl->osd_num;
|
||||||
cl->ping_time_remaining = 0;
|
cl->ping_time_remaining = 0;
|
||||||
delete op;
|
delete op;
|
||||||
if (fail_fd >= 0)
|
if (fail_client_id)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Ping failed for OSD %ju (client %d), disconnecting peer\n", fail_osd_num, fail_fd);
|
fprintf(stderr, "Ping failed for OSD %ju (client %ju), disconnecting peer\n", fail_osd_num, fail_client_id);
|
||||||
stop_client(fail_fd, true);
|
stop_client(fail_client_id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cl->ping_time_remaining = osd_ping_timeout;
|
cl->ping_time_remaining = osd_ping_timeout;
|
||||||
cl->idle_time_remaining = osd_idle_timeout;
|
cl->idle_time_remaining = osd_idle_timeout;
|
||||||
outbox_push(op);
|
ops_to_send.push_back(op);
|
||||||
// Restart iterator because it may be invalidated
|
|
||||||
cl_it = clients.upper_bound(peer_fd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -251,6 +249,14 @@ void osd_messenger_t::init()
|
|||||||
cl->idle_time_remaining = osd_idle_timeout;
|
cl->idle_time_remaining = osd_idle_timeout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (uint64_t client_id: clients_to_stop)
|
||||||
|
{
|
||||||
|
stop_client(client_id);
|
||||||
|
}
|
||||||
|
for (osd_op_t *op: ops_to_send)
|
||||||
|
{
|
||||||
|
outbox_push(op);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +269,7 @@ osd_messenger_t::~osd_messenger_t()
|
|||||||
}
|
}
|
||||||
while (clients.size() > 0)
|
while (clients.size() > 0)
|
||||||
{
|
{
|
||||||
stop_client(clients.begin()->first, true, true);
|
stop_client(clients.begin()->first, true);
|
||||||
}
|
}
|
||||||
if (iothreads.size())
|
if (iothreads.size())
|
||||||
{
|
{
|
||||||
@@ -440,7 +446,7 @@ void osd_messenger_t::try_connect_peer(uint64_t peer_osd)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (osd_peer_fds.find(peer_osd) != osd_peer_fds.end())
|
if (osd_peers.find(peer_osd) != osd_peers.end())
|
||||||
{
|
{
|
||||||
wanted_peers.erase(peer_osd);
|
wanted_peers.erase(peer_osd);
|
||||||
return;
|
return;
|
||||||
@@ -467,20 +473,20 @@ void osd_messenger_t::try_connect_peer_tcp(osd_num_t peer_osd, const char *peer_
|
|||||||
#ifdef WITH_RDMACM
|
#ifdef WITH_RDMACM
|
||||||
if (disable_tcp)
|
if (disable_tcp)
|
||||||
{
|
{
|
||||||
on_connect_peer(peer_osd, -EINVAL);
|
on_connect_peer(peer_osd, -EINVAL, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
if (!string_to_addr(peer_host, 0, peer_port, &addr))
|
if (!string_to_addr(peer_host, 0, peer_port, &addr))
|
||||||
{
|
{
|
||||||
on_connect_peer(peer_osd, -EINVAL);
|
on_connect_peer(peer_osd, -EINVAL, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int peer_fd = socket(addr.ss_family, SOCK_STREAM, 0);
|
int peer_fd = socket(addr.ss_family, SOCK_STREAM, 0);
|
||||||
if (peer_fd < 0)
|
if (peer_fd < 0)
|
||||||
{
|
{
|
||||||
on_connect_peer(peer_osd, -errno);
|
on_connect_peer(peer_osd, -errno, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fcntl(peer_fd, F_SETFL, fcntl(peer_fd, F_GETFL, 0) | O_NONBLOCK);
|
fcntl(peer_fd, F_SETFL, fcntl(peer_fd, F_GETFL, 0) | O_NONBLOCK);
|
||||||
@@ -488,21 +494,25 @@ void osd_messenger_t::try_connect_peer_tcp(osd_num_t peer_osd, const char *peer_
|
|||||||
if (r < 0 && errno != EINPROGRESS)
|
if (r < 0 && errno != EINPROGRESS)
|
||||||
{
|
{
|
||||||
close(peer_fd);
|
close(peer_fd);
|
||||||
on_connect_peer(peer_osd, -errno);
|
on_connect_peer(peer_osd, -errno, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clients[peer_fd] = new osd_client_t();
|
const uint64_t client_id = next_client_id++;
|
||||||
|
osd_client_t *cl = new osd_client_t();
|
||||||
if (log_level > 0)
|
if (log_level > 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Connecting to OSD %ju at %s:%d (client %d)\n", peer_osd, peer_host, peer_port, peer_fd);
|
fprintf(stderr, "Connecting to OSD %ju at %s:%d (client %ju, FD %d)\n", peer_osd, peer_host, peer_port, client_id, peer_fd);
|
||||||
}
|
}
|
||||||
clients[peer_fd]->peer_addr = addr;
|
cl->client_id = client_id;
|
||||||
clients[peer_fd]->peer_port = peer_port;
|
cl->peer_addr = addr;
|
||||||
clients[peer_fd]->peer_fd = peer_fd;
|
cl->peer_port = peer_port;
|
||||||
clients[peer_fd]->peer_state = PEER_CONNECTING;
|
cl->peer_fd = peer_fd;
|
||||||
clients[peer_fd]->connect_timeout_id = -1;
|
cl->peer_state = PEER_CONNECTING;
|
||||||
clients[peer_fd]->osd_num = peer_osd;
|
cl->connect_timeout_id = -1;
|
||||||
clients[peer_fd]->in_buf = malloc_or_die(receive_buffer_size);
|
cl->osd_num = peer_osd;
|
||||||
|
cl->in_buf = malloc_or_die(receive_buffer_size);
|
||||||
|
clients[client_id] = cl;
|
||||||
|
clients_by_fd[peer_fd] = cl;
|
||||||
tfd->set_fd_handler(peer_fd, true, [this](int peer_fd, int epoll_events)
|
tfd->set_fd_handler(peer_fd, true, [this](int peer_fd, int epoll_events)
|
||||||
{
|
{
|
||||||
// Either OUT (connected) or HUP
|
// Either OUT (connected) or HUP
|
||||||
@@ -510,11 +520,11 @@ void osd_messenger_t::try_connect_peer_tcp(osd_num_t peer_osd, const char *peer_
|
|||||||
});
|
});
|
||||||
if (peer_connect_timeout > 0)
|
if (peer_connect_timeout > 0)
|
||||||
{
|
{
|
||||||
clients[peer_fd]->connect_timeout_id = tfd->set_timer(1000*peer_connect_timeout, false, [this, peer_fd](int timer_id)
|
cl->connect_timeout_id = tfd->set_timer(1000*peer_connect_timeout, false, [this, client_id](int timer_id)
|
||||||
{
|
{
|
||||||
osd_num_t peer_osd = clients.at(peer_fd)->osd_num;
|
osd_num_t peer_osd = clients.at(client_id)->osd_num;
|
||||||
stop_client(peer_fd, true);
|
stop_client(client_id);
|
||||||
on_connect_peer(peer_osd, -EPIPE);
|
on_connect_peer(peer_osd, -EPIPE, 0);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -522,7 +532,7 @@ void osd_messenger_t::try_connect_peer_tcp(osd_num_t peer_osd, const char *peer_
|
|||||||
|
|
||||||
void osd_messenger_t::handle_connect_epoll(int peer_fd)
|
void osd_messenger_t::handle_connect_epoll(int peer_fd)
|
||||||
{
|
{
|
||||||
auto cl = clients[peer_fd];
|
auto cl = clients_by_fd.at(peer_fd);
|
||||||
if (cl->connect_timeout_id >= 0)
|
if (cl->connect_timeout_id >= 0)
|
||||||
{
|
{
|
||||||
tfd->clear_timer(cl->connect_timeout_id);
|
tfd->clear_timer(cl->connect_timeout_id);
|
||||||
@@ -537,8 +547,8 @@ void osd_messenger_t::handle_connect_epoll(int peer_fd)
|
|||||||
}
|
}
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
stop_client(peer_fd, true);
|
stop_client(cl->client_id);
|
||||||
on_connect_peer(peer_osd, -result);
|
on_connect_peer(peer_osd, -result, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int one = 1;
|
int one = 1;
|
||||||
@@ -555,23 +565,23 @@ void osd_messenger_t::handle_connect_epoll(int peer_fd)
|
|||||||
void osd_messenger_t::handle_peer_epoll(int peer_fd, int epoll_events)
|
void osd_messenger_t::handle_peer_epoll(int peer_fd, int epoll_events)
|
||||||
{
|
{
|
||||||
// Mark client as ready (i.e. some data is available)
|
// Mark client as ready (i.e. some data is available)
|
||||||
|
auto cl = clients_by_fd.at(peer_fd);
|
||||||
if (epoll_events & EPOLLRDHUP)
|
if (epoll_events & EPOLLRDHUP)
|
||||||
{
|
{
|
||||||
// Stop client
|
// Stop client
|
||||||
if (log_level > 0)
|
if (log_level > 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[OSD %ju] client %d disconnected\n", this->osd_num, peer_fd);
|
fprintf(stderr, "[OSD %ju] client %ju disconnected\n", this->osd_num, cl->client_id);
|
||||||
}
|
}
|
||||||
stop_client(peer_fd, true);
|
stop_client(cl->client_id);
|
||||||
}
|
}
|
||||||
else if (epoll_events & EPOLLIN)
|
else if (epoll_events & EPOLLIN)
|
||||||
{
|
{
|
||||||
// Mark client as ready (i.e. some data is available)
|
// Mark client as ready (i.e. some data is available)
|
||||||
auto cl = clients[peer_fd];
|
|
||||||
cl->read_ready++;
|
cl->read_ready++;
|
||||||
if (cl->read_ready == 1)
|
if (cl->read_ready == 1)
|
||||||
{
|
{
|
||||||
read_ready_clients.push_back(cl->peer_fd);
|
read_ready_clients.push_back(cl->client_id);
|
||||||
if (ringloop)
|
if (ringloop)
|
||||||
ringloop->wakeup();
|
ringloop->wakeup();
|
||||||
else
|
else
|
||||||
@@ -580,13 +590,13 @@ void osd_messenger_t::handle_peer_epoll(int peer_fd, int epoll_events)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_messenger_t::on_connect_peer(osd_num_t peer_osd, int peer_fd)
|
void osd_messenger_t::on_connect_peer(osd_num_t peer_osd, int errcode, uint64_t client_id)
|
||||||
{
|
{
|
||||||
auto & wp = wanted_peers.at(peer_osd);
|
auto & wp = wanted_peers.at(peer_osd);
|
||||||
wp.connecting = false;
|
wp.connecting = false;
|
||||||
if (peer_fd < 0)
|
if (errcode < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to connect to peer OSD %ju address %s port %d: %s\n", peer_osd, wp.cur_addr.c_str(), wp.cur_port, strerror(-peer_fd));
|
fprintf(stderr, "Failed to connect to peer OSD %ju address %s port %d: %s\n", peer_osd, wp.cur_addr.c_str(), wp.cur_port, strerror(-errcode));
|
||||||
if (wp.address_changed)
|
if (wp.address_changed)
|
||||||
{
|
{
|
||||||
wp.address_changed = false;
|
wp.address_changed = false;
|
||||||
@@ -613,7 +623,7 @@ void osd_messenger_t::on_connect_peer(osd_num_t peer_osd, int peer_fd)
|
|||||||
}
|
}
|
||||||
if (log_level > 0)
|
if (log_level > 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[OSD %ju] Connected with peer OSD %ju (client %d)\n", osd_num, peer_osd, peer_fd);
|
fprintf(stderr, "[OSD %ju] Connected with peer OSD %ju (client %ju)\n", osd_num, peer_osd, client_id);
|
||||||
}
|
}
|
||||||
wanted_peers.erase(peer_osd);
|
wanted_peers.erase(peer_osd);
|
||||||
repeer_pgs(peer_osd);
|
repeer_pgs(peer_osd);
|
||||||
@@ -623,7 +633,7 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
|
|||||||
{
|
{
|
||||||
osd_op_t *op = new osd_op_t();
|
osd_op_t *op = new osd_op_t();
|
||||||
op->op_type = OSD_OP_OUT;
|
op->op_type = OSD_OP_OUT;
|
||||||
op->peer_fd = cl->peer_fd;
|
op->client_id = cl->client_id;
|
||||||
op->req = (osd_any_op_t){
|
op->req = (osd_any_op_t){
|
||||||
.show_conf = {
|
.show_conf = {
|
||||||
.header = {
|
.header = {
|
||||||
@@ -647,7 +657,7 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
|
|||||||
if (!selected_ctx)
|
if (!selected_ctx)
|
||||||
{
|
{
|
||||||
if (log_level > 0)
|
if (log_level > 0)
|
||||||
fprintf(stderr, "No RDMA context for OSD %ju connection (peer %d), using only TCP\n", cl->osd_num, cl->peer_fd);
|
fprintf(stderr, "No RDMA context for OSD %ju connection (client %ju), using only TCP\n", cl->osd_num, cl->client_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -708,8 +718,8 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
|
|||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
osd_num_t peer_osd = cl->osd_num;
|
osd_num_t peer_osd = cl->osd_num;
|
||||||
stop_client(op->peer_fd);
|
stop_client(op->client_id);
|
||||||
on_connect_peer(peer_osd, -EINVAL);
|
on_connect_peer(peer_osd, -EINVAL, 0);
|
||||||
delete op;
|
delete op;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -744,8 +754,8 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
osd_peer_fds[cl->osd_num] = cl->peer_fd;
|
osd_peers[cl->osd_num] = cl;
|
||||||
on_connect_peer(cl->osd_num, cl->peer_fd);
|
on_connect_peer(cl->osd_num, 0, cl->client_id);
|
||||||
delete op;
|
delete op;
|
||||||
};
|
};
|
||||||
outbox_push(op);
|
outbox_push(op);
|
||||||
@@ -760,13 +770,16 @@ void osd_messenger_t::accept_connections(int listen_fd)
|
|||||||
while ((peer_fd = accept(listen_fd, (sockaddr*)&addr, &peer_addr_size)) >= 0)
|
while ((peer_fd = accept(listen_fd, (sockaddr*)&addr, &peer_addr_size)) >= 0)
|
||||||
{
|
{
|
||||||
assert(peer_fd != 0);
|
assert(peer_fd != 0);
|
||||||
fprintf(stderr, "[OSD %ju] new client %d: connection from %s\n", this->osd_num, peer_fd,
|
const uint64_t client_id = next_client_id++;
|
||||||
|
fprintf(stderr, "[OSD %ju] new client %ju (FD %d): connection from %s\n", this->osd_num, client_id, peer_fd,
|
||||||
addr_to_string(addr).c_str());
|
addr_to_string(addr).c_str());
|
||||||
fcntl(peer_fd, F_SETFL, fcntl(peer_fd, F_GETFL, 0) | O_NONBLOCK);
|
fcntl(peer_fd, F_SETFL, fcntl(peer_fd, F_GETFL, 0) | O_NONBLOCK);
|
||||||
int one = 1;
|
int one = 1;
|
||||||
setsockopt(peer_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
|
setsockopt(peer_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
|
||||||
auto cl = new osd_client_t();
|
auto cl = new osd_client_t();
|
||||||
clients[peer_fd] = cl;
|
cl->client_id = client_id;
|
||||||
|
clients[cl->client_id] = cl;
|
||||||
|
clients_by_fd[peer_fd] = cl;
|
||||||
cl->is_incoming = true;
|
cl->is_incoming = true;
|
||||||
cl->peer_addr = addr;
|
cl->peer_addr = addr;
|
||||||
cl->peer_addr = addr;
|
cl->peer_addr = addr;
|
||||||
|
|||||||
+16
-12
@@ -12,6 +12,7 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../util/robin_hood.h"
|
||||||
#include "malloc_or_die.h"
|
#include "malloc_or_die.h"
|
||||||
#include "json11/json11.hpp"
|
#include "json11/json11.hpp"
|
||||||
#include "msgr_op.h"
|
#include "msgr_op.h"
|
||||||
@@ -50,6 +51,7 @@ struct msgr_rdma_context_t;
|
|||||||
|
|
||||||
struct osd_client_t
|
struct osd_client_t
|
||||||
{
|
{
|
||||||
|
uint64_t client_id = 0;
|
||||||
int refs = 0;
|
int refs = 0;
|
||||||
|
|
||||||
sockaddr_storage peer_addr = {};
|
sockaddr_storage peer_addr = {};
|
||||||
@@ -85,7 +87,7 @@ struct osd_client_t
|
|||||||
std::vector<osd_op_t*> received_ops;
|
std::vector<osd_op_t*> received_ops;
|
||||||
|
|
||||||
// Outbound operations
|
// Outbound operations
|
||||||
std::map<uint64_t, osd_op_t*> sent_ops;
|
robin_hood::unordered_flat_map<uint64_t, osd_op_t*> sent_ops;
|
||||||
uint64_t send_op_id = 0;
|
uint64_t send_op_id = 0;
|
||||||
|
|
||||||
// PGs dirtied by this client's primary-writes
|
// PGs dirtied by this client's primary-writes
|
||||||
@@ -201,13 +203,13 @@ protected:
|
|||||||
uint64_t rdma_max_sge = 0, rdma_max_send = 0, rdma_max_recv = 0;
|
uint64_t rdma_max_sge = 0, rdma_max_send = 0, rdma_max_recv = 0;
|
||||||
uint64_t rdma_max_msg = 0;
|
uint64_t rdma_max_msg = 0;
|
||||||
rdma_event_channel *rdmacm_evch = NULL;
|
rdma_event_channel *rdmacm_evch = NULL;
|
||||||
std::map<rdma_cm_id*, osd_client_t*> rdmacm_connections;
|
robin_hood::unordered_flat_map<rdma_cm_id*, osd_client_t*> rdmacm_connections;
|
||||||
std::map<rdma_cm_id*, rdmacm_connecting_t*> rdmacm_connecting;
|
robin_hood::unordered_flat_map<rdma_cm_id*, rdmacm_connecting_t*> rdmacm_connecting;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<msgr_iothread_t*> iothreads;
|
std::vector<msgr_iothread_t*> iothreads;
|
||||||
std::vector<int> read_ready_clients;
|
std::vector<uint64_t> read_ready_clients;
|
||||||
std::vector<int> write_ready_clients;
|
std::vector<uint64_t> write_ready_clients;
|
||||||
// We don't use ringloop->set_immediate here because we may have no ringloop in client :)
|
// We don't use ringloop->set_immediate here because we may have no ringloop in client :)
|
||||||
std::deque<osd_op_t*> set_immediate_ops;
|
std::deque<osd_op_t*> set_immediate_ops;
|
||||||
|
|
||||||
@@ -216,10 +218,12 @@ public:
|
|||||||
ring_loop_t *ringloop = NULL;
|
ring_loop_t *ringloop = NULL;
|
||||||
bool has_sendmsg_zc = false;
|
bool has_sendmsg_zc = false;
|
||||||
// osd_num_t is only for logging and asserts
|
// osd_num_t is only for logging and asserts
|
||||||
|
uint64_t next_client_id = 1;
|
||||||
osd_num_t osd_num;
|
osd_num_t osd_num;
|
||||||
std::map<int, osd_client_t*> clients;
|
robin_hood::unordered_flat_map<uint64_t, osd_client_t*> clients;
|
||||||
std::map<osd_num_t, osd_wanted_peer_t> wanted_peers;
|
robin_hood::unordered_flat_map<uint64_t, osd_client_t*> osd_peers;
|
||||||
std::map<uint64_t, int> osd_peer_fds;
|
robin_hood::unordered_flat_map<int, osd_client_t*> clients_by_fd;
|
||||||
|
robin_hood::unordered_flat_map<osd_num_t, osd_wanted_peer_t> wanted_peers;
|
||||||
std::vector<std::string> osd_networks;
|
std::vector<std::string> osd_networks;
|
||||||
std::vector<addr_mask_t> osd_network_masks;
|
std::vector<addr_mask_t> osd_network_masks;
|
||||||
std::vector<std::string> osd_cluster_networks;
|
std::vector<std::string> osd_cluster_networks;
|
||||||
@@ -232,7 +236,8 @@ public:
|
|||||||
void init();
|
void init();
|
||||||
void parse_config(const json11::Json & config);
|
void parse_config(const json11::Json & config);
|
||||||
void connect_peer(uint64_t osd_num, json11::Json peer_state);
|
void connect_peer(uint64_t osd_num, json11::Json peer_state);
|
||||||
void stop_client(int peer_fd, bool force = false, bool force_delete = false);
|
void stop_client(uint64_t client_id, bool force_delete = false);
|
||||||
|
void destroy_client(osd_client_t *cl);
|
||||||
void outbox_push(osd_op_t *cur_op);
|
void outbox_push(osd_op_t *cur_op);
|
||||||
std::function<void(osd_op_t*)> exec_op;
|
std::function<void(osd_op_t*)> exec_op;
|
||||||
std::function<void(osd_num_t)> repeer_pgs;
|
std::function<void(osd_num_t)> repeer_pgs;
|
||||||
@@ -251,7 +256,7 @@ public:
|
|||||||
|
|
||||||
#ifdef WITH_RDMA
|
#ifdef WITH_RDMA
|
||||||
bool is_rdma_enabled();
|
bool is_rdma_enabled();
|
||||||
bool connect_rdma(int peer_fd, std::string rdma_address, uint64_t client_max_msg);
|
bool connect_rdma(uint64_t client_id, std::string rdma_address, uint64_t client_max_msg);
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_RDMACM
|
#ifdef WITH_RDMACM
|
||||||
bool is_use_rdmacm();
|
bool is_use_rdmacm();
|
||||||
@@ -267,7 +272,7 @@ protected:
|
|||||||
void try_connect_peer_tcp(osd_num_t peer_osd, const char *peer_host, int peer_port);
|
void try_connect_peer_tcp(osd_num_t peer_osd, const char *peer_host, int peer_port);
|
||||||
void handle_peer_epoll(int peer_fd, int epoll_events);
|
void handle_peer_epoll(int peer_fd, int epoll_events);
|
||||||
void handle_connect_epoll(int peer_fd);
|
void handle_connect_epoll(int peer_fd);
|
||||||
void on_connect_peer(osd_num_t peer_osd, int peer_fd);
|
void on_connect_peer(osd_num_t peer_osd, int errcode, uint64_t client_id);
|
||||||
void check_peer_config(osd_client_t *cl);
|
void check_peer_config(osd_client_t *cl);
|
||||||
void cancel_osd_ops(osd_client_t *cl);
|
void cancel_osd_ops(osd_client_t *cl);
|
||||||
void cancel_op(osd_op_t *op);
|
void cancel_op(osd_op_t *op);
|
||||||
@@ -282,7 +287,6 @@ protected:
|
|||||||
bool handle_reply_hdr(osd_client_t *cl);
|
bool handle_reply_hdr(osd_client_t *cl);
|
||||||
void handle_reply_ready(osd_op_t *op);
|
void handle_reply_ready(osd_op_t *op);
|
||||||
void handle_immediate_ops();
|
void handle_immediate_ops();
|
||||||
void clear_immediate_ops(int peer_fd);
|
|
||||||
|
|
||||||
#ifdef WITH_RDMA
|
#ifdef WITH_RDMA
|
||||||
void try_send_rdma(osd_client_t *cl);
|
void try_send_rdma(osd_client_t *cl);
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ struct __attribute__((visibility("default"))) osd_op_t
|
|||||||
{
|
{
|
||||||
timespec tv_begin = { 0 }, tv_end = { 0 };
|
timespec tv_begin = { 0 }, tv_end = { 0 };
|
||||||
uint64_t op_type = OSD_OP_IN;
|
uint64_t op_type = OSD_OP_IN;
|
||||||
int peer_fd;
|
uint64_t client_id = 0;
|
||||||
osd_any_op_t req;
|
osd_any_op_t req;
|
||||||
osd_any_reply_t reply;
|
osd_any_reply_t reply;
|
||||||
blockstore_op_t *bs_op = NULL;
|
blockstore_op_t *bs_op = NULL;
|
||||||
|
|||||||
+24
-14
@@ -187,6 +187,8 @@ std::vector<msgr_rdma_context_t*> msgr_rdma_context_t::create_all(const std::vec
|
|||||||
ibv_device **raw_dev_list = NULL;
|
ibv_device **raw_dev_list = NULL;
|
||||||
ibv_device **dev_list = NULL;
|
ibv_device **dev_list = NULL;
|
||||||
ibv_device *single_list[2] = {};
|
ibv_device *single_list[2] = {};
|
||||||
|
int up_ports = 0;
|
||||||
|
int single_port_num = 0;
|
||||||
|
|
||||||
raw_dev_list = dev_list = ibv_get_device_list(NULL);
|
raw_dev_list = dev_list = ibv_get_device_list(NULL);
|
||||||
if (!dev_list || !*dev_list)
|
if (!dev_list || !*dev_list)
|
||||||
@@ -221,6 +223,7 @@ std::vector<msgr_rdma_context_t*> msgr_rdma_context_t::create_all(const std::vec
|
|||||||
dev_list = single_list;
|
dev_list = single_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
for (int i = 0; dev_list[i]; ++i)
|
for (int i = 0; dev_list[i]; ++i)
|
||||||
{
|
{
|
||||||
auto dev = dev_list[i];
|
auto dev = dev_list[i];
|
||||||
@@ -258,6 +261,9 @@ std::vector<msgr_rdma_context_t*> msgr_rdma_context_t::create_all(const std::vec
|
|||||||
fprintf(stderr, "RDMA device %s port %d GID %d does not exist\n", ibv_get_device_name(dev), port_num, sel_gid_index);
|
fprintf(stderr, "RDMA device %s port %d GID %d does not exist\n", ibv_get_device_name(dev), port_num, sel_gid_index);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
up_ports++;
|
||||||
|
single_port_num = port_num;
|
||||||
|
single_list[0] = dev;
|
||||||
uint32_t port_mtu = sel_mtu ? sel_mtu : ibv_mtu_to_bytes(portinfo.active_mtu);
|
uint32_t port_mtu = sel_mtu ? sel_mtu : ibv_mtu_to_bytes(portinfo.active_mtu);
|
||||||
#ifdef IBV_ADVISE_MR_ADVICE_PREFETCH_NO_FAULT
|
#ifdef IBV_ADVISE_MR_ADVICE_PREFETCH_NO_FAULT
|
||||||
if (sel_gid_index < 0)
|
if (sel_gid_index < 0)
|
||||||
@@ -298,6 +304,14 @@ cleanup_dev:
|
|||||||
ibv_close_device(context);
|
ibv_close_device(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ret.size() && up_ports == 1 && dev_list != single_list)
|
||||||
|
{
|
||||||
|
// Auto-select the only available device/port if there is only one
|
||||||
|
dev_list = single_list;
|
||||||
|
sel_port_num = single_port_num;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (raw_dev_list)
|
if (raw_dev_list)
|
||||||
ibv_free_device_list(raw_dev_list);
|
ibv_free_device_list(raw_dev_list);
|
||||||
@@ -493,7 +507,7 @@ int msgr_rdma_connection_t::connect(msgr_rdma_address_t *dest)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool osd_messenger_t::connect_rdma(int peer_fd, std::string rdma_address, uint64_t client_max_msg)
|
bool osd_messenger_t::connect_rdma(uint64_t client_id, std::string rdma_address, uint64_t client_max_msg)
|
||||||
{
|
{
|
||||||
// Try to connect to the peer using RDMA
|
// Try to connect to the peer using RDMA
|
||||||
msgr_rdma_address_t addr;
|
msgr_rdma_address_t addr;
|
||||||
@@ -503,12 +517,12 @@ bool osd_messenger_t::connect_rdma(int peer_fd, std::string rdma_address, uint64
|
|||||||
{
|
{
|
||||||
client_max_msg = rdma_max_msg;
|
client_max_msg = rdma_max_msg;
|
||||||
}
|
}
|
||||||
auto cl = clients.at(peer_fd);
|
auto cl = clients.at(client_id);
|
||||||
msgr_rdma_context_t *selected_ctx = choose_rdma_context(cl);
|
msgr_rdma_context_t *selected_ctx = choose_rdma_context(cl);
|
||||||
if (!selected_ctx)
|
if (!selected_ctx)
|
||||||
{
|
{
|
||||||
if (log_level > 0)
|
if (log_level > 0)
|
||||||
fprintf(stderr, "No RDMA context for peer %d, using only TCP\n", cl->peer_fd);
|
fprintf(stderr, "No RDMA context for peer %ju, using only TCP\n", client_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
msgr_rdma_connection_t *rdma_conn = msgr_rdma_connection_t::create(selected_ctx, rdma_max_send, rdma_max_recv, rdma_max_sge, client_max_msg);
|
msgr_rdma_connection_t *rdma_conn = msgr_rdma_connection_t::create(selected_ctx, rdma_max_send, rdma_max_recv, rdma_max_sge, client_max_msg);
|
||||||
@@ -519,14 +533,13 @@ bool osd_messenger_t::connect_rdma(int peer_fd, std::string rdma_address, uint64
|
|||||||
{
|
{
|
||||||
delete rdma_conn;
|
delete rdma_conn;
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr, "Failed to connect RDMA queue pair to %s (client %d)\n",
|
stderr, "Failed to connect RDMA queue pair to %s (client %ju)\n",
|
||||||
addr.to_string().c_str(), peer_fd
|
addr.to_string().c_str(), client_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Remember connection, but switch to RDMA only after sending the configuration response
|
// Remember connection, but switch to RDMA only after sending the configuration response
|
||||||
auto cl = clients.at(peer_fd);
|
|
||||||
cl->rdma_conn = rdma_conn;
|
cl->rdma_conn = rdma_conn;
|
||||||
cl->peer_state = PEER_RDMA_CONNECTING;
|
cl->peer_state = PEER_RDMA_CONNECTING;
|
||||||
return true;
|
return true;
|
||||||
@@ -540,7 +553,7 @@ static void try_send_rdma_wr(osd_client_t *cl, ibv_sge *sge, int op_sge)
|
|||||||
{
|
{
|
||||||
ibv_send_wr *bad_wr = NULL;
|
ibv_send_wr *bad_wr = NULL;
|
||||||
ibv_send_wr wr = {
|
ibv_send_wr wr = {
|
||||||
.wr_id = (uint64_t)(cl->peer_fd*2+1),
|
.wr_id = cl->client_id,
|
||||||
.sg_list = sge,
|
.sg_list = sge,
|
||||||
.num_sge = op_sge,
|
.num_sge = op_sge,
|
||||||
.opcode = IBV_WR_SEND,
|
.opcode = IBV_WR_SEND,
|
||||||
@@ -631,7 +644,7 @@ static void try_recv_rdma_wr(osd_client_t *cl, void *buf)
|
|||||||
};
|
};
|
||||||
ibv_recv_wr *bad_wr = NULL;
|
ibv_recv_wr *bad_wr = NULL;
|
||||||
ibv_recv_wr wr = {
|
ibv_recv_wr wr = {
|
||||||
.wr_id = (uint64_t)(cl->peer_fd*2),
|
.wr_id = cl->client_id,
|
||||||
.sg_list = &sge,
|
.sg_list = &sge,
|
||||||
.num_sge = 1,
|
.num_sge = 1,
|
||||||
};
|
};
|
||||||
@@ -688,8 +701,8 @@ void osd_messenger_t::handle_rdma_events(msgr_rdma_context_t *rdma_context)
|
|||||||
event_count = ibv_poll_cq(rdma_context->cq, RDMA_EVENTS_AT_ONCE, wc);
|
event_count = ibv_poll_cq(rdma_context->cq, RDMA_EVENTS_AT_ONCE, wc);
|
||||||
for (int i = 0; i < event_count; i++)
|
for (int i = 0; i < event_count; i++)
|
||||||
{
|
{
|
||||||
int client_id = wc[i].wr_id >> 1;
|
uint64_t client_id = wc[i].wr_id;
|
||||||
bool is_send = wc[i].wr_id & 1;
|
bool is_send = wc[i].opcode == IBV_WC_SEND;
|
||||||
auto cl_it = clients.find(client_id);
|
auto cl_it = clients.find(client_id);
|
||||||
if (cl_it == clients.end())
|
if (cl_it == clients.end())
|
||||||
{
|
{
|
||||||
@@ -703,14 +716,13 @@ void osd_messenger_t::handle_rdma_events(msgr_rdma_context_t *rdma_context)
|
|||||||
auto rc = cl->rdma_conn;
|
auto rc = cl->rdma_conn;
|
||||||
if (wc[i].status != IBV_WC_SUCCESS)
|
if (wc[i].status != IBV_WC_SUCCESS)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "RDMA work request failed for client %d", client_id);
|
fprintf(stderr, "RDMA work request failed for client %ju", client_id);
|
||||||
if (cl->osd_num)
|
if (cl->osd_num)
|
||||||
{
|
{
|
||||||
fprintf(stderr, " (OSD %ju)", cl->osd_num);
|
fprintf(stderr, " (OSD %ju)", cl->osd_num);
|
||||||
}
|
}
|
||||||
fprintf(stderr, " with status: %s, stopping client\n", ibv_wc_status_str(wc[i].status));
|
fprintf(stderr, " with status: %s, stopping client\n", ibv_wc_status_str(wc[i].status));
|
||||||
stop_client(client_id);
|
stop_client(client_id);
|
||||||
clear_immediate_ops(client_id);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!is_send)
|
if (!is_send)
|
||||||
@@ -721,8 +733,6 @@ void osd_messenger_t::handle_rdma_events(msgr_rdma_context_t *rdma_context)
|
|||||||
rc->cur_recv--;
|
rc->cur_recv--;
|
||||||
if (!handle_read_buffer(cl, rc->recv_buffers[rc->next_recv_buf], wc[i].byte_len))
|
if (!handle_read_buffer(cl, rc->recv_buffers[rc->next_recv_buf], wc[i].byte_len))
|
||||||
{
|
{
|
||||||
// handle_read_buffer may stop the client
|
|
||||||
clear_immediate_ops(client_id);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try_recv_rdma_wr(cl, rc->recv_buffers[rc->next_recv_buf]);
|
try_recv_rdma_wr(cl, rc->recv_buffers[rc->next_recv_buf]);
|
||||||
|
|||||||
+12
-32
@@ -11,7 +11,7 @@
|
|||||||
struct rdmacm_connecting_t
|
struct rdmacm_connecting_t
|
||||||
{
|
{
|
||||||
rdma_cm_id *cmid = NULL;
|
rdma_cm_id *cmid = NULL;
|
||||||
int peer_fd = -1;
|
uint64_t client_id = 0;
|
||||||
osd_num_t peer_osd = 0;
|
osd_num_t peer_osd = 0;
|
||||||
std::string addr;
|
std::string addr;
|
||||||
sockaddr_storage parsed_addr = {};
|
sockaddr_storage parsed_addr = {};
|
||||||
@@ -117,9 +117,9 @@ void osd_messenger_t::handle_rdmacm_events()
|
|||||||
auto cli_it = rdmacm_connections.find(ev->id);
|
auto cli_it = rdmacm_connections.find(ev->id);
|
||||||
if (cli_it != rdmacm_connections.end())
|
if (cli_it != rdmacm_connections.end())
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Received %s event for peer %d, closing connection\n",
|
fprintf(stderr, "Received %s event for client %ju, closing connection\n",
|
||||||
event_type_name, cli_it->second->peer_fd);
|
event_type_name, cli_it->second->client_id);
|
||||||
stop_client(cli_it->second->peer_fd);
|
stop_client(cli_it->second->client_id);
|
||||||
}
|
}
|
||||||
else if (rdmacm_connecting.find(ev->id) != rdmacm_connecting.end())
|
else if (rdmacm_connecting.find(ev->id) != rdmacm_connecting.end())
|
||||||
{
|
{
|
||||||
@@ -265,14 +265,6 @@ msgr_rdma_context_t* osd_messenger_t::rdmacm_create_qp(rdma_cm_id *cmid)
|
|||||||
|
|
||||||
void osd_messenger_t::rdmacm_accept(rdma_cm_event *ev)
|
void osd_messenger_t::rdmacm_accept(rdma_cm_event *ev)
|
||||||
{
|
{
|
||||||
// Make a fake FD (FIXME: do not use FDs for identifying clients!)
|
|
||||||
int fake_fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (fake_fd < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed to allocate a fake socket for RDMA-CM client: %s (code %d)\n", strerror(errno), errno);
|
|
||||||
rdma_destroy_id(ev->id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto rdma_context = rdmacm_create_qp(ev->id);
|
auto rdma_context = rdmacm_create_qp(ev->id);
|
||||||
if (!rdma_context)
|
if (!rdma_context)
|
||||||
{
|
{
|
||||||
@@ -297,12 +289,12 @@ void osd_messenger_t::rdmacm_accept(rdma_cm_event *ev)
|
|||||||
// Wait for RDMA_CM_ESTABLISHED, and enable the connection only after it
|
// Wait for RDMA_CM_ESTABLISHED, and enable the connection only after it
|
||||||
auto conn = new rdmacm_connecting_t;
|
auto conn = new rdmacm_connecting_t;
|
||||||
conn->cmid = ev->id;
|
conn->cmid = ev->id;
|
||||||
conn->peer_fd = fake_fd;
|
conn->client_id = next_client_id++;
|
||||||
conn->parsed_addr = *(sockaddr_storage*)rdma_get_peer_addr(ev->id);
|
conn->parsed_addr = *(sockaddr_storage*)rdma_get_peer_addr(ev->id);
|
||||||
conn->rdma_context = rdma_context;
|
conn->rdma_context = rdma_context;
|
||||||
rdmacm_set_conn_timeout(conn);
|
rdmacm_set_conn_timeout(conn);
|
||||||
rdmacm_connecting[ev->id] = conn;
|
rdmacm_connecting[ev->id] = conn;
|
||||||
fprintf(stderr, "[OSD %ju] new client %d: connection from %s via RDMA-CM\n", this->osd_num, conn->peer_fd,
|
fprintf(stderr, "[OSD %ju] new client %ju: connection from %s via RDMA-CM\n", this->osd_num, conn->client_id,
|
||||||
addr_to_string(conn->parsed_addr).c_str());
|
addr_to_string(conn->parsed_addr).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,8 +324,6 @@ void osd_messenger_t::rdmacm_on_connect_peer_error(rdma_cm_id *cmid, int res)
|
|||||||
auto peer_osd = conn->peer_osd;
|
auto peer_osd = conn->peer_osd;
|
||||||
if (conn->timeout_id >= 0)
|
if (conn->timeout_id >= 0)
|
||||||
tfd->clear_timer(conn->timeout_id);
|
tfd->clear_timer(conn->timeout_id);
|
||||||
if (conn->peer_fd >= 0)
|
|
||||||
close(conn->peer_fd);
|
|
||||||
if (conn->rdma_context)
|
if (conn->rdma_context)
|
||||||
conn->rdma_context->reserve_cqe(-rdma_max_send-rdma_max_recv);
|
conn->rdma_context->reserve_cqe(-rdma_max_send-rdma_max_recv);
|
||||||
if (conn->cmid)
|
if (conn->cmid)
|
||||||
@@ -354,7 +344,7 @@ void osd_messenger_t::rdmacm_on_connect_peer_error(rdma_cm_id *cmid, int res)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TCP is disabled
|
// TCP is disabled
|
||||||
on_connect_peer(peer_osd, res == 0 ? -EINVAL : (res > 0 ? -res : res));
|
on_connect_peer(peer_osd, res == 0 ? -EINVAL : (res > 0 ? -res : res), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,7 +355,7 @@ void osd_messenger_t::rdmacm_try_connect_peer(uint64_t peer_osd, const std::stri
|
|||||||
if (!string_to_addr(addr, false, rdmacm_port, &sa))
|
if (!string_to_addr(addr, false, rdmacm_port, &sa))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Address %s is invalid\n", addr.c_str());
|
fprintf(stderr, "Address %s is invalid\n", addr.c_str());
|
||||||
on_connect_peer(peer_osd, -EINVAL);
|
on_connect_peer(peer_osd, -EINVAL, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rdma_cm_id *cmid = NULL;
|
rdma_cm_id *cmid = NULL;
|
||||||
@@ -376,17 +366,7 @@ void osd_messenger_t::rdmacm_try_connect_peer(uint64_t peer_osd, const std::stri
|
|||||||
if (!disable_tcp)
|
if (!disable_tcp)
|
||||||
try_connect_peer_tcp(peer_osd, addr.c_str(), fallback_tcp_port);
|
try_connect_peer_tcp(peer_osd, addr.c_str(), fallback_tcp_port);
|
||||||
else
|
else
|
||||||
on_connect_peer(peer_osd, res);
|
on_connect_peer(peer_osd, res, 0);
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Make a fake FD (FIXME: do not use FDs for identifying clients!)
|
|
||||||
int fake_fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (fake_fd < 0)
|
|
||||||
{
|
|
||||||
int res = -errno;
|
|
||||||
rdma_destroy_id(cmid);
|
|
||||||
// Can't create socket, pointless to try TCP
|
|
||||||
on_connect_peer(peer_osd, res);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (log_level > 0)
|
if (log_level > 0)
|
||||||
@@ -394,7 +374,7 @@ void osd_messenger_t::rdmacm_try_connect_peer(uint64_t peer_osd, const std::stri
|
|||||||
auto conn = new rdmacm_connecting_t;
|
auto conn = new rdmacm_connecting_t;
|
||||||
rdmacm_connecting[cmid] = conn;
|
rdmacm_connecting[cmid] = conn;
|
||||||
conn->cmid = cmid;
|
conn->cmid = cmid;
|
||||||
conn->peer_fd = fake_fd;
|
conn->client_id = next_client_id++;
|
||||||
conn->peer_osd = peer_osd;
|
conn->peer_osd = peer_osd;
|
||||||
conn->addr = addr;
|
conn->addr = addr;
|
||||||
conn->parsed_addr = sa;
|
conn->parsed_addr = sa;
|
||||||
@@ -511,13 +491,13 @@ void osd_messenger_t::rdmacm_established(rdma_cm_event *ev)
|
|||||||
auto cl = new osd_client_t();
|
auto cl = new osd_client_t();
|
||||||
cl->peer_addr = conn->parsed_addr;
|
cl->peer_addr = conn->parsed_addr;
|
||||||
cl->peer_port = conn->rdmacm_port;
|
cl->peer_port = conn->rdmacm_port;
|
||||||
cl->peer_fd = conn->peer_fd;
|
cl->client_id = conn->client_id;
|
||||||
cl->peer_state = PEER_RDMA;
|
cl->peer_state = PEER_RDMA;
|
||||||
cl->connect_timeout_id = -1;
|
cl->connect_timeout_id = -1;
|
||||||
cl->osd_num = peer_osd;
|
cl->osd_num = peer_osd;
|
||||||
cl->in_buf = malloc_or_die(receive_buffer_size);
|
cl->in_buf = malloc_or_die(receive_buffer_size);
|
||||||
cl->rdma_conn = rc;
|
cl->rdma_conn = rc;
|
||||||
clients[conn->peer_fd] = cl;
|
clients[conn->client_id] = cl;
|
||||||
if (conn->timeout_id >= 0)
|
if (conn->timeout_id >= 0)
|
||||||
{
|
{
|
||||||
tfd->clear_timer(conn->timeout_id);
|
tfd->clear_timer(conn->timeout_id);
|
||||||
|
|||||||
+26
-45
@@ -7,10 +7,10 @@ void osd_messenger_t::read_requests()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < read_ready_clients.size(); i++)
|
for (int i = 0; i < read_ready_clients.size(); i++)
|
||||||
{
|
{
|
||||||
int peer_fd = read_ready_clients[i];
|
uint64_t client_id = read_ready_clients[i];
|
||||||
auto cl_it = clients.find(peer_fd);
|
auto cl_it = clients.find(client_id);
|
||||||
if (cl_it == clients.end() || !cl_it->second || cl_it->second->read_msg.msg_iovlen ||
|
if (cl_it == clients.end() || !cl_it->second || cl_it->second->read_msg.msg_iovlen ||
|
||||||
cl_it->second->peer_state == PEER_RDMA || cl_it->second->peer_state == PEER_RDMA_CONNECTING)
|
cl_it->second->peer_state != PEER_CONNECTED)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ void osd_messenger_t::read_requests()
|
|||||||
cl->refs++;
|
cl->refs++;
|
||||||
if (ringloop && !use_sync_send_recv)
|
if (ringloop && !use_sync_send_recv)
|
||||||
{
|
{
|
||||||
auto iothread = iothreads.size() ? iothreads[peer_fd % iothreads.size()] : NULL;
|
auto iothread = iothreads.size() ? iothreads[cl->peer_fd % iothreads.size()] : NULL;
|
||||||
io_uring_sqe sqe_local;
|
io_uring_sqe sqe_local;
|
||||||
ring_data_t data_local;
|
ring_data_t data_local;
|
||||||
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
|
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
|
||||||
@@ -50,7 +50,7 @@ void osd_messenger_t::read_requests()
|
|||||||
}
|
}
|
||||||
ring_data_t* data = ((ring_data_t*)sqe->user_data);
|
ring_data_t* data = ((ring_data_t*)sqe->user_data);
|
||||||
data->callback = [this, cl](ring_data_t *data) { handle_read(data->res, cl); };
|
data->callback = [this, cl](ring_data_t *data) { handle_read(data->res, cl); };
|
||||||
io_uring_prep_recvmsg(sqe, peer_fd, &cl->read_msg, 0);
|
io_uring_prep_recvmsg(sqe, cl->peer_fd, &cl->read_msg, 0);
|
||||||
if (iothread)
|
if (iothread)
|
||||||
{
|
{
|
||||||
iothread->add_sqe(sqe_local);
|
iothread->add_sqe(sqe_local);
|
||||||
@@ -58,7 +58,7 @@ void osd_messenger_t::read_requests()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int result = recvmsg(peer_fd, &cl->read_msg, 0);
|
int result = recvmsg(cl->peer_fd, &cl->read_msg, 0);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
result = -errno;
|
result = -errno;
|
||||||
@@ -73,7 +73,6 @@ void osd_messenger_t::read_requests()
|
|||||||
bool osd_messenger_t::handle_read(int result, osd_client_t *cl)
|
bool osd_messenger_t::handle_read(int result, osd_client_t *cl)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
int peer_fd = cl->peer_fd;
|
|
||||||
cl->read_msg.msg_iovlen = 0;
|
cl->read_msg.msg_iovlen = 0;
|
||||||
cl->refs--;
|
cl->refs--;
|
||||||
if (cl->peer_state == PEER_RDMA)
|
if (cl->peer_state == PEER_RDMA)
|
||||||
@@ -84,7 +83,7 @@ bool osd_messenger_t::handle_read(int result, osd_client_t *cl)
|
|||||||
{
|
{
|
||||||
if (cl->refs <= 0)
|
if (cl->refs <= 0)
|
||||||
{
|
{
|
||||||
delete cl;
|
destroy_client(cl);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -93,20 +92,20 @@ bool osd_messenger_t::handle_read(int result, osd_client_t *cl)
|
|||||||
// this is a client socket, so don't panic on error. just disconnect it
|
// this is a client socket, so don't panic on error. just disconnect it
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Client %d socket read error: %d (%s). Disconnecting client\n", cl->peer_fd, -result, strerror(-result));
|
fprintf(stderr, "Client %ju socket read error: %d (%s). Disconnecting client\n", cl->client_id, -result, strerror(-result));
|
||||||
}
|
}
|
||||||
stop_client(cl->peer_fd);
|
stop_client(cl->client_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (result == -EAGAIN || result == -EINTR || result < cl->read_iov.iov_len)
|
if (result == -EAGAIN || result == -EINTR || result < cl->read_iov.iov_len)
|
||||||
{
|
{
|
||||||
cl->read_ready--;
|
cl->read_ready--;
|
||||||
if (cl->read_ready > 0)
|
if (cl->read_ready > 0)
|
||||||
read_ready_clients.push_back(cl->peer_fd);
|
read_ready_clients.push_back(cl->client_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
read_ready_clients.push_back(cl->peer_fd);
|
read_ready_clients.push_back(cl->client_id);
|
||||||
}
|
}
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
{
|
{
|
||||||
@@ -114,7 +113,6 @@ bool osd_messenger_t::handle_read(int result, osd_client_t *cl)
|
|||||||
{
|
{
|
||||||
if (!handle_read_buffer(cl, cl->in_buf, result))
|
if (!handle_read_buffer(cl, cl->in_buf, result))
|
||||||
{
|
{
|
||||||
clear_immediate_ops(peer_fd);
|
|
||||||
handle_immediate_ops();
|
handle_immediate_ops();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -128,7 +126,6 @@ bool osd_messenger_t::handle_read(int result, osd_client_t *cl)
|
|||||||
{
|
{
|
||||||
if (!handle_finished_read(cl))
|
if (!handle_finished_read(cl))
|
||||||
{
|
{
|
||||||
clear_immediate_ops(peer_fd);
|
|
||||||
handle_immediate_ops();
|
handle_immediate_ops();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -143,26 +140,6 @@ bool osd_messenger_t::handle_read(int result, osd_client_t *cl)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_messenger_t::clear_immediate_ops(int peer_fd)
|
|
||||||
{
|
|
||||||
size_t i = 0, j = 0;
|
|
||||||
while (i < set_immediate_ops.size())
|
|
||||||
{
|
|
||||||
if (set_immediate_ops[i]->peer_fd == peer_fd && set_immediate_ops[i]->op_type == OSD_OP_IN)
|
|
||||||
{
|
|
||||||
delete set_immediate_ops[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (i != j)
|
|
||||||
set_immediate_ops[j] = set_immediate_ops[i];
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
set_immediate_ops.resize(j);
|
|
||||||
}
|
|
||||||
|
|
||||||
void osd_messenger_t::handle_immediate_ops()
|
void osd_messenger_t::handle_immediate_ops()
|
||||||
{
|
{
|
||||||
while (set_immediate_ops.size())
|
while (set_immediate_ops.size())
|
||||||
@@ -171,7 +148,11 @@ void osd_messenger_t::handle_immediate_ops()
|
|||||||
set_immediate_ops.pop_front();
|
set_immediate_ops.pop_front();
|
||||||
if (op->op_type == OSD_OP_IN)
|
if (op->op_type == OSD_OP_IN)
|
||||||
{
|
{
|
||||||
exec_op(op);
|
auto cl_it = clients.find(op->client_id);
|
||||||
|
if (cl_it != clients.end() && cl_it->second->peer_state != PEER_STOPPED)
|
||||||
|
exec_op(op);
|
||||||
|
else
|
||||||
|
delete op;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -189,7 +170,7 @@ bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, void *curbuf, int rem
|
|||||||
if (!cl->read_op)
|
if (!cl->read_op)
|
||||||
{
|
{
|
||||||
cl->read_op = new osd_op_t;
|
cl->read_op = new osd_op_t;
|
||||||
cl->read_op->peer_fd = cl->peer_fd;
|
cl->read_op->client_id = cl->client_id;
|
||||||
cl->read_op->op_type = OSD_OP_IN;
|
cl->read_op->op_type = OSD_OP_IN;
|
||||||
cl->recv_list.push_back(cl->read_op->req.buf, OSD_PACKET_SIZE);
|
cl->recv_list.push_back(cl->read_op->req.buf, OSD_PACKET_SIZE);
|
||||||
cl->read_remaining = OSD_PACKET_SIZE;
|
cl->read_remaining = OSD_PACKET_SIZE;
|
||||||
@@ -243,8 +224,8 @@ bool osd_messenger_t::handle_finished_read(osd_client_t *cl)
|
|||||||
{
|
{
|
||||||
if (cl->read_op->req.hdr.id != cl->read_op_id)
|
if (cl->read_op->req.hdr.id != cl->read_op_id)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Warning: operation sequencing is broken on client %d: expected num %ju, got %ju, stopping client\n", cl->peer_fd, cl->read_op_id, cl->read_op->req.hdr.id);
|
fprintf(stderr, "Warning: operation sequencing is broken on client %ju: expected num %ju, got %ju, stopping client\n", cl->client_id, cl->read_op_id, cl->read_op->req.hdr.id);
|
||||||
stop_client(cl->peer_fd);
|
stop_client(cl->client_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cl->read_op_id++;
|
cl->read_op_id++;
|
||||||
@@ -253,8 +234,8 @@ bool osd_messenger_t::handle_finished_read(osd_client_t *cl)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Received garbage: magic=%jx id=%ju opcode=%jx from %d\n", cl->read_op->req.hdr.magic, cl->read_op->req.hdr.id, cl->read_op->req.hdr.opcode, cl->peer_fd);
|
fprintf(stderr, "Received garbage: magic=%jx id=%ju opcode=%jx from client %ju\n", cl->read_op->req.hdr.magic, cl->read_op->req.hdr.id, cl->read_op->req.hdr.opcode, cl->client_id);
|
||||||
stop_client(cl->peer_fd);
|
stop_client(cl->client_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,8 +351,8 @@ bool osd_messenger_t::handle_reply_hdr(osd_client_t *cl)
|
|||||||
if (req_it == cl->sent_ops.end())
|
if (req_it == cl->sent_ops.end())
|
||||||
{
|
{
|
||||||
// Command out of sync. Drop connection
|
// Command out of sync. Drop connection
|
||||||
fprintf(stderr, "Client %d command out of sync: id %ju\n", cl->peer_fd, cl->read_op->req.hdr.id);
|
fprintf(stderr, "Client %ju command out of sync: id %ju\n", cl->client_id, cl->read_op->req.hdr.id);
|
||||||
stop_client(cl->peer_fd);
|
stop_client(cl->client_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
osd_op_t *op = req_it->second;
|
osd_op_t *op = req_it->second;
|
||||||
@@ -385,10 +366,10 @@ bool osd_messenger_t::handle_reply_hdr(osd_client_t *cl)
|
|||||||
if (op->reply.hdr.retval >= 0 && (op->reply.hdr.retval != expected_size || bmp_len > op->bitmap_len))
|
if (op->reply.hdr.retval >= 0 && (op->reply.hdr.retval != expected_size || bmp_len > op->bitmap_len))
|
||||||
{
|
{
|
||||||
// Check reply length to not overflow the buffer
|
// Check reply length to not overflow the buffer
|
||||||
fprintf(stderr, "Client %d read reply of different length: expected %u+%u, got %jd+%u\n",
|
fprintf(stderr, "Client %ju read reply of different length: expected %u+%u, got %jd+%u\n",
|
||||||
cl->peer_fd, expected_size, op->bitmap_len, op->reply.hdr.retval, bmp_len);
|
cl->client_id, expected_size, op->bitmap_len, op->reply.hdr.retval, bmp_len);
|
||||||
cl->sent_ops[op->req.hdr.id] = op;
|
cl->sent_ops[op->req.hdr.id] = op;
|
||||||
stop_client(cl->peer_fd);
|
stop_client(cl->client_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (bmp_len > 0)
|
if (bmp_len > 0)
|
||||||
|
|||||||
+27
-26
@@ -9,8 +9,14 @@
|
|||||||
|
|
||||||
void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
||||||
{
|
{
|
||||||
assert(cur_op->peer_fd);
|
assert(cur_op->client_id);
|
||||||
osd_client_t *cl = clients.at(cur_op->peer_fd);
|
auto cl_it = clients.find(cur_op->client_id);
|
||||||
|
if (cl_it == clients.end() || cl_it->second->peer_state == PEER_STOPPED)
|
||||||
|
{
|
||||||
|
delete cur_op;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
osd_client_t *cl = cl_it->second;
|
||||||
if (cur_op->op_type == OSD_OP_OUT)
|
if (cur_op->op_type == OSD_OP_OUT)
|
||||||
{
|
{
|
||||||
clock_gettime(CLOCK_REALTIME, &cur_op->tv_begin);
|
clock_gettime(CLOCK_REALTIME, &cur_op->tv_begin);
|
||||||
@@ -18,8 +24,7 @@ void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Check that operation actually belongs to this client
|
// Remove the operation from received op list
|
||||||
// FIXME: Review if this is still needed
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto it = cl->received_ops.begin(); it != cl->received_ops.end(); it++)
|
for (auto it = cl->received_ops.begin(); it != cl->received_ops.end(); it++)
|
||||||
{
|
{
|
||||||
@@ -30,11 +35,8 @@ void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
// Can't be not found because client IDs are unique
|
||||||
{
|
assert(found);
|
||||||
delete cur_op;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
auto & to_send_list = cl->write_msg.msg_iovlen ? cl->next_send_list : cl->send_list;
|
auto & to_send_list = cl->write_msg.msg_iovlen ? cl->next_send_list : cl->send_list;
|
||||||
auto & to_outbox = cl->write_msg.msg_iovlen ? cl->next_outbox : cl->outbox;
|
auto & to_outbox = cl->write_msg.msg_iovlen ? cl->next_outbox : cl->outbox;
|
||||||
@@ -126,7 +128,7 @@ void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
|||||||
if ((cl->write_msg.msg_iovlen > 0 || !try_send(cl)) && (cl->write_state == 0))
|
if ((cl->write_msg.msg_iovlen > 0 || !try_send(cl)) && (cl->write_state == 0))
|
||||||
{
|
{
|
||||||
cl->write_state = CL_WRITE_READY;
|
cl->write_state = CL_WRITE_READY;
|
||||||
write_ready_clients.push_back(cur_op->peer_fd);
|
write_ready_clients.push_back(cur_op->client_id);
|
||||||
}
|
}
|
||||||
ringloop->wakeup();
|
ringloop->wakeup();
|
||||||
}
|
}
|
||||||
@@ -183,15 +185,14 @@ void osd_messenger_t::measure_exec(osd_op_t *cur_op)
|
|||||||
|
|
||||||
bool osd_messenger_t::try_send(osd_client_t *cl)
|
bool osd_messenger_t::try_send(osd_client_t *cl)
|
||||||
{
|
{
|
||||||
int peer_fd = cl->peer_fd;
|
if (!cl->send_list.size() || cl->write_msg.msg_iovlen > 0 || cl->peer_state == PEER_STOPPED || cl->peer_fd < 0)
|
||||||
if (!cl->send_list.size() || cl->write_msg.msg_iovlen > 0)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
assert(cl->peer_state != PEER_RDMA);
|
assert(cl->peer_state != PEER_RDMA);
|
||||||
if (ringloop && !use_sync_send_recv)
|
if (ringloop && !use_sync_send_recv)
|
||||||
{
|
{
|
||||||
auto iothread = iothreads.size() ? iothreads[peer_fd % iothreads.size()] : NULL;
|
auto iothread = iothreads.size() ? iothreads[cl->peer_fd % iothreads.size()] : NULL;
|
||||||
io_uring_sqe sqe_local;
|
io_uring_sqe sqe_local;
|
||||||
ring_data_t data_local;
|
ring_data_t data_local;
|
||||||
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
|
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
|
||||||
@@ -218,11 +219,11 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
|
|||||||
}
|
}
|
||||||
if (use_zc)
|
if (use_zc)
|
||||||
{
|
{
|
||||||
io_uring_prep_sendmsg_zc(sqe, peer_fd, &cl->write_msg, MSG_WAITALL);
|
io_uring_prep_sendmsg_zc(sqe, cl->peer_fd, &cl->write_msg, MSG_WAITALL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
io_uring_prep_sendmsg(sqe, peer_fd, &cl->write_msg, MSG_WAITALL);
|
io_uring_prep_sendmsg(sqe, cl->peer_fd, &cl->write_msg, MSG_WAITALL);
|
||||||
}
|
}
|
||||||
if (iothread)
|
if (iothread)
|
||||||
{
|
{
|
||||||
@@ -234,7 +235,7 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
|
|||||||
cl->write_msg.msg_iov = cl->send_list.data();
|
cl->write_msg.msg_iov = cl->send_list.data();
|
||||||
cl->write_msg.msg_iovlen = cl->send_list.size() < IOV_MAX ? cl->send_list.size() : IOV_MAX;
|
cl->write_msg.msg_iovlen = cl->send_list.size() < IOV_MAX ? cl->send_list.size() : IOV_MAX;
|
||||||
cl->refs++;
|
cl->refs++;
|
||||||
int result = sendmsg(peer_fd, &cl->write_msg, MSG_NOSIGNAL);
|
int result = sendmsg(cl->peer_fd, &cl->write_msg, MSG_NOSIGNAL);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
result = -errno;
|
result = -errno;
|
||||||
@@ -249,8 +250,8 @@ void osd_messenger_t::send_replies()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < write_ready_clients.size(); i++)
|
for (int i = 0; i < write_ready_clients.size(); i++)
|
||||||
{
|
{
|
||||||
int peer_fd = write_ready_clients[i];
|
uint64_t client_id = write_ready_clients[i];
|
||||||
auto cl_it = clients.find(peer_fd);
|
auto cl_it = clients.find(client_id);
|
||||||
if (cl_it != clients.end() && cl_it->second->peer_state != PEER_RDMA && !try_send(cl_it->second))
|
if (cl_it != clients.end() && cl_it->second->peer_state != PEER_RDMA && !try_send(cl_it->second))
|
||||||
{
|
{
|
||||||
write_ready_clients.erase(write_ready_clients.begin(), write_ready_clients.begin() + i);
|
write_ready_clients.erase(write_ready_clients.begin(), write_ready_clients.begin() + i);
|
||||||
@@ -274,15 +275,15 @@ void osd_messenger_t::handle_send(int result, bool prev, bool more, osd_client_t
|
|||||||
{
|
{
|
||||||
if (cl->refs <= 0)
|
if (cl->refs <= 0)
|
||||||
{
|
{
|
||||||
delete cl;
|
destroy_client(cl);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result < 0 && result != -EAGAIN && result != -EINTR)
|
if (result < 0 && result != -EAGAIN && result != -EINTR)
|
||||||
{
|
{
|
||||||
// this is a client socket, so don't panic. just disconnect it
|
// this is a client socket, so don't panic. just disconnect it
|
||||||
fprintf(stderr, "Client %d socket write error: %d (%s). Disconnecting client\n", cl->peer_fd, -result, strerror(-result));
|
fprintf(stderr, "Client %ju socket write error: %d (%s). Disconnecting client\n", cl->client_id, -result, strerror(-result));
|
||||||
stop_client(cl->peer_fd);
|
stop_client(cl->client_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result >= 0)
|
if (result >= 0)
|
||||||
@@ -326,9 +327,9 @@ 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, "Client %ju socket write error: expected to send "
|
||||||
"%d iovecs with MSG_WAITALL but sent %d. Disconnecting client\n", cl->peer_fd, expected, done);
|
"%d iovecs with MSG_WAITALL but sent %d. Disconnecting client\n", cl->client_id, expected, done);
|
||||||
stop_client(cl->peer_fd);
|
stop_client(cl->client_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cl->zc_free_list.push_back(NULL); // end marker
|
cl->zc_free_list.push_back(NULL); // end marker
|
||||||
@@ -352,7 +353,7 @@ void osd_messenger_t::handle_send(int result, bool prev, bool more, osd_client_t
|
|||||||
// FIXME: Ignore pings during RDMA state transition
|
// FIXME: Ignore pings during RDMA state transition
|
||||||
if (log_level > 0)
|
if (log_level > 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Successfully connected with client %d using RDMA\n", cl->peer_fd);
|
fprintf(stderr, "Successfully connected with client %ju using RDMA\n", cl->client_id);
|
||||||
}
|
}
|
||||||
cl->peer_state = PEER_RDMA;
|
cl->peer_state = PEER_RDMA;
|
||||||
// Add the initial receive request
|
// Add the initial receive request
|
||||||
@@ -362,6 +363,6 @@ void osd_messenger_t::handle_send(int result, bool prev, bool more, osd_client_t
|
|||||||
}
|
}
|
||||||
if (cl->write_state != 0)
|
if (cl->write_state != 0)
|
||||||
{
|
{
|
||||||
write_ready_clients.push_back(cl->peer_fd);
|
write_ready_clients.push_back(cl->client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-36
@@ -43,34 +43,40 @@ void osd_op_t::cancel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
|
// force_delete means stop the client anyway, even if there are refs to it in the event loop.
|
||||||
|
// the flag should be used in the destructor.
|
||||||
|
// why? - because yes, we could close the FD first and let it fail all requests in the event loop,
|
||||||
|
// but in that case it can be quickly reopened and we can get old failed responses for the new FD.
|
||||||
|
void osd_messenger_t::stop_client(uint64_t client_id, bool force_delete)
|
||||||
{
|
{
|
||||||
assert(peer_fd != 0);
|
auto it = clients.find(client_id);
|
||||||
auto it = clients.find(peer_fd);
|
if (!client_id || it == clients.end())
|
||||||
if (it == clients.end())
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
osd_client_t *cl = it->second;
|
osd_client_t *cl = it->second;
|
||||||
// FIXME: This 'force' flag is probably an ugly reenterability hack - check its logic and maybe remove it
|
if (cl->peer_state == PEER_STOPPED)
|
||||||
if (cl->peer_state == PEER_CONNECTING && !force || cl->peer_state == PEER_STOPPED)
|
|
||||||
{
|
{
|
||||||
|
if (force_delete)
|
||||||
|
{
|
||||||
|
destroy_client(cl);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clear_immediate_ops(peer_fd);
|
cl->received_ops.clear();
|
||||||
if (log_level > 0)
|
if (log_level > 0)
|
||||||
{
|
{
|
||||||
if (cl->osd_num)
|
if (cl->osd_num)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[OSD %ju] Stopping client %d (OSD peer %ju)\n", osd_num, peer_fd, cl->osd_num);
|
fprintf(stderr, "[OSD %ju] Stopping client %ju (OSD peer %ju)\n", osd_num, client_id, cl->osd_num);
|
||||||
}
|
}
|
||||||
else if (cl->in_osd_num)
|
else if (cl->in_osd_num)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[OSD %ju] Stopping client %d (incoming OSD peer %ju)\n", osd_num, peer_fd, cl->in_osd_num);
|
fprintf(stderr, "[OSD %ju] Stopping client %ju (incoming OSD peer %ju)\n", osd_num, client_id, cl->in_osd_num);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[OSD %ju] Stopping client %d (regular client)\n", osd_num, peer_fd);
|
fprintf(stderr, "[OSD %ju] Stopping client %ju (regular client)\n", osd_num, client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// First set state to STOPPED so another stop_client() call doesn't try to free it again
|
// First set state to STOPPED so another stop_client() call doesn't try to free it again
|
||||||
@@ -79,11 +85,11 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
|
|||||||
cl->peer_state = PEER_STOPPED;
|
cl->peer_state = PEER_STOPPED;
|
||||||
if (cl->osd_num)
|
if (cl->osd_num)
|
||||||
{
|
{
|
||||||
auto osd_it = osd_peer_fds.find(cl->osd_num);
|
auto osd_it = osd_peers.find(cl->osd_num);
|
||||||
if (osd_it != osd_peer_fds.end() && osd_it->second == cl->peer_fd)
|
if (osd_it != osd_peers.end() && osd_it->second == cl)
|
||||||
{
|
{
|
||||||
// ...and forget OSD peer
|
// ...and forget OSD peer
|
||||||
osd_peer_fds.erase(osd_it);
|
osd_peers.erase(osd_it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef WITH_RDMA
|
#ifdef WITH_RDMA
|
||||||
@@ -97,29 +103,11 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef __MOCK__
|
#ifndef __MOCK__
|
||||||
// Then remove FD from the eventloop so we don't accidentally read something
|
|
||||||
tfd->set_fd_handler(peer_fd, false, NULL);
|
|
||||||
if (cl->connect_timeout_id >= 0)
|
if (cl->connect_timeout_id >= 0)
|
||||||
{
|
{
|
||||||
tfd->clear_timer(cl->connect_timeout_id);
|
tfd->clear_timer(cl->connect_timeout_id);
|
||||||
cl->connect_timeout_id = -1;
|
cl->connect_timeout_id = -1;
|
||||||
}
|
}
|
||||||
for (auto rit = read_ready_clients.begin(); rit != read_ready_clients.end(); rit++)
|
|
||||||
{
|
|
||||||
if (*rit == peer_fd)
|
|
||||||
{
|
|
||||||
read_ready_clients.erase(rit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto wit = write_ready_clients.begin(); wit != write_ready_clients.end(); wit++)
|
|
||||||
{
|
|
||||||
if (*wit == peer_fd)
|
|
||||||
{
|
|
||||||
write_ready_clients.erase(wit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (cl->in_osd_num && break_pg_locks)
|
if (cl->in_osd_num && break_pg_locks)
|
||||||
{
|
{
|
||||||
@@ -134,19 +122,51 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
|
|||||||
// so do not repeer on it.
|
// so do not repeer on it.
|
||||||
repeer_pgs(cl->osd_num);
|
repeer_pgs(cl->osd_num);
|
||||||
}
|
}
|
||||||
// Find the item again because it can be invalidated at this point
|
if (cl->peer_fd >= 0)
|
||||||
it = clients.find(peer_fd);
|
|
||||||
if (it != clients.end())
|
|
||||||
{
|
{
|
||||||
clients.erase(it);
|
int r = shutdown(cl->peer_fd, SHUT_RDWR);
|
||||||
|
if (r != 0 && errno != ENOTCONN)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "[OSD %ju] failed to shutdown a socket: %s (code %d)\n", osd_num, strerror(errno), errno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cl->refs--;
|
cl->refs--;
|
||||||
if (cl->refs <= 0 || force_delete)
|
if (cl->refs <= 0 || force_delete)
|
||||||
{
|
{
|
||||||
delete cl;
|
destroy_client(cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void osd_messenger_t::destroy_client(osd_client_t *cl)
|
||||||
|
{
|
||||||
|
// Find the item again because it can be invalidated at this point
|
||||||
|
clients.erase(cl->client_id);
|
||||||
|
if (cl->peer_fd >= 0)
|
||||||
|
{
|
||||||
|
#ifndef __MOCK__
|
||||||
|
tfd->set_fd_handler(cl->peer_fd, false, NULL);
|
||||||
|
#endif
|
||||||
|
for (auto rit = read_ready_clients.begin(); rit != read_ready_clients.end(); rit++)
|
||||||
|
{
|
||||||
|
if (*rit == cl->client_id)
|
||||||
|
{
|
||||||
|
read_ready_clients.erase(rit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto wit = write_ready_clients.begin(); wit != write_ready_clients.end(); wit++)
|
||||||
|
{
|
||||||
|
if (*wit == cl->client_id)
|
||||||
|
{
|
||||||
|
write_ready_clients.erase(wit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clients_by_fd.erase(cl->peer_fd);
|
||||||
|
}
|
||||||
|
delete cl;
|
||||||
|
}
|
||||||
|
|
||||||
osd_client_t::~osd_client_t()
|
osd_client_t::~osd_client_t()
|
||||||
{
|
{
|
||||||
free(in_buf);
|
free(in_buf);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
|||||||
|
|
||||||
Name: Vitastor
|
Name: Vitastor
|
||||||
Description: Vitastor client library
|
Description: Vitastor client library
|
||||||
Version: 3.0.5
|
Version: 3.0.11
|
||||||
Libs: -L${libdir} -lvitastor_client
|
Libs: -L${libdir} -lvitastor_client
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
@@ -286,6 +286,8 @@ struct rm_inode_t
|
|||||||
.data = data,
|
.data = data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// Wakeup callers (otherwise they wake up only on next loop())
|
||||||
|
parent->ringloop->wakeup();
|
||||||
}
|
}
|
||||||
in_continue = false;
|
in_continue = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ static const char* help_text =
|
|||||||
" --logfile <FILE> log to the specified file\n"
|
" --logfile <FILE> log to the specified file\n"
|
||||||
" --enforce 1 enforce permissions at the server side (default is disabled)\n"
|
" --enforce 1 enforce permissions at the server side (default is disabled)\n"
|
||||||
" --foreground 1 stay in foreground, do not daemonize\n"
|
" --foreground 1 stay in foreground, do not daemonize\n"
|
||||||
|
" --trace trace all NFS requests\n"
|
||||||
"\n"
|
"\n"
|
||||||
"NFS proxy is stateless if you use immediate_commit=all in your cluster and if\n"
|
"NFS proxy is stateless if you use immediate_commit=all in your cluster and if\n"
|
||||||
"you do not use client_enable_writeback=true, so you can freely use multiple\n"
|
"you do not use client_enable_writeback=true, so you can freely use multiple\n"
|
||||||
@@ -158,7 +159,7 @@ json11::Json::object nfs_proxy_t::parse_args(int narg, const char *args[])
|
|||||||
{
|
{
|
||||||
const char *opt = args[i]+2;
|
const char *opt = args[i]+2;
|
||||||
cfg[str_replace(opt, "-", "_")] = !strcmp(opt, "json") || !strcmp(opt, "block") ||
|
cfg[str_replace(opt, "-", "_")] = !strcmp(opt, "json") || !strcmp(opt, "block") ||
|
||||||
!strcmp(opt, "dry-run") || !strcmp(opt, "recalc-stats") ||
|
!strcmp(opt, "dry-run") || !strcmp(opt, "recalc-stats") || !strcmp(opt, "trace") ||
|
||||||
!strcmp(opt, "include-empty") || !strcmp(opt, "no-rm") || i == narg-1 ? "1" : args[++i];
|
!strcmp(opt, "include-empty") || !strcmp(opt, "no-rm") || i == narg-1 ? "1" : args[++i];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -529,6 +529,11 @@ void osd_t::exec_op(osd_op_t *cur_op)
|
|||||||
|
|
||||||
void osd_t::print_stats()
|
void osd_t::print_stats()
|
||||||
{
|
{
|
||||||
|
if (bs && log_level > 1)
|
||||||
|
{
|
||||||
|
printf("[OSD %ju] Live entries: %ju (%ju bytes), garbage entries: %ju (%ju bytes)\n", osd_num,
|
||||||
|
bs->get_live_entries(), bs->get_live_memory(), bs->get_garbage_entries(), bs->get_garbage_memory());
|
||||||
|
}
|
||||||
for (int i = OSD_OP_MIN; i <= OSD_OP_MAX; i++)
|
for (int i = OSD_OP_MIN; i <= OSD_OP_MAX; i++)
|
||||||
{
|
{
|
||||||
if (msgr.stats.op_stat_count[i] != prev_stats.op_stat_count[i] && i != OSD_OP_PING)
|
if (msgr.stats.op_stat_count[i] != prev_stats.op_stat_count[i] && i != OSD_OP_PING)
|
||||||
@@ -616,11 +621,11 @@ void osd_t::print_slow()
|
|||||||
bufprintf("[OSD %ju] Slow op %jx", osd_num, (uint64_t)op);
|
bufprintf("[OSD %ju] Slow op %jx", osd_num, (uint64_t)op);
|
||||||
if (kv.second->osd_num)
|
if (kv.second->osd_num)
|
||||||
{
|
{
|
||||||
bufprintf(" from peer OSD %ju (client %d)", kv.second->osd_num, kv.second->peer_fd);
|
bufprintf(" from peer OSD %ju (client %ju)", kv.second->osd_num, kv.second->client_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bufprintf(" from client %d", kv.second->peer_fd);
|
bufprintf(" from client %ju", kv.second->client_id);
|
||||||
}
|
}
|
||||||
bufprintf(": %s id=%ju", osd_op_names[op->req.hdr.opcode], op->req.hdr.id);
|
bufprintf(": %s id=%ju", osd_op_names[op->req.hdr.opcode], op->req.hdr.id);
|
||||||
if (op->req.hdr.opcode == OSD_OP_SEC_READ || op->req.hdr.opcode == OSD_OP_SEC_WRITE ||
|
if (op->req.hdr.opcode == OSD_OP_SEC_READ || op->req.hdr.opcode == OSD_OP_SEC_WRITE ||
|
||||||
|
|||||||
+1
-1
@@ -347,7 +347,7 @@ class osd_t
|
|||||||
bool check_write_queue(osd_op_t *cur_op, pg_t & pg);
|
bool check_write_queue(osd_op_t *cur_op, pg_t & pg);
|
||||||
pg_osd_set_state_t* add_object_to_set(pg_t & pg, const object_id oid, const pg_osd_set_t & osd_set,
|
pg_osd_set_state_t* add_object_to_set(pg_t & pg, const object_id oid, const pg_osd_set_t & osd_set,
|
||||||
uint64_t old_pg_state, int log_at_level);
|
uint64_t old_pg_state, int log_at_level);
|
||||||
void remove_object_from_state(object_id & oid, pg_osd_set_state_t **object_state, pg_t &pg, bool report = true);
|
bool remove_object_from_state(object_id & oid, pg_osd_set_state_t **object_state, pg_t &pg, bool report = true);
|
||||||
pg_osd_set_state_t *mark_object(pg_t & pg, object_id oid, pg_osd_set_state_t *prev_object_state, bool ref,
|
pg_osd_set_state_t *mark_object(pg_t & pg, object_id oid, pg_osd_set_state_t *prev_object_state, bool ref,
|
||||||
std::function<int(pg_osd_set_t & new_set)> calc_set);
|
std::function<int(pg_osd_set_t & new_set)> calc_set);
|
||||||
pg_osd_set_state_t *mark_object_corrupted(pg_t & pg, object_id oid, pg_osd_set_state_t *prev_object_state,
|
pg_osd_set_state_t *mark_object_corrupted(pg_t & pg, object_id oid, pg_osd_set_state_t *prev_object_state,
|
||||||
|
|||||||
@@ -991,7 +991,7 @@ void osd_t::apply_pg_config()
|
|||||||
// Add peers
|
// Add peers
|
||||||
for (auto pg_osd: all_peers)
|
for (auto pg_osd: all_peers)
|
||||||
{
|
{
|
||||||
if (pg_osd != this->osd_num && msgr.osd_peer_fds.find(pg_osd) == msgr.osd_peer_fds.end())
|
if (pg_osd != this->osd_num && msgr.osd_peers.find(pg_osd) == msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
msgr.connect_peer(pg_osd, st_cli.peer_states[pg_osd]);
|
msgr.connect_peer(pg_osd, st_cli.peer_states[pg_osd]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "osd.h"
|
#include "osd.h"
|
||||||
|
|
||||||
#define FLUSH_BATCH 512
|
#define FLUSH_BATCH 512
|
||||||
|
#define SELF_CLIENT 0
|
||||||
|
|
||||||
void osd_t::submit_pg_flush_ops(pg_t & pg)
|
void osd_t::submit_pg_flush_ops(pg_t & pg)
|
||||||
{
|
{
|
||||||
@@ -91,11 +92,11 @@ void osd_t::handle_flush_op(bool rollback, pool_id_t pool_id, pg_num_t pg_num, p
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Error while doing flush on OSD %ju: %d (%s)\n", osd_num, retval, strerror(-retval));
|
printf("Error while doing flush on OSD %ju: %d (%s)\n", osd_num, retval, strerror(-retval));
|
||||||
auto fd_it = msgr.osd_peer_fds.find(peer_osd);
|
auto peer_it = msgr.osd_peers.find(peer_osd);
|
||||||
if (fd_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
// Will repeer/stop this PG
|
// Will repeer/stop this PG
|
||||||
msgr.stop_client(fd_it->second);
|
msgr.stop_client(peer_it->second->client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,10 +213,10 @@ bool osd_t::submit_flush_op(pool_id_t pool_id, pg_num_t pg_num, pg_flush_batch_t
|
|||||||
handle_flush_op(op->req.hdr.opcode == OSD_OP_SEC_ROLLBACK, pool_id, pg_num, fb, peer_osd, op->reply.hdr.retval);
|
handle_flush_op(op->req.hdr.opcode == OSD_OP_SEC_ROLLBACK, pool_id, pg_num, fb, peer_osd, op->reply.hdr.retval);
|
||||||
delete op;
|
delete op;
|
||||||
};
|
};
|
||||||
auto peer_fd_it = msgr.osd_peer_fds.find(peer_osd);
|
auto peer_it = msgr.osd_peers.find(peer_osd);
|
||||||
if (peer_fd_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
op->peer_fd = peer_fd_it->second;
|
op->client_id = peer_it->second->client_id;
|
||||||
msgr.outbox_push(op);
|
msgr.outbox_push(op);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -307,7 +308,7 @@ void osd_t::submit_recovery_op(osd_recovery_op_t *op)
|
|||||||
{
|
{
|
||||||
printf("Submitting recovery operation for %jx:%jx (%s)\n", op->oid.inode, op->oid.stripe, op->degraded ? "degraded" : "misplaced");
|
printf("Submitting recovery operation for %jx:%jx (%s)\n", op->oid.inode, op->oid.stripe, op->degraded ? "degraded" : "misplaced");
|
||||||
}
|
}
|
||||||
op->osd_op->peer_fd = -1;
|
op->osd_op->client_id = SELF_CLIENT;
|
||||||
op->osd_op->callback = [this, op](osd_op_t *osd_op)
|
op->osd_op->callback = [this, op](osd_op_t *osd_op)
|
||||||
{
|
{
|
||||||
ringloop->set_immediate([this, op]()
|
ringloop->set_immediate([this, op]()
|
||||||
|
|||||||
+20
-21
@@ -9,7 +9,7 @@
|
|||||||
#include "str_util.h"
|
#include "str_util.h"
|
||||||
#include "osd.h"
|
#include "osd.h"
|
||||||
|
|
||||||
#define SELF_FD -1
|
#define SELF_CLIENT 0
|
||||||
|
|
||||||
// Peering loop
|
// Peering loop
|
||||||
void osd_t::handle_peers()
|
void osd_t::handle_peers()
|
||||||
@@ -175,17 +175,17 @@ void osd_t::drop_dirty_pg_connections(pool_pg_num_t pg)
|
|||||||
{
|
{
|
||||||
if (immediate_commit != IMMEDIATE_ALL)
|
if (immediate_commit != IMMEDIATE_ALL)
|
||||||
{
|
{
|
||||||
std::vector<int> to_stop;
|
std::vector<uint64_t> to_stop;
|
||||||
for (auto & cp: msgr.clients)
|
for (auto & cp: msgr.clients)
|
||||||
{
|
{
|
||||||
if (cp.second->dirty_pgs.find(pg) != cp.second->dirty_pgs.end())
|
if (cp.second->dirty_pgs.find(pg) != cp.second->dirty_pgs.end())
|
||||||
{
|
{
|
||||||
to_stop.push_back(cp.first);
|
to_stop.push_back(cp.second->client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto peer_fd: to_stop)
|
for (auto client_id: to_stop)
|
||||||
{
|
{
|
||||||
msgr.stop_client(peer_fd);
|
msgr.stop_client(client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,7 +203,7 @@ void osd_t::start_pg_peering(pg_t & pg)
|
|||||||
for (auto pg_osd: pg.all_peers)
|
for (auto pg_osd: pg.all_peers)
|
||||||
{
|
{
|
||||||
if (pg_osd != this->osd_num &&
|
if (pg_osd != this->osd_num &&
|
||||||
msgr.osd_peer_fds.find(pg_osd) == msgr.osd_peer_fds.end())
|
msgr.osd_peers.find(pg_osd) == msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
if (msgr.wanted_peers.find(pg_osd) == msgr.wanted_peers.end())
|
if (msgr.wanted_peers.find(pg_osd) == msgr.wanted_peers.end())
|
||||||
msgr.connect_peer(pg_osd, st_cli.peer_states[pg_osd]);
|
msgr.connect_peer(pg_osd, st_cli.peer_states[pg_osd]);
|
||||||
@@ -224,7 +224,7 @@ void osd_t::start_pg_peering(pg_t & pg)
|
|||||||
for (int role = 0; role < pg.target_set.size(); role++)
|
for (int role = 0; role < pg.target_set.size(); role++)
|
||||||
{
|
{
|
||||||
pg.cur_set[role] = pg.target_set[role] == this->osd_num ||
|
pg.cur_set[role] = pg.target_set[role] == this->osd_num ||
|
||||||
msgr.osd_peer_fds.find(pg.target_set[role]) != msgr.osd_peer_fds.end() ? pg.target_set[role] : 0;
|
msgr.osd_peers.find(pg.target_set[role]) != msgr.osd_peers.end() ? pg.target_set[role] : 0;
|
||||||
if (pg.cur_set[role] != 0)
|
if (pg.cur_set[role] != 0)
|
||||||
{
|
{
|
||||||
pg.pg_cursize++;
|
pg.pg_cursize++;
|
||||||
@@ -246,7 +246,7 @@ void osd_t::start_pg_peering(pg_t & pg)
|
|||||||
std::set<osd_num_t> dead_peers;
|
std::set<osd_num_t> dead_peers;
|
||||||
for (auto pg_osd: pg.all_peers)
|
for (auto pg_osd: pg.all_peers)
|
||||||
{
|
{
|
||||||
if (pg_osd == this->osd_num || msgr.osd_peer_fds.find(pg_osd) != msgr.osd_peer_fds.end())
|
if (pg_osd == this->osd_num || msgr.osd_peers.find(pg_osd) != msgr.osd_peers.end())
|
||||||
cur_peers.insert(pg_osd);
|
cur_peers.insert(pg_osd);
|
||||||
else
|
else
|
||||||
dead_peers.insert(pg_osd);
|
dead_peers.insert(pg_osd);
|
||||||
@@ -266,7 +266,7 @@ void osd_t::start_pg_peering(pg_t & pg)
|
|||||||
{
|
{
|
||||||
nonzero++;
|
nonzero++;
|
||||||
if (history_osd == this->osd_num ||
|
if (history_osd == this->osd_num ||
|
||||||
msgr.osd_peer_fds.find(history_osd) != msgr.osd_peer_fds.end())
|
msgr.osd_peers.find(history_osd) != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
found++;
|
found++;
|
||||||
}
|
}
|
||||||
@@ -435,8 +435,8 @@ void osd_t::relock_pg(pg_t & pg)
|
|||||||
bool unlock_peer = (i >= relock_osd_count);
|
bool unlock_peer = (i >= relock_osd_count);
|
||||||
uint64_t new_state = unlock_peer ? 0 : pg.state;
|
uint64_t new_state = unlock_peer ? 0 : pg.state;
|
||||||
auto peer_osd = diff_osds[i];
|
auto peer_osd = diff_osds[i];
|
||||||
auto peer_fd_it = msgr.osd_peer_fds.find(peer_osd);
|
auto peer_it = msgr.osd_peers.find(peer_osd);
|
||||||
if (peer_fd_it == msgr.osd_peer_fds.end())
|
if (peer_it == msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
if (unlock_peer)
|
if (unlock_peer)
|
||||||
{
|
{
|
||||||
@@ -446,8 +446,7 @@ void osd_t::relock_pg(pg_t & pg)
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int peer_fd = peer_fd_it->second;
|
auto cl = peer_it->second;
|
||||||
auto cl = msgr.clients.at(peer_fd);
|
|
||||||
if (!cl->enable_pg_locks)
|
if (!cl->enable_pg_locks)
|
||||||
{
|
{
|
||||||
// Peer does not support locking - just instantly remember the lock as successful
|
// Peer does not support locking - just instantly remember the lock as successful
|
||||||
@@ -458,7 +457,7 @@ void osd_t::relock_pg(pg_t & pg)
|
|||||||
pg.inflight_locks++;
|
pg.inflight_locks++;
|
||||||
osd_op_t *op = new osd_op_t();
|
osd_op_t *op = new osd_op_t();
|
||||||
op->op_type = OSD_OP_OUT;
|
op->op_type = OSD_OP_OUT;
|
||||||
op->peer_fd = peer_fd;
|
op->client_id = cl->client_id;
|
||||||
op->req = (osd_any_op_t){
|
op->req = (osd_any_op_t){
|
||||||
.sec_lock = {
|
.sec_lock = {
|
||||||
.header = {
|
.header = {
|
||||||
@@ -529,7 +528,7 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
|
|||||||
// Self
|
// Self
|
||||||
osd_op_t *op = new osd_op_t();
|
osd_op_t *op = new osd_op_t();
|
||||||
op->op_type = 0;
|
op->op_type = 0;
|
||||||
op->peer_fd = SELF_FD;
|
op->client_id = SELF_CLIENT;
|
||||||
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;
|
||||||
@@ -567,8 +566,8 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto role_fd_it = msgr.osd_peer_fds.find(role_osd);
|
auto peer_it = msgr.osd_peers.find(role_osd);
|
||||||
if (role_fd_it == msgr.osd_peer_fds.end())
|
if (peer_it == msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
printf("Failed to get object list from OSD %ju because it is disconnected\n", role_osd);
|
printf("Failed to get object list from OSD %ju because it is disconnected\n", role_osd);
|
||||||
return;
|
return;
|
||||||
@@ -576,7 +575,7 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
|
|||||||
// Peer
|
// Peer
|
||||||
osd_op_t *op = new osd_op_t();
|
osd_op_t *op = new osd_op_t();
|
||||||
op->op_type = OSD_OP_OUT;
|
op->op_type = OSD_OP_OUT;
|
||||||
op->peer_fd = role_fd_it->second;
|
op->client_id = peer_it->second->client_id;
|
||||||
op->req = (osd_any_op_t){
|
op->req = (osd_any_op_t){
|
||||||
.sec_list = {
|
.sec_list = {
|
||||||
.header = {
|
.header = {
|
||||||
@@ -595,10 +594,10 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
|
|||||||
if (op->reply.hdr.retval < 0)
|
if (op->reply.hdr.retval < 0)
|
||||||
{
|
{
|
||||||
printf("Failed to get object list from OSD %ju (retval=%jd), disconnecting peer\n", role_osd, op->reply.hdr.retval);
|
printf("Failed to get object list from OSD %ju (retval=%jd), disconnecting peer\n", role_osd, op->reply.hdr.retval);
|
||||||
int fail_fd = op->peer_fd;
|
uint64_t fail_client_id = op->client_id;
|
||||||
ps->list_ops.erase(role_osd);
|
ps->list_ops.erase(role_osd);
|
||||||
delete op;
|
delete op;
|
||||||
msgr.stop_client(fail_fd);
|
msgr.stop_client(fail_client_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf(
|
printf(
|
||||||
@@ -622,7 +621,7 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
|
|||||||
|
|
||||||
void osd_t::discard_list_subop(osd_op_t *list_op)
|
void osd_t::discard_list_subop(osd_op_t *list_op)
|
||||||
{
|
{
|
||||||
if (list_op->peer_fd == SELF_FD)
|
if (list_op->client_id == SELF_CLIENT)
|
||||||
{
|
{
|
||||||
// Self
|
// Self
|
||||||
list_op->bs_op->callback = [list_op](blockstore_op_t *bs_op)
|
list_op->bs_op->callback = [list_op](blockstore_op_t *bs_op)
|
||||||
|
|||||||
@@ -604,11 +604,11 @@ pg_osd_set_state_t* osd_t::add_object_to_set(pg_t & pg, const object_id oid, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrement pg_osd_set_state_t's object_count and change PG state accordingly
|
// Decrement pg_osd_set_state_t's object_count and change PG state accordingly
|
||||||
void osd_t::remove_object_from_state(object_id & oid, pg_osd_set_state_t **object_state, pg_t & pg, bool report)
|
bool osd_t::remove_object_from_state(object_id & oid, pg_osd_set_state_t **object_state, pg_t & pg, bool report)
|
||||||
{
|
{
|
||||||
if (!*object_state)
|
if (!*object_state)
|
||||||
{
|
{
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
pg_osd_set_state_t *recheck_state = NULL;
|
pg_osd_set_state_t *recheck_state = NULL;
|
||||||
get_object_osd_set(pg, oid, &recheck_state);
|
get_object_osd_set(pg, oid, &recheck_state);
|
||||||
@@ -617,7 +617,7 @@ void osd_t::remove_object_from_state(object_id & oid, pg_osd_set_state_t **objec
|
|||||||
recheck_state->ref_count++;
|
recheck_state->ref_count++;
|
||||||
(*object_state)->ref_count--;
|
(*object_state)->ref_count--;
|
||||||
*object_state = recheck_state;
|
*object_state = recheck_state;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
(*object_state)->object_count--;
|
(*object_state)->object_count--;
|
||||||
@@ -692,6 +692,7 @@ void osd_t::remove_object_from_state(object_id & oid, pg_osd_set_state_t **objec
|
|||||||
{
|
{
|
||||||
report_pg_state(pg);
|
report_pg_state(pg);
|
||||||
}
|
}
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_t::deref_object_state(pg_t & pg, pg_osd_set_state_t **object_state, bool deref)
|
void osd_t::deref_object_state(pg_t & pg, pg_osd_set_state_t **object_state, bool deref)
|
||||||
@@ -794,7 +795,7 @@ resume_5:
|
|||||||
{
|
{
|
||||||
this->dirty_osds.insert(chunk.osd_num);
|
this->dirty_osds.insert(chunk.osd_num);
|
||||||
}
|
}
|
||||||
for (auto cl_it = msgr.clients.find(cur_op->peer_fd); cl_it != msgr.clients.end(); )
|
for (auto cl_it = msgr.clients.find(cur_op->client_id); cl_it != msgr.clients.end(); )
|
||||||
{
|
{
|
||||||
cl_it->second->dirty_pgs.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
|
cl_it->second->dirty_pgs.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ int osd_t::read_bitmaps(osd_op_t *cur_op, pg_t *pg, int base_state)
|
|||||||
goto resume_0;
|
goto resume_0;
|
||||||
else if (op_data->st == base_state+1)
|
else if (op_data->st == base_state+1)
|
||||||
goto resume_1;
|
goto resume_1;
|
||||||
|
assert(op_data->st < base_state);
|
||||||
if (!pg || pg->state == PG_ACTIVE && pg->scheme == POOL_SCHEME_REPLICATED)
|
if (!pg || pg->state == PG_ACTIVE && pg->scheme == POOL_SCHEME_REPLICATED)
|
||||||
{
|
{
|
||||||
// Happy path for clean replicated PGs (all bitmaps are available locally)
|
// Happy path for clean replicated PGs (all bitmaps are available locally)
|
||||||
@@ -112,6 +113,12 @@ resume_0:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
resume_1:
|
resume_1:
|
||||||
|
if (op_data->errors > 0)
|
||||||
|
{
|
||||||
|
// Failure
|
||||||
|
finish_op(cur_op, op_data->errcode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (pg->scheme != POOL_SCHEME_REPLICATED)
|
if (pg->scheme != POOL_SCHEME_REPLICATED)
|
||||||
{
|
{
|
||||||
for (int chain_num = 0; chain_num < op_data->chain_size; chain_num++)
|
for (int chain_num = 0; chain_num < op_data->chain_size; chain_num++)
|
||||||
@@ -312,16 +319,16 @@ int osd_t::submit_bitmap_subops(osd_op_t *cur_op, pg_t & pg)
|
|||||||
}
|
}
|
||||||
handle_primary_subop(subop, cur_op);
|
handle_primary_subop(subop, cur_op);
|
||||||
};
|
};
|
||||||
auto peer_fd_it = msgr.osd_peer_fds.find(subop_osd_num);
|
auto peer_it = msgr.osd_peers.find(subop_osd_num);
|
||||||
if (peer_fd_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
subop->peer_fd = peer_fd_it->second;
|
subop->client_id = peer_it->second->client_id;
|
||||||
msgr.outbox_push(subop);
|
msgr.outbox_push(subop);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Fail it immediately
|
// Fail it immediately
|
||||||
subop->peer_fd = -1;
|
subop->client_id = 0;
|
||||||
subop->reply.hdr.retval = -EPIPE;
|
subop->reply.hdr.retval = -EPIPE;
|
||||||
ringloop->set_immediate([subop]() { std::function<void(osd_op_t*)>(subop->callback)(subop); });
|
ringloop->set_immediate([subop]() { std::function<void(osd_op_t*)>(subop->callback)(subop); });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "osd_primary.h"
|
#include "osd_primary.h"
|
||||||
|
|
||||||
#define SELF_FD -1
|
#define SELF_CLIENT 0
|
||||||
|
|
||||||
void osd_t::autosync()
|
void osd_t::autosync()
|
||||||
{
|
{
|
||||||
@@ -15,7 +15,7 @@ void osd_t::autosync()
|
|||||||
}
|
}
|
||||||
autosync_op = new osd_op_t();
|
autosync_op = new osd_op_t();
|
||||||
autosync_op->op_type = OSD_OP_IN;
|
autosync_op->op_type = OSD_OP_IN;
|
||||||
autosync_op->peer_fd = SELF_FD;
|
autosync_op->client_id = SELF_CLIENT;
|
||||||
autosync_op->req = (osd_any_op_t){
|
autosync_op->req = (osd_any_op_t){
|
||||||
.sync = {
|
.sync = {
|
||||||
.header = {
|
.header = {
|
||||||
@@ -90,7 +90,7 @@ void osd_t::finish_op(osd_op_t *cur_op, int retval)
|
|||||||
cur_op->reply.hdr.id = cur_op->req.hdr.id;
|
cur_op->reply.hdr.id = cur_op->req.hdr.id;
|
||||||
cur_op->reply.hdr.opcode = cur_op->req.hdr.opcode;
|
cur_op->reply.hdr.opcode = cur_op->req.hdr.opcode;
|
||||||
cur_op->reply.hdr.retval = retval;
|
cur_op->reply.hdr.retval = retval;
|
||||||
if (cur_op->peer_fd == SELF_FD)
|
if (cur_op->client_id == SELF_CLIENT)
|
||||||
{
|
{
|
||||||
// Do not include internal primary writes (recovery/rebalance) into client op statistics
|
// Do not include internal primary writes (recovery/rebalance) into client op statistics
|
||||||
if (cur_op->req.hdr.opcode != OSD_OP_WRITE)
|
if (cur_op->req.hdr.opcode != OSD_OP_WRITE)
|
||||||
@@ -103,7 +103,7 @@ void osd_t::finish_op(osd_op_t *cur_op, int retval)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIXME add separate magic number for primary ops
|
// FIXME add separate magic number for primary ops
|
||||||
auto cl_it = msgr.clients.find(cur_op->peer_fd);
|
auto cl_it = msgr.clients.find(cur_op->client_id);
|
||||||
if (cl_it != msgr.clients.end())
|
if (cl_it != msgr.clients.end())
|
||||||
{
|
{
|
||||||
msgr.outbox_push(cur_op);
|
msgr.outbox_push(cur_op);
|
||||||
@@ -243,7 +243,7 @@ void osd_t::submit_primary_subop(osd_op_t *cur_op, osd_op_t *subop,
|
|||||||
.offset = wr ? si->write_start : si->read_start,
|
.offset = wr ? si->write_start : si->read_start,
|
||||||
.len = subop_len,
|
.len = subop_len,
|
||||||
.attr_len = wr ? clean_entry_bitmap_size : 0,
|
.attr_len = wr ? clean_entry_bitmap_size : 0,
|
||||||
.flags = cur_op->peer_fd == SELF_FD && cur_op->req.hdr.opcode != OSD_OP_SCRUB ? OSD_OP_RECOVERY_RELATED : 0,
|
.flags = cur_op->client_id == SELF_CLIENT && cur_op->req.hdr.opcode != OSD_OP_SCRUB ? OSD_OP_RECOVERY_RELATED : 0,
|
||||||
};
|
};
|
||||||
#ifdef OSD_DEBUG
|
#ifdef OSD_DEBUG
|
||||||
printf(
|
printf(
|
||||||
@@ -270,16 +270,16 @@ void osd_t::submit_primary_subop(osd_op_t *cur_op, osd_op_t *subop,
|
|||||||
{
|
{
|
||||||
handle_primary_subop(subop, cur_op);
|
handle_primary_subop(subop, cur_op);
|
||||||
};
|
};
|
||||||
auto peer_fd_it = msgr.osd_peer_fds.find(si->osd_num);
|
auto peer_it = msgr.osd_peers.find(si->osd_num);
|
||||||
if (peer_fd_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
subop->peer_fd = peer_fd_it->second;
|
subop->client_id = peer_it->second->client_id;
|
||||||
msgr.outbox_push(subop);
|
msgr.outbox_push(subop);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Fail it immediately
|
// Fail it immediately
|
||||||
subop->peer_fd = -1;
|
subop->client_id = 0;
|
||||||
subop->reply.hdr.retval = -EPIPE;
|
subop->reply.hdr.retval = -EPIPE;
|
||||||
ringloop->set_immediate([subop]() { std::function<void(osd_op_t*)>(subop->callback)(subop); });
|
ringloop->set_immediate([subop]() { std::function<void(osd_op_t*)>(subop->callback)(subop); });
|
||||||
}
|
}
|
||||||
@@ -326,7 +326,7 @@ void osd_t::handle_primary_bs_subop(osd_op_t *subop)
|
|||||||
}
|
}
|
||||||
throw std::runtime_error("local blockstore modification failed");
|
throw std::runtime_error("local blockstore modification failed");
|
||||||
}
|
}
|
||||||
bool recovery_related = cur_op->peer_fd == SELF_FD && cur_op->req.hdr.opcode != OSD_OP_SCRUB;
|
bool recovery_related = cur_op->client_id == SELF_CLIENT && cur_op->req.hdr.opcode != OSD_OP_SCRUB;
|
||||||
add_bs_subop_stats(subop, recovery_related);
|
add_bs_subop_stats(subop, recovery_related);
|
||||||
subop->req.hdr.opcode = bs_op_to_osd_op[bs_op->opcode];
|
subop->req.hdr.opcode = bs_op_to_osd_op[bs_op->opcode];
|
||||||
subop->reply.hdr.retval = bs_op->retval;
|
subop->reply.hdr.retval = bs_op->retval;
|
||||||
@@ -339,7 +339,7 @@ void osd_t::handle_primary_bs_subop(osd_op_t *subop)
|
|||||||
}
|
}
|
||||||
delete bs_op;
|
delete bs_op;
|
||||||
subop->bs_op = NULL;
|
subop->bs_op = NULL;
|
||||||
subop->peer_fd = SELF_FD;
|
subop->client_id = SELF_CLIENT;
|
||||||
if (recovery_related && recovery_target_sleep_us)
|
if (recovery_related && recovery_target_sleep_us)
|
||||||
{
|
{
|
||||||
tfd->set_timer_us(recovery_target_sleep_us, false, [=](int timer_id)
|
tfd->set_timer_us(recovery_target_sleep_us, false, [=](int timer_id)
|
||||||
@@ -399,11 +399,15 @@ void osd_t::handle_primary_subop(osd_op_t *subop, osd_op_t *cur_op)
|
|||||||
{
|
{
|
||||||
uint64_t version = subop->reply.sec_rw.version;
|
uint64_t version = subop->reply.sec_rw.version;
|
||||||
#ifdef OSD_DEBUG
|
#ifdef OSD_DEBUG
|
||||||
int64_t peer_osd = subop->peer_fd == SELF_FD ? osd_num :
|
if (subop->client_id == SELF_CLIENT)
|
||||||
(msgr.clients.find(subop->peer_fd) != msgr.clients.end()
|
printf("subop %s %jx:%jx from local: version = %ju\n", osd_op_names[opcode],
|
||||||
? msgr.clients[subop->peer_fd]->osd_num : -subop->peer_fd);
|
subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, version);
|
||||||
printf("subop %s %jx:%jx from osd %jd: version = %ju\n", osd_op_names[opcode],
|
else if (msgr.clients.find(subop->client_id) != msgr.clients.end())
|
||||||
subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, peer_osd, version);
|
printf("subop %s %jx:%jx from osd %ju: version = %ju\n", osd_op_names[opcode],
|
||||||
|
subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, msgr.clients.at(subop->client_id)->osd_num, version);
|
||||||
|
else
|
||||||
|
printf("subop %s %jx:%jx from client %ju: version = %ju\n", osd_op_names[opcode],
|
||||||
|
subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, subop->client_id, version);
|
||||||
#endif
|
#endif
|
||||||
if (version != 0 && op_data->fact_ver != UINT64_MAX)
|
if (version != 0 && op_data->fact_ver != UINT64_MAX)
|
||||||
{
|
{
|
||||||
@@ -422,16 +426,16 @@ void osd_t::handle_primary_subop(osd_op_t *subop, osd_op_t *cur_op)
|
|||||||
}
|
}
|
||||||
if (retval != expected)
|
if (retval != expected)
|
||||||
{
|
{
|
||||||
int64_t peer_osd = (msgr.clients.find(subop->peer_fd) != msgr.clients.end()
|
int64_t peer_osd = (msgr.clients.find(subop->client_id) != msgr.clients.end()
|
||||||
? msgr.clients[subop->peer_fd]->osd_num : 0);
|
? msgr.clients.at(subop->client_id)->osd_num : 0);
|
||||||
if (opcode == OSD_OP_SEC_READ || opcode == OSD_OP_SEC_WRITE || opcode == OSD_OP_SEC_WRITE_STABLE)
|
if (opcode == OSD_OP_SEC_READ || opcode == OSD_OP_SEC_WRITE || opcode == OSD_OP_SEC_WRITE_STABLE)
|
||||||
{
|
{
|
||||||
printf("%s subop to %jx:%jx v%ju failed ", osd_op_names[opcode],
|
printf("%s subop to %jx:%jx v%ju failed ", osd_op_names[opcode],
|
||||||
subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, subop->req.sec_rw.version);
|
subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, subop->req.sec_rw.version);
|
||||||
if (subop->peer_fd >= 0 && peer_osd > 0)
|
if (subop->client_id && peer_osd > 0)
|
||||||
printf("on osd %ju: retval = %d (expected %d)\n", peer_osd, retval, expected);
|
printf("on osd %ju: retval = %d (expected %d)\n", peer_osd, retval, expected);
|
||||||
else if (peer_osd > 0)
|
else if (subop->client_id)
|
||||||
printf("on peer %d: retval = %d (expected %d)\n", subop->peer_fd, retval, expected);
|
printf("on client %ju: retval = %d (expected %d)\n", subop->client_id, retval, expected);
|
||||||
else
|
else
|
||||||
printf("locally: retval = %d (expected %d)\n", retval, expected);
|
printf("locally: retval = %d (expected %d)\n", retval, expected);
|
||||||
}
|
}
|
||||||
@@ -446,7 +450,7 @@ void osd_t::handle_primary_subop(osd_op_t *subop, osd_op_t *cur_op)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
"%s subop failed on osd %jd: retval = %d (expected %d)\n",
|
"%s subop failed on osd %ju: retval = %d (expected %d)\n",
|
||||||
osd_op_names[opcode], peer_osd, retval, expected
|
osd_op_names[opcode], peer_osd, retval, expected
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -460,12 +464,12 @@ void osd_t::handle_primary_subop(osd_op_t *subop, osd_op_t *cur_op)
|
|||||||
{
|
{
|
||||||
op_data->errcode = retval;
|
op_data->errcode = retval;
|
||||||
}
|
}
|
||||||
if (subop->peer_fd >= 0 && retval != -EDOM && retval != -ERANGE &&
|
if (subop->client_id && retval != -EDOM && retval != -ERANGE &&
|
||||||
(retval != -ENOSPC || opcode != OSD_OP_SEC_WRITE && opcode != OSD_OP_SEC_WRITE_STABLE) &&
|
(retval != -ENOSPC || opcode != OSD_OP_SEC_WRITE && opcode != OSD_OP_SEC_WRITE_STABLE) &&
|
||||||
(retval != -EIO || opcode != OSD_OP_SEC_READ))
|
(retval != -EIO || opcode != OSD_OP_SEC_READ))
|
||||||
{
|
{
|
||||||
// Drop connection on unexpected errors
|
// Drop connection on unexpected errors
|
||||||
msgr.stop_client(subop->peer_fd);
|
msgr.stop_client(subop->client_id);
|
||||||
op_data->drops++;
|
op_data->drops++;
|
||||||
}
|
}
|
||||||
// Increase op_data->errors after stop_client to prevent >= n_subops running twice
|
// Increase op_data->errors after stop_client to prevent >= n_subops running twice
|
||||||
@@ -606,22 +610,22 @@ void osd_t::submit_primary_del_batch(osd_op_t *cur_op, obj_ver_osd_t *chunks_to_
|
|||||||
},
|
},
|
||||||
.oid = chunk.oid,
|
.oid = chunk.oid,
|
||||||
.version = chunk.version,
|
.version = chunk.version,
|
||||||
.flags = cur_op->peer_fd == SELF_FD && cur_op->req.hdr.opcode != OSD_OP_SCRUB ? OSD_OP_RECOVERY_RELATED : 0,
|
.flags = cur_op->client_id == SELF_CLIENT && cur_op->req.hdr.opcode != OSD_OP_SCRUB ? OSD_OP_RECOVERY_RELATED : 0,
|
||||||
} };
|
} };
|
||||||
subops[i].callback = [cur_op, this](osd_op_t *subop)
|
subops[i].callback = [cur_op, this](osd_op_t *subop)
|
||||||
{
|
{
|
||||||
handle_primary_subop(subop, cur_op);
|
handle_primary_subop(subop, cur_op);
|
||||||
};
|
};
|
||||||
auto peer_fd_it = msgr.osd_peer_fds.find(chunk.osd_num);
|
auto peer_it = msgr.osd_peers.find(chunk.osd_num);
|
||||||
if (peer_fd_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
subops[i].peer_fd = peer_fd_it->second;
|
subops[i].client_id = peer_it->second->client_id;
|
||||||
msgr.outbox_push(&subops[i]);
|
msgr.outbox_push(&subops[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Fail it immediately
|
// Fail it immediately
|
||||||
subops[i].peer_fd = -1;
|
subops[i].client_id = 0;
|
||||||
subops[i].reply.hdr.retval = -EPIPE;
|
subops[i].reply.hdr.retval = -EPIPE;
|
||||||
ringloop->set_immediate([subop = &subops[i]]() { std::function<void(osd_op_t*)>(subop->callback)(subop); });
|
ringloop->set_immediate([subop = &subops[i]]() { std::function<void(osd_op_t*)>(subop->callback)(subop); });
|
||||||
}
|
}
|
||||||
@@ -637,7 +641,7 @@ int osd_t::submit_primary_sync_subops(osd_op_t *cur_op)
|
|||||||
op_data->done = op_data->errors = op_data->errcode = 0;
|
op_data->done = op_data->errors = op_data->errcode = 0;
|
||||||
op_data->n_subops = n_osds;
|
op_data->n_subops = n_osds;
|
||||||
op_data->subops = subops;
|
op_data->subops = subops;
|
||||||
std::map<uint64_t, int>::iterator peer_it;
|
robin_hood::unordered_flat_map<uint64_t, osd_client_t*>::iterator peer_it;
|
||||||
for (int i = 0; i < n_osds; i++)
|
for (int i = 0; i < n_osds; i++)
|
||||||
{
|
{
|
||||||
osd_num_t sync_osd = op_data->dirty_osds[i];
|
osd_num_t sync_osd = op_data->dirty_osds[i];
|
||||||
@@ -654,16 +658,16 @@ int osd_t::submit_primary_sync_subops(osd_op_t *cur_op)
|
|||||||
});
|
});
|
||||||
bs->enqueue_op(subops[i].bs_op);
|
bs->enqueue_op(subops[i].bs_op);
|
||||||
}
|
}
|
||||||
else if ((peer_it = msgr.osd_peer_fds.find(sync_osd)) != msgr.osd_peer_fds.end())
|
else if ((peer_it = msgr.osd_peers.find(sync_osd)) != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
subops[i].op_type = OSD_OP_OUT;
|
subops[i].op_type = OSD_OP_OUT;
|
||||||
subops[i].peer_fd = peer_it->second;
|
subops[i].client_id = peer_it->second->client_id;
|
||||||
subops[i].req = (osd_any_op_t){ .sec_sync = {
|
subops[i].req = (osd_any_op_t){ .sec_sync = {
|
||||||
.header = {
|
.header = {
|
||||||
.magic = SECONDARY_OSD_OP_MAGIC,
|
.magic = SECONDARY_OSD_OP_MAGIC,
|
||||||
.opcode = OSD_OP_SEC_SYNC,
|
.opcode = OSD_OP_SEC_SYNC,
|
||||||
},
|
},
|
||||||
.flags = cur_op->peer_fd == SELF_FD && cur_op->req.hdr.opcode != OSD_OP_SCRUB ? OSD_OP_RECOVERY_RELATED : 0,
|
.flags = cur_op->client_id == SELF_CLIENT && cur_op->req.hdr.opcode != OSD_OP_SCRUB ? OSD_OP_RECOVERY_RELATED : 0,
|
||||||
} };
|
} };
|
||||||
subops[i].callback = [cur_op, this](osd_op_t *subop)
|
subops[i].callback = [cur_op, this](osd_op_t *subop)
|
||||||
{
|
{
|
||||||
@@ -722,23 +726,23 @@ void osd_t::submit_primary_stab_subops(osd_op_t *cur_op)
|
|||||||
.opcode = OSD_OP_SEC_STABILIZE,
|
.opcode = OSD_OP_SEC_STABILIZE,
|
||||||
},
|
},
|
||||||
.len = (uint64_t)(stab_osd.len * sizeof(obj_ver_id)),
|
.len = (uint64_t)(stab_osd.len * sizeof(obj_ver_id)),
|
||||||
.flags = cur_op->peer_fd == SELF_FD && cur_op->req.hdr.opcode != OSD_OP_SCRUB ? OSD_OP_RECOVERY_RELATED : 0,
|
.flags = cur_op->client_id == SELF_CLIENT && cur_op->req.hdr.opcode != OSD_OP_SCRUB ? OSD_OP_RECOVERY_RELATED : 0,
|
||||||
} };
|
} };
|
||||||
subops[i].iov.push_back(op_data->unstable_writes + stab_osd.start, stab_osd.len * sizeof(obj_ver_id));
|
subops[i].iov.push_back(op_data->unstable_writes + stab_osd.start, stab_osd.len * sizeof(obj_ver_id));
|
||||||
subops[i].callback = [cur_op, this](osd_op_t *subop)
|
subops[i].callback = [cur_op, this](osd_op_t *subop)
|
||||||
{
|
{
|
||||||
handle_primary_subop(subop, cur_op);
|
handle_primary_subop(subop, cur_op);
|
||||||
};
|
};
|
||||||
auto peer_fd_it = msgr.osd_peer_fds.find(stab_osd.osd_num);
|
auto peer_it = msgr.osd_peers.find(stab_osd.osd_num);
|
||||||
if (peer_fd_it != msgr.osd_peer_fds.end())
|
if (peer_it != msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
subops[i].peer_fd = peer_fd_it->second;
|
subops[i].client_id = peer_it->second->client_id;
|
||||||
msgr.outbox_push(&subops[i]);
|
msgr.outbox_push(&subops[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Fail it immediately
|
// Fail it immediately
|
||||||
subops[i].peer_fd = -1;
|
subops[i].client_id = 0;
|
||||||
subops[i].reply.hdr.retval = -EPIPE;
|
subops[i].reply.hdr.retval = -EPIPE;
|
||||||
ringloop->set_immediate([subop = &subops[i]]() { std::function<void(osd_op_t*)>(subop->callback)(subop); });
|
ringloop->set_immediate([subop = &subops[i]]() { std::function<void(osd_op_t*)>(subop->callback)(subop); });
|
||||||
}
|
}
|
||||||
@@ -756,7 +760,7 @@ void osd_t::submit_primary_rollback_subops(osd_op_t *cur_op, const uint64_t* osd
|
|||||||
for (int role = 0; role < op_data->pg->pg_size; role++)
|
for (int role = 0; role < op_data->pg->pg_size; role++)
|
||||||
{
|
{
|
||||||
if (osd_set[role] != 0 && !stripes[role].read_error &&
|
if (osd_set[role] != 0 && !stripes[role].read_error &&
|
||||||
(osd_set[role] == this->osd_num || msgr.osd_peer_fds.find(osd_set[role]) != msgr.osd_peer_fds.end()))
|
(osd_set[role] == this->osd_num || msgr.osd_peers.find(osd_set[role]) != msgr.osd_peers.end()))
|
||||||
{
|
{
|
||||||
n_subops++;
|
n_subops++;
|
||||||
}
|
}
|
||||||
@@ -773,7 +777,7 @@ void osd_t::submit_primary_rollback_subops(osd_op_t *cur_op, const uint64_t* osd
|
|||||||
for (int role = 0; role < op_data->pg->pg_size; role++)
|
for (int role = 0; role < op_data->pg->pg_size; role++)
|
||||||
{
|
{
|
||||||
if (osd_set[role] != 0 && !stripes[role].read_error &&
|
if (osd_set[role] != 0 && !stripes[role].read_error &&
|
||||||
(osd_set[role] == this->osd_num || msgr.osd_peer_fds.find(osd_set[role]) != msgr.osd_peer_fds.end()))
|
(osd_set[role] == this->osd_num || msgr.osd_peers.find(osd_set[role]) != msgr.osd_peers.end()))
|
||||||
{
|
{
|
||||||
osd_op_t *subop = &op_data->subops[i];
|
osd_op_t *subop = &op_data->subops[i];
|
||||||
op_data->unstable_writes[i] = (obj_ver_id){
|
op_data->unstable_writes[i] = (obj_ver_id){
|
||||||
@@ -827,7 +831,7 @@ void osd_t::submit_primary_rollback_subops(osd_op_t *cur_op, const uint64_t* osd
|
|||||||
op_data->oid.inode, op_data->oid.stripe | role, op_data->target_ver-1
|
op_data->oid.inode, op_data->oid.stripe | role, op_data->target_ver-1
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
subop->peer_fd = msgr.osd_peer_fds.at(osd_set[role]);
|
subop->client_id = msgr.osd_peers.at(osd_set[role])->client_id;
|
||||||
msgr.outbox_push(subop);
|
msgr.outbox_push(subop);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|||||||
@@ -247,9 +247,9 @@ resume_8:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
finish:
|
finish:
|
||||||
if (cur_op->peer_fd)
|
if (cur_op->client_id)
|
||||||
{
|
{
|
||||||
auto it = msgr.clients.find(cur_op->peer_fd);
|
auto it = msgr.clients.find(cur_op->client_id);
|
||||||
if (it != msgr.clients.end())
|
if (it != msgr.clients.end())
|
||||||
it->second->dirty_pgs.clear();
|
it->second->dirty_pgs.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ resume_12:
|
|||||||
{
|
{
|
||||||
// Any kind of a non-clean object can have extra chunks, because we don't record objects
|
// Any kind of a non-clean object can have extra chunks, because we don't record objects
|
||||||
// as degraded & misplaced or incomplete & misplaced at the same time. So try to remove extra chunks
|
// as degraded & misplaced or incomplete & misplaced at the same time. So try to remove extra chunks
|
||||||
|
bool changed = false;
|
||||||
if (immediate_commit != IMMEDIATE_ALL)
|
if (immediate_commit != IMMEDIATE_ALL)
|
||||||
{
|
{
|
||||||
// We can't remove extra chunks yet if fsyncs are explicit, because
|
// We can't remove extra chunks yet if fsyncs are explicit, because
|
||||||
@@ -303,13 +304,21 @@ resume_12:
|
|||||||
{
|
{
|
||||||
// PG can't be active+clean until extra copies aren't removed, so mark it as PG_HAS_MISPLACED
|
// PG can't be active+clean until extra copies aren't removed, so mark it as PG_HAS_MISPLACED
|
||||||
pg.state |= PG_HAS_MISPLACED;
|
pg.state |= PG_HAS_MISPLACED;
|
||||||
//this->pg_state_dirty.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
|
changed = true;
|
||||||
|
this->pg_state_dirty.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We must forget the unclean state of the object before deleting it
|
// We must forget the unclean state of the object before deleting it
|
||||||
// so the next reads don't accidentally read a deleted version
|
// so the next reads don't accidentally read a deleted version
|
||||||
// And it should be done at the same time as the removal of the version override
|
// And it should be done at the same time as the removal of the version override
|
||||||
remove_object_from_state(op_data->oid, &op_data->object_state, pg);
|
if (remove_object_from_state(op_data->oid, &op_data->object_state, pg, false))
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
report_pg_state(pg);
|
||||||
|
}
|
||||||
pg.clean_count++;
|
pg.clean_count++;
|
||||||
}
|
}
|
||||||
resume_6:
|
resume_6:
|
||||||
@@ -536,7 +545,7 @@ lazy:
|
|||||||
}
|
}
|
||||||
// Remember PG as dirty to drop the connection when PG goes offline
|
// Remember PG as dirty to drop the connection when PG goes offline
|
||||||
// (this is required because of the "lazy sync")
|
// (this is required because of the "lazy sync")
|
||||||
auto cl_it = msgr.clients.find(cur_op->peer_fd);
|
auto cl_it = msgr.clients.find(cur_op->client_id);
|
||||||
if (cl_it != msgr.clients.end())
|
if (cl_it != msgr.clients.end())
|
||||||
{
|
{
|
||||||
cl_it->second->dirty_pgs.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
|
cl_it->second->dirty_pgs.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "osd_primary.h"
|
#include "osd_primary.h"
|
||||||
|
|
||||||
#define SELF_FD -1
|
#define SELF_CLIENT 0
|
||||||
|
|
||||||
void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oid)
|
void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oid)
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
|
|||||||
// Self
|
// Self
|
||||||
osd_op_t *op = new osd_op_t();
|
osd_op_t *op = new osd_op_t();
|
||||||
op->op_type = 0;
|
op->op_type = 0;
|
||||||
op->peer_fd = SELF_FD;
|
op->client_id = SELF_CLIENT;
|
||||||
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;
|
||||||
@@ -61,7 +61,7 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
|
|||||||
// Peer
|
// Peer
|
||||||
osd_op_t *op = new osd_op_t();
|
osd_op_t *op = new osd_op_t();
|
||||||
op->op_type = OSD_OP_OUT;
|
op->op_type = OSD_OP_OUT;
|
||||||
op->peer_fd = msgr.osd_peer_fds.at(role_osd);
|
op->client_id = msgr.osd_peers.at(role_osd)->client_id;
|
||||||
op->req = (osd_any_op_t){
|
op->req = (osd_any_op_t){
|
||||||
.sec_list = {
|
.sec_list = {
|
||||||
.header = {
|
.header = {
|
||||||
@@ -83,9 +83,9 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
|
|||||||
if (op->reply.hdr.retval < 0)
|
if (op->reply.hdr.retval < 0)
|
||||||
{
|
{
|
||||||
printf("Failed to get object list from OSD %ju (retval=%jd), disconnecting peer\n", role_osd, op->reply.hdr.retval);
|
printf("Failed to get object list from OSD %ju (retval=%jd), disconnecting peer\n", role_osd, op->reply.hdr.retval);
|
||||||
int fail_fd = op->peer_fd;
|
uint64_t fail_client_id = op->client_id;
|
||||||
delete op;
|
delete op;
|
||||||
msgr.stop_client(fail_fd);
|
msgr.stop_client(fail_client_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scrub_cur_list = {
|
scrub_cur_list = {
|
||||||
@@ -224,7 +224,7 @@ void osd_t::submit_scrub_op(object_id oid)
|
|||||||
{
|
{
|
||||||
auto osd_op = new osd_op_t();
|
auto osd_op = new osd_op_t();
|
||||||
osd_op->op_type = OSD_OP_OUT;
|
osd_op->op_type = OSD_OP_OUT;
|
||||||
osd_op->peer_fd = -1;
|
osd_op->client_id = SELF_CLIENT;
|
||||||
osd_op->req = (osd_any_op_t){
|
osd_op->req = (osd_any_op_t){
|
||||||
.rw = {
|
.rw = {
|
||||||
.header = {
|
.header = {
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
|
|||||||
exec_sec_lock(cur_op);
|
exec_sec_lock(cur_op);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto cl = msgr.clients.at(cur_op->peer_fd);
|
osd_client_t *cl = msgr.clients.at(cur_op->client_id);
|
||||||
cur_op->bs_op = new blockstore_op_t();
|
cur_op->bs_op = new blockstore_op_t();
|
||||||
cur_op->bs_op->callback = [this, cur_op](blockstore_op_t* bs_op) { secondary_op_callback(cur_op); };
|
cur_op->bs_op->callback = [this, cur_op](blockstore_op_t* bs_op) { secondary_op_callback(cur_op); };
|
||||||
cur_op->bs_op->opcode = (cur_op->req.hdr.opcode == OSD_OP_SEC_READ ? BS_OP_READ
|
cur_op->bs_op->opcode = (cur_op->req.hdr.opcode == OSD_OP_SEC_READ ? BS_OP_READ
|
||||||
@@ -249,7 +249,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
|
|||||||
|
|
||||||
void osd_t::exec_sec_read_bmp(osd_op_t *cur_op)
|
void osd_t::exec_sec_read_bmp(osd_op_t *cur_op)
|
||||||
{
|
{
|
||||||
auto cl = msgr.clients.at(cur_op->peer_fd);
|
auto cl = msgr.clients.at(cur_op->client_id);
|
||||||
int n = cur_op->req.sec_read_bmp.len / sizeof(obj_ver_id);
|
int n = cur_op->req.sec_read_bmp.len / sizeof(obj_ver_id);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
@@ -278,7 +278,7 @@ void osd_t::exec_sec_read_bmp(osd_op_t *cur_op)
|
|||||||
void osd_t::exec_sec_lock(osd_op_t *cur_op)
|
void osd_t::exec_sec_lock(osd_op_t *cur_op)
|
||||||
{
|
{
|
||||||
cur_op->reply.sec_lock.cur_primary = 0;
|
cur_op->reply.sec_lock.cur_primary = 0;
|
||||||
auto cl = msgr.clients.at(cur_op->peer_fd);
|
auto cl = msgr.clients.at(cur_op->client_id);
|
||||||
if (!cl->in_osd_num ||
|
if (!cl->in_osd_num ||
|
||||||
cur_op->req.sec_lock.flags != OSD_SEC_LOCK_PG &&
|
cur_op->req.sec_lock.flags != OSD_SEC_LOCK_PG &&
|
||||||
cur_op->req.sec_lock.flags != OSD_SEC_UNLOCK_PG ||
|
cur_op->req.sec_lock.flags != OSD_SEC_UNLOCK_PG ||
|
||||||
@@ -340,7 +340,7 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
|
|||||||
? json11::Json::parse(std::string((char *)cur_op->buf), json_err)
|
? json11::Json::parse(std::string((char *)cur_op->buf), json_err)
|
||||||
: json11::Json();
|
: json11::Json();
|
||||||
auto peer_osd_num = req_json["osd_num"].uint64_value();
|
auto peer_osd_num = req_json["osd_num"].uint64_value();
|
||||||
auto cl = msgr.clients.at(cur_op->peer_fd);
|
auto cl = msgr.clients.at(cur_op->client_id);
|
||||||
cl->in_osd_num = peer_osd_num;
|
cl->in_osd_num = peer_osd_num;
|
||||||
if (req_json["features"]["check_sequencing"].bool_value())
|
if (req_json["features"]["check_sequencing"].bool_value())
|
||||||
{
|
{
|
||||||
@@ -369,7 +369,7 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
|
|||||||
if (req_json["connect_rdma"].is_string())
|
if (req_json["connect_rdma"].is_string())
|
||||||
{
|
{
|
||||||
// Peer is trying to connect using RDMA, try to satisfy him
|
// Peer is trying to connect using RDMA, try to satisfy him
|
||||||
bool ok = msgr.connect_rdma(cur_op->peer_fd, req_json["connect_rdma"].string_value(), req_json["rdma_max_msg"].uint64_value());
|
bool ok = msgr.connect_rdma(cur_op->client_id, req_json["connect_rdma"].string_value(), req_json["rdma_max_msg"].uint64_value());
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
auto rc = cl->rdma_conn;
|
auto rc = cl->rdma_conn;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8...3.30)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ osd_messenger_t::~osd_messenger_t()
|
|||||||
{
|
{
|
||||||
while (clients.size() > 0)
|
while (clients.size() > 0)
|
||||||
{
|
{
|
||||||
stop_client(clients.begin()->first, true, true);
|
stop_client(clients.begin()->first, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
||||||
{
|
{
|
||||||
auto cl = clients.at(cur_op->peer_fd);
|
auto cl = clients.at(cur_op->client_id);
|
||||||
cur_op->req.hdr.id = ++cl->send_op_id;
|
cur_op->req.hdr.id = ++cl->send_op_id;
|
||||||
cl->sent_ops[cur_op->req.hdr.id] = cur_op;
|
cl->sent_ops[cur_op->req.hdr.id] = cur_op;
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,3 @@ json11::Json::object osd_messenger_t::merge_configs(const json11::Json::object &
|
|||||||
{
|
{
|
||||||
return cli_config;
|
return cli_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_messenger_t::clear_immediate_ops(int peer_fd)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ void stub_exec_op(osd_messenger_t *msgr, osd_op_t *op)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("client %d: unsupported stub opcode: %ju\n", op->peer_fd, op->req.hdr.opcode);
|
printf("client %ju: unsupported stub opcode: %ju\n", op->client_id, op->req.hdr.opcode);
|
||||||
op->reply.hdr.retval = -EINVAL;
|
op->reply.hdr.retval = -EINVAL;
|
||||||
}
|
}
|
||||||
msgr->outbox_push(op);
|
msgr->outbox_push(op);
|
||||||
|
|||||||
@@ -118,11 +118,14 @@ void pretend_connected(cluster_client_t *cli, osd_num_t osd_num)
|
|||||||
{
|
{
|
||||||
printf("OSD %ju connected\n", osd_num);
|
printf("OSD %ju connected\n", osd_num);
|
||||||
int peer_fd = cli->msgr.clients.size() ? std::prev(cli->msgr.clients.end())->first+1 : 10;
|
int peer_fd = cli->msgr.clients.size() ? std::prev(cli->msgr.clients.end())->first+1 : 10;
|
||||||
cli->msgr.osd_peer_fds[osd_num] = peer_fd;
|
auto cl = new osd_client_t();
|
||||||
cli->msgr.clients[peer_fd] = new osd_client_t();
|
cl->client_id = cli->msgr.next_client_id++;
|
||||||
cli->msgr.clients[peer_fd]->osd_num = osd_num;
|
cl->osd_num = osd_num;
|
||||||
cli->msgr.clients[peer_fd]->peer_fd = peer_fd;
|
cl->peer_fd = peer_fd;
|
||||||
cli->msgr.clients[peer_fd]->peer_state = PEER_CONNECTED;
|
cl->peer_state = PEER_CONNECTED;
|
||||||
|
cli->msgr.osd_peers[osd_num] = cl;
|
||||||
|
cli->msgr.clients[cl->client_id] = cl;
|
||||||
|
cli->msgr.clients_by_fd[peer_fd] = cl;
|
||||||
cli->msgr.wanted_peers.erase(osd_num);
|
cli->msgr.wanted_peers.erase(osd_num);
|
||||||
cli->msgr.repeer_pgs(osd_num);
|
cli->msgr.repeer_pgs(osd_num);
|
||||||
}
|
}
|
||||||
@@ -130,12 +133,12 @@ void pretend_connected(cluster_client_t *cli, osd_num_t osd_num)
|
|||||||
void pretend_disconnected(cluster_client_t *cli, osd_num_t osd_num)
|
void pretend_disconnected(cluster_client_t *cli, osd_num_t osd_num)
|
||||||
{
|
{
|
||||||
printf("OSD %ju disconnected\n", osd_num);
|
printf("OSD %ju disconnected\n", osd_num);
|
||||||
cli->msgr.stop_client(cli->msgr.osd_peer_fds.at(osd_num));
|
cli->msgr.stop_client(cli->msgr.osd_peers.at(osd_num)->client_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_disconnected(cluster_client_t *cli, osd_num_t osd_num)
|
void check_disconnected(cluster_client_t *cli, osd_num_t osd_num)
|
||||||
{
|
{
|
||||||
if (cli->msgr.osd_peer_fds.find(osd_num) != cli->msgr.osd_peer_fds.end())
|
if (cli->msgr.osd_peers.find(osd_num) != cli->msgr.osd_peers.end())
|
||||||
{
|
{
|
||||||
printf("OSD %ju not disconnected as it ought to be\n", osd_num);
|
printf("OSD %ju not disconnected as it ought to be\n", osd_num);
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -144,8 +147,8 @@ void check_disconnected(cluster_client_t *cli, osd_num_t osd_num)
|
|||||||
|
|
||||||
void check_op_count(cluster_client_t *cli, osd_num_t osd_num, int ops)
|
void check_op_count(cluster_client_t *cli, osd_num_t osd_num, int ops)
|
||||||
{
|
{
|
||||||
int peer_fd = cli->msgr.osd_peer_fds.at(osd_num);
|
osd_client_t *cl = cli->msgr.osd_peers.at(osd_num);
|
||||||
int real_ops = cli->msgr.clients[peer_fd]->sent_ops.size();
|
int real_ops = cl->sent_ops.size();
|
||||||
if (real_ops != ops)
|
if (real_ops != ops)
|
||||||
{
|
{
|
||||||
printf("error: %d ops expected, but %d queued\n", ops, real_ops);
|
printf("error: %d ops expected, but %d queued\n", ops, real_ops);
|
||||||
@@ -155,9 +158,9 @@ void check_op_count(cluster_client_t *cli, osd_num_t osd_num, int ops)
|
|||||||
|
|
||||||
osd_op_t *find_op(cluster_client_t *cli, osd_num_t osd_num, uint64_t opcode, uint64_t offset, uint64_t len)
|
osd_op_t *find_op(cluster_client_t *cli, osd_num_t osd_num, uint64_t opcode, uint64_t offset, uint64_t len)
|
||||||
{
|
{
|
||||||
int peer_fd = cli->msgr.osd_peer_fds.at(osd_num);
|
osd_client_t *cl = cli->msgr.osd_peers.at(osd_num);
|
||||||
auto op_it = cli->msgr.clients[peer_fd]->sent_ops.begin();
|
auto op_it = cl->sent_ops.begin();
|
||||||
while (op_it != cli->msgr.clients[peer_fd]->sent_ops.end())
|
while (op_it != cl->sent_ops.end())
|
||||||
{
|
{
|
||||||
auto op = op_it->second;
|
auto op = op_it->second;
|
||||||
if (op->req.hdr.opcode == opcode && (opcode == OSD_OP_SYNC ||
|
if (op->req.hdr.opcode == opcode && (opcode == OSD_OP_SYNC ||
|
||||||
@@ -167,8 +170,8 @@ osd_op_t *find_op(cluster_client_t *cli, osd_num_t osd_num, uint64_t opcode, uin
|
|||||||
}
|
}
|
||||||
op_it++;
|
op_it++;
|
||||||
}
|
}
|
||||||
op_it = cli->msgr.clients[peer_fd]->sent_ops.begin();
|
op_it = cl->sent_ops.begin();
|
||||||
while (op_it != cli->msgr.clients[peer_fd]->sent_ops.end())
|
while (op_it != cl->sent_ops.end())
|
||||||
{
|
{
|
||||||
printf("Found opcode %ju offset %jx size %x\n", op_it->second->req.hdr.opcode, op_it->second->req.rw.offset, op_it->second->req.rw.len);
|
printf("Found opcode %ju offset %jx size %x\n", op_it->second->req.hdr.opcode, op_it->second->req.rw.offset, op_it->second->req.rw.len);
|
||||||
op_it++;
|
op_it++;
|
||||||
@@ -183,8 +186,8 @@ void pretend_op_completed(cluster_client_t *cli, osd_op_t *op, int64_t retval)
|
|||||||
printf("Pretend completed %s %jx+%x\n", op->req.hdr.opcode == OSD_OP_SYNC
|
printf("Pretend completed %s %jx+%x\n", op->req.hdr.opcode == OSD_OP_SYNC
|
||||||
? "sync" : (op->req.hdr.opcode == OSD_OP_WRITE ? "write" : "read"), op->req.rw.offset, op->req.rw.len);
|
? "sync" : (op->req.hdr.opcode == OSD_OP_WRITE ? "write" : "read"), op->req.rw.offset, op->req.rw.len);
|
||||||
uint64_t op_id = op->req.hdr.id;
|
uint64_t op_id = op->req.hdr.id;
|
||||||
int peer_fd = op->peer_fd;
|
uint64_t client_id = op->client_id;
|
||||||
cli->msgr.clients[peer_fd]->sent_ops.erase(op_id);
|
cli->msgr.clients[client_id]->sent_ops.erase(op_id);
|
||||||
op->reply.hdr.magic = SECONDARY_OSD_REPLY_MAGIC;
|
op->reply.hdr.magic = SECONDARY_OSD_REPLY_MAGIC;
|
||||||
op->reply.hdr.id = op->req.hdr.id;
|
op->reply.hdr.id = op->req.hdr.id;
|
||||||
op->reply.hdr.opcode = op->req.hdr.opcode;
|
op->reply.hdr.opcode = op->req.hdr.opcode;
|
||||||
@@ -264,7 +267,7 @@ void test1()
|
|||||||
uint64_t replay_start = UINT64_MAX;
|
uint64_t replay_start = UINT64_MAX;
|
||||||
uint64_t replay_end = 0;
|
uint64_t replay_end = 0;
|
||||||
std::vector<osd_op_t*> replay_ops;
|
std::vector<osd_op_t*> replay_ops;
|
||||||
auto osd_cl = cli->msgr.clients.at(cli->msgr.osd_peer_fds.at(1));
|
auto osd_cl = cli->msgr.osd_peers.at(1);
|
||||||
for (auto & op_p: osd_cl->sent_ops)
|
for (auto & op_p: osd_cl->sent_ops)
|
||||||
{
|
{
|
||||||
auto op = op_p.second;
|
auto op = op_p.second;
|
||||||
|
|||||||
@@ -1893,7 +1893,8 @@ void test_big_intent_csums()
|
|||||||
heap.finish_recheck();
|
heap.finish_recheck();
|
||||||
|
|
||||||
auto mod = heap.get_recheck_modified_blocks();
|
auto mod = heap.get_recheck_modified_blocks();
|
||||||
assert(mod.size() == 0);
|
assert(mod.size() == 1);
|
||||||
|
assert(mod[0] == 0);
|
||||||
|
|
||||||
// read object 1 - big_intent should be there
|
// read object 1 - big_intent should be there
|
||||||
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||||
@@ -1990,6 +1991,7 @@ void test_redirect_intent_csums()
|
|||||||
|
|
||||||
// reload heap to check that the write is still here
|
// reload heap to check that the write is still here
|
||||||
{
|
{
|
||||||
|
dsk.gc_on_start = false;
|
||||||
blockstore_heap_t heap(&dsk, buffer_area.data(), 10);
|
blockstore_heap_t heap(&dsk, buffer_area.data(), 10);
|
||||||
uint64_t entries_loaded;
|
uint64_t entries_loaded;
|
||||||
heap.load_blocks(0, dsk.meta_block_size, tmp.data(), false, entries_loaded);
|
heap.load_blocks(0, dsk.meta_block_size, tmp.data(), false, entries_loaded);
|
||||||
|
|||||||
Reference in New Issue
Block a user