Compare commits
42 Commits
Author | SHA1 | Date | |
---|---|---|---|
b529f77264 | |||
bf9519dcdc | |||
4ba687738b | |||
8427f6fe46 | |||
efa6bc3e70 | |||
da33e9b12d | |||
![]() |
265127c1a7 | ||
2b30acfc1d | |||
7fbc38ef29 | |||
e5070e991a | |||
625552c441 | |||
78c95c94f6 | |||
488e20bf55 | |||
25d6281b3e | |||
1676e50b3a | |||
8049e3c14a | |||
93a30efd86 | |||
83fb121f36 | |||
afc97b757b | |||
68905cbf41 | |||
3fff667f13 | |||
980aec1d9b | |||
f515fcce62 | |||
97bb809b54 | |||
6022a61329 | |||
a3c1996101 | |||
8d2a1f0297 | |||
91cbc313c2 | |||
f0a025428e | |||
67071158bd | |||
cd028612c8 | |||
f390e73dae | |||
de2539c491 | |||
957a4fce7e | |||
f201ecdd51 | |||
4afb617f59 | |||
d3fde0569f | |||
438b64f6c3 | |||
2b0a802ea1 | |||
0dd49c1d67 | |||
410170db96 | |||
7d8523e0e5 |
@@ -144,6 +144,24 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_change_pg_count_online:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: /root/vitastor/tests/test_change_pg_count_online.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
test_change_pg_size:
|
test_change_pg_size:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
@@ -684,6 +702,24 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_write_iothreads:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: TEST_NAME=iothreads GLOBAL_CONFIG=',"client_iothread_count":4' /root/vitastor/tests/test_write.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
test_write_no_same:
|
test_write_no_same:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
|
@@ -2,6 +2,6 @@ cmake_minimum_required(VERSION 2.8.12)
|
|||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
set(VITASTOR_VERSION "2.2.0")
|
set(VITASTOR_VERSION "2.2.3")
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
VITASTOR_VERSION ?= v2.2.0
|
VITASTOR_VERSION ?= v2.2.3
|
||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
@@ -49,7 +49,7 @@ spec:
|
|||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
allowPrivilegeEscalation: true
|
allowPrivilegeEscalation: true
|
||||||
image: vitalif/vitastor-csi:v2.2.0
|
image: vitalif/vitastor-csi:v2.2.3
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
@@ -121,7 +121,7 @@ spec:
|
|||||||
privileged: true
|
privileged: true
|
||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
image: vitalif/vitastor-csi:v2.2.0
|
image: vitalif/vitastor-csi:v2.2.3
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
@@ -5,7 +5,7 @@ package vitastor
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
vitastorCSIDriverName = "csi.vitastor.io"
|
vitastorCSIDriverName = "csi.vitastor.io"
|
||||||
vitastorCSIDriverVersion = "2.2.0"
|
vitastorCSIDriverVersion = "2.2.3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct fills the parameters of request or user input
|
// Config struct fills the parameters of request or user input
|
||||||
|
7
debian/build-vitastor-bookworm.sh
vendored
7
debian/build-vitastor-bookworm.sh
vendored
@@ -1,7 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
cat < vitastor.Dockerfile > ../Dockerfile
|
docker build --build-arg DISTRO=debian --build-arg REL=bookworm -t vitastor-buildenv:bookworm -f vitastor-buildenv.Dockerfile .
|
||||||
cd ..
|
docker run -i --rm -e REL=bookworm -v `dirname $0`/../:/root/vitastor vitastor-buildenv:bookworm /root/vitastor/debian/vitastor-build.sh
|
||||||
mkdir -p packages
|
|
||||||
sudo podman build --build-arg DISTRO=debian --build-arg REL=bookworm -v `pwd`/packages:/root/packages -f Dockerfile .
|
|
||||||
rm Dockerfile
|
|
||||||
|
7
debian/build-vitastor-bullseye.sh
vendored
7
debian/build-vitastor-bullseye.sh
vendored
@@ -1,7 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
cat < vitastor.Dockerfile > ../Dockerfile
|
docker build --build-arg DISTRO=debian --build-arg REL=bullseye -t vitastor-buildenv:bullseye -f vitastor-buildenv.Dockerfile .
|
||||||
cd ..
|
docker run -i --rm -e REL=bullseye -v `dirname $0`/../:/root/vitastor vitastor-buildenv:bullseye /root/vitastor/debian/vitastor-build.sh
|
||||||
mkdir -p packages
|
|
||||||
sudo podman build --build-arg DISTRO=debian --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f Dockerfile .
|
|
||||||
rm Dockerfile
|
|
||||||
|
7
debian/build-vitastor-buster.sh
vendored
7
debian/build-vitastor-buster.sh
vendored
@@ -1,7 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
cat < vitastor.Dockerfile > ../Dockerfile
|
docker build --build-arg DISTRO=debian --build-arg REL=buster -t vitastor-buildenv:buster -f vitastor-buildenv.Dockerfile .
|
||||||
cd ..
|
docker run -i --rm -e REL=buster -v `dirname $0`/../:/root/vitastor vitastor-buildenv:buster /root/vitastor/debian/vitastor-build.sh
|
||||||
mkdir -p packages
|
|
||||||
sudo podman build --build-arg DISTRO=debian --build-arg REL=buster -v `pwd`/packages:/root/packages -f Dockerfile .
|
|
||||||
rm Dockerfile
|
|
||||||
|
8
debian/build-vitastor-ubuntu-jammy.sh
vendored
8
debian/build-vitastor-ubuntu-jammy.sh
vendored
@@ -1,7 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Ubuntu 22.04 Jammy Jellyfish
|
||||||
|
|
||||||
cat < vitastor.Dockerfile > ../Dockerfile
|
docker build --build-arg DISTRO=ubuntu --build-arg REL=jammy -t vitastor-buildenv:jammy -f vitastor-buildenv.Dockerfile .
|
||||||
cd ..
|
docker run -i --rm -e REL=jammy -v `dirname $0`/../:/root/vitastor vitastor-buildenv:jammy /root/vitastor/debian/vitastor-build.sh
|
||||||
mkdir -p packages
|
|
||||||
sudo podman build --build-arg DISTRO=ubuntu --build-arg REL=jammy -v `pwd`/packages:/root/packages -f Dockerfile .
|
|
||||||
rm Dockerfile
|
|
||||||
|
5
debian/build-vitastor-ubuntu-noble.sh
vendored
Executable file
5
debian/build-vitastor-ubuntu-noble.sh
vendored
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 24.04 Noble Numbat
|
||||||
|
|
||||||
|
docker build --build-arg DISTRO=ubuntu --build-arg REL=noble -t vitastor-buildenv:noble -f vitastor-buildenv.Dockerfile .
|
||||||
|
docker run -i --rm -e REL=noble -v `dirname $0`/../:/root/vitastor vitastor-buildenv:noble /root/vitastor/debian/vitastor-build.sh
|
2
debian/changelog
vendored
2
debian/changelog
vendored
@@ -1,4 +1,4 @@
|
|||||||
vitastor (2.2.0-1) unstable; urgency=medium
|
vitastor (2.2.3-1) unstable; urgency=medium
|
||||||
|
|
||||||
* Bugfixes
|
* Bugfixes
|
||||||
|
|
||||||
|
59
debian/vitastor-build.sh
vendored
Executable file
59
debian/vitastor-build.sh
vendored
Executable file
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# To be ran inside buildenv docker
|
||||||
|
|
||||||
|
set -e -x
|
||||||
|
|
||||||
|
[ -e /usr/lib/x86_64-linux-gnu/pkgconfig/libisal.pc ] || cp /root/vitastor/debian/libisal.pc /usr/lib/x86_64-linux-gnu/pkgconfig
|
||||||
|
|
||||||
|
mkdir -p /root/fio-build/
|
||||||
|
cd /root/fio-build/
|
||||||
|
rm -rf /root/fio-build/*
|
||||||
|
dpkg-source -x /root/fio*.dsc
|
||||||
|
|
||||||
|
FULLVER=`head -n1 /root/vitastor/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'`
|
||||||
|
VER=${FULLVER%%-*}
|
||||||
|
rm -rf /root/vitastor-$VER
|
||||||
|
mkdir /root/vitastor-$VER
|
||||||
|
cd /root/vitastor
|
||||||
|
cp -a $(ls | grep -v packages) /root/vitastor-$VER
|
||||||
|
|
||||||
|
rm -rf /root/vitastor/packages/vitastor-$REL
|
||||||
|
mkdir -p /root/vitastor/packages/vitastor-$REL
|
||||||
|
mv /root/vitastor-$VER /root/vitastor/packages/vitastor-$REL/
|
||||||
|
|
||||||
|
cd /root/vitastor/packages/vitastor-$REL/vitastor-$VER
|
||||||
|
|
||||||
|
rm -rf fio
|
||||||
|
ln -s /root/fio-build/fio-*/ ./fio
|
||||||
|
FIO=`head -n1 fio/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'`
|
||||||
|
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h
|
||||||
|
sh copy-fio-includes.sh
|
||||||
|
rm fio
|
||||||
|
mkdir -p a b debian/patches
|
||||||
|
mv fio-copy b/fio
|
||||||
|
diff -NaurpbB a b > debian/patches/fio-headers.patch || true
|
||||||
|
echo fio-headers.patch >> debian/patches/series
|
||||||
|
rm -rf a b
|
||||||
|
|
||||||
|
echo "dep:fio=$FIO" > debian/fio_version
|
||||||
|
|
||||||
|
cd /root/vitastor/packages/vitastor-$REL/vitastor-$VER
|
||||||
|
mkdir mon/node_modules
|
||||||
|
cd mon/node_modules
|
||||||
|
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
|
||||||
|
|
||||||
|
cd /root/vitastor/packages/vitastor-$REL
|
||||||
|
tar --sort=name --mtime='2020-01-01' --owner=0 --group=0 --exclude=debian -cJf vitastor_$VER.orig.tar.xz vitastor-$VER
|
||||||
|
cd vitastor-$VER
|
||||||
|
DEBEMAIL="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v "$FULLVER""$REL" "Rebuild for $REL"
|
||||||
|
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa
|
||||||
|
rm -rf /root/vitastor/packages/vitastor-$REL/vitastor-*/
|
||||||
|
|
||||||
|
# Why does ubuntu rename debug packages to *.ddeb?
|
||||||
|
if ls *.ddeb >/dev/null; then
|
||||||
|
perl -i -pe 's/\.ddeb/.deb/' *.buildinfo *.changes
|
||||||
|
for i in *.ddeb; do
|
||||||
|
mv $i ${i%%.ddeb}.deb
|
||||||
|
done
|
||||||
|
fi
|
31
debian/vitastor-buildenv.Dockerfile
vendored
Normal file
31
debian/vitastor-buildenv.Dockerfile
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Build environment for building Vitastor packages for Debian inside a container
|
||||||
|
# cd ..
|
||||||
|
# docker build --build-arg DISTRO=debian --build-arg REL=bullseye -f debian/vitastor.Dockerfile -t vitastor-buildenv:bullseye .
|
||||||
|
# docker run --rm -e REL=bullseye -v ./:/root/vitastor /root/vitastor/debian/vitastor-build.sh
|
||||||
|
|
||||||
|
ARG DISTRO=debian
|
||||||
|
ARG REL=
|
||||||
|
FROM $DISTRO:$REL
|
||||||
|
ARG DISTRO=debian
|
||||||
|
ARG REL=
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
|
||||||
|
RUN set -e -x; \
|
||||||
|
if [ "$REL" = "buster" ]; then \
|
||||||
|
perl -i -pe 's/deb.debian.org/archive.debian.org/' /etc/apt/sources.list; \
|
||||||
|
apt-get update; \
|
||||||
|
apt-get -y install wget; \
|
||||||
|
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg; \
|
||||||
|
echo "deb https://vitastor.io/debian $REL main" >> /etc/apt/sources.list; \
|
||||||
|
fi; \
|
||||||
|
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
|
||||||
|
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/*.sources || true; \
|
||||||
|
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
|
||||||
|
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts libjerasure-dev cmake \
|
||||||
|
libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl nodejs npm node-nan node-bindings && \
|
||||||
|
apt-get -y build-dep fio && \
|
||||||
|
apt-get --download-only source fio
|
65
debian/vitastor.Dockerfile
vendored
65
debian/vitastor.Dockerfile
vendored
@@ -1,65 +0,0 @@
|
|||||||
# Build Vitastor packages for Debian inside a container
|
|
||||||
# cd ..; podman build --build-arg DISTRO=debian --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/vitastor.Dockerfile .
|
|
||||||
|
|
||||||
ARG DISTRO=debian
|
|
||||||
ARG REL=
|
|
||||||
FROM $DISTRO:$REL
|
|
||||||
ARG DISTRO=debian
|
|
||||||
ARG REL=
|
|
||||||
|
|
||||||
WORKDIR /root
|
|
||||||
|
|
||||||
RUN set -e -x; \
|
|
||||||
if [ "$REL" = "buster" ]; then \
|
|
||||||
apt-get update; \
|
|
||||||
apt-get -y install wget; \
|
|
||||||
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg; \
|
|
||||||
echo "deb https://vitastor.io/debian $REL main" >> /etc/apt/sources.list; \
|
|
||||||
fi; \
|
|
||||||
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
|
|
||||||
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/debian.sources || true; \
|
|
||||||
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
|
|
||||||
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts libjerasure-dev cmake \
|
|
||||||
libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl nodejs npm node-nan node-bindings && \
|
|
||||||
apt-get -y build-dep fio && \
|
|
||||||
apt-get --download-only source fio
|
|
||||||
|
|
||||||
ADD . /root/vitastor
|
|
||||||
RUN set -e -x; \
|
|
||||||
[ -e /usr/lib/x86_64-linux-gnu/pkgconfig/libisal.pc ] || cp /root/vitastor/debian/libisal.pc /usr/lib/x86_64-linux-gnu/pkgconfig; \
|
|
||||||
mkdir -p /root/fio-build/; \
|
|
||||||
cd /root/fio-build/; \
|
|
||||||
rm -rf /root/fio-build/*; \
|
|
||||||
dpkg-source -x /root/fio*.dsc; \
|
|
||||||
mkdir -p /root/packages/vitastor-$REL; \
|
|
||||||
rm -rf /root/packages/vitastor-$REL/*; \
|
|
||||||
cd /root/packages/vitastor-$REL; \
|
|
||||||
FULLVER=$(head -n1 /root/vitastor/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
|
||||||
VER=${FULLVER%%-*}; \
|
|
||||||
cp -r /root/vitastor vitastor-$VER; \
|
|
||||||
cd vitastor-$VER; \
|
|
||||||
ln -s /root/fio-build/fio-*/ ./fio; \
|
|
||||||
FIO=$(head -n1 fio/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
|
||||||
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
|
|
||||||
sh copy-fio-includes.sh; \
|
|
||||||
rm fio; \
|
|
||||||
mkdir -p a b debian/patches; \
|
|
||||||
mv fio-copy b/fio; \
|
|
||||||
diff -NaurpbB a b > debian/patches/fio-headers.patch || true; \
|
|
||||||
echo fio-headers.patch >> debian/patches/series; \
|
|
||||||
rm -rf a b; \
|
|
||||||
echo "dep:fio=$FIO" > debian/fio_version; \
|
|
||||||
cd /root/packages/vitastor-$REL/vitastor-$VER; \
|
|
||||||
mkdir mon/node_modules; \
|
|
||||||
cd mon/node_modules; \
|
|
||||||
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; \
|
|
||||||
cd /root/packages/vitastor-$REL; \
|
|
||||||
tar --sort=name --mtime='2020-01-01' --owner=0 --group=0 --exclude=debian -cJf vitastor_$VER.orig.tar.xz vitastor-$VER; \
|
|
||||||
cd vitastor-$VER; \
|
|
||||||
DEBFULLNAME="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v "$FULLVER""$REL" "Rebuild for $REL"; \
|
|
||||||
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \
|
|
||||||
rm -rf /root/packages/vitastor-$REL/vitastor-*/
|
|
@@ -1,4 +1,4 @@
|
|||||||
VITASTOR_VERSION ?= v2.2.0
|
VITASTOR_VERSION ?= v2.2.3
|
||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
3
docker/etc/apt/preferences
Normal file
3
docker/etc/apt/preferences
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Package: *
|
||||||
|
Pin: release n=bookworm-backports
|
||||||
|
Pin-Priority: 500
|
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Desired Vitastor version
|
# Desired Vitastor version
|
||||||
VITASTOR_VERSION=v2.2.0
|
VITASTOR_VERSION=v2.2.3
|
||||||
|
|
||||||
# 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
|
||||||
|
@@ -74,7 +74,7 @@ Consider `use_rdmacm` for such networks.
|
|||||||
## use_rdmacm
|
## use_rdmacm
|
||||||
|
|
||||||
- Type: boolean
|
- Type: boolean
|
||||||
- Default: true
|
- Default: false
|
||||||
|
|
||||||
Use an alternative implementation of RDMA through RDMA-CM (Connection
|
Use an alternative implementation of RDMA through RDMA-CM (Connection
|
||||||
Manager). Works with all RDMA networks: Infiniband, iWARP and
|
Manager). Works with all RDMA networks: Infiniband, iWARP and
|
||||||
|
@@ -74,7 +74,7 @@ RDMA-устройства, но они не имеют соединения с
|
|||||||
## use_rdmacm
|
## use_rdmacm
|
||||||
|
|
||||||
- Тип: булево (да/нет)
|
- Тип: булево (да/нет)
|
||||||
- Значение по умолчанию: true
|
- Значение по умолчанию: false
|
||||||
|
|
||||||
Использовать альтернативную реализацию RDMA на основе RDMA-CM (Connection
|
Использовать альтернативную реализацию RDMA на основе RDMA-CM (Connection
|
||||||
Manager). Работает со всеми типами RDMA-сетей: Infiniband, iWARP и
|
Manager). Работает со всеми типами RDMA-сетей: Infiniband, iWARP и
|
||||||
|
@@ -51,7 +51,7 @@
|
|||||||
Рассмотрите включение `use_rdmacm` для таких сетей.
|
Рассмотрите включение `use_rdmacm` для таких сетей.
|
||||||
- name: use_rdmacm
|
- name: use_rdmacm
|
||||||
type: bool
|
type: bool
|
||||||
default: true
|
default: false
|
||||||
info: |
|
info: |
|
||||||
Use an alternative implementation of RDMA through RDMA-CM (Connection
|
Use an alternative implementation of RDMA through RDMA-CM (Connection
|
||||||
Manager). Works with all RDMA networks: Infiniband, iWARP and
|
Manager). Works with all RDMA networks: Infiniband, iWARP and
|
||||||
|
@@ -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 vitastor:v2.2.0`
|
`docker pull vitalif/vitastor:v2.2.3`
|
||||||
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 vitastor:v2.2.0 install.sh`
|
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v2.2.3 install.sh`
|
||||||
3. Reload udev rules: \
|
3. Reload udev rules: \
|
||||||
`udevadm control --reload-rules`
|
`udevadm control --reload-rules`
|
||||||
|
|
||||||
|
@@ -25,9 +25,9 @@ Vitastor можно установить в Docker/Podman. При этом etcd,
|
|||||||
Инструкция по установке максимально простая.
|
Инструкция по установке максимально простая.
|
||||||
|
|
||||||
1. Скачайте Docker-образ желаемой версии: \
|
1. Скачайте Docker-образ желаемой версии: \
|
||||||
`docker pull vitastor:v2.2.0`
|
`docker pull vitalif/vitastor:v2.2.3`
|
||||||
2. Установите скрипты в хост-систему командой: \
|
2. Установите скрипты в хост-систему командой: \
|
||||||
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitastor:v2.2.0 install.sh`
|
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v2.2.3 install.sh`
|
||||||
3. Перезагрузите правила udev: \
|
3. Перезагрузите правила udev: \
|
||||||
`udevadm control --reload-rules`
|
`udevadm control --reload-rules`
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
- Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main`
|
- Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main`
|
||||||
- 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`
|
||||||
- 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
|
||||||
- Install packages: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86`
|
- Install packages: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86`
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
- Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main`
|
- Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main`
|
||||||
- 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`
|
||||||
- Добавьте `-oldstable` к слову bookworm/bullseye/buster в этой строке, чтобы
|
- Добавьте `-oldstable` к слову bookworm/bullseye/buster в этой строке, чтобы
|
||||||
установить последнюю стабильную версию из ветки 0.9.x вместо 1.x
|
установить последнюю стабильную версию из ветки 0.9.x вместо 1.x
|
||||||
- Установите пакеты: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86`
|
- Установите пакеты: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86`
|
||||||
|
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
# Proxmox VE
|
# Proxmox VE
|
||||||
|
|
||||||
To enable Vitastor support in Proxmox Virtual Environment (6.4-8.1 are supported):
|
To enable Vitastor support in Proxmox Virtual Environment (6.4-8.x are supported):
|
||||||
|
|
||||||
- Add the corresponding Vitastor Debian repository into sources.list on Proxmox hosts:
|
- Add the corresponding Vitastor Debian repository into sources.list on Proxmox hosts:
|
||||||
bookworm for 8.1, pve8.0 for 8.0, bullseye for 7.4, pve7.3 for 7.3, pve7.2 for 7.2, pve7.1 for 7.1, buster for 6.4
|
bookworm for 8.1+, pve8.0 for 8.0, bullseye for 7.4, pve7.3 for 7.3, pve7.2 for 7.2, pve7.1 for 7.1, buster for 6.4
|
||||||
- Install vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* or see note) packages from Vitastor repository
|
- Install vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* or see note) packages from Vitastor repository
|
||||||
- Define storage in `/etc/pve/storage.cfg` (see below)
|
- Define storage in `/etc/pve/storage.cfg` (see below)
|
||||||
- Block network access from VMs to Vitastor network (to OSDs and etcd),
|
- Block network access from VMs to Vitastor network (to OSDs and etcd),
|
||||||
|
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
# Proxmox VE
|
# Proxmox VE
|
||||||
|
|
||||||
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-8.1):
|
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-8.x):
|
||||||
|
|
||||||
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
|
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
|
||||||
bookworm для 8.1, pve8.0 для 8.0, bullseye для 7.4, pve7.3 для 7.3, pve7.2 для 7.2, pve7.1 для 7.1, buster для 6.4
|
bookworm для 8.1+, pve8.0 для 8.0, bullseye для 7.4, pve7.3 для 7.3, pve7.2 для 7.2, pve7.1 для 7.1, buster для 6.4
|
||||||
- Установите пакеты vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* или см. сноску) из репозитория Vitastor
|
- Установите пакеты vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* или см. сноску) из репозитория Vitastor
|
||||||
- Определите тип хранилища в `/etc/pve/storage.cfg` (см. ниже)
|
- Определите тип хранилища в `/etc/pve/storage.cfg` (см. ниже)
|
||||||
- Обязательно заблокируйте доступ от виртуальных машин к сети Vitastor (OSD и etcd), т.к. Vitastor (пока) не поддерживает аутентификацию
|
- Обязательно заблокируйте доступ от виртуальных машин к сети Vitastor (OSD и etcd), т.к. Vitastor (пока) не поддерживает аутентификацию
|
||||||
|
@@ -10,8 +10,17 @@ Copyright (c) Vitaliy Filippov (vitalif [at] yourcmc.ru), 2019+
|
|||||||
|
|
||||||
Join Vitastor Telegram Chat: https://t.me/vitastor
|
Join Vitastor Telegram Chat: https://t.me/vitastor
|
||||||
|
|
||||||
All server-side code (OSD, Monitor and so on) is licensed under the terms of
|
License: VNPL 1.1 for server-side code and dual VNPL 1.1 + GPL 2.0+ for client tools.
|
||||||
Vitastor Network Public License 1.1 (VNPL 1.1), a copyleft license based on
|
|
||||||
|
Server-side code is licensed only under the terms of VNPL.
|
||||||
|
|
||||||
|
Client libraries (cluster_client and so on) are dual-licensed under the same
|
||||||
|
VNPL 1.1 and also GNU GPL 2.0 or later to allow for compatibility with GPLed
|
||||||
|
software like QEMU and fio.
|
||||||
|
|
||||||
|
## VNPL
|
||||||
|
|
||||||
|
Vitastor Network Public License 1.1 (VNPL 1.1) is a copyleft license based on
|
||||||
GNU GPLv3.0 with the additional "Network Interaction" clause which requires
|
GNU GPLv3.0 with the additional "Network Interaction" clause which requires
|
||||||
opensourcing all programs directly or indirectly interacting with Vitastor
|
opensourcing all programs directly or indirectly interacting with Vitastor
|
||||||
through a computer network and expressly designed to be used in conjunction
|
through a computer network and expressly designed to be used in conjunction
|
||||||
@@ -20,18 +29,83 @@ the terms of the same license, but also under the terms of any GPL-Compatible
|
|||||||
Free Software License, as listed by the Free Software Foundation.
|
Free Software License, as listed by the Free Software Foundation.
|
||||||
This is a stricter copyleft license than the Affero GPL.
|
This is a stricter copyleft license than the Affero GPL.
|
||||||
|
|
||||||
Please note that VNPL doesn't require you to open the code of proprietary
|
The idea of VNPL is, in addition to modules linked to Vitastor code in a single
|
||||||
software running inside a VM if it's not specially designed to be used with
|
binary file, to extend copyleft action to micro-service modules only interacting
|
||||||
Vitastor.
|
with it over the network.
|
||||||
|
|
||||||
Basically, you can't use the software in a proprietary environment to provide
|
Basically, you can't use the software in a proprietary environment to provide
|
||||||
its functionality to users without opensourcing all intermediary components
|
its functionality to users without opensourcing all intermediary components
|
||||||
standing between the user and Vitastor or purchasing a commercial license
|
standing between the user and Vitastor or purchasing a commercial license
|
||||||
from the author 😀.
|
from the author 😀.
|
||||||
|
|
||||||
Client libraries (cluster_client and so on) are dual-licensed under the same
|
At the same time, VNPL doesn't impose any restrictions on software *not specially designed*
|
||||||
VNPL 1.1 and also GNU GPL 2.0 or later to allow for compatibility with GPLed
|
to be used with Vitastor, for example, on Windows running inside a VM with a Vitastor disk.
|
||||||
software like QEMU and fio.
|
|
||||||
|
|
||||||
You can find the full text of VNPL-1.1 in the file [VNPL-1.1.txt](../../VNPL-1.1.txt).
|
## Explanation
|
||||||
GPL 2.0 is also included in this repository as [GPL-2.0.txt](../../GPL-2.0.txt).
|
|
||||||
|
Network copyleft is governed by the clause **13. Remote Network Interaction** of VNPL.
|
||||||
|
|
||||||
|
A program is considered to be a "Proxy Program" if it meets both conditions:
|
||||||
|
- It is specially designed to be used with Vitastor. Basically, it means that the program
|
||||||
|
has any functionality specific to Vitastor and thus "knows" that it works with Vitastor,
|
||||||
|
not with something random.
|
||||||
|
- It interacts with Vitastor directly or indirectly through any programming interface,
|
||||||
|
including API, CLI, network or any wrapper (also considered a Proxy Program itself).
|
||||||
|
|
||||||
|
If, in addition to that:
|
||||||
|
- You give any user an apportunity to interact with Vitastor directly or indirectly through
|
||||||
|
any computer interface including the network or any number of wrappers (Proxy Programs).
|
||||||
|
|
||||||
|
Then VNPL requires you to publish the code of all above Proxy Programs to all above users
|
||||||
|
under the terms of any GPL-compatible license - that is, GPL, LGPL, MIT/BSD or Apache 2,
|
||||||
|
because "GPL compatibility" is treated as an ability to legally include licensed code in
|
||||||
|
a GPL application.
|
||||||
|
|
||||||
|
So, if you have a "Proxy Program", but it's not open to the user who directly or indirectly
|
||||||
|
interacts with Vitastor - you are forbidden to use Vitastor under the terms of VNPL and you
|
||||||
|
need a commercial license which doesn't contain open-source requirements.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
- Vitastor Kubernetes CSI driver which creates PersistentVolumes by calling `vitastor-cli create`.
|
||||||
|
- Yes, it interacts with Vitastor through vitastor-cli.
|
||||||
|
- Yes, it is designed specially for use with Vitastor (it has no sense otherwise).
|
||||||
|
- So, CSI driver **definitely IS** a Proxy Program and must be published under the terms of
|
||||||
|
a free software license.
|
||||||
|
- Windows, installed in a VM with the system disk on Vitastor storage.
|
||||||
|
- Yes, it interacts with Vitastor indirectly - it reads and writes data through the block
|
||||||
|
device interface, emulated by QEMU.
|
||||||
|
- No, it definitely isn't designed specially for use with Vitastor - Windows was created long
|
||||||
|
ago before Vitastor and doesn't know anything about it.
|
||||||
|
- So, Windows **definitely IS NOT** a Proxy Program and VNPL doesn't require to open it.
|
||||||
|
- Cloud control panel which makes requests to Vitastor Kubernetes CSI driver.
|
||||||
|
- Yes, it interacts with Vitastor indirectly through the CSI driver, which is a Proxy Program.
|
||||||
|
- May or may not be designed specially for use with Vitastor. How to determine exactly?
|
||||||
|
Imagine that Vitastor is replaced with any other storage (for example, with a proprietary).
|
||||||
|
Do control panel functions change in any way? If they do (for example, if snapshots stop working),
|
||||||
|
then the panel contains specific functionality and thus is designed specially for use with Vitastor.
|
||||||
|
Otherwise, the panel is universal and isn't designed specially for Vitastor.
|
||||||
|
- So, whether you are required to open-source the panel also **depends** on whether it
|
||||||
|
contains specific functionality or not.
|
||||||
|
|
||||||
|
## Why?
|
||||||
|
|
||||||
|
Because I believe into the spirit of copyleft (Linux wouldn't become so popular without GPL!)
|
||||||
|
and, at the same time, I want to have a way to monetize the product.
|
||||||
|
|
||||||
|
Existing licenses including AGPL are useless for it with an SDS - SDS is a very deeply
|
||||||
|
internal software which is almost definitely invisible to the user and thus AGPL doesn't
|
||||||
|
require anyone to open the code even if they make a proprietary fork.
|
||||||
|
|
||||||
|
And, in fact, the current situation in the world where GPL is though to only restrict direct
|
||||||
|
linking of programs into a single executable file, isn't much correct. Nowadays, programs
|
||||||
|
are more often linked with network API calls, not with /usr/bin/ld, and a software product
|
||||||
|
may consist of dozens of microservices interacting with each other over the network.
|
||||||
|
|
||||||
|
That's why we need VNPL to keep the license sufficiently copyleft.
|
||||||
|
|
||||||
|
## License Texts
|
||||||
|
|
||||||
|
- VNPL 1.1 in English: [VNPL-1.1.txt](../../VNPL-1.1.txt)
|
||||||
|
- VNPL 1.1 in Russian: [VNPL-1.1-RU.txt](../../VNPL-1.1-RU.txt)
|
||||||
|
- GPL 2.0: [GPL-2.0.txt](../../GPL-2.0.txt)
|
||||||
|
@@ -12,6 +12,14 @@
|
|||||||
|
|
||||||
Лицензия: VNPL 1.1 на серверный код и двойная VNPL 1.1 + GPL 2.0+ на клиентский.
|
Лицензия: VNPL 1.1 на серверный код и двойная VNPL 1.1 + GPL 2.0+ на клиентский.
|
||||||
|
|
||||||
|
Серверные компоненты распространяются только на условиях VNPL.
|
||||||
|
|
||||||
|
Клиентские библиотеки распространяются на условиях двойной лицензии VNPL 1.0
|
||||||
|
и также на условиях GNU GPL 2.0 или более поздней версии. Так сделано в целях
|
||||||
|
совместимости с таким ПО, как QEMU и fio.
|
||||||
|
|
||||||
|
## VNPL
|
||||||
|
|
||||||
VNPL - "сетевой копилефт", собственная свободная копилефт-лицензия
|
VNPL - "сетевой копилефт", собственная свободная копилефт-лицензия
|
||||||
Vitastor Network Public License 1.1, основанная на GNU GPL 3.0 с дополнительным
|
Vitastor Network Public License 1.1, основанная на GNU GPL 3.0 с дополнительным
|
||||||
условием "Сетевого взаимодействия", требующим распространять все программы,
|
условием "Сетевого взаимодействия", требующим распространять все программы,
|
||||||
@@ -29,9 +37,70 @@ Vitastor Network Public License 1.1, основанная на GNU GPL 3.0 с д
|
|||||||
На Windows и любое другое ПО, не разработанное *специально* для использования
|
На Windows и любое другое ПО, не разработанное *специально* для использования
|
||||||
вместе с Vitastor, никакие ограничения не накладываются.
|
вместе с Vitastor, никакие ограничения не накладываются.
|
||||||
|
|
||||||
Клиентские библиотеки распространяются на условиях двойной лицензии VNPL 1.0
|
## Пояснение
|
||||||
и также на условиях GNU GPL 2.0 или более поздней версии. Так сделано в целях
|
|
||||||
совместимости с таким ПО, как QEMU и fio.
|
|
||||||
|
|
||||||
Вы можете найти полный текст VNPL 1.1 на английском языке в файле [VNPL-1.1.txt](../../VNPL-1.1.txt),
|
Сетевой копилефт регулируется пунктом лицензии **13. Удалённое сетевое взаимодействие**.
|
||||||
VNPL 1.1 на русском языке в файле [VNPL-1.1-RU.txt](../../VNPL-1.1-RU.txt), а GPL 2.0 в файле [GPL-2.0.txt](../../GPL-2.0.txt).
|
|
||||||
|
Программа считается "прокси-программой", если верны оба условия:
|
||||||
|
- Она создана специально для работы вместе с Vitastor. По сути это означает, что программа
|
||||||
|
должна иметь специфичный для Vitastor функционал, то есть, "знать", что она взаимодействует
|
||||||
|
именно с Vitastor.
|
||||||
|
- Она прямо или косвенно взаимодействует с Vitastor через абсолютно любой программный
|
||||||
|
интерфейс, включая любые способы вызова: API, CLI, сеть или через какую-то обёртку (в
|
||||||
|
свою очередь тоже являющуюся прокси-программой).
|
||||||
|
|
||||||
|
Если в дополнение к этому также:
|
||||||
|
- Вы предоставляете любому пользователю возможность взаимодействовать с Vitastor по сети,
|
||||||
|
опять-таки, через любой интерфейс или любую серию "обёрток" (прокси-программ)
|
||||||
|
|
||||||
|
То, согласно VNPL, вы должны открыть код "прокси-программ" **таким пользователям** на условиях
|
||||||
|
любой GPL-совместимой лицензии - то есть, GPL, LGPL, MIT/BSD или Apache 2 - "совместимость с GPL"
|
||||||
|
понимается как возможность включать лицензируемый код в GPL-приложение.
|
||||||
|
|
||||||
|
Соответственно, если у вас есть "прокси-программа", но её код не открыт пользователю,
|
||||||
|
который прямо или косвенно взаимодействует с Vitastor - вам запрещено использовать Vitastor
|
||||||
|
на условиях VNPL и вам нужна коммерческая лицензия, не содержащая требований об открытии кода.
|
||||||
|
|
||||||
|
## Примеры
|
||||||
|
|
||||||
|
- Kubernetes CSI-драйвер Vitastor, создающий PersistentVolume с помощью вызова `vitastor-cli create`.
|
||||||
|
- Да, взаимодействует с Vitastor через vitastor-cli.
|
||||||
|
- Да, создавался специально для работы с Vitastor (иначе в чём же ещё его смысл).
|
||||||
|
- Значит, CSI-драйвер **точно считается** "прокси-программой" и должен быть открыт под свободной
|
||||||
|
лицензией.
|
||||||
|
- Windows, установленный в виртуальную машину на диске Vitastor.
|
||||||
|
- Да, взаимодействует с Vitastor "прямо или косвенно" - пишет и читает данные через интерфейс
|
||||||
|
блочного устройства, эмулируемый QEMU.
|
||||||
|
- Нет, точно не создан *специально для работы с Vitastor* - когда его создавали, никакого
|
||||||
|
Vitastor ещё и в помине не было.
|
||||||
|
- Значит, Windows **точно не считается** "прокси-программой" и на него требования VNPL не распространяются.
|
||||||
|
- Панель управления облака, делающая запросы к Kubernetes CSI-драйверу Vitastor.
|
||||||
|
- Да, взаимодействует с Vitastor косвенно через CSI-драйвер, являющийся "прокси-программой".
|
||||||
|
- Сходу не известно, создавалась ли конкретно для работы с Vitastor. Как понять, да или нет?
|
||||||
|
Представьте, что Vitastor заменён на любую другую систему хранения (например, на проприетарную).
|
||||||
|
Работа панели управления изменится? Если да (например, перестанут работать снапшоты) - значит,
|
||||||
|
панель содержит специфичный функционал и "создана специально для работы с Vitastor".
|
||||||
|
Если нет - значит, специфичного функционала панель не содержит и в принципе она универсальна.
|
||||||
|
- Нужно ли открывать панель - **зависит** от того, содержит она специфичный функционал или нет.
|
||||||
|
|
||||||
|
## Почему так?
|
||||||
|
|
||||||
|
Потому что я одновременно верю в дух копилефт-лицензий (Linux не стал бы так популярен,
|
||||||
|
если бы не GPL!) и хочу иметь возможность монетизации продукта.
|
||||||
|
|
||||||
|
При этом использовать даже AGPL для программной СХД бессмысленно - это глубоко внутреннее
|
||||||
|
ПО, которое пользователь почти наверняка не увидит вообще, поэтому и открывать код никому
|
||||||
|
никогда не придётся, даже при создании производного продукта.
|
||||||
|
|
||||||
|
Да и в целом сложившаяся в мире ситуация, при которой действие GPL ограничивается только
|
||||||
|
прямым связыванием в один исполняемый файл, не очень корректна. В настоящее время программы
|
||||||
|
гораздо чаще интегрируют сетевыми вызовами, а не с помощью /usr/bin/ld, и общий программный
|
||||||
|
продукт может состоять из нескольких десятков микросервисов, взаимодействующих по сети.
|
||||||
|
|
||||||
|
Поэтому для сохранения достаточной "копилефтности" и придумана VNPL.
|
||||||
|
|
||||||
|
## Тексты лицензий
|
||||||
|
|
||||||
|
- VNPL 1.1 на английском языке: [VNPL-1.1.txt](../../VNPL-1.1.txt)
|
||||||
|
- VNPL 1.1 на русском языке: [VNPL-1.1-RU.txt](../../VNPL-1.1-RU.txt)
|
||||||
|
- GPL 2.0: [GPL-2.0.txt](../../GPL-2.0.txt)
|
||||||
|
@@ -96,6 +96,7 @@ class Mon
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');
|
||||||
res.write(export_prometheus_metrics(this.state));
|
res.write(export_prometheus_metrics(this.state));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vitastor-mon",
|
"name": "vitastor-mon",
|
||||||
"version": "2.2.0",
|
"version": "2.2.3",
|
||||||
"description": "Vitastor SDS monitor service",
|
"description": "Vitastor SDS monitor service",
|
||||||
"main": "mon-main.js",
|
"main": "mon-main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vitastor",
|
"name": "vitastor",
|
||||||
"version": "2.2.0",
|
"version": "2.2.3",
|
||||||
"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": [
|
||||||
|
@@ -410,8 +410,8 @@ sub volume_size_info
|
|||||||
my $prefix = defined $scfg->{vitastor_prefix} ? $scfg->{vitastor_prefix} : 'pve/';
|
my $prefix = defined $scfg->{vitastor_prefix} ? $scfg->{vitastor_prefix} : 'pve/';
|
||||||
my ($vtype, $name, $vmid) = $class->parse_volname($volname);
|
my ($vtype, $name, $vmid) = $class->parse_volname($volname);
|
||||||
my $info = _process_list($scfg, $storeid, run_cli($scfg, [ 'ls', $prefix.$name ]))->[0];
|
my $info = _process_list($scfg, $storeid, run_cli($scfg, [ 'ls', $prefix.$name ]))->[0];
|
||||||
#return wantarray ? ($size, $format, $used, $parent, $st->ctime) : $size;
|
# (size, format, used, parent, ctime)
|
||||||
return $info->{size};
|
return wantarray ? ($info->{size}, $info->{format}, $info->{size}, $info->{parent}, 0) : $info->{size};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub volume_resize
|
sub volume_resize
|
||||||
|
@@ -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 = '2.2.0'
|
VITASTOR_VERSION = '2.2.3'
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
637
patches/libvirt-11.5-vitastor.diff
Normal file
637
patches/libvirt-11.5-vitastor.diff
Normal 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 1e24e41a48..ce359a4cf8 100644
|
||||||
|
--- a/src/conf/domain_conf.c
|
||||||
|
+++ b/src/conf/domain_conf.c
|
||||||
|
@@ -7435,7 +7435,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)
|
||||||
|
@@ -31871,6 +31872,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 b28af7fa56..d1aae6e43e 100644
|
||||||
|
--- a/src/conf/domain_validate.c
|
||||||
|
+++ b/src/conf/domain_validate.c
|
||||||
|
@@ -504,6 +504,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:
|
||||||
|
@@ -576,7 +577,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) {
|
||||||
|
@@ -584,10 +585,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 183dd5db5e..dcc0d1a778 100644
|
||||||
|
--- a/src/conf/schemas/domaincommon.rng
|
||||||
|
+++ b/src/conf/schemas/domaincommon.rng
|
||||||
|
@@ -2066,6 +2066,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">
|
||||||
|
@@ -2416,6 +2445,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 8a063be244..dd9c7f11a2 100644
|
||||||
|
--- a/src/conf/storage_source_conf.c
|
||||||
|
+++ b/src/conf/storage_source_conf.c
|
||||||
|
@@ -89,6 +89,7 @@ VIR_ENUM_IMPL(virStorageNetProtocol,
|
||||||
|
"ssh",
|
||||||
|
"vxhs",
|
||||||
|
"nfs",
|
||||||
|
+ "vitastor",
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1314,6 +1315,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 ebddf28cd6..873a2be65c 100644
|
||||||
|
--- a/src/conf/storage_source_conf.h
|
||||||
|
+++ b/src/conf/storage_source_conf.h
|
||||||
|
@@ -130,6 +130,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 bdd30dd65a..5353e00b4a 100644
|
||||||
|
--- a/src/libxl/libxl_conf.c
|
||||||
|
+++ b/src/libxl/libxl_conf.c
|
||||||
|
@@ -1081,6 +1081,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 ec8de30c01..61eab9606d 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 32568d4ae6..e625fa0720 100644
|
||||||
|
--- a/src/qemu/qemu_block.c
|
||||||
|
+++ b/src/qemu/qemu_block.c
|
||||||
|
@@ -731,6 +731,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)
|
||||||
|
{
|
||||||
|
@@ -1082,6 +1114,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)))
|
||||||
|
@@ -1985,6 +2023,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:
|
||||||
|
@@ -2365,6 +2404,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 0d2548d8d4..91121d6e1f 100644
|
||||||
|
--- a/src/qemu/qemu_domain.c
|
||||||
|
+++ b/src/qemu/qemu_domain.c
|
||||||
|
@@ -4526,7 +4526,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;
|
||||||
|
@@ -8954,6 +8955,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 8128154749..afb339b9b0 100644
|
||||||
|
--- a/src/qemu/qemu_snapshot.c
|
||||||
|
+++ b/src/qemu/qemu_snapshot.c
|
||||||
|
@@ -662,6 +662,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:
|
||||||
|
@@ -887,6 +888,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 80681924ea..8a3ade9ec0 100644
|
||||||
|
--- a/src/storage_file/storage_source_backingstore.c
|
||||||
|
+++ b/src/storage_file/storage_source_backingstore.c
|
||||||
|
@@ -287,6 +287,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)
|
||||||
|
@@ -399,6 +468,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:
|
||||||
|
@@ -975,6 +1049,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,
|
||||||
|
@@ -1152,6 +1274,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 25335d9002..cf54069fbe 100644
|
||||||
|
--- a/src/test/test_driver.c
|
||||||
|
+++ b/src/test/test_driver.c
|
||||||
|
@@ -7340,6 +7340,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;
|
||||||
|
}
|
@@ -7,22 +7,24 @@ set -e
|
|||||||
VITASTOR=$(dirname $0)
|
VITASTOR=$(dirname $0)
|
||||||
VITASTOR=$(realpath "$VITASTOR/..")
|
VITASTOR=$(realpath "$VITASTOR/..")
|
||||||
|
|
||||||
EL=$(rpm --eval '%dist')
|
REL=$(rpm --eval '%dist')
|
||||||
if [ "$EL" = ".el8" ]; then
|
REL=${REL##.}
|
||||||
|
if [ "$REL" = "el8" ]; then
|
||||||
# CentOS 8
|
# CentOS 8
|
||||||
. /opt/rh/gcc-toolset-9/enable
|
. /opt/rh/gcc-toolset-9/enable
|
||||||
elif [ "$EL" = ".el7" ]; then
|
elif [ "$REL" = "el7" ]; then
|
||||||
# CentOS 7
|
# CentOS 7
|
||||||
. /opt/rh/devtoolset-9/enable
|
. /opt/rh/devtoolset-9/enable
|
||||||
fi
|
fi
|
||||||
cd ~/rpmbuild/SPECS
|
cd ~/rpmbuild/SPECS
|
||||||
rpmbuild -bp fio.spec
|
rpmbuild -bp fio.spec
|
||||||
cd $VITASTOR
|
cd $VITASTOR
|
||||||
VER=$(grep ^Version: rpm/vitastor-el7.spec | awk '{print $2}')
|
VER=$(grep ^Version: rpm/vitastor-$REL.spec | awk '{print $2}')
|
||||||
|
rm -rf fio
|
||||||
ln -s ~/rpmbuild/BUILD/fio*/ fio
|
ln -s ~/rpmbuild/BUILD/fio*/ fio
|
||||||
sh copy-fio-includes.sh
|
sh copy-fio-includes.sh
|
||||||
rm fio
|
rm fio
|
||||||
mv fio-copy fio
|
mv fio-copy fio
|
||||||
FIO=`rpm -qi fio | perl -e 'while(<>) { /^Epoch[\s:]+(\S+)/ && print "$1:"; /^Version[\s:]+(\S+)/ && print $1; /^Release[\s:]+(\S+)/ && print "-$1"; }'`
|
FIO=`rpm -qi fio | perl -e 'while(<>) { /^Epoch[\s:]+(\S+)/ && print "$1:"; /^Version[\s:]+(\S+)/ && print $1; /^Release[\s:]+(\S+)/ && print "-$1"; }'`
|
||||||
perl -i -pe 's/(Requires:\s*fio)([^\n]+)?/$1 = '$FIO'/' $VITASTOR/rpm/vitastor-el$EL.spec
|
perl -i -pe 's/(Requires:\s*fio)([^\n]+)?/$1 = '$FIO'/' $VITASTOR/rpm/vitastor-$REL.spec
|
||||||
tar --transform "s#^#vitastor-$VER/#" --exclude 'rpm/*.rpm' -czf $VITASTOR/../vitastor-$VER$(rpm --eval '%dist').tar.gz *
|
tar --transform "s#^#vitastor-$VER/#" --exclude 'rpm/*.rpm' -czf $VITASTOR/../vitastor-$VER.$REL.tar.gz $(ls | grep -v packages)
|
||||||
|
16
rpm/vitastor-build.sh
Executable file
16
rpm/vitastor-build.sh
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e -x
|
||||||
|
REL=$(rpm --eval '%dist')
|
||||||
|
REL=${REL##.}
|
||||||
|
cd /root/vitastor/rpm
|
||||||
|
./build-tarball.sh
|
||||||
|
VER=$(grep ^Version: vitastor-$REL.spec | awk '{print $2}')
|
||||||
|
cp /root/vitastor-$VER.$REL.tar.gz ~/rpmbuild/SOURCES
|
||||||
|
cp vitastor-$REL.spec ~/rpmbuild/SPECS/vitastor.spec
|
||||||
|
cd ~/rpmbuild/SPECS/
|
||||||
|
rpmbuild -ba vitastor.spec
|
||||||
|
mkdir -p /root/vitastor/packages/vitastor-$REL
|
||||||
|
rm -rf /root/vitastor/packages/vitastor-$REL/*
|
||||||
|
cp ~/rpmbuild/RPMS/*/*vitastor* /root/vitastor/packages/vitastor-$REL/
|
||||||
|
cp ~/rpmbuild/SRPMS/vitastor* /root/vitastor/packages/vitastor-$REL/
|
@@ -1,5 +1,8 @@
|
|||||||
# Build packages for CentOS 7 inside a container
|
# Build packages for CentOS 7 inside a container
|
||||||
# cd ..; podman build -t vitastor-el7 -v `pwd`/packages:/root/packages -f rpm/vitastor-el7.Dockerfile .
|
# cd ..
|
||||||
|
# docker build -t vitastor-buildenv:el7 -f rpm/vitastor-el7.Dockerfile .
|
||||||
|
# docker run -i --rm -v ./:/root/vitastor vitastor-buildenv:el7 /root/vitastor/rpm/vitastor-build.sh
|
||||||
|
|
||||||
# localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
|
# localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
|
||||||
|
|
||||||
FROM centos:7
|
FROM centos:7
|
||||||
@@ -7,7 +10,9 @@ FROM centos:7
|
|||||||
WORKDIR /root
|
WORKDIR /root
|
||||||
|
|
||||||
RUN rm -f /etc/yum.repos.d/CentOS-Media.repo
|
RUN rm -f /etc/yum.repos.d/CentOS-Media.repo
|
||||||
|
RUN sed -i 's/^mirrorlist=/#mirrorlist=/; s!#baseurl=http://mirror.centos.org/centos/\$releasever!baseurl=http://vault.centos.org/7.9.2009!' /etc/yum.repos.d/*.repo
|
||||||
RUN yum -y --enablerepo=extras install centos-release-scl epel-release yum-utils rpm-build
|
RUN yum -y --enablerepo=extras install centos-release-scl epel-release yum-utils rpm-build
|
||||||
|
RUN perl -i -pe 's!mirrorlist=!#mirrorlist=!s; s!#\s*baseurl=http://mirror.centos.org!baseurl=http://vault.centos.org!' /etc/yum.repos.d/CentOS-SCLo-scl*.repo
|
||||||
RUN yum -y install https://vitastor.io/rpms/centos/7/vitastor-release-1.0-1.el7.noarch.rpm
|
RUN yum -y install https://vitastor.io/rpms/centos/7/vitastor-release-1.0-1.el7.noarch.rpm
|
||||||
RUN yum -y install devtoolset-9-gcc-c++ devtoolset-9-libatomic-devel gcc make cmake gperftools-devel \
|
RUN yum -y install devtoolset-9-gcc-c++ devtoolset-9-libatomic-devel gcc make cmake gperftools-devel \
|
||||||
fio rh-nodejs12 jerasure-devel libisa-l-devel gf-complete-devel rdma-core-devel libnl3-devel
|
fio rh-nodejs12 jerasure-devel libisa-l-devel gf-complete-devel rdma-core-devel libnl3-devel
|
||||||
@@ -30,18 +35,3 @@ RUN set -e; \
|
|||||||
cp ~/rpmbuild/SRPMS/liburing* /root/packages/liburing-el7/
|
cp ~/rpmbuild/SRPMS/liburing* /root/packages/liburing-el7/
|
||||||
|
|
||||||
RUN rpm -i `ls /root/packages/liburing-el7/liburing-*.x86_64.rpm | grep -v debug`
|
RUN rpm -i `ls /root/packages/liburing-el7/liburing-*.x86_64.rpm | grep -v debug`
|
||||||
|
|
||||||
ADD . /root/vitastor
|
|
||||||
|
|
||||||
RUN set -e; \
|
|
||||||
cd /root/vitastor/rpm; \
|
|
||||||
sh build-tarball.sh; \
|
|
||||||
VER=$(grep ^Version: vitastor-el7.spec | awk '{print $2}'); \
|
|
||||||
cp /root/vitastor-$VER.el7.tar.gz ~/rpmbuild/SOURCES; \
|
|
||||||
cp vitastor-el7.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
|
||||||
cd ~/rpmbuild/SPECS/; \
|
|
||||||
rpmbuild -ba vitastor.spec; \
|
|
||||||
mkdir -p /root/packages/vitastor-el7; \
|
|
||||||
rm -rf /root/packages/vitastor-el7/*; \
|
|
||||||
cp ~/rpmbuild/RPMS/*/*vitastor* /root/packages/vitastor-el7/; \
|
|
||||||
cp ~/rpmbuild/SRPMS/vitastor* /root/packages/vitastor-el7/
|
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 2.2.0
|
Version: 2.2.3
|
||||||
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-2.2.0.el7.tar.gz
|
Source0: vitastor-2.2.3.el7.tar.gz
|
||||||
|
|
||||||
BuildRequires: liburing-devel >= 0.6
|
BuildRequires: liburing-devel >= 0.6
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
@@ -82,7 +82,7 @@ Vitastor library headers for development.
|
|||||||
Summary: Vitastor - fio drivers
|
Summary: Vitastor - fio drivers
|
||||||
Group: Development/Libraries
|
Group: Development/Libraries
|
||||||
Requires: vitastor-client = %{version}-%{release}
|
Requires: vitastor-client = %{version}-%{release}
|
||||||
Requires: fio = 3.7-1.el7
|
Requires: fio = 3.7-2.el7
|
||||||
|
|
||||||
|
|
||||||
%description -n vitastor-fio
|
%description -n vitastor-fio
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
# Build packages for CentOS 8 inside a container
|
# Build packages for CentOS 8 inside a container
|
||||||
# cd ..; podman build -t vitastor-el8 -v `pwd`/packages:/root/packages -f rpm/vitastor-el8.Dockerfile .
|
# cd ..
|
||||||
|
# docker build -t vitastor-buildenv:el8 -f rpm/vitastor-el8.Dockerfile .
|
||||||
|
# docker run -i --rm -v ./:/root/vitastor vitastor-buildenv:el8 /root/vitastor/rpm/vitastor-build.sh
|
||||||
|
|
||||||
FROM centos:8
|
FROM centos:8
|
||||||
|
|
||||||
@@ -29,18 +31,3 @@ RUN set -e; \
|
|||||||
cp ~/rpmbuild/SRPMS/liburing* /root/packages/liburing-el8/
|
cp ~/rpmbuild/SRPMS/liburing* /root/packages/liburing-el8/
|
||||||
|
|
||||||
RUN rpm -i `ls /root/packages/liburing-el8/liburing-*.x86_64.rpm | grep -v debug`
|
RUN rpm -i `ls /root/packages/liburing-el8/liburing-*.x86_64.rpm | grep -v debug`
|
||||||
|
|
||||||
ADD . /root/vitastor
|
|
||||||
|
|
||||||
RUN set -e; \
|
|
||||||
cd /root/vitastor/rpm; \
|
|
||||||
sh build-tarball.sh; \
|
|
||||||
VER=$(grep ^Version: vitastor-el8.spec | awk '{print $2}'); \
|
|
||||||
cp /root/vitastor-$VER.el8.tar.gz ~/rpmbuild/SOURCES; \
|
|
||||||
cp vitastor-el8.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
|
||||||
cd ~/rpmbuild/SPECS/; \
|
|
||||||
rpmbuild -ba vitastor.spec; \
|
|
||||||
mkdir -p /root/packages/vitastor-el8; \
|
|
||||||
rm -rf /root/packages/vitastor-el8/*; \
|
|
||||||
cp ~/rpmbuild/RPMS/*/*vitastor* /root/packages/vitastor-el8/; \
|
|
||||||
cp ~/rpmbuild/SRPMS/vitastor* /root/packages/vitastor-el8/
|
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 2.2.0
|
Version: 2.2.3
|
||||||
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-2.2.0.el8.tar.gz
|
Source0: vitastor-2.2.3.el8.tar.gz
|
||||||
|
|
||||||
BuildRequires: liburing-devel >= 0.6
|
BuildRequires: liburing-devel >= 0.6
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
@@ -80,7 +80,7 @@ Vitastor library headers for development.
|
|||||||
Summary: Vitastor - fio drivers
|
Summary: Vitastor - fio drivers
|
||||||
Group: Development/Libraries
|
Group: Development/Libraries
|
||||||
Requires: vitastor-client = %{version}-%{release}
|
Requires: vitastor-client = %{version}-%{release}
|
||||||
Requires: fio = 3.7-3.el8
|
Requires: fio = 3.19-3.el8
|
||||||
|
|
||||||
|
|
||||||
%description -n vitastor-fio
|
%description -n vitastor-fio
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
# Build packages for AlmaLinux 9 inside a container
|
# Build packages for AlmaLinux 9 inside a container
|
||||||
# cd ..; podman build -t vitastor-el9 -v `pwd`/packages:/root/packages -f rpm/vitastor-el9.Dockerfile .
|
# cd ..
|
||||||
|
# docker build -t vitastor-buildenv:el9 -f rpm/vitastor-el9.Dockerfile .
|
||||||
|
# docker run -i --rm -v ./:/root/vitastor vitastor-buildenv:el9 /root/vitastor/rpm/vitastor-build.sh
|
||||||
|
|
||||||
FROM almalinux:9
|
FROM almalinux:9
|
||||||
|
|
||||||
@@ -12,18 +14,3 @@ RUN dnf -y install gcc-c++ gperftools-devel fio nodejs rpm-build jerasure-devel
|
|||||||
RUN dnf download --source fio
|
RUN dnf download --source fio
|
||||||
RUN rpm --nomd5 -i fio*.src.rpm
|
RUN rpm --nomd5 -i fio*.src.rpm
|
||||||
RUN cd ~/rpmbuild/SPECS && dnf builddep -y --spec fio.spec
|
RUN cd ~/rpmbuild/SPECS && dnf builddep -y --spec fio.spec
|
||||||
|
|
||||||
ADD . /root/vitastor
|
|
||||||
|
|
||||||
RUN set -e; \
|
|
||||||
cd /root/vitastor/rpm; \
|
|
||||||
sh build-tarball.sh; \
|
|
||||||
VER=$(grep ^Version: vitastor-el9.spec | awk '{print $2}'); \
|
|
||||||
cp /root/vitastor-$VER.el9.tar.gz ~/rpmbuild/SOURCES; \
|
|
||||||
cp vitastor-el9.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
|
||||||
cd ~/rpmbuild/SPECS/; \
|
|
||||||
rpmbuild -ba vitastor.spec; \
|
|
||||||
mkdir -p /root/packages/vitastor-el9; \
|
|
||||||
rm -rf /root/packages/vitastor-el9/*; \
|
|
||||||
cp ~/rpmbuild/RPMS/*/*vitastor* /root/packages/vitastor-el9/; \
|
|
||||||
cp ~/rpmbuild/SRPMS/vitastor* /root/packages/vitastor-el9/
|
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 2.2.0
|
Version: 2.2.3
|
||||||
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-2.2.0.el9.tar.gz
|
Source0: vitastor-2.2.3.el9.tar.gz
|
||||||
|
|
||||||
BuildRequires: liburing-devel >= 0.6
|
BuildRequires: liburing-devel >= 0.6
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
|
@@ -19,7 +19,7 @@ if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/local/?$")
|
|||||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-DVITASTOR_VERSION="2.2.0")
|
add_definitions(-DVITASTOR_VERSION="2.2.3")
|
||||||
add_definitions(-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 -I ${CMAKE_SOURCE_DIR}/src)
|
add_definitions(-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 -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})
|
||||||
|
@@ -42,8 +42,7 @@
|
|||||||
#define BS_OP_DELETE 6
|
#define BS_OP_DELETE 6
|
||||||
#define BS_OP_LIST 7
|
#define BS_OP_LIST 7
|
||||||
#define BS_OP_ROLLBACK 8
|
#define BS_OP_ROLLBACK 8
|
||||||
#define BS_OP_SYNC_STAB_ALL 9
|
#define BS_OP_MAX 8
|
||||||
#define BS_OP_MAX 9
|
|
||||||
|
|
||||||
#define BS_OP_PRIVATE_DATA_SIZE 256
|
#define BS_OP_PRIVATE_DATA_SIZE 256
|
||||||
|
|
||||||
@@ -113,14 +112,6 @@ Input:
|
|||||||
Output:
|
Output:
|
||||||
- retval = 0 or negative error number (-ENOENT if no such version for stabilize)
|
- retval = 0 or negative error number (-ENOENT if no such version for stabilize)
|
||||||
|
|
||||||
## BS_OP_SYNC_STAB_ALL
|
|
||||||
|
|
||||||
ONLY FOR TESTS! Sync and mark all unstable object versions as stable, at once.
|
|
||||||
|
|
||||||
Input: Nothing except opcode
|
|
||||||
Output:
|
|
||||||
- retval = 0 or negative error number (-EINVAL)
|
|
||||||
|
|
||||||
## BS_OP_LIST
|
## BS_OP_LIST
|
||||||
|
|
||||||
Get a list of all objects in this Blockstore.
|
Get a list of all objects in this Blockstore.
|
||||||
@@ -147,7 +138,7 @@ Output:
|
|||||||
struct blockstore_op_t
|
struct blockstore_op_t
|
||||||
{
|
{
|
||||||
// operation
|
// operation
|
||||||
uint64_t opcode;
|
uint64_t opcode = 0;
|
||||||
// finish callback
|
// finish callback
|
||||||
std::function<void (blockstore_op_t*)> callback;
|
std::function<void (blockstore_op_t*)> callback;
|
||||||
union __attribute__((__packed__))
|
union __attribute__((__packed__))
|
||||||
@@ -171,9 +162,9 @@ struct blockstore_op_t
|
|||||||
uint32_t list_stable_limit;
|
uint32_t list_stable_limit;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
void *buf;
|
void *buf = NULL;
|
||||||
void *bitmap;
|
void *bitmap = NULL;
|
||||||
int retval;
|
int retval = 0;
|
||||||
|
|
||||||
uint8_t private_data[BS_OP_PRIVATE_DATA_SIZE];
|
uint8_t private_data[BS_OP_PRIVATE_DATA_SIZE];
|
||||||
};
|
};
|
||||||
|
@@ -343,44 +343,6 @@ void blockstore_impl_t::enqueue_op(blockstore_op_t *op)
|
|||||||
ringloop->set_immediate([op]() { std::function<void (blockstore_op_t*)>(op->callback)(op); });
|
ringloop->set_immediate([op]() { std::function<void (blockstore_op_t*)>(op->callback)(op); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (op->opcode == BS_OP_SYNC_STAB_ALL)
|
|
||||||
{
|
|
||||||
std::function<void(blockstore_op_t*)> *old_callback = new std::function<void(blockstore_op_t*)>(op->callback);
|
|
||||||
op->opcode = BS_OP_SYNC;
|
|
||||||
op->callback = [this, old_callback](blockstore_op_t *op)
|
|
||||||
{
|
|
||||||
if (op->retval >= 0 && unstable_writes.size() > 0)
|
|
||||||
{
|
|
||||||
op->opcode = BS_OP_STABLE;
|
|
||||||
op->len = unstable_writes.size();
|
|
||||||
obj_ver_id *vers = new obj_ver_id[op->len];
|
|
||||||
op->buf = vers;
|
|
||||||
int i = 0;
|
|
||||||
for (auto it = unstable_writes.begin(); it != unstable_writes.end(); it++, i++)
|
|
||||||
{
|
|
||||||
vers[i] = {
|
|
||||||
.oid = it->first,
|
|
||||||
.version = it->second,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
unstable_writes.clear();
|
|
||||||
op->callback = [old_callback](blockstore_op_t *op)
|
|
||||||
{
|
|
||||||
obj_ver_id *vers = (obj_ver_id*)op->buf;
|
|
||||||
delete[] vers;
|
|
||||||
op->buf = NULL;
|
|
||||||
(*old_callback)(op);
|
|
||||||
delete old_callback;
|
|
||||||
};
|
|
||||||
this->enqueue_op(op);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
(*old_callback)(op);
|
|
||||||
delete old_callback;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if ((op->opcode == BS_OP_WRITE || op->opcode == BS_OP_WRITE_STABLE || op->opcode == BS_OP_DELETE) && !enqueue_write(op))
|
if ((op->opcode == BS_OP_WRITE || op->opcode == BS_OP_WRITE_STABLE || op->opcode == BS_OP_DELETE) && !enqueue_write(op))
|
||||||
{
|
{
|
||||||
ringloop->set_immediate([op]() { std::function<void (blockstore_op_t*)>(op->callback)(op); });
|
ringloop->set_immediate([op]() { std::function<void (blockstore_op_t*)>(op->callback)(op); });
|
||||||
|
@@ -5,14 +5,14 @@
|
|||||||
//
|
//
|
||||||
// Initialize storage for tests:
|
// Initialize storage for tests:
|
||||||
//
|
//
|
||||||
// dd if=/dev/zero of=test_data.bin bs=1024 count=1048576
|
// dd if=/dev/zero of=test_data.bin bs=1M count=1024
|
||||||
// dd if=/dev/zero of=test_meta.bin bs=1024 count=256
|
|
||||||
// dd if=/dev/zero of=test_journal.bin bs=1024 count=4096
|
|
||||||
//
|
//
|
||||||
// Random write:
|
// Random write:
|
||||||
//
|
//
|
||||||
// fio -thread -ioengine=./libfio_blockstore.so -name=test -bs=4k -direct=1 -fsync=16 -iodepth=16 -rw=randwrite \
|
// [LD_PRELOAD=libasan.so.8] \
|
||||||
// -bs_config='{"data_device":"./test_data.bin"}' -size=1000M
|
// fio -name=test -thread -ioengine=../build/src/blockstore/libfio_vitastor_blk.so \
|
||||||
|
// -bs=4k -direct=1 -rw=randwrite -iodepth=16 -size=900M -loops=10 \
|
||||||
|
// -bs_config='{"data_device":"./test_data.bin","meta_offset":0,"journal_offset":16777216,"data_offset":33554432,"disable_data_fsync":true,"immediate_commit":"all","journal_no_same_sector_overwrites":true}'
|
||||||
//
|
//
|
||||||
// Linear write:
|
// Linear write:
|
||||||
//
|
//
|
||||||
@@ -38,12 +38,14 @@ struct bs_data
|
|||||||
std::vector<io_u*> completed;
|
std::vector<io_u*> completed;
|
||||||
int op_n = 0, inflight = 0;
|
int op_n = 0, inflight = 0;
|
||||||
bool last_sync = false;
|
bool last_sync = false;
|
||||||
|
bool trace = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bs_options
|
struct bs_options
|
||||||
{
|
{
|
||||||
int __pad;
|
int __pad;
|
||||||
char *json_config = NULL;
|
char *json_config = NULL;
|
||||||
|
int trace = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct fio_option options[] = {
|
static struct fio_option options[] = {
|
||||||
@@ -56,6 +58,16 @@ static struct fio_option options[] = {
|
|||||||
.category = FIO_OPT_C_ENGINE,
|
.category = FIO_OPT_C_ENGINE,
|
||||||
.group = FIO_OPT_G_FILENAME,
|
.group = FIO_OPT_G_FILENAME,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "bs_trace",
|
||||||
|
.lname = "trace",
|
||||||
|
.type = FIO_OPT_BOOL,
|
||||||
|
.off1 = offsetof(struct bs_options, trace),
|
||||||
|
.help = "Trace operations",
|
||||||
|
.def = "0",
|
||||||
|
.category = FIO_OPT_C_ENGINE,
|
||||||
|
.group = FIO_OPT_G_FILENAME,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = NULL,
|
.name = NULL,
|
||||||
},
|
},
|
||||||
@@ -63,6 +75,7 @@ static struct fio_option options[] = {
|
|||||||
|
|
||||||
static int bs_setup(struct thread_data *td)
|
static int bs_setup(struct thread_data *td)
|
||||||
{
|
{
|
||||||
|
bs_options *o = (bs_options*)td->eo;
|
||||||
bs_data *bsd;
|
bs_data *bsd;
|
||||||
//fio_file *f;
|
//fio_file *f;
|
||||||
//int r;
|
//int r;
|
||||||
@@ -83,6 +96,8 @@ static int bs_setup(struct thread_data *td)
|
|||||||
td->o.open_files++;
|
td->o.open_files++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bsd->trace = o->trace ? true : false;
|
||||||
|
|
||||||
//f = td->files[0];
|
//f = td->files[0];
|
||||||
//f->real_file_size = size;
|
//f->real_file_size = size;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -176,20 +191,19 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io)
|
|||||||
op->version = UINT64_MAX; // last unstable
|
op->version = UINT64_MAX; // last unstable
|
||||||
op->offset = io->offset % bsd->bs->get_block_size();
|
op->offset = io->offset % bsd->bs->get_block_size();
|
||||||
op->len = io->xfer_buflen;
|
op->len = io->xfer_buflen;
|
||||||
op->callback = [io](blockstore_op_t *op)
|
op->callback = [io, n = bsd->op_n](blockstore_op_t *op)
|
||||||
{
|
{
|
||||||
io->error = op->retval < 0 ? -op->retval : 0;
|
io->error = op->retval < 0 ? -op->retval : 0;
|
||||||
bs_data *bsd = (bs_data*)io->engine_data;
|
bs_data *bsd = (bs_data*)io->engine_data;
|
||||||
bsd->inflight--;
|
bsd->inflight--;
|
||||||
bsd->completed.push_back(io);
|
bsd->completed.push_back(io);
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
if (bsd->trace)
|
||||||
printf("--- OP_READ %llx n=%d retval=%d\n", io, n, op->retval);
|
printf("--- OP_READ %zx n=%d retval=%d\n", (size_t)op, n, op->retval);
|
||||||
#endif
|
|
||||||
delete op;
|
delete op;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case DDIR_WRITE:
|
case DDIR_WRITE:
|
||||||
op->opcode = BS_OP_WRITE;
|
op->opcode = BS_OP_WRITE_STABLE;
|
||||||
op->buf = io->xfer_buf;
|
op->buf = io->xfer_buf;
|
||||||
op->oid = {
|
op->oid = {
|
||||||
.inode = 1,
|
.inode = 1,
|
||||||
@@ -198,30 +212,28 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io)
|
|||||||
op->version = 0; // assign automatically
|
op->version = 0; // assign automatically
|
||||||
op->offset = io->offset % bsd->bs->get_block_size();
|
op->offset = io->offset % bsd->bs->get_block_size();
|
||||||
op->len = io->xfer_buflen;
|
op->len = io->xfer_buflen;
|
||||||
op->callback = [io](blockstore_op_t *op)
|
op->callback = [io, n = bsd->op_n](blockstore_op_t *op)
|
||||||
{
|
{
|
||||||
io->error = op->retval < 0 ? -op->retval : 0;
|
io->error = op->retval < 0 ? -op->retval : 0;
|
||||||
bs_data *bsd = (bs_data*)io->engine_data;
|
bs_data *bsd = (bs_data*)io->engine_data;
|
||||||
bsd->inflight--;
|
bsd->inflight--;
|
||||||
bsd->completed.push_back(io);
|
bsd->completed.push_back(io);
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
if (bsd->trace)
|
||||||
printf("--- OP_WRITE %llx n=%d retval=%d\n", io, n, op->retval);
|
printf("--- OP_WRITE %zx n=%d retval=%d\n", (size_t)op, n, op->retval);
|
||||||
#endif
|
|
||||||
delete op;
|
delete op;
|
||||||
};
|
};
|
||||||
bsd->last_sync = false;
|
bsd->last_sync = false;
|
||||||
break;
|
break;
|
||||||
case DDIR_SYNC:
|
case DDIR_SYNC:
|
||||||
op->opcode = BS_OP_SYNC_STAB_ALL;
|
op->opcode = BS_OP_SYNC;
|
||||||
op->callback = [io](blockstore_op_t *op)
|
op->callback = [io, n = bsd->op_n](blockstore_op_t *op)
|
||||||
{
|
{
|
||||||
bs_data *bsd = (bs_data*)io->engine_data;
|
bs_data *bsd = (bs_data*)io->engine_data;
|
||||||
io->error = op->retval < 0 ? -op->retval : 0;
|
io->error = op->retval < 0 ? -op->retval : 0;
|
||||||
bsd->completed.push_back(io);
|
bsd->completed.push_back(io);
|
||||||
bsd->inflight--;
|
bsd->inflight--;
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
if (bsd->trace)
|
||||||
printf("--- OP_SYNC %llx n=%d retval=%d\n", io, n, op->retval);
|
printf("--- OP_SYNC %zx n=%d retval=%d\n", (size_t)op, n, op->retval);
|
||||||
#endif
|
|
||||||
delete op;
|
delete op;
|
||||||
};
|
};
|
||||||
bsd->last_sync = true;
|
bsd->last_sync = true;
|
||||||
@@ -232,9 +244,8 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io)
|
|||||||
return FIO_Q_COMPLETED;
|
return FIO_Q_COMPLETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
if (bsd->trace)
|
||||||
printf("+++ %s %llx n=%d\n", op->opcode == OP_READ ? "OP_READ" : (op->opcode == OP_WRITE ? "OP_WRITE" : "OP_SYNC"), io, n);
|
printf("+++ %s %zx n=%d\n", op->opcode == BS_OP_READ ? "OP_READ" : (op->opcode == BS_OP_WRITE_STABLE ? "OP_WRITE" : "OP_SYNC"), (size_t)op, bsd->op_n);
|
||||||
#endif
|
|
||||||
io->error = 0;
|
io->error = 0;
|
||||||
bsd->inflight++;
|
bsd->inflight++;
|
||||||
bsd->bs->enqueue_op(op);
|
bsd->bs->enqueue_op(op);
|
||||||
|
@@ -57,6 +57,7 @@ cluster_client_t::cluster_client_t(ring_loop_t *ringloop, timerfd_manager_t *tfd
|
|||||||
st_cli.on_load_config_hook = [this](json11::Json::object & cfg) { on_load_config_hook(cfg); };
|
st_cli.on_load_config_hook = [this](json11::Json::object & cfg) { on_load_config_hook(cfg); };
|
||||||
st_cli.on_change_osd_state_hook = [this](uint64_t peer_osd) { on_change_osd_state_hook(peer_osd); };
|
st_cli.on_change_osd_state_hook = [this](uint64_t peer_osd) { on_change_osd_state_hook(peer_osd); };
|
||||||
st_cli.on_change_pool_config_hook = [this]() { on_change_pool_config_hook(); };
|
st_cli.on_change_pool_config_hook = [this]() { on_change_pool_config_hook(); };
|
||||||
|
st_cli.on_change_pg_config_hook = [this]() { on_change_pool_config_hook(); };
|
||||||
st_cli.on_change_pg_state_hook = [this](pool_id_t pool_id, pg_num_t pg_num, osd_num_t prev_primary) { on_change_pg_state_hook(pool_id, pg_num, prev_primary); };
|
st_cli.on_change_pg_state_hook = [this](pool_id_t pool_id, pg_num_t pg_num, osd_num_t prev_primary) { on_change_pg_state_hook(pool_id, pg_num, prev_primary); };
|
||||||
st_cli.on_change_node_placement_hook = [this]() { on_change_node_placement_hook(); };
|
st_cli.on_change_node_placement_hook = [this]() { on_change_node_placement_hook(); };
|
||||||
st_cli.on_load_pgs_hook = [this](bool success) { on_load_pgs_hook(success); };
|
st_cli.on_load_pgs_hook = [this](bool success) { on_load_pgs_hook(success); };
|
||||||
@@ -563,7 +564,7 @@ osd_num_t cluster_client_t::select_nearest_osd(const std::vector<osd_num_t> & os
|
|||||||
|
|
||||||
void cluster_client_t::on_load_pgs_hook(bool success)
|
void cluster_client_t::on_load_pgs_hook(bool success)
|
||||||
{
|
{
|
||||||
for (auto pool_item: st_cli.pool_config)
|
for (auto & pool_item: st_cli.pool_config)
|
||||||
{
|
{
|
||||||
pg_counts[pool_item.first] = pool_item.second.real_pg_count;
|
pg_counts[pool_item.first] = pool_item.second.real_pg_count;
|
||||||
}
|
}
|
||||||
@@ -583,10 +584,15 @@ void cluster_client_t::on_load_pgs_hook(bool success)
|
|||||||
|
|
||||||
void cluster_client_t::on_change_pool_config_hook()
|
void cluster_client_t::on_change_pool_config_hook()
|
||||||
{
|
{
|
||||||
for (auto pool_item: st_cli.pool_config)
|
for (auto & pool_item: st_cli.pool_config)
|
||||||
{
|
{
|
||||||
if (pg_counts[pool_item.first] != pool_item.second.real_pg_count)
|
if (pg_counts[pool_item.first] != pool_item.second.real_pg_count)
|
||||||
{
|
{
|
||||||
|
if (log_level > 2 && pg_counts[pool_item.first])
|
||||||
|
{
|
||||||
|
printf("Pool %u (%s) PG count changed from %lu to %lu\n", pool_item.first, pool_item.second.name.c_str(),
|
||||||
|
pg_counts[pool_item.first], pool_item.second.real_pg_count);
|
||||||
|
}
|
||||||
// At this point, all pool operations should have been suspended
|
// At this point, all pool operations should have been suspended
|
||||||
// And now they have to be resliced!
|
// And now they have to be resliced!
|
||||||
for (auto op = op_queue_head; op; op = op->next)
|
for (auto op = op_queue_head; op; op = op->next)
|
||||||
|
@@ -1056,6 +1056,10 @@ void etcd_state_client_t::parse_state(const etcd_kv_t & kv)
|
|||||||
}
|
}
|
||||||
pool_item.second.real_pg_count = n;
|
pool_item.second.real_pg_count = n;
|
||||||
}
|
}
|
||||||
|
if (on_change_pg_config_hook)
|
||||||
|
{
|
||||||
|
on_change_pg_config_hook();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (key.substr(0, etcd_prefix.length()+12) == etcd_prefix+"/pg/history/")
|
else if (key.substr(0, etcd_prefix.length()+12) == etcd_prefix+"/pg/history/")
|
||||||
{
|
{
|
||||||
@@ -1182,9 +1186,7 @@ void etcd_state_client_t::parse_state(const etcd_kv_t & kv)
|
|||||||
osd_num_t peer_osd = std::stoull(key.substr(etcd_prefix.length()+11));
|
osd_num_t peer_osd = std::stoull(key.substr(etcd_prefix.length()+11));
|
||||||
if (peer_osd > 0)
|
if (peer_osd > 0)
|
||||||
{
|
{
|
||||||
if (value.is_object() && value["state"] == "up" &&
|
if (value.is_object() && value["state"] == "up")
|
||||||
value["addresses"].is_array() &&
|
|
||||||
value["port"].int64_value() > 0 && value["port"].int64_value() < 65536)
|
|
||||||
{
|
{
|
||||||
this->peer_states[peer_osd] = value;
|
this->peer_states[peer_osd] = value;
|
||||||
this->seen_peers.insert(peer_osd);
|
this->seen_peers.insert(peer_osd);
|
||||||
|
@@ -142,6 +142,7 @@ public:
|
|||||||
std::function<json11::Json()> load_pgs_checks_hook;
|
std::function<json11::Json()> load_pgs_checks_hook;
|
||||||
std::function<void(bool)> on_load_pgs_hook;
|
std::function<void(bool)> on_load_pgs_hook;
|
||||||
std::function<void()> on_change_pool_config_hook;
|
std::function<void()> on_change_pool_config_hook;
|
||||||
|
std::function<void()> on_change_pg_config_hook;
|
||||||
std::function<void(pool_id_t)> on_change_backfillfull_hook;
|
std::function<void(pool_id_t)> on_change_backfillfull_hook;
|
||||||
std::function<void(pool_id_t, pg_num_t, osd_num_t)> on_change_pg_state_hook;
|
std::function<void(pool_id_t, pg_num_t, osd_num_t)> on_change_pg_state_hook;
|
||||||
std::function<void(pool_id_t, pg_num_t)> on_change_pg_history_hook;
|
std::function<void(pool_id_t, pg_num_t)> on_change_pg_history_hook;
|
||||||
|
@@ -188,7 +188,7 @@ void osd_messenger_t::init()
|
|||||||
auto cl = cl_it->second;
|
auto cl = cl_it->second;
|
||||||
cl_it++;
|
cl_it++;
|
||||||
auto peer_fd = cl->peer_fd;
|
auto peer_fd = cl->peer_fd;
|
||||||
if (!cl->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
|
||||||
continue;
|
continue;
|
||||||
@@ -199,7 +199,7 @@ 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->osd_num, cl->peer_fd);
|
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);
|
||||||
stop_client(peer_fd, true);
|
stop_client(peer_fd, true);
|
||||||
// Restart iterator because it may be invalidated
|
// Restart iterator because it may be invalidated
|
||||||
cl_it = clients.upper_bound(peer_fd);
|
cl_it = clients.upper_bound(peer_fd);
|
||||||
@@ -230,7 +230,7 @@ void osd_messenger_t::init()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int fail_fd = (op->reply.hdr.retval != 0 ? op->peer_fd : -1);
|
int fail_fd = (op->reply.hdr.retval != 0 ? op->peer_fd : -1);
|
||||||
auto fail_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_fd >= 0)
|
||||||
|
@@ -60,6 +60,7 @@ struct osd_client_t
|
|||||||
int ping_time_remaining = 0;
|
int ping_time_remaining = 0;
|
||||||
int idle_time_remaining = 0;
|
int idle_time_remaining = 0;
|
||||||
osd_num_t osd_num = 0;
|
osd_num_t osd_num = 0;
|
||||||
|
osd_num_t in_osd_num = 0;
|
||||||
bool is_incoming = false;
|
bool is_incoming = false;
|
||||||
|
|
||||||
void *in_buf = NULL;
|
void *in_buf = NULL;
|
||||||
@@ -98,6 +99,7 @@ struct osd_client_t
|
|||||||
std::vector<osd_op_t*> zc_free_list;
|
std::vector<osd_op_t*> zc_free_list;
|
||||||
|
|
||||||
~osd_client_t();
|
~osd_client_t();
|
||||||
|
void cancel_ops();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct osd_wanted_peer_t
|
struct osd_wanted_peer_t
|
||||||
@@ -235,6 +237,7 @@ public:
|
|||||||
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;
|
||||||
|
std::function<void(osd_num_t)> break_pg_locks;
|
||||||
std::function<bool(osd_client_t*, json11::Json)> check_config_hook;
|
std::function<bool(osd_client_t*, json11::Json)> check_config_hook;
|
||||||
void read_requests();
|
void read_requests();
|
||||||
void send_replies();
|
void send_replies();
|
||||||
|
@@ -173,6 +173,7 @@ struct osd_op_t
|
|||||||
osd_op_buf_list_t iov;
|
osd_op_buf_list_t iov;
|
||||||
|
|
||||||
~osd_op_t();
|
~osd_op_t();
|
||||||
|
void cancel();
|
||||||
|
|
||||||
bool is_recovery_related();
|
bool is_recovery_related();
|
||||||
};
|
};
|
||||||
|
@@ -510,7 +510,6 @@ void osd_messenger_t::rdmacm_established(rdma_cm_event *ev)
|
|||||||
rc->qp = conn->cmid->qp;
|
rc->qp = conn->cmid->qp;
|
||||||
// And an osd_client_t
|
// And an osd_client_t
|
||||||
auto cl = new osd_client_t();
|
auto cl = new osd_client_t();
|
||||||
cl->is_incoming = true;
|
|
||||||
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->peer_fd = conn->peer_fd;
|
||||||
|
@@ -8,11 +8,12 @@ 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];
|
int peer_fd = read_ready_clients[i];
|
||||||
osd_client_t *cl = clients[peer_fd];
|
auto cl_it = clients.find(peer_fd);
|
||||||
if (cl->read_msg.msg_iovlen)
|
if (cl_it == clients.end() || !cl_it->second || cl_it->second->read_msg.msg_iovlen)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
auto cl = cl_it->second;
|
||||||
if (cl->read_remaining < receive_buffer_size)
|
if (cl->read_remaining < receive_buffer_size)
|
||||||
{
|
{
|
||||||
cl->read_iov.iov_base = cl->in_buf;
|
cl->read_iov.iov_base = cl->in_buf;
|
||||||
@@ -33,8 +34,12 @@ void osd_messenger_t::read_requests()
|
|||||||
auto iothread = iothreads.size() ? iothreads[peer_fd % iothreads.size()] : NULL;
|
auto iothread = iothreads.size() ? iothreads[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;
|
||||||
sqe_local.user_data = (uint64_t)&data_local;
|
|
||||||
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
|
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
|
||||||
|
if (iothread)
|
||||||
|
{
|
||||||
|
sqe_local = { .user_data = (uint64_t)&data_local };
|
||||||
|
data_local = {};
|
||||||
|
}
|
||||||
if (!sqe)
|
if (!sqe)
|
||||||
{
|
{
|
||||||
cl->read_msg.msg_iovlen = 0;
|
cl->read_msg.msg_iovlen = 0;
|
||||||
@@ -56,7 +61,8 @@ void osd_messenger_t::read_requests()
|
|||||||
{
|
{
|
||||||
result = -errno;
|
result = -errno;
|
||||||
}
|
}
|
||||||
handle_read(result, cl);
|
// like set_immediate
|
||||||
|
tfd->set_timer_us(0, false, [this, result, cl](int){ handle_read(result, cl); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
read_ready_clients.clear();
|
read_ready_clients.clear();
|
||||||
@@ -228,7 +234,7 @@ 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, stopping client\n", cl->peer_fd);
|
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);
|
||||||
stop_client(cl->peer_fd);
|
stop_client(cl->peer_fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -194,12 +194,14 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
|
|||||||
auto iothread = iothreads.size() ? iothreads[peer_fd % iothreads.size()] : NULL;
|
auto iothread = iothreads.size() ? iothreads[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;
|
||||||
sqe_local.user_data = (uint64_t)&data_local;
|
|
||||||
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
|
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
|
||||||
if (!sqe)
|
if (iothread)
|
||||||
{
|
{
|
||||||
return false;
|
sqe_local = { .user_data = (uint64_t)&data_local };
|
||||||
|
data_local = {};
|
||||||
}
|
}
|
||||||
|
if (!sqe)
|
||||||
|
return false;
|
||||||
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++;
|
||||||
@@ -237,7 +239,8 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
|
|||||||
{
|
{
|
||||||
result = -errno;
|
result = -errno;
|
||||||
}
|
}
|
||||||
handle_send(result, false, false, cl);
|
// like set_immediate
|
||||||
|
tfd->set_timer_us(0, false, [this, result, cl](int){ handle_send(result, false, false, cl); });
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -9,38 +9,37 @@
|
|||||||
#include "msgr_rdma.h"
|
#include "msgr_rdma.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void osd_messenger_t::cancel_osd_ops(osd_client_t *cl)
|
void osd_client_t::cancel_ops()
|
||||||
{
|
{
|
||||||
std::vector<osd_op_t*> cancel_ops;
|
std::vector<osd_op_t*> cancel_ops;
|
||||||
cancel_ops.resize(cl->sent_ops.size());
|
cancel_ops.resize(sent_ops.size());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto p: cl->sent_ops)
|
for (auto p: sent_ops)
|
||||||
{
|
{
|
||||||
cancel_ops[i++] = p.second;
|
cancel_ops[i++] = p.second;
|
||||||
}
|
}
|
||||||
cl->sent_ops.clear();
|
sent_ops.clear();
|
||||||
cl->outbox.clear();
|
|
||||||
for (auto op: cancel_ops)
|
for (auto op: cancel_ops)
|
||||||
{
|
{
|
||||||
cancel_op(op);
|
op->cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_messenger_t::cancel_op(osd_op_t *op)
|
void osd_op_t::cancel()
|
||||||
{
|
{
|
||||||
if (op->op_type == OSD_OP_OUT)
|
if (op_type == OSD_OP_OUT && callback)
|
||||||
{
|
{
|
||||||
op->reply.hdr.magic = SECONDARY_OSD_REPLY_MAGIC;
|
reply.hdr.magic = SECONDARY_OSD_REPLY_MAGIC;
|
||||||
op->reply.hdr.id = op->req.hdr.id;
|
reply.hdr.id = req.hdr.id;
|
||||||
op->reply.hdr.opcode = op->req.hdr.opcode;
|
reply.hdr.opcode = req.hdr.opcode;
|
||||||
op->reply.hdr.retval = -EPIPE;
|
reply.hdr.retval = -EPIPE;
|
||||||
// Copy lambda to be unaffected by `delete op`
|
// Copy lambda to be unaffected by `delete this`
|
||||||
std::function<void(osd_op_t*)>(op->callback)(op);
|
(std::function<void(osd_op_t*)>(callback))(this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This function is only called in stop_client(), so it's fine to destroy the operation
|
// This function is only called in stop_client(), so it's fine to destroy the operation
|
||||||
delete op;
|
delete this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +62,10 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "[OSD %ju] Stopping client %d (OSD peer %ju)\n", osd_num, peer_fd, cl->osd_num);
|
fprintf(stderr, "[OSD %ju] Stopping client %d (OSD peer %ju)\n", osd_num, peer_fd, cl->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);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[OSD %ju] Stopping client %d (regular client)\n", osd_num, peer_fd);
|
fprintf(stderr, "[OSD %ju] Stopping client %d (regular client)\n", osd_num, peer_fd);
|
||||||
@@ -73,8 +76,12 @@ 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)
|
||||||
{
|
{
|
||||||
// ...and forget OSD peer
|
auto osd_it = osd_peer_fds.find(cl->osd_num);
|
||||||
osd_peer_fds.erase(cl->osd_num);
|
if (osd_it != osd_peer_fds.end() && osd_it->second == cl->peer_fd)
|
||||||
|
{
|
||||||
|
// ...and forget OSD peer
|
||||||
|
osd_peer_fds.erase(osd_it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifndef __MOCK__
|
#ifndef __MOCK__
|
||||||
// Then remove FD from the eventloop so we don't accidentally read something
|
// Then remove FD from the eventloop so we don't accidentally read something
|
||||||
@@ -101,30 +108,17 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (cl->in_osd_num && break_pg_locks)
|
||||||
|
{
|
||||||
|
// Break PG locks
|
||||||
|
break_pg_locks(cl->in_osd_num);
|
||||||
|
}
|
||||||
if (cl->osd_num)
|
if (cl->osd_num)
|
||||||
{
|
{
|
||||||
// Then repeer PGs because cancel_op() callbacks can try to perform
|
// Then repeer PGs because cancel_op() callbacks can try to perform
|
||||||
// some actions and we need correct PG states to not do something silly
|
// some actions and we need correct PG states to not do something silly
|
||||||
repeer_pgs(cl->osd_num);
|
repeer_pgs(cl->osd_num);
|
||||||
}
|
}
|
||||||
// Then cancel all operations
|
|
||||||
if (cl->read_op)
|
|
||||||
{
|
|
||||||
if (!cl->read_op->callback)
|
|
||||||
{
|
|
||||||
delete cl->read_op;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cancel_op(cl->read_op);
|
|
||||||
}
|
|
||||||
cl->read_op = NULL;
|
|
||||||
}
|
|
||||||
if (cl->osd_num)
|
|
||||||
{
|
|
||||||
// Cancel outbound operations
|
|
||||||
cancel_osd_ops(cl);
|
|
||||||
}
|
|
||||||
// Find the item again because it can be invalidated at this point
|
// Find the item again because it can be invalidated at this point
|
||||||
it = clients.find(peer_fd);
|
it = clients.find(peer_fd);
|
||||||
if (it != clients.end())
|
if (it != clients.end())
|
||||||
@@ -149,6 +143,17 @@ osd_client_t::~osd_client_t()
|
|||||||
close(peer_fd);
|
close(peer_fd);
|
||||||
peer_fd = -1;
|
peer_fd = -1;
|
||||||
}
|
}
|
||||||
|
// Then cancel all operations
|
||||||
|
// Operations have to be canceled only after clearing all references to osd_client_t
|
||||||
|
// because otherwise their buffers may be still present in io_uring asynchronous requests
|
||||||
|
if (read_op)
|
||||||
|
{
|
||||||
|
// read_op may be an incoming op or a continued response for an outbound op
|
||||||
|
read_op->cancel();
|
||||||
|
read_op = NULL;
|
||||||
|
}
|
||||||
|
// Cancel outbound ops
|
||||||
|
cancel_ops();
|
||||||
#ifndef __MOCK__
|
#ifndef __MOCK__
|
||||||
#ifdef WITH_RDMA
|
#ifdef WITH_RDMA
|
||||||
if (rdma_conn)
|
if (rdma_conn)
|
||||||
|
@@ -58,6 +58,7 @@ typedef struct VitastorClient
|
|||||||
{
|
{
|
||||||
void *proxy;
|
void *proxy;
|
||||||
int uring_eventfd;
|
int uring_eventfd;
|
||||||
|
int auto_loop;
|
||||||
|
|
||||||
void *watch;
|
void *watch;
|
||||||
char *config_path;
|
char *config_path;
|
||||||
@@ -155,16 +156,19 @@ static void qemu_vitastor_unescape(char *src)
|
|||||||
// vitastor[:key=value]*
|
// vitastor[:key=value]*
|
||||||
// vitastor[:etcd_host=127.0.0.1]:inode=1:pool=1[:rdma_gid_index=3]
|
// vitastor[:etcd_host=127.0.0.1]:inode=1:pool=1[:rdma_gid_index=3]
|
||||||
// vitastor:config_path=/etc/vitastor/vitastor.conf:image=testimg
|
// vitastor:config_path=/etc/vitastor/vitastor.conf:image=testimg
|
||||||
|
// vitastor://?config_path=/etc/vitastor/vitastor.conf&image=testimg
|
||||||
static void vitastor_parse_filename(const char *filename, QDict *options, Error **errp)
|
static void vitastor_parse_filename(const char *filename, QDict *options, Error **errp)
|
||||||
{
|
{
|
||||||
const char *start;
|
const char *start;
|
||||||
char *p, *buf;
|
char *p, *buf;
|
||||||
|
|
||||||
if (!strstart(filename, "vitastor:", &start))
|
int url_style = strstart(filename, "vitastor://?", &start);
|
||||||
|
if (!url_style && !strstart(filename, "vitastor:", &start))
|
||||||
{
|
{
|
||||||
error_setg(errp, "File name must start with 'vitastor:'");
|
error_setg(errp, "File name must start with 'vitastor:'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
char delim = url_style ? '&' : ':';
|
||||||
|
|
||||||
buf = g_strdup(start);
|
buf = g_strdup(start);
|
||||||
p = buf;
|
p = buf;
|
||||||
@@ -184,7 +188,7 @@ static void vitastor_parse_filename(const char *filename, QDict *options, Error
|
|||||||
if (name[i] == '_')
|
if (name[i] == '_')
|
||||||
name[i] = '-';
|
name[i] = '-';
|
||||||
qemu_vitastor_unescape(name);
|
qemu_vitastor_unescape(name);
|
||||||
value = qemu_vitastor_next_tok(p, ':', &p);
|
value = qemu_vitastor_next_tok(p, delim, &p);
|
||||||
qemu_vitastor_unescape(value);
|
qemu_vitastor_unescape(value);
|
||||||
if (!strcmp(name, "inode") ||
|
if (!strcmp(name, "inode") ||
|
||||||
!strcmp(name, "pool") ||
|
!strcmp(name, "pool") ||
|
||||||
@@ -294,9 +298,8 @@ static void coroutine_fn vitastor_co_get_metadata(VitastorRPC *task)
|
|||||||
|
|
||||||
qemu_mutex_lock(&client->mutex);
|
qemu_mutex_lock(&client->mutex);
|
||||||
vitastor_c_watch_inode(client->proxy, client->image, vitastor_co_generic_cb, task);
|
vitastor_c_watch_inode(client->proxy, client->image, vitastor_co_generic_cb, task);
|
||||||
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
|
if (!client->auto_loop)
|
||||||
vitastor_schedule_uring_handler(client);
|
vitastor_schedule_uring_handler(client);
|
||||||
#endif
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
|
|
||||||
while (!task->complete)
|
while (!task->complete)
|
||||||
@@ -449,6 +452,9 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
|
|||||||
client->ctx = bdrv_get_aio_context(bs);
|
client->ctx = bdrv_get_aio_context(bs);
|
||||||
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
|
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
|
||||||
str_array opt = {};
|
str_array opt = {};
|
||||||
|
char version_buffer[32];
|
||||||
|
memset(version_buffer, ' ', sizeof(version_buffer));
|
||||||
|
version_buffer[sizeof(version_buffer)-1] = '\0';
|
||||||
strarray_push_kv(&opt, "config_path", qdict_get_try_str(options, "config-path"));
|
strarray_push_kv(&opt, "config_path", qdict_get_try_str(options, "config-path"));
|
||||||
strarray_push_kv(&opt, "etcd_address", qdict_get_try_str(options, "etcd-host"));
|
strarray_push_kv(&opt, "etcd_address", qdict_get_try_str(options, "etcd-host"));
|
||||||
strarray_push_kv(&opt, "etcd_prefix", qdict_get_try_str(options, "etcd-prefix"));
|
strarray_push_kv(&opt, "etcd_prefix", qdict_get_try_str(options, "etcd-prefix"));
|
||||||
@@ -458,7 +464,9 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
|
|||||||
strarray_push_kv(&opt, "rdma_gid_index", qdict_get_try_str(options, "rdma-gid-index"));
|
strarray_push_kv(&opt, "rdma_gid_index", qdict_get_try_str(options, "rdma-gid-index"));
|
||||||
strarray_push_kv(&opt, "rdma_mtu", qdict_get_try_str(options, "rdma-mtu"));
|
strarray_push_kv(&opt, "rdma_mtu", qdict_get_try_str(options, "rdma-mtu"));
|
||||||
strarray_push_kv(&opt, "client_writeback_allowed", (flags & BDRV_O_NOCACHE) ? "0" : "1");
|
strarray_push_kv(&opt, "client_writeback_allowed", (flags & BDRV_O_NOCACHE) ? "0" : "1");
|
||||||
|
strarray_push_kv(&opt, "__version_check_buffer", version_buffer);
|
||||||
client->proxy = vitastor_c_create_uring_json(opt.items, opt.len);
|
client->proxy = vitastor_c_create_uring_json(opt.items, opt.len);
|
||||||
|
client->auto_loop = 0;
|
||||||
strarray_free(&opt);
|
strarray_free(&opt);
|
||||||
if (client->proxy)
|
if (client->proxy)
|
||||||
{
|
{
|
||||||
@@ -471,6 +479,12 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
universal_aio_set_fd_handler(client->ctx, client->uring_eventfd, vitastor_uring_handler, NULL, client);
|
universal_aio_set_fd_handler(client->ctx, client->uring_eventfd, vitastor_uring_handler, NULL, client);
|
||||||
|
int vitastor_version[3] = { 0 };
|
||||||
|
if (sscanf(version_buffer, "%d.%d.%d", &vitastor_version[0], &vitastor_version[1], &vitastor_version[2]) == 3 &&
|
||||||
|
vitastor_version[0] >= 2)
|
||||||
|
{
|
||||||
|
client->auto_loop = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -604,6 +618,29 @@ static void vitastor_close(BlockDriverState *bs)
|
|||||||
client->last_bitmap = NULL;
|
client->last_bitmap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 2
|
||||||
|
static void vitastor_refresh_filename(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
VitastorClient *client = bs->opaque;
|
||||||
|
size_t len = 0;
|
||||||
|
int n = 0;
|
||||||
|
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), "vitastor://");
|
||||||
|
if (len < sizeof(bs->exact_filename))
|
||||||
|
{
|
||||||
|
if (client->image)
|
||||||
|
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cimage=%s", (n++ ? '&' : '?'), client->image);
|
||||||
|
else
|
||||||
|
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cpool=%ju&inode=%ju&size=%ju", (n++ ? '&' : '?'), client->pool, client->inode, client->size);
|
||||||
|
}
|
||||||
|
if (client->config_path && len < sizeof(bs->exact_filename))
|
||||||
|
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cconfig_path=%s", (n++ ? '&' : '?'), client->config_path);
|
||||||
|
if (client->etcd_host && len < sizeof(bs->exact_filename))
|
||||||
|
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cetcd_host=%s", (n++ ? '&' : '?'), client->etcd_host);
|
||||||
|
if (client->etcd_prefix && len < sizeof(bs->exact_filename))
|
||||||
|
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cetcd_prefix=%s", (n++ ? '&' : '?'), client->etcd_prefix);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
|
||||||
static int vitastor_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
|
static int vitastor_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
|
||||||
{
|
{
|
||||||
@@ -767,9 +804,8 @@ static int coroutine_fn vitastor_co_preadv(BlockDriverState *bs,
|
|||||||
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
||||||
qemu_mutex_lock(&client->mutex);
|
qemu_mutex_lock(&client->mutex);
|
||||||
vitastor_c_read(client->proxy, inode, offset, bytes, iov->iov, iov->niov, vitastor_co_read_cb, &task);
|
vitastor_c_read(client->proxy, inode, offset, bytes, iov->iov, iov->niov, vitastor_co_read_cb, &task);
|
||||||
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
|
if (!client->auto_loop)
|
||||||
vitastor_schedule_uring_handler(client);
|
vitastor_schedule_uring_handler(client);
|
||||||
#endif
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
|
|
||||||
while (!task.complete)
|
while (!task.complete)
|
||||||
@@ -803,9 +839,8 @@ static int coroutine_fn vitastor_co_pwritev(BlockDriverState *bs,
|
|||||||
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
|
||||||
qemu_mutex_lock(&client->mutex);
|
qemu_mutex_lock(&client->mutex);
|
||||||
vitastor_c_write(client->proxy, inode, offset, bytes, 0, iov->iov, iov->niov, vitastor_co_generic_cb, &task);
|
vitastor_c_write(client->proxy, inode, offset, bytes, 0, iov->iov, iov->niov, vitastor_co_generic_cb, &task);
|
||||||
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
|
if (!client->auto_loop)
|
||||||
vitastor_schedule_uring_handler(client);
|
vitastor_schedule_uring_handler(client);
|
||||||
#endif
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
|
|
||||||
while (!task.complete)
|
while (!task.complete)
|
||||||
@@ -885,9 +920,8 @@ static int coroutine_fn vitastor_co_block_status(
|
|||||||
task.bitmap = client->last_bitmap = NULL;
|
task.bitmap = client->last_bitmap = NULL;
|
||||||
qemu_mutex_lock(&client->mutex);
|
qemu_mutex_lock(&client->mutex);
|
||||||
vitastor_c_read_bitmap(client->proxy, task.inode, task.offset, task.len, !client->skip_parents, vitastor_co_read_bitmap_cb, &task);
|
vitastor_c_read_bitmap(client->proxy, task.inode, task.offset, task.len, !client->skip_parents, vitastor_co_read_bitmap_cb, &task);
|
||||||
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
|
if (!client->auto_loop)
|
||||||
vitastor_schedule_uring_handler(client);
|
vitastor_schedule_uring_handler(client);
|
||||||
#endif
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
while (!task.complete)
|
while (!task.complete)
|
||||||
{
|
{
|
||||||
@@ -974,9 +1008,8 @@ static int coroutine_fn vitastor_co_flush(BlockDriverState *bs)
|
|||||||
|
|
||||||
qemu_mutex_lock(&client->mutex);
|
qemu_mutex_lock(&client->mutex);
|
||||||
vitastor_c_sync(client->proxy, vitastor_co_generic_cb, &task);
|
vitastor_c_sync(client->proxy, vitastor_co_generic_cb, &task);
|
||||||
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
|
if (!client->auto_loop)
|
||||||
vitastor_schedule_uring_handler(client);
|
vitastor_schedule_uring_handler(client);
|
||||||
#endif
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
|
|
||||||
while (!task.complete)
|
while (!task.complete)
|
||||||
@@ -1038,6 +1071,9 @@ static BlockDriver bdrv_vitastor = {
|
|||||||
.bdrv_get_info = vitastor_get_info,
|
.bdrv_get_info = vitastor_get_info,
|
||||||
.bdrv_getlength = vitastor_getlength,
|
.bdrv_getlength = vitastor_getlength,
|
||||||
#endif
|
#endif
|
||||||
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 2
|
||||||
|
.bdrv_refresh_filename = vitastor_refresh_filename,
|
||||||
|
#endif
|
||||||
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
|
||||||
.bdrv_probe_blocksizes = vitastor_probe_blocksizes,
|
.bdrv_probe_blocksizes = vitastor_probe_blocksizes,
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
|||||||
|
|
||||||
Name: Vitastor
|
Name: Vitastor
|
||||||
Description: Vitastor client library
|
Description: Vitastor client library
|
||||||
Version: 2.2.0
|
Version: 2.2.3
|
||||||
Libs: -L${libdir} -lvitastor_client
|
Libs: -L${libdir} -lvitastor_client
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
||||||
|
@@ -178,7 +178,14 @@ vitastor_c *vitastor_c_create_uring_json(const char **options, int options_len)
|
|||||||
json11::Json::object cfg;
|
json11::Json::object cfg;
|
||||||
for (int i = 0; i < options_len-1; i += 2)
|
for (int i = 0; i < options_len-1; i += 2)
|
||||||
{
|
{
|
||||||
cfg[options[i]] = std::string(options[i+1]);
|
if (!strcmp(options[i], "__version_check_buffer"))
|
||||||
|
{
|
||||||
|
int buf_size = strlen(options[i+1])+1;
|
||||||
|
if (buf_size > strlen(VITASTOR_VERSION))
|
||||||
|
strncpy((char*)options[i+1], VITASTOR_VERSION, buf_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cfg[options[i]] = std::string(options[i+1]);
|
||||||
}
|
}
|
||||||
json11::Json cfg_json(cfg);
|
json11::Json cfg_json(cfg);
|
||||||
vitastor_c *self = new vitastor_c;
|
vitastor_c *self = new vitastor_c;
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
#define VITASTOR_QEMU_PROXY_H
|
#define VITASTOR_QEMU_PROXY_H
|
||||||
|
|
||||||
// C API wrapper version
|
// C API wrapper version
|
||||||
#define VITASTOR_C_API_VERSION 5
|
#define VITASTOR_C_API_VERSION 4
|
||||||
|
|
||||||
#ifndef POOL_ID_BITS
|
#ifndef POOL_ID_BITS
|
||||||
#define POOL_ID_BITS 16
|
#define POOL_ID_BITS 16
|
||||||
|
@@ -70,7 +70,7 @@ struct rm_osd_t
|
|||||||
{
|
{
|
||||||
if (parent->cli->st_cli.peer_states.find(osd_id) != parent->cli->st_cli.peer_states.end())
|
if (parent->cli->st_cli.peer_states.find(osd_id) != parent->cli->st_cli.peer_states.end())
|
||||||
{
|
{
|
||||||
is_warning = true;
|
is_warning = !allow_up;
|
||||||
still_up.push_back(osd_id);
|
still_up.push_back(osd_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -72,12 +72,14 @@ static const char* help_text =
|
|||||||
" --port <PORT> use port <PORT> for NFS services (default is 2049)\n"
|
" --port <PORT> use port <PORT> for NFS services (default is 2049)\n"
|
||||||
" specify \"auto\" to auto-select and print port\n"
|
" specify \"auto\" to auto-select and print port\n"
|
||||||
" --portmap 0 do not listen on port 111 (portmap/rpcbind, requires root)\n"
|
" --portmap 0 do not listen on port 111 (portmap/rpcbind, requires root)\n"
|
||||||
|
#ifdef WITH_RDMACM
|
||||||
" --nfs_rdma <PORT> enable NFS-RDMA at RDMA-CM port <PORT> (you can try 20049)\n"
|
" --nfs_rdma <PORT> enable NFS-RDMA at RDMA-CM port <PORT> (you can try 20049)\n"
|
||||||
" if RDMA is enabled and --port is set to 0, TCP will be disabled\n"
|
" if RDMA is enabled and --port is set to 0, TCP will be disabled\n"
|
||||||
" --nfs_rdma_credit 16 maximum operation credit for RDMA clients (max iodepth)\n"
|
" --nfs_rdma_credit 16 maximum operation credit for RDMA clients (max iodepth)\n"
|
||||||
" --nfs_rdma_send 1024 maximum RDMA send operation count (should be larger than iodepth)\n"
|
" --nfs_rdma_send 1024 maximum RDMA send operation count (should be larger than iodepth)\n"
|
||||||
" --nfs_rdma_alloc 1M RDMA memory allocation rounding\n"
|
" --nfs_rdma_alloc 1M RDMA memory allocation rounding\n"
|
||||||
" --nfs_rdma_gc 64M maximum unused RDMA buffers\n"
|
" --nfs_rdma_gc 64M maximum unused RDMA buffers\n"
|
||||||
|
#endif
|
||||||
"\n"
|
"\n"
|
||||||
"vitastor-nfs --fs <NAME> upgrade\n"
|
"vitastor-nfs --fs <NAME> upgrade\n"
|
||||||
" Upgrade FS metadata. Can be run online, but server(s) should be restarted\n"
|
" Upgrade FS metadata. Can be run online, but server(s) should be restarted\n"
|
||||||
@@ -205,12 +207,15 @@ void nfs_proxy_t::run(json11::Json cfg)
|
|||||||
default_pool = cfg["pool"].as_string();
|
default_pool = cfg["pool"].as_string();
|
||||||
portmap_enabled = !json_is_false(cfg["portmap"]);
|
portmap_enabled = !json_is_false(cfg["portmap"]);
|
||||||
nfs_port = cfg["port"].uint64_value() & 0xffff;
|
nfs_port = cfg["port"].uint64_value() & 0xffff;
|
||||||
|
#ifdef WITH_RDMACM
|
||||||
nfs_rdma_port = cfg["nfs_rdma"].uint64_value() & 0xffff;
|
nfs_rdma_port = cfg["nfs_rdma"].uint64_value() & 0xffff;
|
||||||
|
#endif
|
||||||
// Allow RDMA-only mode if port is explicitly set to 0
|
// Allow RDMA-only mode if port is explicitly set to 0
|
||||||
// Allow port auto-selection in server mode if explicitly set to --port auto
|
// Allow port auto-selection in server mode if explicitly set to --port auto
|
||||||
nfs_port_auto = cfg["port"] == "auto";
|
nfs_port_auto = cfg["port"] == "auto";
|
||||||
if (!nfs_port)
|
if (!nfs_port)
|
||||||
nfs_port = nfs_port_auto ? 0 : (!cfg["port"].is_null() && nfs_rdma_port ? -1 : 2049);
|
nfs_port = nfs_port_auto ? 0 : (!cfg["port"].is_null() && nfs_rdma_port ? -1 : 2049);
|
||||||
|
#ifdef WITH_RDMACM
|
||||||
nfs_rdma_credit = cfg["nfs_rdma_credit"].uint64_value();
|
nfs_rdma_credit = cfg["nfs_rdma_credit"].uint64_value();
|
||||||
if (!nfs_rdma_credit)
|
if (!nfs_rdma_credit)
|
||||||
nfs_rdma_credit = 16;
|
nfs_rdma_credit = 16;
|
||||||
@@ -223,6 +228,7 @@ void nfs_proxy_t::run(json11::Json cfg)
|
|||||||
nfs_rdma_gc = cfg["nfs_rdma_gc"].uint64_value();
|
nfs_rdma_gc = cfg["nfs_rdma_gc"].uint64_value();
|
||||||
if (!nfs_rdma_gc)
|
if (!nfs_rdma_gc)
|
||||||
nfs_rdma_gc = 64*1048576;
|
nfs_rdma_gc = 64*1048576;
|
||||||
|
#endif
|
||||||
export_root = cfg["nfspath"].string_value();
|
export_root = cfg["nfspath"].string_value();
|
||||||
if (!export_root.size())
|
if (!export_root.size())
|
||||||
export_root = "/";
|
export_root = "/";
|
||||||
@@ -391,10 +397,12 @@ void nfs_proxy_t::run_server(json11::Json cfg)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_RDMACM
|
||||||
if (nfs_rdma_port)
|
if (nfs_rdma_port)
|
||||||
{
|
{
|
||||||
rdma_context = create_rdma(bind_address, nfs_rdma_port, nfs_rdma_credit, nfs_rdma_max_send, nfs_rdma_alloc, nfs_rdma_gc);
|
rdma_context = create_rdma(bind_address, nfs_rdma_port, nfs_rdma_credit, nfs_rdma_max_send, nfs_rdma_alloc, nfs_rdma_gc);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (mountpoint != "")
|
if (mountpoint != "")
|
||||||
{
|
{
|
||||||
mount_fs();
|
mount_fs();
|
||||||
|
@@ -85,6 +85,7 @@ osd_t::osd_t(const json11::Json & config, ring_loop_t *ringloop)
|
|||||||
msgr.ringloop = this->ringloop;
|
msgr.ringloop = this->ringloop;
|
||||||
msgr.exec_op = [this](osd_op_t *op) { exec_op(op); };
|
msgr.exec_op = [this](osd_op_t *op) { exec_op(op); };
|
||||||
msgr.repeer_pgs = [this](osd_num_t peer_osd) { repeer_pgs(peer_osd); };
|
msgr.repeer_pgs = [this](osd_num_t peer_osd) { repeer_pgs(peer_osd); };
|
||||||
|
msgr.break_pg_locks = [this](osd_num_t peer_osd) { break_pg_locks(peer_osd); };
|
||||||
msgr.check_config_hook = [this](osd_client_t *cl, json11::Json conf) { return check_peer_config(cl, conf); };
|
msgr.check_config_hook = [this](osd_client_t *cl, json11::Json conf) { return check_peer_config(cl, conf); };
|
||||||
msgr.init();
|
msgr.init();
|
||||||
|
|
||||||
@@ -195,7 +196,6 @@ void osd_t::parse_config(bool init)
|
|||||||
etcd_stats_interval = 30;
|
etcd_stats_interval = 30;
|
||||||
readonly = json_is_true(config["readonly"]);
|
readonly = json_is_true(config["readonly"]);
|
||||||
run_primary = !json_is_false(config["run_primary"]);
|
run_primary = !json_is_false(config["run_primary"]);
|
||||||
allow_test_ops = json_is_true(config["allow_test_ops"]);
|
|
||||||
}
|
}
|
||||||
log_level = config["log_level"].uint64_value();
|
log_level = config["log_level"].uint64_value();
|
||||||
auto old_no_rebalance = no_rebalance;
|
auto old_no_rebalance = no_rebalance;
|
||||||
@@ -469,11 +469,7 @@ void osd_t::exec_op(osd_op_t *cur_op)
|
|||||||
finish_op(cur_op, -EROFS);
|
finish_op(cur_op, -EROFS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cur_op->req.hdr.opcode == OSD_OP_TEST_SYNC_STAB_ALL)
|
if (cur_op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)
|
||||||
{
|
|
||||||
exec_sync_stab_all(cur_op);
|
|
||||||
}
|
|
||||||
else if (cur_op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)
|
|
||||||
{
|
{
|
||||||
exec_show_config(cur_op);
|
exec_show_config(cur_op);
|
||||||
}
|
}
|
||||||
|
@@ -119,7 +119,6 @@ class osd_t
|
|||||||
bool disable_tcp = false;
|
bool disable_tcp = false;
|
||||||
// FIXME: Implement client queue depth limit
|
// FIXME: Implement client queue depth limit
|
||||||
int client_queue_depth = 128;
|
int client_queue_depth = 128;
|
||||||
bool allow_test_ops = false;
|
|
||||||
int print_stats_interval = 3;
|
int print_stats_interval = 3;
|
||||||
int slow_log_interval = 10;
|
int slow_log_interval = 10;
|
||||||
int immediate_commit = IMMEDIATE_NONE;
|
int immediate_commit = IMMEDIATE_NONE;
|
||||||
@@ -278,6 +277,8 @@ class osd_t
|
|||||||
void handle_peers();
|
void handle_peers();
|
||||||
bool check_peer_config(osd_client_t *cl, json11::Json conf);
|
bool check_peer_config(osd_client_t *cl, json11::Json conf);
|
||||||
void repeer_pgs(osd_num_t osd_num);
|
void repeer_pgs(osd_num_t osd_num);
|
||||||
|
void repeer_pg(pg_t & pg);
|
||||||
|
void break_pg_locks(osd_num_t osd_num);
|
||||||
void start_pg_peering(pg_t & pg);
|
void start_pg_peering(pg_t & pg);
|
||||||
void drop_dirty_pg_connections(pool_pg_num_t pg);
|
void drop_dirty_pg_connections(pool_pg_num_t pg);
|
||||||
void record_pg_lock(pg_t & pg, osd_num_t peer_osd, uint64_t pg_state);
|
void record_pg_lock(pg_t & pg, osd_num_t peer_osd, uint64_t pg_state);
|
||||||
@@ -317,7 +318,6 @@ class osd_t
|
|||||||
|
|
||||||
// secondary ops
|
// secondary ops
|
||||||
bool sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid);
|
bool sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid);
|
||||||
void exec_sync_stab_all(osd_op_t *cur_op);
|
|
||||||
void exec_show_config(osd_op_t *cur_op);
|
void exec_show_config(osd_op_t *cur_op);
|
||||||
void exec_secondary(osd_op_t *cur_op);
|
void exec_secondary(osd_op_t *cur_op);
|
||||||
void exec_secondary_real(osd_op_t *cur_op);
|
void exec_secondary_real(osd_op_t *cur_op);
|
||||||
|
@@ -432,9 +432,16 @@ void osd_t::apply_pg_locks_localize_only()
|
|||||||
}
|
}
|
||||||
auto & pool_cfg = pool_it->second;
|
auto & pool_cfg = pool_it->second;
|
||||||
auto & pg = pp.second;
|
auto & pg = pp.second;
|
||||||
|
auto old_disable_pg_locks = pg.disable_pg_locks;
|
||||||
pg.disable_pg_locks = pg_locks_localize_only &&
|
pg.disable_pg_locks = pg_locks_localize_only &&
|
||||||
pool_cfg.scheme == POOL_SCHEME_REPLICATED &&
|
(pool_cfg.scheme != POOL_SCHEME_REPLICATED ||
|
||||||
pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY;
|
pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY);
|
||||||
|
if (!pg.disable_pg_locks && old_disable_pg_locks)
|
||||||
|
{
|
||||||
|
// Relock PG
|
||||||
|
printf("[PG %u/%u] Repeer to enable PG locks\n", pg.pool_id, pg.pg_num);
|
||||||
|
repeer_pg(pg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,8 +884,8 @@ void osd_t::apply_pg_config()
|
|||||||
pg.next_scrub = pg_cfg.next_scrub;
|
pg.next_scrub = pg_cfg.next_scrub;
|
||||||
pg.target_set = pg_cfg.target_set;
|
pg.target_set = pg_cfg.target_set;
|
||||||
pg.disable_pg_locks = pg_locks_localize_only &&
|
pg.disable_pg_locks = pg_locks_localize_only &&
|
||||||
pool_item.second.scheme == POOL_SCHEME_REPLICATED &&
|
(pool_item.second.scheme != POOL_SCHEME_REPLICATED ||
|
||||||
pool_item.second.local_reads == POOL_LOCAL_READ_PRIMARY;
|
pool_item.second.local_reads == POOL_LOCAL_READ_PRIMARY);
|
||||||
if (pg.scheme == POOL_SCHEME_EC)
|
if (pg.scheme == POOL_SCHEME_EC)
|
||||||
{
|
{
|
||||||
use_ec(pg.pg_size, pg.pg_data_size, true);
|
use_ec(pg.pg_size, pg.pg_data_size, true);
|
||||||
|
@@ -189,7 +189,7 @@ bool osd_t::submit_flush_op(pool_id_t pool_id, pg_num_t pg_num, pg_flush_batch_t
|
|||||||
{
|
{
|
||||||
.len = (uint32_t)count,
|
.len = (uint32_t)count,
|
||||||
},
|
},
|
||||||
.buf = op->buf,
|
.buf = (uint8_t*)op->buf,
|
||||||
});
|
});
|
||||||
bs->enqueue_op(op->bs_op);
|
bs->enqueue_op(op->bs_op);
|
||||||
}
|
}
|
||||||
|
@@ -73,18 +73,25 @@ void osd_t::handle_peers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void osd_t::break_pg_locks(osd_num_t peer_osd)
|
||||||
|
{
|
||||||
|
for (auto lock_it = pg_locks.begin(); lock_it != pg_locks.end(); )
|
||||||
|
{
|
||||||
|
if (lock_it->second.primary_osd == peer_osd)
|
||||||
|
{
|
||||||
|
if (log_level > 3)
|
||||||
|
{
|
||||||
|
printf("Break PG %u/%u lock on disconnection of OSD %ju\n", lock_it->first.pool_id, lock_it->first.pg_num, peer_osd);
|
||||||
|
}
|
||||||
|
pg_locks.erase(lock_it++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lock_it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void osd_t::repeer_pgs(osd_num_t peer_osd)
|
void osd_t::repeer_pgs(osd_num_t peer_osd)
|
||||||
{
|
{
|
||||||
if (msgr.osd_peer_fds.find(peer_osd) == msgr.osd_peer_fds.end())
|
|
||||||
{
|
|
||||||
for (auto lock_it = pg_locks.begin(); lock_it != pg_locks.end(); )
|
|
||||||
{
|
|
||||||
if (lock_it->second.primary_osd == peer_osd)
|
|
||||||
pg_locks.erase(lock_it++);
|
|
||||||
else
|
|
||||||
lock_it++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Re-peer affected PGs
|
// Re-peer affected PGs
|
||||||
for (auto & p: pgs)
|
for (auto & p: pgs)
|
||||||
{
|
{
|
||||||
@@ -104,21 +111,26 @@ void osd_t::repeer_pgs(osd_num_t peer_osd)
|
|||||||
{
|
{
|
||||||
// Repeer this pg
|
// Repeer this pg
|
||||||
printf("[PG %u/%u] Repeer because of OSD %ju\n", pg.pool_id, pg.pg_num, peer_osd);
|
printf("[PG %u/%u] Repeer because of OSD %ju\n", pg.pool_id, pg.pg_num, peer_osd);
|
||||||
if (!(pg.state & (PG_ACTIVE | PG_REPEERING)) || pg.can_repeer())
|
repeer_pg(pg);
|
||||||
{
|
|
||||||
start_pg_peering(pg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Stop accepting new operations, wait for current ones to finish or fail
|
|
||||||
pg.state = pg.state & ~PG_ACTIVE | PG_REPEERING;
|
|
||||||
report_pg_state(pg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void osd_t::repeer_pg(pg_t & pg)
|
||||||
|
{
|
||||||
|
if (!(pg.state & (PG_ACTIVE | PG_REPEERING)) || pg.can_repeer())
|
||||||
|
{
|
||||||
|
start_pg_peering(pg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Stop accepting new operations, wait for current ones to finish or fail
|
||||||
|
pg.state = pg.state & ~PG_ACTIVE | PG_REPEERING;
|
||||||
|
report_pg_state(pg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reset PG state (when peering or stopping)
|
// Reset PG state (when peering or stopping)
|
||||||
void osd_t::reset_pg(pg_t & pg)
|
void osd_t::reset_pg(pg_t & pg)
|
||||||
{
|
{
|
||||||
@@ -466,6 +478,7 @@ void osd_t::relock_pg(pg_t & pg)
|
|||||||
auto pg_it = pgs.find(pg_id);
|
auto pg_it = pgs.find(pg_id);
|
||||||
if (pg_it == pgs.end())
|
if (pg_it == pgs.end())
|
||||||
{
|
{
|
||||||
|
printf("Warning: PG %u/%u is gone during lock attempt\n", pg_id.pool_id, pg_id.pg_num);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto & pg = pg_it->second;
|
auto & pg = pg_it->second;
|
||||||
@@ -475,15 +488,14 @@ void osd_t::relock_pg(pg_t & pg)
|
|||||||
}
|
}
|
||||||
else if (op->reply.hdr.retval != -EPIPE)
|
else if (op->reply.hdr.retval != -EPIPE)
|
||||||
{
|
{
|
||||||
printf(
|
printf("Failed to %s PG %u/%u on OSD %ju - ", op->req.sec_lock.flags == OSD_SEC_UNLOCK_PG ? "unlock" : "lock",
|
||||||
(op->reply.hdr.retval == -ENOENT
|
pg_id.pool_id, pg_id.pg_num, peer_osd);
|
||||||
? "Failed to %1$s PG %2$u/%3$u on OSD %4$ju - peer didn't load PG info yet\n"
|
if (op->reply.hdr.retval == -ENOENT)
|
||||||
: (op->reply.sec_lock.cur_primary
|
printf("peer didn't load PG info yet\n");
|
||||||
? "Failed to %1$s PG %2$u/%3$u on OSD %4$ju - taken by OSD %6$ju (retval=%5$jd)\n"
|
else if (op->reply.sec_lock.cur_primary)
|
||||||
: "Failed to %1$s PG %2$u/%3$u on OSD %4$ju - retval=%5$jd\n")),
|
printf("taken by OSD %ju (retval=%jd)\n", op->reply.sec_lock.cur_primary, op->reply.hdr.retval);
|
||||||
op->req.sec_lock.flags == OSD_SEC_UNLOCK_PG ? "unlock" : "lock",
|
else
|
||||||
pg_id.pool_id, pg_id.pg_num, peer_osd, op->reply.hdr.retval, op->reply.sec_lock.cur_primary
|
printf("retval=%jd\n", op->reply.hdr.retval);
|
||||||
);
|
|
||||||
// Retry relocking/unlocking PG after a short time
|
// Retry relocking/unlocking PG after a short time
|
||||||
pg.lock_waiting = true;
|
pg.lock_waiting = true;
|
||||||
tfd->set_timer(pg_lock_retry_interval_ms, false, [this, pg_id](int)
|
tfd->set_timer(pg_lock_retry_interval_ms, false, [this, pg_id](int)
|
||||||
|
@@ -209,8 +209,8 @@ 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,
|
||||||
} },
|
} },
|
||||||
.buf = wr ? si->write_buf : si->read_buf,
|
.buf = (uint8_t*)(wr ? si->write_buf : si->read_buf),
|
||||||
.bitmap = si->bmp_buf,
|
.bitmap = (uint8_t*)si->bmp_buf,
|
||||||
});
|
});
|
||||||
#ifdef OSD_DEBUG
|
#ifdef OSD_DEBUG
|
||||||
printf(
|
printf(
|
||||||
@@ -290,7 +290,6 @@ static uint64_t bs_op_to_osd_op[] = {
|
|||||||
OSD_OP_SEC_DELETE, // BS_OP_DELETE = 6
|
OSD_OP_SEC_DELETE, // BS_OP_DELETE = 6
|
||||||
OSD_OP_SEC_LIST, // BS_OP_LIST = 7
|
OSD_OP_SEC_LIST, // BS_OP_LIST = 7
|
||||||
OSD_OP_SEC_ROLLBACK, // BS_OP_ROLLBACK = 8
|
OSD_OP_SEC_ROLLBACK, // BS_OP_ROLLBACK = 8
|
||||||
OSD_OP_TEST_SYNC_STAB_ALL, // BS_OP_SYNC_STAB_ALL = 9
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void osd_t::handle_primary_bs_subop(osd_op_t *subop)
|
void osd_t::handle_primary_bs_subop(osd_op_t *subop)
|
||||||
@@ -417,16 +416,17 @@ 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->peer_fd) != msgr.clients.end()
|
||||||
? msgr.clients[subop->peer_fd]->osd_num : -subop->peer_fd);
|
? msgr.clients[subop->peer_fd]->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(
|
printf("%s subop to %jx:%jx v%ju failed ", osd_op_names[opcode],
|
||||||
subop->peer_fd >= 0
|
subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, subop->req.sec_rw.version);
|
||||||
? "%1$s subop to %2$jx:%3$jx v%4$ju failed on osd %7$jd: retval = %5$d (expected %6$d)\n"
|
if (subop->peer_fd >= 0 && peer_osd > 0)
|
||||||
: "%1$s subop to %2$jx:%3$jx v%4$ju failed locally: retval = %5$d (expected %6$d)\n",
|
printf("on osd %ju: retval = %d (expected %d)\n", peer_osd, retval, expected);
|
||||||
osd_op_names[opcode], subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, subop->req.sec_rw.version,
|
else if (peer_osd > 0)
|
||||||
retval, expected, peer_osd
|
printf("on peer %d: retval = %d (expected %d)\n", subop->peer_fd, retval, expected);
|
||||||
);
|
else
|
||||||
|
printf("locally: retval = %d (expected %d)\n", retval, expected);
|
||||||
}
|
}
|
||||||
else if (opcode == OSD_OP_SEC_DELETE)
|
else if (opcode == OSD_OP_SEC_DELETE)
|
||||||
{
|
{
|
||||||
@@ -702,7 +702,7 @@ void osd_t::submit_primary_stab_subops(osd_op_t *cur_op)
|
|||||||
{
|
{
|
||||||
.len = (uint32_t)stab_osd.len,
|
.len = (uint32_t)stab_osd.len,
|
||||||
},
|
},
|
||||||
.buf = (void*)(op_data->unstable_writes + stab_osd.start),
|
.buf = (uint8_t*)(op_data->unstable_writes + stab_osd.start),
|
||||||
});
|
});
|
||||||
bs->enqueue_op(subops[i].bs_op);
|
bs->enqueue_op(subops[i].bs_op);
|
||||||
}
|
}
|
||||||
@@ -789,7 +789,7 @@ void osd_t::submit_primary_rollback_subops(osd_op_t *cur_op, const uint64_t* osd
|
|||||||
{
|
{
|
||||||
.len = 1,
|
.len = 1,
|
||||||
},
|
},
|
||||||
.buf = (void*)(op_data->unstable_writes + i),
|
.buf = (uint8_t*)(op_data->unstable_writes + i),
|
||||||
});
|
});
|
||||||
#ifdef OSD_DEBUG
|
#ifdef OSD_DEBUG
|
||||||
printf(
|
printf(
|
||||||
|
@@ -91,16 +91,17 @@ bool osd_t::sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
auto & pool_cfg = pool_cfg_it->second;
|
||||||
|
if (pg_locks_localize_only && (pool_cfg.scheme != POOL_SCHEME_REPLICATED || pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
auto ppg = (pool_pg_num_t){ .pool_id = pool_id, .pg_num = map_to_pg(oid, pool_cfg_it->second.pg_stripe_size) };
|
auto ppg = (pool_pg_num_t){ .pool_id = pool_id, .pg_num = map_to_pg(oid, pool_cfg_it->second.pg_stripe_size) };
|
||||||
auto pg_it = pgs.find(ppg);
|
auto pg_it = pgs.find(ppg);
|
||||||
if (pg_it != pgs.end() && pg_it->second.state != PG_OFFLINE)
|
if (pg_it != pgs.end() && pg_it->second.state != PG_OFFLINE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (pg_it->second.disable_pg_locks)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
auto lock_it = pg_locks.find(ppg);
|
auto lock_it = pg_locks.find(ppg);
|
||||||
return lock_it != pg_locks.end() && lock_it->second.primary_osd == primary_osd;
|
return lock_it != pg_locks.end() && lock_it->second.primary_osd == primary_osd;
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
|
|||||||
cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE)
|
cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE)
|
||||||
{
|
{
|
||||||
if (!(cur_op->req.sec_rw.flags & OSD_OP_IGNORE_PG_LOCK) &&
|
if (!(cur_op->req.sec_rw.flags & OSD_OP_IGNORE_PG_LOCK) &&
|
||||||
!sec_check_pg_lock(cl->osd_num, cur_op->req.sec_rw.oid))
|
!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_rw.oid))
|
||||||
{
|
{
|
||||||
cur_op->bs_op->retval = -EPIPE;
|
cur_op->bs_op->retval = -EPIPE;
|
||||||
secondary_op_callback(cur_op);
|
secondary_op_callback(cur_op);
|
||||||
@@ -160,8 +161,8 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
|
|||||||
cur_op->bs_op->version = cur_op->req.sec_rw.version;
|
cur_op->bs_op->version = cur_op->req.sec_rw.version;
|
||||||
cur_op->bs_op->offset = cur_op->req.sec_rw.offset;
|
cur_op->bs_op->offset = cur_op->req.sec_rw.offset;
|
||||||
cur_op->bs_op->len = cur_op->req.sec_rw.len;
|
cur_op->bs_op->len = cur_op->req.sec_rw.len;
|
||||||
cur_op->bs_op->buf = cur_op->buf;
|
cur_op->bs_op->buf = (uint8_t*)cur_op->buf;
|
||||||
cur_op->bs_op->bitmap = cur_op->bitmap;
|
cur_op->bs_op->bitmap = (uint8_t*)cur_op->bitmap;
|
||||||
#ifdef OSD_STUB
|
#ifdef OSD_STUB
|
||||||
cur_op->bs_op->retval = cur_op->bs_op->len;
|
cur_op->bs_op->retval = cur_op->bs_op->len;
|
||||||
#endif
|
#endif
|
||||||
@@ -169,7 +170,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
|
|||||||
else if (cur_op->req.hdr.opcode == OSD_OP_SEC_DELETE)
|
else if (cur_op->req.hdr.opcode == OSD_OP_SEC_DELETE)
|
||||||
{
|
{
|
||||||
if (!(cur_op->req.sec_del.flags & OSD_OP_IGNORE_PG_LOCK) &&
|
if (!(cur_op->req.sec_del.flags & OSD_OP_IGNORE_PG_LOCK) &&
|
||||||
!sec_check_pg_lock(cl->osd_num, cur_op->req.sec_del.oid))
|
!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_del.oid))
|
||||||
{
|
{
|
||||||
cur_op->bs_op->retval = -EPIPE;
|
cur_op->bs_op->retval = -EPIPE;
|
||||||
secondary_op_callback(cur_op);
|
secondary_op_callback(cur_op);
|
||||||
@@ -185,7 +186,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
|
|||||||
cur_op->req.hdr.opcode == OSD_OP_SEC_ROLLBACK)
|
cur_op->req.hdr.opcode == OSD_OP_SEC_ROLLBACK)
|
||||||
{
|
{
|
||||||
cur_op->bs_op->len = cur_op->req.sec_stab.len/sizeof(obj_ver_id);
|
cur_op->bs_op->len = cur_op->req.sec_stab.len/sizeof(obj_ver_id);
|
||||||
cur_op->bs_op->buf = cur_op->buf;
|
cur_op->bs_op->buf = (uint8_t*)cur_op->buf;
|
||||||
#ifdef OSD_STUB
|
#ifdef OSD_STUB
|
||||||
cur_op->bs_op->retval = 0;
|
cur_op->bs_op->retval = 0;
|
||||||
#endif
|
#endif
|
||||||
@@ -193,7 +194,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < cur_op->bs_op->len; i++)
|
for (int i = 0; i < cur_op->bs_op->len; i++)
|
||||||
{
|
{
|
||||||
if (!sec_check_pg_lock(cl->osd_num, ((obj_ver_id*)cur_op->buf)[i].oid))
|
if (!sec_check_pg_lock(cl->in_osd_num, ((obj_ver_id*)cur_op->buf)[i].oid))
|
||||||
{
|
{
|
||||||
cur_op->bs_op->retval = -EPIPE;
|
cur_op->bs_op->retval = -EPIPE;
|
||||||
secondary_op_callback(cur_op);
|
secondary_op_callback(cur_op);
|
||||||
@@ -247,7 +248,7 @@ void osd_t::exec_sec_read_bmp(osd_op_t *cur_op)
|
|||||||
void *cur_buf = reply_buf;
|
void *cur_buf = reply_buf;
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
if (!sec_check_pg_lock(cl->osd_num, ov[i].oid) &&
|
if (!sec_check_pg_lock(cl->in_osd_num, ov[i].oid) &&
|
||||||
!(cur_op->req.sec_read_bmp.flags & OSD_OP_IGNORE_PG_LOCK))
|
!(cur_op->req.sec_read_bmp.flags & OSD_OP_IGNORE_PG_LOCK))
|
||||||
{
|
{
|
||||||
free(reply_buf);
|
free(reply_buf);
|
||||||
@@ -269,7 +270,7 @@ 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->peer_fd);
|
||||||
if (!cl->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 ||
|
||||||
cur_op->req.sec_lock.pool_id > ((uint64_t)1<<POOL_ID_BITS) ||
|
cur_op->req.sec_lock.pool_id > ((uint64_t)1<<POOL_ID_BITS) ||
|
||||||
@@ -290,7 +291,7 @@ void osd_t::exec_sec_lock(osd_op_t *cur_op)
|
|||||||
auto lock_it = pg_locks.find(ppg);
|
auto lock_it = pg_locks.find(ppg);
|
||||||
if (cur_op->req.sec_lock.flags == OSD_SEC_LOCK_PG)
|
if (cur_op->req.sec_lock.flags == OSD_SEC_LOCK_PG)
|
||||||
{
|
{
|
||||||
if (lock_it != pg_locks.end() && lock_it->second.primary_osd != cl->osd_num)
|
if (lock_it != pg_locks.end() && lock_it->second.primary_osd != cl->in_osd_num)
|
||||||
{
|
{
|
||||||
cur_op->reply.sec_lock.cur_primary = lock_it->second.primary_osd;
|
cur_op->reply.sec_lock.cur_primary = lock_it->second.primary_osd;
|
||||||
finish_op(cur_op, -EBUSY);
|
finish_op(cur_op, -EBUSY);
|
||||||
@@ -303,13 +304,21 @@ void osd_t::exec_sec_lock(osd_op_t *cur_op)
|
|||||||
finish_op(cur_op, -EBUSY);
|
finish_op(cur_op, -EBUSY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (log_level > 3)
|
||||||
|
{
|
||||||
|
printf("Lock PG %u/%u for OSD %ju\n", ppg.pool_id, ppg.pg_num, cl->in_osd_num);
|
||||||
|
}
|
||||||
pg_locks[ppg] = (osd_pg_lock_t){
|
pg_locks[ppg] = (osd_pg_lock_t){
|
||||||
.primary_osd = cl->osd_num,
|
.primary_osd = cl->in_osd_num,
|
||||||
.state = cur_op->req.sec_lock.pg_state,
|
.state = cur_op->req.sec_lock.pg_state,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (lock_it != pg_locks.end() && lock_it->second.primary_osd == cl->osd_num)
|
else if (lock_it != pg_locks.end() && lock_it->second.primary_osd == cl->in_osd_num)
|
||||||
{
|
{
|
||||||
|
if (log_level > 3)
|
||||||
|
{
|
||||||
|
printf("Unlock PG %u/%u by OSD %ju\n", ppg.pool_id, ppg.pg_num, cl->in_osd_num);
|
||||||
|
}
|
||||||
pg_locks.erase(lock_it);
|
pg_locks.erase(lock_it);
|
||||||
}
|
}
|
||||||
finish_op(cur_op, 0);
|
finish_op(cur_op, 0);
|
||||||
@@ -323,7 +332,7 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
|
|||||||
: 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->peer_fd);
|
||||||
cl->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())
|
||||||
{
|
{
|
||||||
cl->check_sequencing = true;
|
cl->check_sequencing = true;
|
||||||
@@ -369,27 +378,3 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
|
|||||||
cur_op->iov.push_back(cur_op->buf, cfg_str.size()+1);
|
cur_op->iov.push_back(cur_op->buf, cfg_str.size()+1);
|
||||||
finish_op(cur_op, cfg_str.size()+1);
|
finish_op(cur_op, cfg_str.size()+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_t::exec_sync_stab_all(osd_op_t *cur_op)
|
|
||||||
{
|
|
||||||
// Sync and stabilize all objects
|
|
||||||
// This command is only valid for tests
|
|
||||||
cur_op->bs_op = new blockstore_op_t();
|
|
||||||
if (!allow_test_ops)
|
|
||||||
{
|
|
||||||
cur_op->bs_op->retval = -EINVAL;
|
|
||||||
secondary_op_callback(cur_op);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cur_op->bs_op->opcode = BS_OP_SYNC_STAB_ALL;
|
|
||||||
cur_op->bs_op->callback = [this, cur_op](blockstore_op_t *bs_op)
|
|
||||||
{
|
|
||||||
secondary_op_callback(cur_op);
|
|
||||||
};
|
|
||||||
#ifdef OSD_STUB
|
|
||||||
cur_op->bs_op->retval = 0;
|
|
||||||
secondary_op_callback(cur_op);
|
|
||||||
#else
|
|
||||||
bs->enqueue_op(cur_op->bs_op);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
@@ -121,6 +121,7 @@ void pretend_connected(cluster_client_t *cli, osd_num_t osd_num)
|
|||||||
cli->msgr.osd_peer_fds[osd_num] = peer_fd;
|
cli->msgr.osd_peer_fds[osd_num] = peer_fd;
|
||||||
cli->msgr.clients[peer_fd] = new osd_client_t();
|
cli->msgr.clients[peer_fd] = new osd_client_t();
|
||||||
cli->msgr.clients[peer_fd]->osd_num = osd_num;
|
cli->msgr.clients[peer_fd]->osd_num = osd_num;
|
||||||
|
cli->msgr.clients[peer_fd]->peer_fd = peer_fd;
|
||||||
cli->msgr.clients[peer_fd]->peer_state = PEER_CONNECTED;
|
cli->msgr.clients[peer_fd]->peer_state = PEER_CONNECTED;
|
||||||
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);
|
||||||
|
@@ -125,6 +125,8 @@ void ring_loop_t::loop()
|
|||||||
if (cqe->flags & IORING_CQE_F_MORE)
|
if (cqe->flags & IORING_CQE_F_MORE)
|
||||||
{
|
{
|
||||||
// There will be a second notification
|
// There will be a second notification
|
||||||
|
if (mt)
|
||||||
|
mu.unlock();
|
||||||
d->res = cqe->res;
|
d->res = cqe->res;
|
||||||
d->more = true;
|
d->more = true;
|
||||||
if (d->callback)
|
if (d->callback)
|
||||||
|
@@ -10,6 +10,8 @@ cd $(dirname $0)
|
|||||||
./test_change_pg_count.sh
|
./test_change_pg_count.sh
|
||||||
SCHEME=ec ./test_change_pg_count.sh
|
SCHEME=ec ./test_change_pg_count.sh
|
||||||
|
|
||||||
|
./test_change_pg_count_online.sh
|
||||||
|
|
||||||
./test_change_pg_size.sh
|
./test_change_pg_size.sh
|
||||||
|
|
||||||
./test_create_nomaxid.sh
|
./test_create_nomaxid.sh
|
||||||
@@ -59,6 +61,7 @@ SCHEME=ec IMMEDIATE_COMMIT=1 ./test_rebalance_verify.sh
|
|||||||
|
|
||||||
./test_write.sh
|
./test_write.sh
|
||||||
SCHEME=xor ./test_write.sh
|
SCHEME=xor ./test_write.sh
|
||||||
|
TEST_NAME=iothreads GLOBAL_CONFIG=',"client_iothread_count":4' ./test_write.sh
|
||||||
|
|
||||||
./test_write_no_same.sh
|
./test_write_no_same.sh
|
||||||
|
|
||||||
|
61
tests/test_change_pg_count_online.sh
Executable file
61
tests/test_change_pg_count_online.sh
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
OSD_COUNT=${OSD_COUNT:-6}
|
||||||
|
PG_COUNT=16
|
||||||
|
GLOBAL_CONFIG=',"client_retry_interval":1000'
|
||||||
|
|
||||||
|
. `dirname $0`/run_3osds.sh
|
||||||
|
|
||||||
|
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
||||||
|
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
|
||||||
|
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M
|
||||||
|
|
||||||
|
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
||||||
|
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -rw=randrw \
|
||||||
|
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M -loops=100 -cluster_log_level=3 -runtime=60 &>./testdata/fio.log &
|
||||||
|
FIO_PID=$!
|
||||||
|
|
||||||
|
try_change()
|
||||||
|
{
|
||||||
|
n=$1
|
||||||
|
|
||||||
|
for i in {1..6}; do
|
||||||
|
echo --- Change PG count to $n --- >>testdata/osd$i.log
|
||||||
|
done
|
||||||
|
echo --- Change PG count to $n --- >>testdata/mon.log
|
||||||
|
|
||||||
|
$ETCDCTL put /vitastor/config/pools '{"1":{'$POOLCFG',"pg_size":'$PG_SIZE',"pg_minsize":'$PG_MINSIZE',"pg_count":'$n'}}'
|
||||||
|
echo "Pool 1 (testpool) PG count changed from $PG_COUNT to $n" >> testdata/pgr.log
|
||||||
|
PG_COUNT=$n
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# 16 -> 32
|
||||||
|
|
||||||
|
try_change 32
|
||||||
|
|
||||||
|
# 32 -> 16
|
||||||
|
|
||||||
|
try_change 16
|
||||||
|
|
||||||
|
# 16 -> 25
|
||||||
|
|
||||||
|
try_change 25
|
||||||
|
|
||||||
|
# 25 -> 17
|
||||||
|
|
||||||
|
try_change 17
|
||||||
|
|
||||||
|
# 17 -> 16
|
||||||
|
|
||||||
|
try_change 16
|
||||||
|
|
||||||
|
wait $FIO_PID
|
||||||
|
|
||||||
|
grep -P 'Pool 1 \(testpool\) PG count changed from \d+ to \d+' testdata/fio.log > testdata/pgc.log
|
||||||
|
diff testdata/pgr.log testdata/pgc.log
|
||||||
|
|
||||||
|
format_green OK
|
Reference in New Issue
Block a user