Compare commits

...
Author SHA1 Message Date
Vitaliy Filippov b30635b932 Release 3.0.8
- Surrogate increment-only peer IDs are now used instead of file descriptor numbers,
  and client cleanup sequence is reworked in another attempt to fix a possible PG hang
  in 'peering' states. The history of this bug is still unclear and it still hasn't been
  reproduced in tests, but several users have reported it since 3.0.4 (only with enabled RDMA).
- Fix a minor bug where an OSD could skip reporting misplaced PG state when moving
  an object in non-immediate_commit mode.
- Add Ubuntu 26.04 (Resolute Raccoon) support and patches for qemu 10.2 and libvirt 12.0
2026-03-30 02:09:02 +03:00
Vitaliy Filippov 0c1154833c Add Ubuntu 26.04 support 2026-03-30 02:06:10 +03:00
Vitaliy Filippov c227bb05b6 Fix incorrect patch contents for qemu 10.1, add patch for qemu 10.2 2026-03-30 02:06:10 +03:00
Vitaliy Filippov dd85315f22 Update CMake supported versions 2026-03-30 02:06:10 +03:00
Vitaliy Filippov 47d2f4e0be Add patch for libvirt 12.0 2026-03-30 02:06:10 +03:00
Vitaliy Filippov 2a5028d17f Use robin_hood_map in messenger 2026-03-30 02:06:10 +03:00
Vitaliy Filippov 07915c2881 Use surrogate peer IDs instead of FDs 2026-03-30 02:06:10 +03:00
Vitaliy Filippov 79141eb383 Fix commented out //this->pg_state_dirty.insert 2026-03-28 20:08:52 +03:00
Vitaliy Filippov f7cbb6ed56 Remove FD from the event loop in destroy_client, not in stop_client 2026-03-28 14:18:20 +03:00
Vitaliy Filippov 8f8172db99 clear_immediate_ops is now done by stop_client 2026-03-26 01:08:23 +03:00
Vitaliy Filippov 94be147e80 Clear received_ops - they are already freed 2026-03-26 01:08:02 +03:00
Vitaliy Filippov 538620b400 Release 3.0.6
- Fix one more bug in old store checksums O_o - checksum verification wasn't
  working correctly on reads quickly after small initial offsetted writes
  (when a BIG_WRITE was read from the journal).
- Fix clients possibly not destroyed after being switched to RDMA. Not 100%
  verified, but in theory it could rarely lead to PGs hanging in peering/stopping
  states with RDMA enabled.
- Use vitastor-cli in the Cinder driver for modifications instead of direct etcd
  interaction.
- Fix mon_https_ca parsing.
- Fix Docker install.sh, add instructions for Podman.
2026-03-22 22:49:51 +03:00
62 changed files with 1401 additions and 440 deletions
+1 -1
View File
@@ -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
View File
@@ -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.8")
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
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.5 VITASTOR_VERSION ?= v3.0.8
all: build push all: build push
+1 -1
View File
@@ -49,7 +49,7 @@ spec:
capabilities: capabilities:
add: ["SYS_ADMIN"] add: ["SYS_ADMIN"]
allowPrivilegeEscalation: true allowPrivilegeEscalation: true
image: vitalif/vitastor-csi:v3.0.5 image: vitalif/vitastor-csi:v3.0.8
args: args:
- "--node=$(NODE_ID)" - "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -121,7 +121,7 @@ spec:
privileged: true privileged: true
capabilities: capabilities:
add: ["SYS_ADMIN"] add: ["SYS_ADMIN"]
image: vitalif/vitastor-csi:v3.0.5 image: vitalif/vitastor-csi:v3.0.8
args: args:
- "--node=$(NODE_ID)" - "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -5,7 +5,7 @@ package vitastor
const ( const (
vitastorCSIDriverName = "csi.vitastor.io" vitastorCSIDriverName = "csi.vitastor.io"
vitastorCSIDriverVersion = "3.0.5" vitastorCSIDriverVersion = "3.0.8"
) )
// Config struct fills the parameters of request or user input // Config struct fills the parameters of request or user input
+1 -1
View File
@@ -1,4 +1,4 @@
vitastor (3.0.5-1) unstable; urgency=medium vitastor (3.0.8-1) unstable; urgency=medium
* Bugfixes * Bugfixes
+1 -1
View File
@@ -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
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.5 VITASTOR_VERSION ?= v3.0.8
all: build push all: build push
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# Desired Vitastor version # Desired Vitastor version
VITASTOR_VERSION=v3.0.5 VITASTOR_VERSION=v3.0.8
# 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
+2 -2
View File
@@ -26,9 +26,9 @@ at Vitastor Kubernetes operator: https://github.com/Antilles7227/vitastor-operat
The instruction is very simple. The instruction is very simple.
1. Download a Docker image of the desired version: \ 1. Download a Docker image of the desired version: \
`docker pull vitalif/vitastor:v3.0.5` `docker pull vitalif/vitastor:v3.0.8`
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.8 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: \
+2 -2
View File
@@ -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.8`
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.8 install.sh`
3. Перезагрузите правила udev: \ 3. Перезагрузите правила udev: \
`udevadm control --reload-rules` `udevadm control --reload-rules`
4. Включите сервис vitastor-host: \ 4. Включите сервис vitastor-host: \
+1
View File
@@ -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`:
+1
View File
@@ -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`:
+1 -1
Submodule json11 updated: fd37016cf8...edcd85b8bd
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "vitastor-mon", "name": "vitastor-mon",
"version": "3.0.5", "version": "3.0.8",
"description": "Vitastor SDS monitor service", "description": "Vitastor SDS monitor service",
"main": "mon-main.js", "main": "mon-main.js",
"scripts": { "scripts": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "vitastor", "name": "vitastor",
"version": "3.0.5", "version": "3.0.8",
"description": "Low-level native bindings to Vitastor client library", "description": "Low-level native bindings to Vitastor client library",
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
+1 -1
View File
@@ -50,7 +50,7 @@ from cinder.volume import configuration
from cinder.volume import driver from cinder.volume import driver
from cinder.volume import volume_utils from cinder.volume import volume_utils
VITASTOR_VERSION = '3.0.5' VITASTOR_VERSION = '3.0.8'
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
+637
View File
@@ -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;
}
+171 -28
View File
@@ -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 ;;
+172
View File
@@ -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 ;;
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.5 Version: 3.0.8
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.8.el10.tar.gz
BuildRequires: gperftools-devel BuildRequires: gperftools-devel
BuildRequires: gcc-c++ BuildRequires: gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.5 Version: 3.0.8
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.8.el7.tar.gz
BuildRequires: gperftools-devel BuildRequires: gperftools-devel
BuildRequires: devtoolset-9-gcc-c++ BuildRequires: devtoolset-9-gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.5 Version: 3.0.8
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.8.el8.tar.gz
BuildRequires: gperftools-devel BuildRequires: gperftools-devel
BuildRequires: gcc-toolset-9-gcc-c++ BuildRequires: gcc-toolset-9-gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.5 Version: 3.0.8
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.8.el9.tar.gz
BuildRequires: gperftools-devel BuildRequires: gperftools-devel
BuildRequires: gcc-c++ BuildRequires: gcc-c++
+2 -3
View File
@@ -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.8")
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 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+23 -23
View File
@@ -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++);
} }
@@ -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
@@ -1401,10 +1401,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 +1419,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 +1468,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 +1522,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 +1567,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 +1597,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)
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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;
+10 -14
View File
@@ -493,7 +493,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 +503,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 +519,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 +539,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 +630,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 +687,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 +702,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 +719,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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: Vitastor Name: Vitastor
Description: Vitastor client library Description: Vitastor client library
Version: 3.0.5 Version: 3.0.8
Libs: -L${libdir} -lvitastor_client Libs: -L${libdir} -lvitastor_client
Cflags: -I${includedir} Cflags: -I${includedir}
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+2 -2
View File
@@ -616,11 +616,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
View File
@@ -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,
+1 -1
View File
@@ -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]);
} }
+8 -7
View File
@@ -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
View File
@@ -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)
+5 -4
View File
@@ -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;
+5 -5
View File
@@ -312,16 +312,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); });
} }
@@ -607,7 +607,7 @@ void osd_t::send_chained_read_results(pg_t *pg, osd_op_t *cur_op)
{ {
if (cur > prev) if (cur > prev)
{ {
// Send buffer in parts to avoid copying // Send buffer in parts to avoid copying
if (!prev_set) if (!prev_set)
{ {
while ((cur-prev) > zero_buffer_size/bs_bitmap_granularity) while ((cur-prev) > zero_buffer_size/bs_bitmap_granularity)
+45 -41
View File
@@ -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++;
+2 -2
View File
@@ -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();
} }
+12 -3
View File
@@ -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 });
+6 -6
View File
@@ -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 = {
+5 -5
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor) project(vitastor)
+2 -6
View File
@@ -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)
{
}
+1 -1
View File
@@ -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);
+20 -17
View File
@@ -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;