Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee1dcfea25 |
@@ -10,9 +10,6 @@ RUN set -e -x; \
|
|||||||
ln -s /root/fio-build/fio-*/ ./fio; \
|
ln -s /root/fio-build/fio-*/ ./fio; \
|
||||||
ln -s /root/qemu-build/qemu-*/ ./qemu; \
|
ln -s /root/qemu-build/qemu-*/ ./qemu; \
|
||||||
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
|
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
|
||||||
cd mon; \
|
|
||||||
npm install; \
|
|
||||||
cd ..; \
|
|
||||||
mkdir build; \
|
mkdir build; \
|
||||||
cd build; \
|
cd build; \
|
||||||
cmake .. -DWITH_ASAN=yes -DWITH_QEMU=yes; \
|
cmake .. -DWITH_ASAN=yes -DWITH_QEMU=yes; \
|
||||||
|
|||||||
+147
-201
@@ -71,7 +71,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Run test
|
- name: Run test
|
||||||
id: test
|
id: test
|
||||||
timeout-minutes: 10
|
timeout-minutes: 3
|
||||||
run: /root/vitastor/tests/test_add_osd.sh
|
run: /root/vitastor/tests/test_add_osd.sh
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
if: always() && steps.test.outcome == 'failure'
|
if: always() && steps.test.outcome == 'failure'
|
||||||
@@ -190,6 +190,24 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_failure_domain:
|
||||||
|
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_failure_domain.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_interrupted_rebalance:
|
test_interrupted_rebalance:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
@@ -262,7 +280,7 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
test_failure_domain:
|
test_minsize_1:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
@@ -270,7 +288,115 @@ jobs:
|
|||||||
- name: Run test
|
- name: Run test
|
||||||
id: test
|
id: test
|
||||||
timeout-minutes: 3
|
timeout-minutes: 3
|
||||||
run: /root/vitastor/tests/test_failure_domain.sh
|
run: /root/vitastor/tests/test_minsize_1.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_move_reappear:
|
||||||
|
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_move_reappear.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_rebalance_verify:
|
||||||
|
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_rebalance_verify.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_rebalance_verify_imm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: IMMEDIATE_COMMIT=1 /root/vitastor/tests/test_rebalance_verify.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_rebalance_verify_ec:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: SCHEME=ec /root/vitastor/tests/test_rebalance_verify.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_rebalance_verify_ec_imm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: SCHEME=ec IMMEDIATE_COMMIT=1 /root/vitastor/tests/test_rebalance_verify.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_rm:
|
||||||
|
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_rm.sh
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
if: always() && steps.test.outcome == 'failure'
|
if: always() && steps.test.outcome == 'failure'
|
||||||
run: |
|
run: |
|
||||||
@@ -316,132 +442,6 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
test_minsize_1:
|
|
||||||
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_minsize_1.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_move_reappear:
|
|
||||||
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_move_reappear.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_rm:
|
|
||||||
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_rm.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_snapshot_chain:
|
|
||||||
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_snapshot_chain.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_snapshot_chain_ec:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: SCHEME=ec /root/vitastor/tests/test_snapshot_chain.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_snapshot_down:
|
|
||||||
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_snapshot_down.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_snapshot_down_ec:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: SCHEME=ec /root/vitastor/tests/test_snapshot_down.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_splitbrain:
|
test_splitbrain:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
@@ -460,78 +460,6 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
test_rebalance_verify:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 10
|
|
||||||
run: /root/vitastor/tests/test_rebalance_verify.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_rebalance_verify_imm:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 10
|
|
||||||
run: IMMEDIATE_COMMIT=1 /root/vitastor/tests/test_rebalance_verify.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_rebalance_verify_ec:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 10
|
|
||||||
run: SCHEME=ec /root/vitastor/tests/test_rebalance_verify.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_rebalance_verify_ec_imm:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 10
|
|
||||||
run: SCHEME=ec IMMEDIATE_COMMIT=1 /root/vitastor/tests/test_rebalance_verify.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:
|
test_write:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
@@ -622,6 +550,24 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_heal_imm_ec:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: IMMEDIATE_COMMIT=1 SCHEME=ec /root/vitastor/tests/test_heal.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_scrub:
|
test_scrub:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ for my $line (<>)
|
|||||||
chomp $line;
|
chomp $line;
|
||||||
my $test_name = $1;
|
my $test_name = $1;
|
||||||
my $timeout = 3;
|
my $timeout = 3;
|
||||||
if ($test_name eq 'test_etcd_fail' || $test_name eq 'test_heal' || $test_name eq 'test_add_osd' ||
|
if ($test_name eq 'test_etcd_fail' || $test_name eq 'test_heal' || $test_name eq 'test_interrupted_rebalance')
|
||||||
$test_name eq 'test_interrupted_rebalance' || $test_name eq 'test_rebalance_verify')
|
|
||||||
{
|
{
|
||||||
$timeout = 10;
|
$timeout = 10;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -2,6 +2,6 @@ cmake_minimum_required(VERSION 2.8.12)
|
|||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
set(VERSION "0.9.2")
|
set(VERSION "0.9.0")
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
VERSION ?= v0.9.2
|
VERSION ?= v0.9.0
|
||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ spec:
|
|||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
allowPrivilegeEscalation: true
|
allowPrivilegeEscalation: true
|
||||||
image: vitalif/vitastor-csi:v0.9.2
|
image: vitalif/vitastor-csi:v0.9.0
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ spec:
|
|||||||
privileged: true
|
privileged: true
|
||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
image: vitalif/vitastor-csi:v0.9.2
|
image: vitalif/vitastor-csi:v0.9.0
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ package vitastor
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
vitastorCSIDriverName = "csi.vitastor.io"
|
vitastorCSIDriverName = "csi.vitastor.io"
|
||||||
vitastorCSIDriverVersion = "0.9.2"
|
vitastorCSIDriverVersion = "0.9.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct fills the parameters of request or user input
|
// Config struct fills the parameters of request or user input
|
||||||
|
|||||||
Vendored
-58
@@ -1,58 +0,0 @@
|
|||||||
exit
|
|
||||||
|
|
||||||
git clone https://git.yourcmc.ru/vitalif/pve-qemu .
|
|
||||||
|
|
||||||
# bookworm
|
|
||||||
|
|
||||||
docker run -it -v `pwd`/pve-qemu:/root/pve-qemu --name pve-qemu-bullseye debian:bullseye bash
|
|
||||||
|
|
||||||
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/debian.sources
|
|
||||||
echo 'deb [arch=amd64] http://download.proxmox.com/debian/pve bookworm pve-no-subscription' >> /etc/apt/sources.list
|
|
||||||
echo 'deb https://vitastor.io/debian bookworm main' >> /etc/apt/sources.list
|
|
||||||
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf
|
|
||||||
echo 'ru_RU UTF-8' >> /etc/locale.gen
|
|
||||||
echo 'en_US UTF-8' >> /etc/locale.gen
|
|
||||||
apt-get update
|
|
||||||
apt-get install wget ca-certificates
|
|
||||||
wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg
|
|
||||||
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg
|
|
||||||
apt-get update
|
|
||||||
apt-get install git devscripts equivs wget mc libjemalloc-dev vitastor-client-dev lintian locales
|
|
||||||
mk-build-deps --install ./control
|
|
||||||
|
|
||||||
# bullseye
|
|
||||||
|
|
||||||
docker run -it -v `pwd`/pve-qemu:/root/pve-qemu --name pve-qemu-bullseye debian:bullseye bash
|
|
||||||
|
|
||||||
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb /deb-src /' >> /etc/apt/sources.list
|
|
||||||
echo 'deb [arch=amd64] http://download.proxmox.com/debian/pve bullseye pve-no-subscription' >> /etc/apt/sources.list
|
|
||||||
echo 'deb https://vitastor.io/debian bullseye main' >> /etc/apt/sources.list
|
|
||||||
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf
|
|
||||||
echo 'ru_RU UTF-8' >> /etc/locale.gen
|
|
||||||
echo 'en_US UTF-8' >> /etc/locale.gen
|
|
||||||
apt-get update
|
|
||||||
apt-get install wget
|
|
||||||
wget https://enterprise.proxmox.com/debian/proxmox-release-bullseye.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bullseye.gpg
|
|
||||||
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg
|
|
||||||
apt-get update
|
|
||||||
apt-get install git devscripts equivs wget mc libjemalloc-dev vitastor-client-dev lintian locales
|
|
||||||
mk-build-deps --install ./control
|
|
||||||
|
|
||||||
# buster
|
|
||||||
|
|
||||||
docker run -it -v `pwd`/pve-qemu:/root/pve-qemu --name pve-qemu-buster debian:buster bash
|
|
||||||
|
|
||||||
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb /deb-src /' >> /etc/apt/sources.list
|
|
||||||
echo 'deb [arch=amd64] http://download.proxmox.com/debian/pve buster pve-no-subscription' >> /etc/apt/sources.list
|
|
||||||
echo 'deb https://vitastor.io/debian buster main' >> /etc/apt/sources.list
|
|
||||||
echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
|
|
||||||
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf
|
|
||||||
echo 'ru_RU UTF-8' >> /etc/locale.gen
|
|
||||||
echo 'en_US UTF-8' >> /etc/locale.gen
|
|
||||||
apt-get update
|
|
||||||
apt-get install wget ca-certificates
|
|
||||||
wget http://download.proxmox.com/debian/proxmox-ve-release-6.x.gpg -O /etc/apt/trusted.gpg.d/proxmox-ve-release-6.x.gpg
|
|
||||||
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg
|
|
||||||
apt-get update
|
|
||||||
apt-get install git devscripts equivs wget mc libjemalloc-dev vitastor-client-dev lintian locales
|
|
||||||
mk-build-deps --install ./control
|
|
||||||
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
cat < vitastor.Dockerfile > ../Dockerfile
|
|
||||||
cd ..
|
|
||||||
mkdir -p packages
|
|
||||||
sudo podman build --build-arg REL=bookworm -v `pwd`/packages:/root/packages -f Dockerfile .
|
|
||||||
rm Dockerfile
|
|
||||||
Vendored
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
vitastor (0.9.2-1) unstable; urgency=medium
|
vitastor (0.9.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
* Bugfixes
|
* Bugfixes
|
||||||
|
|
||||||
-- Vitaliy Filippov <vitalif@yourcmc.ru> Fri, 03 Jun 2022 02:09:44 +0300
|
-- Vitaliy Filippov <vitalif@yourcmc.ru> Fri, 03 Jun 2022 02:09:44 +0300
|
||||||
|
|
||||||
vitastor (0.9.2-1) unstable; urgency=medium
|
vitastor (0.9.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
* Implement NFS proxy
|
* Implement NFS proxy
|
||||||
* Add documentation
|
* Add documentation
|
||||||
|
|||||||
Vendored
+17
-10
@@ -1,4 +1,4 @@
|
|||||||
# Build patched QEMU for Debian inside a container
|
# Build patched QEMU for Debian Buster or Bullseye/Sid inside a container
|
||||||
# cd ..; podman build --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/patched-qemu.Dockerfile .
|
# cd ..; podman build --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/patched-qemu.Dockerfile .
|
||||||
|
|
||||||
ARG REL=
|
ARG REL=
|
||||||
@@ -15,19 +15,17 @@ RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" ]; then \
|
|||||||
echo 'Pin-Priority: 500' >> /etc/apt/preferences; \
|
echo 'Pin-Priority: 500' >> /etc/apt/preferences; \
|
||||||
fi; \
|
fi; \
|
||||||
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
|
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-Recommends false;' >> /etc/apt/apt.conf; \
|
||||||
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts
|
RUN apt-get -y install qemu fio liburing1 liburing-dev libgoogle-perftools-dev devscripts
|
||||||
RUN apt-get -y build-dep qemu
|
RUN apt-get -y build-dep qemu
|
||||||
# To build a custom version
|
# To build a custom version
|
||||||
#RUN cp /root/packages/qemu-orig/* /root
|
#RUN cp /root/packages/qemu-orig/* /root
|
||||||
RUN apt-get --download-only source qemu
|
RUN apt-get --download-only source qemu
|
||||||
|
|
||||||
ADD patches /root/vitastor/patches
|
ADD patches/qemu-5.0-vitastor.patch patches/qemu-5.1-vitastor.patch patches/qemu-6.1-vitastor.patch src/qemu_driver.c /root/vitastor/patches/
|
||||||
ADD src/qemu_driver.c /root/vitastor/src/qemu_driver.c
|
|
||||||
RUN set -e; \
|
RUN set -e; \
|
||||||
apt-get install -y wget; \
|
apt-get install -y wget; \
|
||||||
wget -q -O /etc/apt/trusted.gpg.d/vitastor.gpg https://vitastor.io/debian/pubkey.gpg; \
|
wget -q -O /etc/apt/trusted.gpg.d/vitastor.gpg https://vitastor.io/debian/pubkey.gpg; \
|
||||||
@@ -39,14 +37,23 @@ RUN set -e; \
|
|||||||
rm -rf /root/packages/qemu-$REL/*; \
|
rm -rf /root/packages/qemu-$REL/*; \
|
||||||
cd /root/packages/qemu-$REL; \
|
cd /root/packages/qemu-$REL; \
|
||||||
dpkg-source -x /root/qemu*.dsc; \
|
dpkg-source -x /root/qemu*.dsc; \
|
||||||
QEMU_VER=$(ls -d qemu*/ | perl -pe 's!^.*(\d+\.\d+).*!$1!'); \
|
if ls -d /root/packages/qemu-$REL/qemu-5.0*; then \
|
||||||
D=$(ls -d qemu*/); \
|
D=$(ls -d /root/packages/qemu-$REL/qemu-5.0*); \
|
||||||
cp /root/vitastor/patches/qemu-$QEMU_VER-vitastor.patch ./qemu-*/debian/patches; \
|
cp /root/vitastor/patches/qemu-5.0-vitastor.patch $D/debian/patches; \
|
||||||
echo qemu-$QEMU_VER-vitastor.patch >> $D/debian/patches/series; \
|
echo qemu-5.0-vitastor.patch >> $D/debian/patches/series; \
|
||||||
|
elif ls /root/packages/qemu-$REL/qemu-6.1*; then \
|
||||||
|
D=$(ls -d /root/packages/qemu-$REL/qemu-6.1*); \
|
||||||
|
cp /root/vitastor/patches/qemu-6.1-vitastor.patch $D/debian/patches; \
|
||||||
|
echo qemu-6.1-vitastor.patch >> $D/debian/patches/series; \
|
||||||
|
else \
|
||||||
|
cp /root/vitastor/patches/qemu-5.1-vitastor.patch /root/packages/qemu-$REL/qemu-*/debian/patches; \
|
||||||
|
P=`ls -d /root/packages/qemu-$REL/qemu-*/debian/patches`; \
|
||||||
|
echo qemu-5.1-vitastor.patch >> $P/series; \
|
||||||
|
fi; \
|
||||||
cd /root/packages/qemu-$REL/qemu-*/; \
|
cd /root/packages/qemu-$REL/qemu-*/; \
|
||||||
quilt push -a; \
|
quilt push -a; \
|
||||||
quilt add block/vitastor.c; \
|
quilt add block/vitastor.c; \
|
||||||
cp /root/vitastor/src/qemu_driver.c block/vitastor.c; \
|
cp /root/vitastor/patches/qemu_driver.c block/vitastor.c; \
|
||||||
quilt refresh; \
|
quilt refresh; \
|
||||||
V=$(head -n1 debian/changelog | perl -pe 's/^.*\((.*?)(~bpo[\d\+]*)?\).*$/$1/')+vitastor1; \
|
V=$(head -n1 debian/changelog | perl -pe 's/^.*\((.*?)(~bpo[\d\+]*)?\).*$/$1/')+vitastor1; \
|
||||||
DEBEMAIL="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v $V 'Plug Vitastor block driver'; \
|
DEBEMAIL="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v $V 'Plug Vitastor block driver'; \
|
||||||
|
|||||||
Vendored
+6
-7
@@ -1,4 +1,4 @@
|
|||||||
# Build Vitastor packages for Debian inside a container
|
# Build Vitastor packages for Debian Buster or Bullseye/Sid inside a container
|
||||||
# cd ..; podman build --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/vitastor.Dockerfile .
|
# cd ..; podman build --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/vitastor.Dockerfile .
|
||||||
|
|
||||||
ARG REL=
|
ARG REL=
|
||||||
@@ -15,12 +15,11 @@ RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" ]; then \
|
|||||||
echo 'Pin-Priority: 500' >> /etc/apt/preferences; \
|
echo 'Pin-Priority: 500' >> /etc/apt/preferences; \
|
||||||
fi; \
|
fi; \
|
||||||
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
|
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-Recommends false;' >> /etc/apt/apt.conf; \
|
||||||
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts
|
RUN apt-get -y install fio liburing1 liburing-dev libgoogle-perftools-dev devscripts
|
||||||
RUN apt-get -y build-dep fio
|
RUN apt-get -y build-dep fio
|
||||||
RUN apt-get --download-only source fio
|
RUN apt-get --download-only source fio
|
||||||
RUN apt-get update && apt-get -y install libjerasure-dev cmake libibverbs-dev libisal-dev
|
RUN apt-get update && apt-get -y install libjerasure-dev cmake libibverbs-dev libisal-dev
|
||||||
@@ -35,8 +34,8 @@ RUN set -e -x; \
|
|||||||
mkdir -p /root/packages/vitastor-$REL; \
|
mkdir -p /root/packages/vitastor-$REL; \
|
||||||
rm -rf /root/packages/vitastor-$REL/*; \
|
rm -rf /root/packages/vitastor-$REL/*; \
|
||||||
cd /root/packages/vitastor-$REL; \
|
cd /root/packages/vitastor-$REL; \
|
||||||
cp -r /root/vitastor vitastor-0.9.2; \
|
cp -r /root/vitastor vitastor-0.9.0; \
|
||||||
cd vitastor-0.9.2; \
|
cd vitastor-0.9.0; \
|
||||||
ln -s /root/fio-build/fio-*/ ./fio; \
|
ln -s /root/fio-build/fio-*/ ./fio; \
|
||||||
FIO=$(head -n1 fio/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
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; \
|
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
|
||||||
@@ -49,8 +48,8 @@ RUN set -e -x; \
|
|||||||
rm -rf a b; \
|
rm -rf a b; \
|
||||||
echo "dep:fio=$FIO" > debian/fio_version; \
|
echo "dep:fio=$FIO" > debian/fio_version; \
|
||||||
cd /root/packages/vitastor-$REL; \
|
cd /root/packages/vitastor-$REL; \
|
||||||
tar --sort=name --mtime='2020-01-01' --owner=0 --group=0 --exclude=debian -cJf vitastor_0.9.2.orig.tar.xz vitastor-0.9.2; \
|
tar --sort=name --mtime='2020-01-01' --owner=0 --group=0 --exclude=debian -cJf vitastor_0.9.0.orig.tar.xz vitastor-0.9.0; \
|
||||||
cd vitastor-0.9.2; \
|
cd vitastor-0.9.0; \
|
||||||
V=$(head -n1 debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
V=$(head -n1 debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
||||||
DEBFULLNAME="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v "$V""$REL" "Rebuild for $REL"; \
|
DEBFULLNAME="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v "$V""$REL" "Rebuild for $REL"; \
|
||||||
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \
|
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ Configuration parameters can be set in 3 places:
|
|||||||
mon, fio and QEMU options, OpenStack/Proxmox/etc configuration. The latter
|
mon, fio and QEMU options, OpenStack/Proxmox/etc configuration. The latter
|
||||||
doesn't allow to set all variables directly, but it allows to override the
|
doesn't allow to set all variables directly, but it allows to override the
|
||||||
configuration file and set everything you need inside it.
|
configuration file and set everything you need inside it.
|
||||||
- OSD superblocks created by [vitastor-disk](usage/disk.en.md) contain
|
- OSD superblocks created by [vitastor-disk](../usage/disk.en.md) contain
|
||||||
primarily disk layout parameters of specific OSDs. In fact, these parameters
|
primarily disk layout parameters of specific OSDs. In fact, these parameters
|
||||||
are automatically passed into the command line of vitastor-osd process, so
|
are automatically passed into the command line of vitastor-osd process, so
|
||||||
they have the same "status" as command-line parameters.
|
they have the same "status" as command-line parameters.
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@
|
|||||||
монитора, опциях fio и QEMU, настроек OpenStack, Proxmox и т.п. Последние,
|
монитора, опциях fio и QEMU, настроек OpenStack, Proxmox и т.п. Последние,
|
||||||
как правило, не включают полный набор параметров напрямую, но позволяют
|
как правило, не включают полный набор параметров напрямую, но позволяют
|
||||||
определить путь к файлу конфигурации и задать любые параметры в нём.
|
определить путь к файлу конфигурации и задать любые параметры в нём.
|
||||||
- В суперблоке OSD, записываемом [vitastor-disk](usage/disk.ru.md) - параметры,
|
- В суперблоке OSD, записываемом [vitastor-disk](../usage/disk.ru.md) - параметры,
|
||||||
связанные с дисковым форматом и с этим конкретным OSD. На самом деле,
|
связанные с дисковым форматом и с этим конкретным OSD. На самом деле,
|
||||||
при запуске OSD эти параметры автоматически передаются в командную строку
|
при запуске OSD эти параметры автоматически передаются в командную строку
|
||||||
процесса vitastor-osd, то есть по "статусу" они эквивалентны параметрам
|
процесса vitastor-osd, то есть по "статусу" они эквивалентны параметрам
|
||||||
|
|||||||
@@ -1,145 +0,0 @@
|
|||||||
#!/usr/bin/nodejs
|
|
||||||
|
|
||||||
const fsp = require('fs').promises;
|
|
||||||
|
|
||||||
run(process.argv).catch(console.error);
|
|
||||||
|
|
||||||
async function run(argv)
|
|
||||||
{
|
|
||||||
if (argv.length < 3)
|
|
||||||
{
|
|
||||||
console.log('Markdown preprocessor\nUSAGE: ./include.js file.md');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const index_file = await fsp.realpath(argv[2]);
|
|
||||||
const re = /(\{\{[\s\S]*?\}\}|\[[^\]]+\]\([^\)]+\)|(?:^|\n)#[^\n]+)/;
|
|
||||||
let text = await fsp.readFile(index_file, { encoding: 'utf-8' });
|
|
||||||
text = text.split(re);
|
|
||||||
let included = {};
|
|
||||||
let heading = 0, heading_name = '', m;
|
|
||||||
for (let i = 0; i < text.length; i++)
|
|
||||||
{
|
|
||||||
if (text[i].substr(0, 2) == '{{')
|
|
||||||
{
|
|
||||||
// Inclusion
|
|
||||||
let incfile = text[i].substr(2, text[i].length-4);
|
|
||||||
let section = null;
|
|
||||||
let indent = heading;
|
|
||||||
incfile = incfile.replace(/\s*\|\s*indent\s*=\s*(-?\d+)\s*$/, (m, m1) => { indent = parseInt(m1); return ''; });
|
|
||||||
incfile = incfile.replace(/\s*#\s*([^#]+)$/, (m, m1) => { section = m1; return ''; });
|
|
||||||
let inc_heading = section;
|
|
||||||
incfile = rel2abs(index_file, incfile);
|
|
||||||
let inc = await fsp.readFile(incfile, { encoding: 'utf-8' });
|
|
||||||
inc = inc.trim().replace(/^[\s\S]+?\n#/, '#'); // remove until the first header
|
|
||||||
inc = inc.split(re);
|
|
||||||
const indent_str = new Array(indent+1).join('#');
|
|
||||||
let section_start = -1, section_end = -1;
|
|
||||||
for (let j = 0; j < inc.length; j++)
|
|
||||||
{
|
|
||||||
if ((m = /^(\n?)(#+\s*)([\s\S]+)$/.exec(inc[j])))
|
|
||||||
{
|
|
||||||
if (!inc_heading)
|
|
||||||
{
|
|
||||||
inc_heading = m[3].trim();
|
|
||||||
}
|
|
||||||
if (section)
|
|
||||||
{
|
|
||||||
if (m[3].trim() == section)
|
|
||||||
section_start = j;
|
|
||||||
else if (section_start >= 0)
|
|
||||||
{
|
|
||||||
section_end = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inc[j] = m[1] + indent_str + m[2] + m[3];
|
|
||||||
}
|
|
||||||
else if ((m = /^(\[[^\]]+\]\()([^\)]+)(\))$/.exec(inc[j])) && !/^https?:(\/\/)|^#/.exec(m[2]))
|
|
||||||
{
|
|
||||||
const abs_m2 = rel2abs(incfile, m[2]);
|
|
||||||
const rel_m = abs2rel(__filename, abs_m2);
|
|
||||||
if (rel_m.substr(0, 9) == '../../../') // outside docs
|
|
||||||
inc[j] = m[1] + 'https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/'+rel2abs('docs/config/src/include.js', rel_m) + m[3];
|
|
||||||
else
|
|
||||||
inc[j] = m[1] + abs_m2 + m[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (section)
|
|
||||||
{
|
|
||||||
inc = section_start >= 0 ? inc.slice(section_start, section_end < 0 ? inc.length : section_end) : [];
|
|
||||||
}
|
|
||||||
if (inc.length)
|
|
||||||
{
|
|
||||||
if (!inc_heading)
|
|
||||||
inc_heading = heading_name||'';
|
|
||||||
included[incfile+(section ? '#'+section : '')] = '#'+inc_heading.toLowerCase().replace(/\P{L}+/ug, '-').replace(/^-|-$/g, '');
|
|
||||||
inc[0] = inc[0].replace(/^\s+/, '');
|
|
||||||
inc[inc.length-1] = inc[inc.length-1].replace(/\s+$/, '');
|
|
||||||
}
|
|
||||||
text.splice(i, 1, ...inc);
|
|
||||||
i = i + inc.length - 1;
|
|
||||||
}
|
|
||||||
else if ((m = /^\n?(#+)\s*([\s\S]+)$/.exec(text[i])))
|
|
||||||
{
|
|
||||||
// Heading
|
|
||||||
heading = m[1].length;
|
|
||||||
heading_name = m[2].trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i = 0; i < text.length; i++)
|
|
||||||
{
|
|
||||||
if ((m = /^(\[[^\]]+\]\()([^\)]+)(\))$/.exec(text[i])) && !/^https?:(\/\/)|^#/.exec(m[2]))
|
|
||||||
{
|
|
||||||
const p = m[2].indexOf('#');
|
|
||||||
if (included[m[2]])
|
|
||||||
{
|
|
||||||
text[i] = m[1]+included[m[2]]+m[3];
|
|
||||||
}
|
|
||||||
else if (p >= 0 && included[m[2].substr(0, p)])
|
|
||||||
{
|
|
||||||
text[i] = m[1]+m[2].substr(p)+m[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(text.join(''));
|
|
||||||
}
|
|
||||||
|
|
||||||
function rel2abs(ref, rel)
|
|
||||||
{
|
|
||||||
rel = [ ...ref.replace(/^(.*)\/[^\/]+$/, '$1').split(/\/+/), ...rel.split(/\/+/) ];
|
|
||||||
return killdots(rel).join('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function abs2rel(ref, abs)
|
|
||||||
{
|
|
||||||
ref = ref.split(/\/+/);
|
|
||||||
abs = abs.split(/\/+/);
|
|
||||||
while (ref.length > 1 && ref[0] == abs[0])
|
|
||||||
{
|
|
||||||
ref.shift();
|
|
||||||
abs.shift();
|
|
||||||
}
|
|
||||||
for (let i = 1; i < ref.length; i++)
|
|
||||||
{
|
|
||||||
abs.unshift('..');
|
|
||||||
}
|
|
||||||
return killdots(abs).join('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function killdots(rel)
|
|
||||||
{
|
|
||||||
for (let i = 0; i < rel.length; i++)
|
|
||||||
{
|
|
||||||
if (rel[i] == '.')
|
|
||||||
{
|
|
||||||
rel.splice(i, 1);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
else if (i >= 1 && rel[i] == '..' && rel[i-1] != '..')
|
|
||||||
{
|
|
||||||
rel.splice(i-1, 2);
|
|
||||||
i -= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rel;
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# Vitastor
|
|
||||||
|
|
||||||
{{../../../README.md#The Idea}}
|
|
||||||
|
|
||||||
{{../../../README.md#Talks and presentations}}
|
|
||||||
|
|
||||||
{{../../intro/features.en.md}}
|
|
||||||
|
|
||||||
{{../../intro/quickstart.en.md}}
|
|
||||||
|
|
||||||
{{../../intro/architecture.en.md}}
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
{{../../installation/packages.en.md}}
|
|
||||||
|
|
||||||
{{../../installation/proxmox.en.md}}
|
|
||||||
|
|
||||||
{{../../installation/openstack.en.md}}
|
|
||||||
|
|
||||||
{{../../installation/kubernetes.en.md}}
|
|
||||||
|
|
||||||
{{../../installation/source.en.md}}
|
|
||||||
|
|
||||||
{{../../config.en.md|indent=1}}
|
|
||||||
|
|
||||||
{{../../config/common.en.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/network.en.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/layout-cluster.en.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/layout-osd.en.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/osd.en.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/monitor.en.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/pool.en.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/inode.en.md|indent=2}}
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
{{../../usage/cli.en.md}}
|
|
||||||
|
|
||||||
{{../../usage/disk.en.md}}
|
|
||||||
|
|
||||||
{{../../usage/fio.en.md}}
|
|
||||||
|
|
||||||
{{../../usage/nbd.en.md}}
|
|
||||||
|
|
||||||
{{../../usage/qemu.en.md}}
|
|
||||||
|
|
||||||
{{../../usage/nfs.en.md}}
|
|
||||||
|
|
||||||
## Performance
|
|
||||||
|
|
||||||
{{../../performance/understanding.en.md}}
|
|
||||||
|
|
||||||
{{../../performance/theoretical.en.md}}
|
|
||||||
|
|
||||||
{{../../performance/comparison1.en.md}}
|
|
||||||
|
|
||||||
{{../../intro/author.en.md|indent=1}}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# Vitastor
|
|
||||||
|
|
||||||
{{../../../README-ru.md#Идея|indent=0}}
|
|
||||||
|
|
||||||
{{../../../README-ru.md#Презентации и записи докладов|indent=0}}
|
|
||||||
|
|
||||||
{{../../intro/features.ru.md}}
|
|
||||||
|
|
||||||
{{../../intro/quickstart.ru.md}}
|
|
||||||
|
|
||||||
{{../../intro/architecture.ru.md}}
|
|
||||||
|
|
||||||
## Установка
|
|
||||||
|
|
||||||
{{../../installation/packages.ru.md}}
|
|
||||||
|
|
||||||
{{../../installation/proxmox.ru.md}}
|
|
||||||
|
|
||||||
{{../../installation/openstack.ru.md}}
|
|
||||||
|
|
||||||
{{../../installation/kubernetes.ru.md}}
|
|
||||||
|
|
||||||
{{../../installation/source.ru.md}}
|
|
||||||
|
|
||||||
{{../../config.ru.md|indent=1}}
|
|
||||||
|
|
||||||
{{../../config/common.ru.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/network.ru.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/layout-cluster.ru.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/layout-osd.ru.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/osd.ru.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/monitor.ru.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/pool.ru.md|indent=2}}
|
|
||||||
|
|
||||||
{{../../config/inode.ru.md|indent=2}}
|
|
||||||
|
|
||||||
## Использование
|
|
||||||
|
|
||||||
{{../../usage/cli.ru.md}}
|
|
||||||
|
|
||||||
{{../../usage/disk.ru.md}}
|
|
||||||
|
|
||||||
{{../../usage/fio.ru.md}}
|
|
||||||
|
|
||||||
{{../../usage/nbd.ru.md}}
|
|
||||||
|
|
||||||
{{../../usage/qemu.ru.md}}
|
|
||||||
|
|
||||||
{{../../usage/nfs.ru.md}}
|
|
||||||
|
|
||||||
## Производительность
|
|
||||||
|
|
||||||
{{../../performance/understanding.ru.md}}
|
|
||||||
|
|
||||||
{{../../performance/theoretical.ru.md}}
|
|
||||||
|
|
||||||
{{../../performance/comparison1.ru.md}}
|
|
||||||
|
|
||||||
{{../../intro/author.ru.md|indent=1}}
|
|
||||||
@@ -8,13 +8,13 @@
|
|||||||
|
|
||||||
У Vitastor есть CSI-плагин для Kubernetes, поддерживающий RWO, а также блочные RWX, тома.
|
У Vitastor есть CSI-плагин для Kubernetes, поддерживающий RWO, а также блочные RWX, тома.
|
||||||
|
|
||||||
Для установки возьмите манифесты из директории [csi/deploy/](../../csi/deploy/), поместите
|
Для установки возьмите манифесты из директории [csi/deploy/](../csi/deploy/), поместите
|
||||||
вашу конфигурацию подключения к Vitastor в [csi/deploy/001-csi-config-map.yaml](../../csi/deploy/001-csi-config-map.yaml),
|
вашу конфигурацию подключения к Vitastor в [csi/deploy/001-csi-config-map.yaml](../csi/deploy/001-csi-config-map.yaml),
|
||||||
настройте StorageClass в [csi/deploy/009-storage-class.yaml](../../csi/deploy/009-storage-class.yaml)
|
настройте StorageClass в [csi/deploy/009-storage-class.yaml](../csi/deploy/009-storage-class.yaml)
|
||||||
и примените все `NNN-*.yaml` к вашей инсталляции Kubernetes.
|
и примените все `NNN-*.yaml` к вашей инсталляции Kubernetes.
|
||||||
|
|
||||||
```
|
```
|
||||||
for i in ./???-*.yaml; do kubectl apply -f $i; done
|
for i in ./???-*.yaml; do kubectl apply -f $i; done
|
||||||
```
|
```
|
||||||
|
|
||||||
После этого вы сможете создавать PersistentVolume. Пример смотрите в файле [csi/deploy/example-pvc.yaml](../../csi/deploy/example-pvc.yaml).
|
После этого вы сможете создавать PersistentVolume. Пример смотрите в файле [csi/deploy/example-pvc.yaml](../csi/deploy/example-pvc.yaml).
|
||||||
|
|||||||
@@ -36,5 +36,5 @@ vitastor_pool_id = 1
|
|||||||
image_upload_use_cinder_backend = True
|
image_upload_use_cinder_backend = True
|
||||||
```
|
```
|
||||||
|
|
||||||
To put Glance images in Vitastor, use [volume-backed images](https://docs.openstack.org/cinder/pike/admin/blockstorage-volume-backed-image.html),
|
To put Glance images in Vitastor, use [https://docs.openstack.org/cinder/pike/admin/blockstorage-volume-backed-image.html](volume-backed images),
|
||||||
although the support has not been verified yet.
|
although the support has not been verified yet.
|
||||||
|
|||||||
@@ -36,5 +36,5 @@ image_upload_use_cinder_backend = True
|
|||||||
```
|
```
|
||||||
|
|
||||||
Чтобы помещать в Vitastor Glance-образы, нужно использовать
|
Чтобы помещать в Vitastor Glance-образы, нужно использовать
|
||||||
[образы на основе томов Cinder](https://docs.openstack.org/cinder/pike/admin/blockstorage-volume-backed-image.html),
|
[https://docs.openstack.org/cinder/pike/admin/blockstorage-volume-backed-image.html](образы на основе томов Cinder),
|
||||||
однако, поддержка этой функции ещё не проверялась.
|
однако, поддержка этой функции ещё не проверялась.
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
- Trust Vitastor package signing key:
|
- Trust Vitastor package signing key:
|
||||||
`wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg`
|
`wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg`
|
||||||
- Add Vitastor package repository to your /etc/apt/sources.list:
|
- Add Vitastor package repository to your /etc/apt/sources.list:
|
||||||
- Debian 12 (Bookworm/Sid): `deb https://vitastor.io/debian bookworm main`
|
- Debian 11 (Bullseye/Sid): `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`
|
||||||
- For Debian 10 (Buster) also enable backports repository:
|
- For Debian 10 (Buster) also enable backports repository:
|
||||||
`deb http://deb.debian.org/debian buster-backports main`
|
`deb http://deb.debian.org/debian buster-backports main`
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
- Добавьте ключ репозитория Vitastor:
|
- Добавьте ключ репозитория Vitastor:
|
||||||
`wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg`
|
`wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg`
|
||||||
- Добавьте репозиторий Vitastor в /etc/apt/sources.list:
|
- Добавьте репозиторий Vitastor в /etc/apt/sources.list:
|
||||||
- Debian 12 (Bookworm/Sid): `deb https://vitastor.io/debian bookworm main`
|
- Debian 11 (Bullseye/Sid): `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`
|
||||||
- Для Debian 10 (Buster) также включите репозиторий backports:
|
- Для Debian 10 (Buster) также включите репозиторий backports:
|
||||||
`deb http://deb.debian.org/debian buster-backports main`
|
`deb http://deb.debian.org/debian buster-backports main`
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
# Proxmox VE
|
# Proxmox VE
|
||||||
|
|
||||||
To enable Vitastor support in Proxmox Virtual Environment (6.4-8.0 are supported):
|
To enable Vitastor support in Proxmox Virtual Environment (6.4-7.4 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.0, bullseye for 7.4, pve7.3 for 7.3, pve7.2 for 7.2, pve7.1 for 7.1, buster for 6.4
|
buster for 6.4, bullseye for 7.4, pve7.1 for 7.1, pve7.2 for 7.2, pve7.3 for 7.3
|
||||||
- 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),
|
||||||
@@ -35,5 +35,5 @@ vitastor: vitastor
|
|||||||
vitastor_nbd 0
|
vitastor_nbd 0
|
||||||
```
|
```
|
||||||
|
|
||||||
\* Note: you can also manually copy [patches/VitastorPlugin.pm](../../patches/VitastorPlugin.pm) to Proxmox hosts
|
\* Note: you can also manually copy [patches/VitastorPlugin.pm](patches/VitastorPlugin.pm) to Proxmox hosts
|
||||||
as `/usr/share/perl5/PVE/Storage/Custom/VitastorPlugin.pm` instead of installing pve-storage-vitastor.
|
as `/usr/share/perl5/PVE/Storage/Custom/VitastorPlugin.pm` instead of installing pve-storage-vitastor.
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
[Read in English](proxmox.en.md)
|
[Read in English](proxmox.en.md)
|
||||||
|
|
||||||
# Proxmox VE
|
# Proxmox
|
||||||
|
|
||||||
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-8.0):
|
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-7.4):
|
||||||
|
|
||||||
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
|
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
|
||||||
bookworm для 8.0, bullseye для 7.4, pve7.3 для 7.3, pve7.2 для 7.2, pve7.1 для 7.1, buster для 6.4
|
buster для 6.4, bullseye для 7.4, pve7.1 для 7.1, pve7.2 для 7.2, pve7.3 для 7.3
|
||||||
- Установите пакеты 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 (пока) не поддерживает аутентификацию
|
||||||
@@ -35,5 +35,5 @@ vitastor: vitastor
|
|||||||
```
|
```
|
||||||
|
|
||||||
\* Примечание: вместо установки пакета pve-storage-vitastor вы можете вручную скопировать файл
|
\* Примечание: вместо установки пакета pve-storage-vitastor вы можете вручную скопировать файл
|
||||||
[patches/VitastorPlugin.pm](../../patches/VitastorPlugin.pm) на хосты Proxmox как
|
[patches/VitastorPlugin.pm](patches/VitastorPlugin.pm) на хосты Proxmox как
|
||||||
`/usr/share/perl5/PVE/Storage/Custom/VitastorPlugin.pm`.
|
`/usr/share/perl5/PVE/Storage/Custom/VitastorPlugin.pm`.
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
depends linearly on drive capacity and data store block size which is 128 KB by default.
|
depends linearly on drive capacity and data store block size which is 128 KB by default.
|
||||||
With 128 KB blocks metadata takes around 512 MB per 1 TB (which is still less than Ceph wants).
|
With 128 KB blocks metadata takes around 512 MB per 1 TB (which is still less than Ceph wants).
|
||||||
Journal is also kept in memory by default, but in SSD-only clusters it's only 32 MB, and in SSD+HDD
|
Journal is also kept in memory by default, but in SSD-only clusters it's only 32 MB, and in SSD+HDD
|
||||||
clusters, where it's beneficial to increase it, [inmemory_journal](../config/osd.en.md#inmemory_journal) can be disabled.
|
clusters, where it's beneficial to increase it, [inmemory_journal](docs/config/osd.en.md#inmemory_journal) can be disabled.
|
||||||
- Vitastor storage layer doesn't have internal copy-on-write or redirect-write. I know that maybe
|
- Vitastor storage layer doesn't have internal copy-on-write or redirect-write. I know that maybe
|
||||||
it's possible to create a good copy-on-write storage, but it's much harder and makes performance
|
it's possible to create a good copy-on-write storage, but it's much harder and makes performance
|
||||||
less deterministic, so CoW isn't used in Vitastor.
|
less deterministic, so CoW isn't used in Vitastor.
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
блока хранилища (block_size, по умолчанию 128 КБ). С 128 КБ блоком потребление памяти
|
блока хранилища (block_size, по умолчанию 128 КБ). С 128 КБ блоком потребление памяти
|
||||||
составляет примерно 512 МБ на 1 ТБ данных. Журналы по умолчанию тоже хранятся в памяти,
|
составляет примерно 512 МБ на 1 ТБ данных. Журналы по умолчанию тоже хранятся в памяти,
|
||||||
но в SSD-кластерах нужный размер журнала составляет всего 32 МБ, а в гибридных (SSD+HDD)
|
но в SSD-кластерах нужный размер журнала составляет всего 32 МБ, а в гибридных (SSD+HDD)
|
||||||
кластерах, в которых есть смысл делать журналы больше, можно отключить [inmemory_journal](../config/osd.ru.md#inmemory_journal).
|
кластерах, в которых есть смысл делать журналы больше, можно отключить [inmemory_journal](../docs/config/osd.ru.md#inmemory_journal).
|
||||||
- В Vitastor нет внутреннего copy-on-write. Я считаю, что реализация CoW-хранилища гораздо сложнее,
|
- В Vitastor нет внутреннего copy-on-write. Я считаю, что реализация CoW-хранилища гораздо сложнее,
|
||||||
поэтому сложнее добиться устойчиво хороших результатов. Возможно, в один прекрасный день
|
поэтому сложнее добиться устойчиво хороших результатов. Возможно, в один прекрасный день
|
||||||
я придумаю красивый алгоритм для CoW-хранилища, но пока нет — внутреннего CoW в Vitastor не будет.
|
я придумаю красивый алгоритм для CoW-хранилища, но пока нет — внутреннего CoW в Vitastor не будет.
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
- [Debian and CentOS packages](../installation/packages.en.md)
|
- [Debian and CentOS packages](../installation/packages.en.md)
|
||||||
- [Image management CLI (vitastor-cli)](../usage/cli.en.md)
|
- [Image management CLI (vitastor-cli)](../usage/cli.en.md)
|
||||||
- [Disk management CLI (vitastor-disk)](../usage/disk.en.md)
|
- [Disk management CLI (vitastor-disk)](docs/usage/disk.en.md)
|
||||||
- Generic user-space client library
|
- Generic user-space client library
|
||||||
- [Native QEMU driver](../usage/qemu.en.md)
|
- [Native QEMU driver](../usage/qemu.en.md)
|
||||||
- [Loadable fio engine for benchmarks](../usage/fio.en.md)
|
- [Loadable fio engine for benchmarks](../usage/fio.en.md)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
## Серверные функции
|
## Серверные функции
|
||||||
|
|
||||||
- Базовая часть - надёжное кластерное блочное хранилище без единой точки отказа
|
- Базовая часть - надёжное кластерное блочное хранилище без единой точки отказа
|
||||||
- [Производительность](../performance/comparison1.ru.md) ;-D
|
- [Производительность](../comparison1.ru.md) ;-D
|
||||||
- [Несколько схем отказоустойчивости](../config/pool.ru.md#scheme): репликация, XOR n+1 (1 диск чётности), коды коррекции ошибок
|
- [Несколько схем отказоустойчивости](../config/pool.ru.md#scheme): репликация, XOR n+1 (1 диск чётности), коды коррекции ошибок
|
||||||
Рида-Соломона на основе библиотек jerasure и ISA-L с любым числом дисков данных и чётности в группе
|
Рида-Соломона на основе библиотек jerasure и ISA-L с любым числом дисков данных и чётности в группе
|
||||||
- Конфигурация через простые человекочитаемые JSON-структуры в etcd
|
- Конфигурация через простые человекочитаемые JSON-структуры в etcd
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
- [Пакеты для Debian и CentOS](../installation/packages.ru.md)
|
- [Пакеты для Debian и CentOS](../installation/packages.ru.md)
|
||||||
- [Консольный интерфейс управления образами (vitastor-cli)](../usage/cli.ru.md)
|
- [Консольный интерфейс управления образами (vitastor-cli)](../usage/cli.ru.md)
|
||||||
- [Инструмент управления дисками (vitastor-disk)](../usage/disk.ru.md)
|
- [Инструмент управления дисками (vitastor-disk)](docs/usage/disk.ru.md)
|
||||||
- Общая пользовательская клиентская библиотека для работы с кластером
|
- Общая пользовательская клиентская библиотека для работы с кластером
|
||||||
- [Драйвер диска для QEMU](../usage/qemu.ru.md)
|
- [Драйвер диска для QEMU](../usage/qemu.ru.md)
|
||||||
- [Драйвер диска для утилиты тестирования производительности fio](../usage/fio.ru.md)
|
- [Драйвер диска для утилиты тестирования производительности fio](../usage/fio.ru.md)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ vitastor-nfs [--etcd_address ADDR] [ДРУГИЕ ОПЦИИ]
|
|||||||
--bind <IP> принимать соединения по адресу <IP> (по умолчанию 0.0.0.0 - на всех)
|
--bind <IP> принимать соединения по адресу <IP> (по умолчанию 0.0.0.0 - на всех)
|
||||||
--nfspath <PATH> установить путь NFS-экспорта в <PATH> (по умолчанию /)
|
--nfspath <PATH> установить путь NFS-экспорта в <PATH> (по умолчанию /)
|
||||||
--port <PORT> использовать порт <PORT> для NFS-сервисов (по умолчанию 2049)
|
--port <PORT> использовать порт <PORT> для NFS-сервисов (по умолчанию 2049)
|
||||||
--pool <POOL> использовать пул <POOL> для новых образов (обязательно, если пул в кластере не один)
|
--pool <POOL> исползовать пул <POOL> для новых образов (обязательно, если пул в кластере не один)
|
||||||
--foreground 1 не уходить в фон после запуска
|
--foreground 1 не уходить в фон после запуска
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ Wants=network-online.target local-fs.target time-sync.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Restart=always
|
Restart=always
|
||||||
ExecStart=etcd -name etcd${num} --data-dir /var/lib/etcd${num}.etcd \\
|
ExecStart=/usr/local/bin/etcd -name etcd${num} --data-dir /var/lib/etcd${num}.etcd \\
|
||||||
--advertise-client-urls http://${etcds[num]}:2379 --listen-client-urls http://${etcds[num]}:2379 \\
|
--advertise-client-urls http://${etcds[num]}:2379 --listen-client-urls http://${etcds[num]}:2379 \\
|
||||||
--initial-advertise-peer-urls http://${etcds[num]}:2380 --listen-peer-urls http://${etcds[num]}:2380 \\
|
--initial-advertise-peer-urls http://${etcds[num]}:2380 --listen-peer-urls http://${etcds[num]}:2380 \\
|
||||||
--initial-cluster-token vitastor-etcd-1 --initial-cluster ${etcd_cluster} \\
|
--initial-cluster-token vitastor-etcd-1 --initial-cluster ${etcd_cluster} \\
|
||||||
|
|||||||
+54
-67
@@ -391,7 +391,6 @@ class Mon
|
|||||||
this.etcd_start_timeout = (config.etcd_start_timeout || 5) * 1000;
|
this.etcd_start_timeout = (config.etcd_start_timeout || 5) * 1000;
|
||||||
this.state = JSON.parse(JSON.stringify(this.constructor.etcd_tree));
|
this.state = JSON.parse(JSON.stringify(this.constructor.etcd_tree));
|
||||||
this.signals_set = false;
|
this.signals_set = false;
|
||||||
this.stat_time = Date.now();
|
|
||||||
this.ws = null;
|
this.ws = null;
|
||||||
this.ws_alive = false;
|
this.ws_alive = false;
|
||||||
this.ws_keepalive_timer = null;
|
this.ws_keepalive_timer = null;
|
||||||
@@ -1411,75 +1410,65 @@ class Mon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_osd_stats(st, prev)
|
|
||||||
{
|
|
||||||
const zero_stats = { op: { bps: 0n, iops: 0n, lat: 0n }, subop: { iops: 0n, lat: 0n }, recovery: { bps: 0n, iops: 0n } };
|
|
||||||
const diff = { op_stats: {}, subop_stats: {}, recovery_stats: {} };
|
|
||||||
if (!st || !st.time || prev && (prev.time || this.stat_time/1000) >= st.time)
|
|
||||||
{
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
const timediff = BigInt(st.time*1000 - (prev && prev.time*1000 || this.stat_time));
|
|
||||||
for (const op in st.op_stats||{})
|
|
||||||
{
|
|
||||||
const pr = prev && prev.op_stats && prev.op_stats[op];
|
|
||||||
let c = st.op_stats[op];
|
|
||||||
c = { bytes: BigInt(c.bytes||0), usec: BigInt(c.usec||0), count: BigInt(c.count||0) };
|
|
||||||
const b = c.bytes - BigInt(pr && pr.bytes||0);
|
|
||||||
const us = c.usec - BigInt(pr && pr.usec||0);
|
|
||||||
const n = c.count - BigInt(pr && pr.count||0);
|
|
||||||
if (n > 0)
|
|
||||||
diff.op_stats[op] = { ...c, bps: b*1000n/timediff, iops: n*1000n/timediff, lat: us/n };
|
|
||||||
}
|
|
||||||
for (const op in st.subop_stats||{})
|
|
||||||
{
|
|
||||||
const pr = prev && prev.subop_stats && prev.subop_stats[op];
|
|
||||||
let c = st.subop_stats[op];
|
|
||||||
c = { usec: BigInt(c.usec||0), count: BigInt(c.count||0) };
|
|
||||||
const us = c.usec - BigInt(pr && pr.usec||0);
|
|
||||||
const n = c.count - BigInt(pr && pr.count||0);
|
|
||||||
if (n > 0)
|
|
||||||
diff.subop_stats[op] = { ...c, iops: n*1000n/timediff, lat: us/n };
|
|
||||||
}
|
|
||||||
for (const op in st.recovery_stats||{})
|
|
||||||
{
|
|
||||||
const pr = prev && prev.recovery_stats && prev.recovery_stats[op];
|
|
||||||
let c = st.recovery_stats[op];
|
|
||||||
c = { bytes: BigInt(c.bytes||0), count: BigInt(c.count||0) };
|
|
||||||
const b = c.bytes - BigInt(pr && pr.bytes||0);
|
|
||||||
const n = c.count - BigInt(pr && pr.count||0);
|
|
||||||
if (n > 0)
|
|
||||||
diff.recovery_stats[op] = { ...c, bps: b*1000n/timediff, iops: n*1000n/timediff };
|
|
||||||
}
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
sum_op_stats(timestamp, prev_stats)
|
sum_op_stats(timestamp, prev_stats)
|
||||||
{
|
{
|
||||||
const sum_diff = { op_stats: {}, subop_stats: {}, recovery_stats: {} };
|
const op_stats = {}, subop_stats = {}, recovery_stats = {};
|
||||||
if (!prev_stats || prev_stats.timestamp >= timestamp)
|
|
||||||
{
|
|
||||||
return sum_diff;
|
|
||||||
}
|
|
||||||
const tm = BigInt(timestamp - (prev_stats.timestamp || 0));
|
|
||||||
// Sum derived values instead of deriving summed
|
|
||||||
for (const osd in this.state.osd.stats)
|
for (const osd in this.state.osd.stats)
|
||||||
{
|
{
|
||||||
const derived = this.derive_osd_stats(this.state.osd.stats[osd],
|
const st = this.state.osd.stats[osd]||{};
|
||||||
this.prev_stats && this.prev_stats.osd_stats && this.prev_stats.osd_stats[osd]);
|
for (const op in st.op_stats||{})
|
||||||
for (const type in derived)
|
|
||||||
{
|
{
|
||||||
for (const op in derived[type])
|
op_stats[op] = op_stats[op] || { count: 0n, usec: 0n, bytes: 0n };
|
||||||
{
|
op_stats[op].count += BigInt(st.op_stats[op].count||0);
|
||||||
for (const k in derived[type][op])
|
op_stats[op].usec += BigInt(st.op_stats[op].usec||0);
|
||||||
{
|
op_stats[op].bytes += BigInt(st.op_stats[op].bytes||0);
|
||||||
sum_diff[type][op] = sum_diff[type][op] || {};
|
}
|
||||||
sum_diff[type][op][k] = (sum_diff[type][op][k] || 0n) + derived[type][op][k];
|
for (const op in st.subop_stats||{})
|
||||||
}
|
{
|
||||||
}
|
subop_stats[op] = subop_stats[op] || { count: 0n, usec: 0n };
|
||||||
|
subop_stats[op].count += BigInt(st.subop_stats[op].count||0);
|
||||||
|
subop_stats[op].usec += BigInt(st.subop_stats[op].usec||0);
|
||||||
|
}
|
||||||
|
for (const op in st.recovery_stats||{})
|
||||||
|
{
|
||||||
|
recovery_stats[op] = recovery_stats[op] || { count: 0n, bytes: 0n };
|
||||||
|
recovery_stats[op].count += BigInt(st.recovery_stats[op].count||0);
|
||||||
|
recovery_stats[op].bytes += BigInt(st.recovery_stats[op].bytes||0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sum_diff;
|
if (prev_stats && prev_stats.timestamp >= timestamp)
|
||||||
|
{
|
||||||
|
prev_stats = null;
|
||||||
|
}
|
||||||
|
const tm = prev_stats ? BigInt(timestamp - prev_stats.timestamp) : 0;
|
||||||
|
for (const op in op_stats)
|
||||||
|
{
|
||||||
|
if (prev_stats && prev_stats.op_stats && prev_stats.op_stats[op])
|
||||||
|
{
|
||||||
|
op_stats[op].bps = (op_stats[op].bytes - prev_stats.op_stats[op].bytes) * 1000n / tm;
|
||||||
|
op_stats[op].iops = (op_stats[op].count - prev_stats.op_stats[op].count) * 1000n / tm;
|
||||||
|
op_stats[op].lat = (op_stats[op].usec - prev_stats.op_stats[op].usec)
|
||||||
|
/ ((op_stats[op].count - prev_stats.op_stats[op].count) || 1n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const op in subop_stats)
|
||||||
|
{
|
||||||
|
if (prev_stats && prev_stats.subop_stats && prev_stats.subop_stats[op])
|
||||||
|
{
|
||||||
|
subop_stats[op].iops = (subop_stats[op].count - prev_stats.subop_stats[op].count) * 1000n / tm;
|
||||||
|
subop_stats[op].lat = (subop_stats[op].usec - prev_stats.subop_stats[op].usec)
|
||||||
|
/ ((subop_stats[op].count - prev_stats.subop_stats[op].count) || 1n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const op in recovery_stats)
|
||||||
|
{
|
||||||
|
if (prev_stats && prev_stats.recovery_stats && prev_stats.recovery_stats[op])
|
||||||
|
{
|
||||||
|
recovery_stats[op].bps = (recovery_stats[op].bytes - prev_stats.recovery_stats[op].bytes) * 1000n / tm;
|
||||||
|
recovery_stats[op].iops = (recovery_stats[op].count - prev_stats.recovery_stats[op].count) * 1000n / tm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { op_stats, subop_stats, recovery_stats };
|
||||||
}
|
}
|
||||||
|
|
||||||
sum_object_counts()
|
sum_object_counts()
|
||||||
@@ -1638,8 +1627,7 @@ class Mon
|
|||||||
this.prev_stats ? this.prev_stats.inode_stats : null,
|
this.prev_stats ? this.prev_stats.inode_stats : null,
|
||||||
timestamp, this.prev_stats ? this.prev_stats.timestamp : null
|
timestamp, this.prev_stats ? this.prev_stats.timestamp : null
|
||||||
);
|
);
|
||||||
this.prev_stats = { timestamp, inode_stats, osd_stats: { ...this.state.osd.stats } };
|
this.prev_stats = { timestamp, ...stats, inode_stats };
|
||||||
this.stat_time = Date.now();
|
|
||||||
stats.object_counts = object_counts;
|
stats.object_counts = object_counts;
|
||||||
stats.object_bytes = object_bytes;
|
stats.object_bytes = object_bytes;
|
||||||
stats = this.serialize_bigints(stats);
|
stats = this.serialize_bigints(stats);
|
||||||
@@ -1755,14 +1743,13 @@ class Mon
|
|||||||
else if (key_parts[0] === 'osd' && key_parts[1] === 'stats')
|
else if (key_parts[0] === 'osd' && key_parts[1] === 'stats')
|
||||||
{
|
{
|
||||||
// Recheck OSD tree on OSD addition/deletion
|
// Recheck OSD tree on OSD addition/deletion
|
||||||
const osd_num = key_parts[2];
|
|
||||||
if ((!old) != (!kv.value) || old && kv.value && old.size != kv.value.size)
|
if ((!old) != (!kv.value) || old && kv.value && old.size != kv.value.size)
|
||||||
{
|
{
|
||||||
this.schedule_recheck();
|
this.schedule_recheck();
|
||||||
}
|
}
|
||||||
// Recheck PGs <osd_out_time> after last OSD statistics report
|
// Recheck PGs <osd_out_time> after last OSD statistics report
|
||||||
this.schedule_next_recheck_at(
|
this.schedule_next_recheck_at(
|
||||||
!this.state.osd.stats[osd_num] ? 0 : this.state.osd.stats[osd_num].time+this.config.osd_out_time
|
!this.state.osd.stats[key[2]] ? 0 : this.state.osd.stats[key[2]].time+this.config.osd_out_time
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,6 +388,8 @@ sub unmap_volume
|
|||||||
my ($class, $storeid, $scfg, $volname, $snapname) = @_;
|
my ($class, $storeid, $scfg, $volname, $snapname) = @_;
|
||||||
my $prefix = defined $scfg->{vitastor_prefix} ? $scfg->{vitastor_prefix} : 'pve/';
|
my $prefix = defined $scfg->{vitastor_prefix} ? $scfg->{vitastor_prefix} : 'pve/';
|
||||||
|
|
||||||
|
return 1 if !$scfg->{vitastor_nbd};
|
||||||
|
|
||||||
my ($vtype, $name, $vmid) = $class->parse_volname($volname);
|
my ($vtype, $name, $vmid) = $class->parse_volname($volname);
|
||||||
$name .= '@'.$snapname if $snapname;
|
$name .= '@'.$snapname if $snapname;
|
||||||
|
|
||||||
@@ -411,7 +413,7 @@ sub activate_volume
|
|||||||
sub deactivate_volume
|
sub deactivate_volume
|
||||||
{
|
{
|
||||||
my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
|
my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_;
|
||||||
$class->unmap_volume($storeid, $scfg, $volname, $snapname) if $scfg->{vitastor_nbd};
|
$class->unmap_volume($storeid, $scfg, $volname, $snapname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
VERSION = '0.9.2'
|
VERSION = '0.9.0'
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -1,644 +0,0 @@
|
|||||||
commit e6f935157944279c2c0634915c3c00feeec748c9
|
|
||||||
Author: Vitaliy Filippov <vitalif@yourcmc.ru>
|
|
||||||
Date: Mon Jun 19 00:58:19 2023 +0300
|
|
||||||
|
|
||||||
Add Vitastor support
|
|
||||||
|
|
||||||
diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h
|
|
||||||
index aaad4a3..5f5daa8 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 45965fa..b7c23d3 100644
|
|
||||||
--- a/src/conf/domain_conf.c
|
|
||||||
+++ b/src/conf/domain_conf.c
|
|
||||||
@@ -7103,7 +7103,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)
|
|
||||||
@@ -30121,6 +30122,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 5a9bf20..05058b8 100644
|
|
||||||
--- a/src/conf/domain_validate.c
|
|
||||||
+++ b/src/conf/domain_validate.c
|
|
||||||
@@ -494,6 +494,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:
|
|
||||||
@@ -541,7 +542,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) {
|
|
||||||
@@ -550,11 +551,15 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
|
|
||||||
"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"));
|
|
||||||
+ "only with 'rbd' and 'vitastor' disks"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
|
|
||||||
index 6cb0a20..8bf7de9 100644
|
|
||||||
--- a/src/conf/schemas/domaincommon.rng
|
|
||||||
+++ b/src/conf/schemas/domaincommon.rng
|
|
||||||
@@ -1972,6 +1972,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">
|
|
||||||
@@ -2264,6 +2293,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 f5a9636..8339bc4 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 |
|
|
||||||
@@ -542,6 +554,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;
|
|
||||||
@@ -1132,6 +1149,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 fc67957..720c07e 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 cecd7e8..d7b79a4 100644
|
|
||||||
--- a/src/conf/storage_source_conf.c
|
|
||||||
+++ b/src/conf/storage_source_conf.c
|
|
||||||
@@ -87,6 +87,7 @@ VIR_ENUM_IMPL(virStorageNetProtocol,
|
|
||||||
"ssh",
|
|
||||||
"vxhs",
|
|
||||||
"nfs",
|
|
||||||
+ "vitastor",
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1286,6 +1287,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 14a6825..eb4acac 100644
|
|
||||||
--- a/src/conf/storage_source_conf.h
|
|
||||||
+++ b/src/conf/storage_source_conf.h
|
|
||||||
@@ -128,6 +128,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 e6c187e..035b423 100644
|
|
||||||
--- a/src/conf/virstorageobj.c
|
|
||||||
+++ b/src/conf/virstorageobj.c
|
|
||||||
@@ -1433,6 +1433,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:
|
|
||||||
@@ -1918,6 +1919,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 8490034..ab2cdaa 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 17ac880..59711b5 100644
|
|
||||||
--- a/src/libxl/libxl_conf.c
|
|
||||||
+++ b/src/libxl/libxl_conf.c
|
|
||||||
@@ -970,6 +970,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 6919325..55ffc32 100644
|
|
||||||
--- a/src/libxl/xen_xl.c
|
|
||||||
+++ b/src/libxl/xen_xl.c
|
|
||||||
@@ -1445,6 +1445,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 e865aa1..40162af 100644
|
|
||||||
--- a/src/qemu/qemu_block.c
|
|
||||||
+++ b/src/qemu/qemu_block.c
|
|
||||||
@@ -604,6 +604,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 *
|
|
||||||
qemuBlockStorageSourceGetSheepdogProps(virStorageSource *src)
|
|
||||||
{
|
|
||||||
@@ -917,6 +949,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_SHEEPDOG:
|
|
||||||
driver = "sheepdog";
|
|
||||||
if (!(fileprops = qemuBlockStorageSourceGetSheepdogProps(src)))
|
|
||||||
@@ -1860,6 +1898,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:
|
|
||||||
@@ -2242,6 +2281,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_SHEEPDOG:
|
|
||||||
driver = "sheepdog";
|
|
||||||
if (!(location = qemuBlockStorageSourceGetSheepdogProps(src)))
|
|
||||||
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
||||||
index 2eb5653..60ee82d 100644
|
|
||||||
--- a/src/qemu/qemu_domain.c
|
|
||||||
+++ b/src/qemu/qemu_domain.c
|
|
||||||
@@ -4958,7 +4958,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;
|
|
||||||
@@ -10129,6 +10130,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 b841680..a6be771 100644
|
|
||||||
--- a/src/qemu/qemu_snapshot.c
|
|
||||||
+++ b/src/qemu/qemu_snapshot.c
|
|
||||||
@@ -373,6 +373,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:
|
|
||||||
@@ -578,6 +579,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 d90c1c9..e853457 100644
|
|
||||||
--- a/src/storage/storage_driver.c
|
|
||||||
+++ b/src/storage/storage_driver.c
|
|
||||||
@@ -1627,6 +1627,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 e48ae72..2017ccc 100644
|
|
||||||
--- a/src/storage_file/storage_source_backingstore.c
|
|
||||||
+++ b/src/storage_file/storage_source_backingstore.c
|
|
||||||
@@ -284,6 +284,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)
|
|
||||||
@@ -396,6 +465,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:
|
|
||||||
@@ -984,6 +1058,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,
|
|
||||||
@@ -1162,6 +1284,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 bd6f063..cce34e1 100644
|
|
||||||
--- a/src/test/test_driver.c
|
|
||||||
+++ b/src/test/test_driver.c
|
|
||||||
@@ -7338,6 +7338,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 eee75af..8bd0a57 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 805950a..852df0d 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 e8e40d6..db55fe5 100644
|
|
||||||
--- a/tests/storagepoolxml2argvtest.c
|
|
||||||
+++ b/tests/storagepoolxml2argvtest.c
|
|
||||||
@@ -65,6 +65,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 8a98c6a..4b1bbd4 100644
|
|
||||||
--- a/tools/virsh-pool.c
|
|
||||||
+++ b/tools/virsh-pool.c
|
|
||||||
@@ -1221,6 +1221,9 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
|
|
||||||
case VIR_STORAGE_POOL_VSTORAGE:
|
|
||||||
flags |= VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE;
|
|
||||||
break;
|
|
||||||
+ case VIR_STORAGE_POOL_VITASTOR:
|
|
||||||
+ flags |= VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR;
|
|
||||||
+ break;
|
|
||||||
case VIR_STORAGE_POOL_LAST:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
diff --git a/block/meson.build b/block/meson.build
|
|
||||||
index 382bec0e7d..af6207dbce 100644
|
|
||||||
--- a/block/meson.build
|
|
||||||
+++ b/block/meson.build
|
|
||||||
@@ -114,6 +114,7 @@ foreach m : [
|
|
||||||
[libnfs, 'nfs', files('nfs.c')],
|
|
||||||
[libssh, 'ssh', files('ssh.c')],
|
|
||||||
[rbd, 'rbd', files('rbd.c')],
|
|
||||||
+ [vitastor, 'vitastor', files('vitastor.c')],
|
|
||||||
]
|
|
||||||
if m[0].found()
|
|
||||||
module_ss = ss.source_set()
|
|
||||||
diff --git a/meson.build b/meson.build
|
|
||||||
index c44d05a13f..ebedb42843 100644
|
|
||||||
--- a/meson.build
|
|
||||||
+++ b/meson.build
|
|
||||||
@@ -1028,6 +1028,26 @@ if not get_option('rbd').auto() or have_block
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
+vitastor = not_found
|
|
||||||
+if not get_option('vitastor').auto() or have_block
|
|
||||||
+ libvitastor_client = cc.find_library('vitastor_client', has_headers: ['vitastor_c.h'],
|
|
||||||
+ required: get_option('vitastor'), kwargs: static_kwargs)
|
|
||||||
+ if libvitastor_client.found()
|
|
||||||
+ if cc.links('''
|
|
||||||
+ #include <vitastor_c.h>
|
|
||||||
+ int main(void) {
|
|
||||||
+ vitastor_c_create_qemu(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
||||||
+ return 0;
|
|
||||||
+ }''', dependencies: libvitastor_client)
|
|
||||||
+ vitastor = declare_dependency(dependencies: libvitastor_client)
|
|
||||||
+ elif get_option('vitastor').enabled()
|
|
||||||
+ error('could not link libvitastor_client')
|
|
||||||
+ else
|
|
||||||
+ warning('could not link libvitastor_client, disabling')
|
|
||||||
+ endif
|
|
||||||
+ endif
|
|
||||||
+endif
|
|
||||||
+
|
|
||||||
glusterfs = not_found
|
|
||||||
glusterfs_ftruncate_has_stat = false
|
|
||||||
glusterfs_iocb_has_stat = false
|
|
||||||
@@ -1882,6 +1902,7 @@ endif
|
|
||||||
config_host_data.set('CONFIG_OPENGL', opengl.found())
|
|
||||||
config_host_data.set('CONFIG_PROFILER', get_option('profiler'))
|
|
||||||
config_host_data.set('CONFIG_RBD', rbd.found())
|
|
||||||
+config_host_data.set('CONFIG_VITASTOR', vitastor.found())
|
|
||||||
config_host_data.set('CONFIG_RDMA', rdma.found())
|
|
||||||
config_host_data.set('CONFIG_SDL', sdl.found())
|
|
||||||
config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found())
|
|
||||||
@@ -4020,6 +4041,7 @@ if spice_protocol.found()
|
|
||||||
summary_info += {' spice server support': spice}
|
|
||||||
endif
|
|
||||||
summary_info += {'rbd support': rbd}
|
|
||||||
+summary_info += {'vitastor support': vitastor}
|
|
||||||
summary_info += {'smartcard support': cacard}
|
|
||||||
summary_info += {'U2F support': u2f}
|
|
||||||
summary_info += {'libusb': libusb}
|
|
||||||
diff --git a/meson_options.txt b/meson_options.txt
|
|
||||||
index fc9447d267..c4ac55c283 100644
|
|
||||||
--- a/meson_options.txt
|
|
||||||
+++ b/meson_options.txt
|
|
||||||
@@ -173,6 +173,8 @@ option('lzo', type : 'feature', value : 'auto',
|
|
||||||
description: 'lzo compression support')
|
|
||||||
option('rbd', type : 'feature', value : 'auto',
|
|
||||||
description: 'Ceph block device driver')
|
|
||||||
+option('vitastor', type : 'feature', value : 'auto',
|
|
||||||
+ description: 'Vitastor block device driver')
|
|
||||||
option('opengl', type : 'feature', value : 'auto',
|
|
||||||
description: 'OpenGL support')
|
|
||||||
option('rdma', type : 'feature', value : 'auto',
|
|
||||||
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
|
||||||
index c05ad0c07e..f5eb701604 100644
|
|
||||||
--- a/qapi/block-core.json
|
|
||||||
+++ b/qapi/block-core.json
|
|
||||||
@@ -3308,7 +3308,7 @@
|
|
||||||
'raw', 'rbd',
|
|
||||||
{ 'name': 'replication', 'if': 'CONFIG_REPLICATION' },
|
|
||||||
'pbs',
|
|
||||||
- 'ssh', 'throttle', 'vdi', 'vhdx',
|
|
||||||
+ 'ssh', 'throttle', 'vdi', 'vhdx', 'vitastor',
|
|
||||||
{ 'name': 'virtio-blk-vfio-pci', 'if': 'CONFIG_BLKIO' },
|
|
||||||
{ 'name': 'virtio-blk-vhost-user', 'if': 'CONFIG_BLKIO' },
|
|
||||||
{ 'name': 'virtio-blk-vhost-vdpa', 'if': 'CONFIG_BLKIO' },
|
|
||||||
@@ -4338,6 +4338,28 @@
|
|
||||||
'*key-secret': 'str',
|
|
||||||
'*server': ['InetSocketAddressBase'] } }
|
|
||||||
|
|
||||||
+##
|
|
||||||
+# @BlockdevOptionsVitastor:
|
|
||||||
+#
|
|
||||||
+# Driver specific block device options for vitastor
|
|
||||||
+#
|
|
||||||
+# @image: Image name
|
|
||||||
+# @inode: Inode number
|
|
||||||
+# @pool: Pool ID
|
|
||||||
+# @size: Desired image size in bytes
|
|
||||||
+# @config-path: Path to Vitastor configuration
|
|
||||||
+# @etcd-host: etcd connection address(es)
|
|
||||||
+# @etcd-prefix: etcd key/value prefix
|
|
||||||
+##
|
|
||||||
+{ 'struct': 'BlockdevOptionsVitastor',
|
|
||||||
+ 'data': { '*inode': 'uint64',
|
|
||||||
+ '*pool': 'uint64',
|
|
||||||
+ '*size': 'uint64',
|
|
||||||
+ '*image': 'str',
|
|
||||||
+ '*config-path': 'str',
|
|
||||||
+ '*etcd-host': 'str',
|
|
||||||
+ '*etcd-prefix': 'str' } }
|
|
||||||
+
|
|
||||||
##
|
|
||||||
# @ReplicationMode:
|
|
||||||
#
|
|
||||||
@@ -4787,6 +4809,7 @@
|
|
||||||
'throttle': 'BlockdevOptionsThrottle',
|
|
||||||
'vdi': 'BlockdevOptionsGenericFormat',
|
|
||||||
'vhdx': 'BlockdevOptionsGenericFormat',
|
|
||||||
+ 'vitastor': 'BlockdevOptionsVitastor',
|
|
||||||
'virtio-blk-vfio-pci':
|
|
||||||
{ 'type': 'BlockdevOptionsVirtioBlkVfioPci',
|
|
||||||
'if': 'CONFIG_BLKIO' },
|
|
||||||
@@ -5187,6 +5210,17 @@
|
|
||||||
'*cluster-size' : 'size',
|
|
||||||
'*encrypt' : 'RbdEncryptionCreateOptions' } }
|
|
||||||
|
|
||||||
+##
|
|
||||||
+# @BlockdevCreateOptionsVitastor:
|
|
||||||
+#
|
|
||||||
+# Driver specific image creation options for Vitastor.
|
|
||||||
+#
|
|
||||||
+# @size: Size of the virtual disk in bytes
|
|
||||||
+##
|
|
||||||
+{ 'struct': 'BlockdevCreateOptionsVitastor',
|
|
||||||
+ 'data': { 'location': 'BlockdevOptionsVitastor',
|
|
||||||
+ 'size': 'size' } }
|
|
||||||
+
|
|
||||||
##
|
|
||||||
# @BlockdevVmdkSubformat:
|
|
||||||
#
|
|
||||||
@@ -5385,6 +5419,7 @@
|
|
||||||
'ssh': 'BlockdevCreateOptionsSsh',
|
|
||||||
'vdi': 'BlockdevCreateOptionsVdi',
|
|
||||||
'vhdx': 'BlockdevCreateOptionsVhdx',
|
|
||||||
+ 'vitastor': 'BlockdevCreateOptionsVitastor',
|
|
||||||
'vmdk': 'BlockdevCreateOptionsVmdk',
|
|
||||||
'vpc': 'BlockdevCreateOptionsVpc'
|
|
||||||
} }
|
|
||||||
diff --git a/scripts/ci/org.centos/stream/8/x86_64/configure b/scripts/ci/org.centos/stream/8/x86_64/configure
|
|
||||||
index 6e8983f39c..1b0b9fcf3e 100755
|
|
||||||
--- a/scripts/ci/org.centos/stream/8/x86_64/configure
|
|
||||||
+++ b/scripts/ci/org.centos/stream/8/x86_64/configure
|
|
||||||
@@ -32,7 +32,7 @@
|
|
||||||
--with-git=meson \
|
|
||||||
--with-git-submodules=update \
|
|
||||||
--target-list="x86_64-softmmu" \
|
|
||||||
---block-drv-rw-whitelist="qcow2,raw,file,host_device,nbd,iscsi,rbd,blkdebug,luks,null-co,nvme,copy-on-read,throttle,gluster" \
|
|
||||||
+--block-drv-rw-whitelist="qcow2,raw,file,host_device,nbd,iscsi,rbd,vitastor,blkdebug,luks,null-co,nvme,copy-on-read,throttle,gluster" \
|
|
||||||
--audio-drv-list="" \
|
|
||||||
--block-drv-ro-whitelist="vmdk,vhdx,vpc,https,ssh" \
|
|
||||||
--with-coroutine=ucontext \
|
|
||||||
@@ -179,6 +179,7 @@
|
|
||||||
--enable-opengl \
|
|
||||||
--enable-pie \
|
|
||||||
--enable-rbd \
|
|
||||||
+--enable-vitastor \
|
|
||||||
--enable-rdma \
|
|
||||||
--enable-seccomp \
|
|
||||||
--enable-snappy \
|
|
||||||
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
|
|
||||||
index 009fab1515..95914e6ebc 100644
|
|
||||||
--- a/scripts/meson-buildoptions.sh
|
|
||||||
+++ b/scripts/meson-buildoptions.sh
|
|
||||||
@@ -144,6 +144,7 @@ meson_options_help() {
|
|
||||||
printf "%s\n" ' qed qed image format support'
|
|
||||||
printf "%s\n" ' qga-vss build QGA VSS support (broken with MinGW)'
|
|
||||||
printf "%s\n" ' rbd Ceph block device driver'
|
|
||||||
+ printf "%s\n" ' vitastor Vitastor block device driver'
|
|
||||||
printf "%s\n" ' rdma Enable RDMA-based migration'
|
|
||||||
printf "%s\n" ' replication replication support'
|
|
||||||
printf "%s\n" ' sdl SDL user interface'
|
|
||||||
@@ -392,6 +393,8 @@ _meson_option_parse() {
|
|
||||||
--disable-qom-cast-debug) printf "%s" -Dqom_cast_debug=false ;;
|
|
||||||
--enable-rbd) printf "%s" -Drbd=enabled ;;
|
|
||||||
--disable-rbd) printf "%s" -Drbd=disabled ;;
|
|
||||||
+ --enable-vitastor) printf "%s" -Dvitastor=enabled ;;
|
|
||||||
+ --disable-vitastor) printf "%s" -Dvitastor=disabled ;;
|
|
||||||
--enable-rdma) printf "%s" -Drdma=enabled ;;
|
|
||||||
--disable-rdma) printf "%s" -Drdma=disabled ;;
|
|
||||||
--enable-replication) printf "%s" -Dreplication=enabled ;;
|
|
||||||
@@ -24,4 +24,4 @@ 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-el$EL.spec
|
||||||
tar --transform 's#^#vitastor-0.9.2/#' --exclude 'rpm/*.rpm' -czf $VITASTOR/../vitastor-0.9.2$(rpm --eval '%dist').tar.gz *
|
tar --transform 's#^#vitastor-0.9.0/#' --exclude 'rpm/*.rpm' -czf $VITASTOR/../vitastor-0.9.0$(rpm --eval '%dist').tar.gz *
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ ADD . /root/vitastor
|
|||||||
RUN set -e; \
|
RUN set -e; \
|
||||||
cd /root/vitastor/rpm; \
|
cd /root/vitastor/rpm; \
|
||||||
sh build-tarball.sh; \
|
sh build-tarball.sh; \
|
||||||
cp /root/vitastor-0.9.2.el7.tar.gz ~/rpmbuild/SOURCES; \
|
cp /root/vitastor-0.9.0.el7.tar.gz ~/rpmbuild/SOURCES; \
|
||||||
cp vitastor-el7.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
cp vitastor-el7.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
||||||
cd ~/rpmbuild/SPECS/; \
|
cd ~/rpmbuild/SPECS/; \
|
||||||
rpmbuild -ba vitastor.spec; \
|
rpmbuild -ba vitastor.spec; \
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 0.9.2
|
Version: 0.9.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Vitastor, a fast software-defined clustered block storage
|
Summary: Vitastor, a fast software-defined clustered block storage
|
||||||
|
|
||||||
License: Vitastor Network Public License 1.1
|
License: Vitastor Network Public License 1.1
|
||||||
URL: https://vitastor.io/
|
URL: https://vitastor.io/
|
||||||
Source0: vitastor-0.9.2.el7.tar.gz
|
Source0: vitastor-0.9.0.el7.tar.gz
|
||||||
|
|
||||||
BuildRequires: liburing-devel >= 0.6
|
BuildRequires: liburing-devel >= 0.6
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ ADD . /root/vitastor
|
|||||||
RUN set -e; \
|
RUN set -e; \
|
||||||
cd /root/vitastor/rpm; \
|
cd /root/vitastor/rpm; \
|
||||||
sh build-tarball.sh; \
|
sh build-tarball.sh; \
|
||||||
cp /root/vitastor-0.9.2.el8.tar.gz ~/rpmbuild/SOURCES; \
|
cp /root/vitastor-0.9.0.el8.tar.gz ~/rpmbuild/SOURCES; \
|
||||||
cp vitastor-el8.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
cp vitastor-el8.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
||||||
cd ~/rpmbuild/SPECS/; \
|
cd ~/rpmbuild/SPECS/; \
|
||||||
rpmbuild -ba vitastor.spec; \
|
rpmbuild -ba vitastor.spec; \
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 0.9.2
|
Version: 0.9.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Vitastor, a fast software-defined clustered block storage
|
Summary: Vitastor, a fast software-defined clustered block storage
|
||||||
|
|
||||||
License: Vitastor Network Public License 1.1
|
License: Vitastor Network Public License 1.1
|
||||||
URL: https://vitastor.io/
|
URL: https://vitastor.io/
|
||||||
Source0: vitastor-0.9.2.el8.tar.gz
|
Source0: vitastor-0.9.0.el8.tar.gz
|
||||||
|
|
||||||
BuildRequires: liburing-devel >= 0.6
|
BuildRequires: liburing-devel >= 0.6
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ ADD . /root/vitastor
|
|||||||
RUN set -e; \
|
RUN set -e; \
|
||||||
cd /root/vitastor/rpm; \
|
cd /root/vitastor/rpm; \
|
||||||
sh build-tarball.sh; \
|
sh build-tarball.sh; \
|
||||||
cp /root/vitastor-0.9.2.el9.tar.gz ~/rpmbuild/SOURCES; \
|
cp /root/vitastor-0.9.0.el9.tar.gz ~/rpmbuild/SOURCES; \
|
||||||
cp vitastor-el9.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
cp vitastor-el9.spec ~/rpmbuild/SPECS/vitastor.spec; \
|
||||||
cd ~/rpmbuild/SPECS/; \
|
cd ~/rpmbuild/SPECS/; \
|
||||||
rpmbuild -ba vitastor.spec; \
|
rpmbuild -ba vitastor.spec; \
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Name: vitastor
|
Name: vitastor
|
||||||
Version: 0.9.2
|
Version: 0.9.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Vitastor, a fast software-defined clustered block storage
|
Summary: Vitastor, a fast software-defined clustered block storage
|
||||||
|
|
||||||
License: Vitastor Network Public License 1.1
|
License: Vitastor Network Public License 1.1
|
||||||
URL: https://vitastor.io/
|
URL: https://vitastor.io/
|
||||||
Source0: vitastor-0.9.2.el9.tar.gz
|
Source0: vitastor-0.9.0.el9.tar.gz
|
||||||
|
|
||||||
BuildRequires: liburing-devel >= 0.6
|
BuildRequires: liburing-devel >= 0.6
|
||||||
BuildRequires: gperftools-devel
|
BuildRequires: gperftools-devel
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,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(-DVERSION="0.9.2")
|
add_definitions(-DVERSION="0.9.0")
|
||||||
add_definitions(-Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -I ${CMAKE_SOURCE_DIR}/src)
|
add_definitions(-Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -I ${CMAKE_SOURCE_DIR}/src)
|
||||||
if (${WITH_ASAN})
|
if (${WITH_ASAN})
|
||||||
add_definitions(-fsanitize=address -fno-omit-frame-pointer)
|
add_definitions(-fsanitize=address -fno-omit-frame-pointer)
|
||||||
|
|||||||
+38
-43
@@ -675,58 +675,53 @@ resume_1:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
flusher->trimming = true;
|
flusher->trimming = true;
|
||||||
// Recheck the position with the "lock" taken
|
// First update journal "superblock" and only then update <used_start> in memory
|
||||||
new_trim_pos = bs->journal.get_trim_pos();
|
await_sqe(12);
|
||||||
if (new_trim_pos != bs->journal.used_start)
|
*((journal_entry_start*)flusher->journal_superblock) = {
|
||||||
|
.crc32 = 0,
|
||||||
|
.magic = JOURNAL_MAGIC,
|
||||||
|
.type = JE_START,
|
||||||
|
.size = sizeof(journal_entry_start),
|
||||||
|
.reserved = 0,
|
||||||
|
.journal_start = new_trim_pos,
|
||||||
|
.version = JOURNAL_VERSION,
|
||||||
|
};
|
||||||
|
((journal_entry_start*)flusher->journal_superblock)->crc32 = je_crc32((journal_entry*)flusher->journal_superblock);
|
||||||
|
data->iov = (struct iovec){ flusher->journal_superblock, bs->dsk.journal_block_size };
|
||||||
|
data->callback = simple_callback_w;
|
||||||
|
my_uring_prep_writev(sqe, bs->dsk.journal_fd, &data->iov, 1, bs->journal.offset);
|
||||||
|
wait_count++;
|
||||||
|
resume_13:
|
||||||
|
if (wait_count > 0)
|
||||||
{
|
{
|
||||||
// First update journal "superblock" and only then update <used_start> in memory
|
wait_state = 13;
|
||||||
await_sqe(12);
|
return false;
|
||||||
*((journal_entry_start*)flusher->journal_superblock) = {
|
}
|
||||||
.crc32 = 0,
|
if (!bs->disable_journal_fsync)
|
||||||
.magic = JOURNAL_MAGIC,
|
{
|
||||||
.type = JE_START,
|
await_sqe(20);
|
||||||
.size = sizeof(journal_entry_start),
|
my_uring_prep_fsync(sqe, bs->dsk.journal_fd, IORING_FSYNC_DATASYNC);
|
||||||
.reserved = 0,
|
data->iov = { 0 };
|
||||||
.journal_start = new_trim_pos,
|
|
||||||
.version = JOURNAL_VERSION,
|
|
||||||
};
|
|
||||||
((journal_entry_start*)flusher->journal_superblock)->crc32 = je_crc32((journal_entry*)flusher->journal_superblock);
|
|
||||||
data->iov = (struct iovec){ flusher->journal_superblock, bs->dsk.journal_block_size };
|
|
||||||
data->callback = simple_callback_w;
|
data->callback = simple_callback_w;
|
||||||
my_uring_prep_writev(sqe, bs->dsk.journal_fd, &data->iov, 1, bs->journal.offset);
|
resume_21:
|
||||||
wait_count++;
|
|
||||||
resume_13:
|
|
||||||
if (wait_count > 0)
|
if (wait_count > 0)
|
||||||
{
|
{
|
||||||
wait_state = 13;
|
wait_state = 21;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!bs->disable_journal_fsync)
|
|
||||||
{
|
|
||||||
await_sqe(20);
|
|
||||||
my_uring_prep_fsync(sqe, bs->dsk.journal_fd, IORING_FSYNC_DATASYNC);
|
|
||||||
data->iov = { 0 };
|
|
||||||
data->callback = simple_callback_w;
|
|
||||||
resume_21:
|
|
||||||
if (wait_count > 0)
|
|
||||||
{
|
|
||||||
wait_state = 21;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bs->journal.used_start = new_trim_pos;
|
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
|
||||||
printf("Journal trimmed to %08lx (next_free=%08lx)\n", bs->journal.used_start, bs->journal.next_free);
|
|
||||||
#endif
|
|
||||||
if (bs->journal.flush_journal && !flusher->flush_queue.size())
|
|
||||||
{
|
|
||||||
assert(bs->journal.used_start == bs->journal.next_free);
|
|
||||||
printf("Journal flushed\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
bs->journal.used_start = new_trim_pos;
|
||||||
|
#ifdef BLOCKSTORE_DEBUG
|
||||||
|
printf("Journal trimmed to %08lx (next_free=%08lx)\n", bs->journal.used_start, bs->journal.next_free);
|
||||||
|
#endif
|
||||||
flusher->trimming = false;
|
flusher->trimming = false;
|
||||||
}
|
}
|
||||||
|
if (bs->journal.flush_journal && !flusher->flush_queue.size())
|
||||||
|
{
|
||||||
|
assert(bs->journal.used_start == bs->journal.next_free);
|
||||||
|
printf("Journal flushed\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// All done
|
// All done
|
||||||
flusher->active_flushers--;
|
flusher->active_flushers--;
|
||||||
|
|||||||
@@ -790,7 +790,7 @@ int blockstore_init_journal::handle_journal_part(void *buf, uint64_t done_pos, u
|
|||||||
unstab = unstab < ov.version ? ov.version : unstab;
|
unstab = unstab < ov.version ? ov.version : unstab;
|
||||||
if (je->type == JE_SMALL_WRITE_INSTANT)
|
if (je->type == JE_SMALL_WRITE_INSTANT)
|
||||||
{
|
{
|
||||||
bs->mark_stable(ov, true);
|
bs->mark_stable(ov);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -890,7 +890,7 @@ int blockstore_init_journal::handle_journal_part(void *buf, uint64_t done_pos, u
|
|||||||
unstab = unstab < ov.version ? ov.version : unstab;
|
unstab = unstab < ov.version ? ov.version : unstab;
|
||||||
if (je->type == JE_BIG_WRITE_INSTANT)
|
if (je->type == JE_BIG_WRITE_INSTANT)
|
||||||
{
|
{
|
||||||
bs->mark_stable(ov, true);
|
bs->mark_stable(ov);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -904,7 +904,7 @@ int blockstore_init_journal::handle_journal_part(void *buf, uint64_t done_pos, u
|
|||||||
.oid = je->stable.oid,
|
.oid = je->stable.oid,
|
||||||
.version = je->stable.version,
|
.version = je->stable.version,
|
||||||
};
|
};
|
||||||
bs->mark_stable(ov, true);
|
bs->mark_stable(ov);
|
||||||
}
|
}
|
||||||
else if (je->type == JE_ROLLBACK)
|
else if (je->type == JE_ROLLBACK)
|
||||||
{
|
{
|
||||||
@@ -961,7 +961,7 @@ int blockstore_init_journal::handle_journal_part(void *buf, uint64_t done_pos, u
|
|||||||
bs->journal.used_sectors[proc_pos]++;
|
bs->journal.used_sectors[proc_pos]++;
|
||||||
// Deletions are treated as immediately stable, because
|
// Deletions are treated as immediately stable, because
|
||||||
// "2-phase commit" (write->stabilize) isn't sufficient for them anyway
|
// "2-phase commit" (write->stabilize) isn't sufficient for them anyway
|
||||||
bs->mark_stable(ov, true);
|
bs->mark_stable(ov);
|
||||||
}
|
}
|
||||||
// Ignore delete if neither preceding dirty entries nor the clean one are present
|
// Ignore delete if neither preceding dirty entries nor the clean one are present
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,6 +236,14 @@ journal_t::~journal_t()
|
|||||||
uint64_t journal_t::get_trim_pos()
|
uint64_t journal_t::get_trim_pos()
|
||||||
{
|
{
|
||||||
auto journal_used_it = used_sectors.lower_bound(used_start);
|
auto journal_used_it = used_sectors.lower_bound(used_start);
|
||||||
|
#ifdef BLOCKSTORE_DEBUG
|
||||||
|
printf(
|
||||||
|
"Trimming journal (used_start=%08lx, next_free=%08lx, dirty_start=%08lx, new_start=%08lx, new_refcount=%ld)\n",
|
||||||
|
used_start, next_free, dirty_start,
|
||||||
|
journal_used_it == used_sectors.end() ? 0 : journal_used_it->first,
|
||||||
|
journal_used_it == used_sectors.end() ? 0 : journal_used_it->second
|
||||||
|
);
|
||||||
|
#endif
|
||||||
if (journal_used_it == used_sectors.end())
|
if (journal_used_it == used_sectors.end())
|
||||||
{
|
{
|
||||||
// Journal is cleared to its end, restart from the beginning
|
// Journal is cleared to its end, restart from the beginning
|
||||||
@@ -248,26 +256,12 @@ uint64_t journal_t::get_trim_pos()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// next_free does not need updating during trim
|
// next_free does not need updating during trim
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
|
||||||
printf(
|
|
||||||
"Trimming journal (used_start=%08lx, next_free=%08lx, dirty_start=%08lx, new_start=%08lx, new_refcount=%ld)\n",
|
|
||||||
used_start, next_free, dirty_start,
|
|
||||||
journal_used_it->first, journal_used_it->second
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
return journal_used_it->first;
|
return journal_used_it->first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (journal_used_it->first > used_start)
|
else if (journal_used_it->first > used_start)
|
||||||
{
|
{
|
||||||
// Journal is cleared up to <journal_used_it>
|
// Journal is cleared up to <journal_used_it>
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
|
||||||
printf(
|
|
||||||
"Trimming journal (used_start=%08lx, next_free=%08lx, dirty_start=%08lx, new_start=%08lx, new_refcount=%ld)\n",
|
|
||||||
used_start, next_free, dirty_start,
|
|
||||||
journal_used_it->first, journal_used_it->second
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
return journal_used_it->first;
|
return journal_used_it->first;
|
||||||
}
|
}
|
||||||
// Can't trim journal
|
// Can't trim journal
|
||||||
|
|||||||
@@ -138,6 +138,10 @@ int blockstore_impl_t::dequeue_read(blockstore_op_t *read_op)
|
|||||||
{
|
{
|
||||||
dirty_entry& dirty = dirty_it->second;
|
dirty_entry& dirty = dirty_it->second;
|
||||||
bool version_ok = !IS_IN_FLIGHT(dirty.state) && read_op->version >= dirty_it->first.version;
|
bool version_ok = !IS_IN_FLIGHT(dirty.state) && read_op->version >= dirty_it->first.version;
|
||||||
|
if (IS_SYNCED(dirty.state))
|
||||||
|
{
|
||||||
|
version_ok = true;
|
||||||
|
}
|
||||||
if (version_ok)
|
if (version_ok)
|
||||||
{
|
{
|
||||||
if (IS_DELETE(dirty.state))
|
if (IS_DELETE(dirty.state))
|
||||||
|
|||||||
@@ -458,16 +458,6 @@ void blockstore_impl_t::mark_stable(const obj_ver_id & v, bool forget_dirty)
|
|||||||
big_to_flush++;
|
big_to_flush++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IS_IN_FLIGHT(dirty_it->second.state))
|
|
||||||
{
|
|
||||||
// mark_stable should never be called for in-flight or submitted writes
|
|
||||||
printf(
|
|
||||||
"BUG: Attempt to mark_stable object %lx:%lx v%lu state of which is %x\n",
|
|
||||||
dirty_it->first.oid.inode, dirty_it->first.oid.stripe, dirty_it->first.version,
|
|
||||||
dirty_it->second.state
|
|
||||||
);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (forget_dirty && (IS_BIG_WRITE(dirty_it->second.state) ||
|
if (forget_dirty && (IS_BIG_WRITE(dirty_it->second.state) ||
|
||||||
IS_DELETE(dirty_it->second.state)))
|
IS_DELETE(dirty_it->second.state)))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -409,23 +409,7 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op)
|
|||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
// Figure out where data will be
|
// Figure out where data will be
|
||||||
auto next_next_free = (journal.next_free + op->len) <= journal.len ? journal.next_free : dsk.journal_block_size;
|
journal.next_free = (journal.next_free + op->len) <= journal.len ? journal.next_free : dsk.journal_block_size;
|
||||||
if (op->len > 0)
|
|
||||||
{
|
|
||||||
auto journal_used_it = journal.used_sectors.lower_bound(next_next_free);
|
|
||||||
if (journal_used_it != journal.used_sectors.end() &&
|
|
||||||
journal_used_it->first < next_next_free + op->len)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"BUG: Attempt to overwrite used offset (%lx, %lu refs) of the journal with the object %lx:%lx v%lu: data at %lx, len %x!"
|
|
||||||
" Journal used_start=%08lx (%lu refs), next_free=%08lx, dirty_start=%08lx\n",
|
|
||||||
journal_used_it->first, journal_used_it->second, op->oid.inode, op->oid.stripe, op->version, next_next_free, op->len,
|
|
||||||
journal.used_start, journal.used_sectors[journal.used_start], journal.next_free, journal.dirty_start
|
|
||||||
);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
journal.next_free = next_next_free;
|
|
||||||
je->oid = op->oid;
|
je->oid = op->oid;
|
||||||
je->version = op->version;
|
je->version = op->version;
|
||||||
je->offset = op->offset;
|
je->offset = op->offset;
|
||||||
|
|||||||
+6
-7
@@ -41,7 +41,7 @@ struct snap_merger_t
|
|||||||
int fsync_interval = 128;
|
int fsync_interval = 128;
|
||||||
|
|
||||||
// -- STATE --
|
// -- STATE --
|
||||||
inode_t target, to_num;
|
inode_t target;
|
||||||
int target_rank;
|
int target_rank;
|
||||||
bool inside_continue = false;
|
bool inside_continue = false;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
@@ -98,7 +98,6 @@ struct snap_merger_t
|
|||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
to_num = to_cfg->num;
|
|
||||||
// Check that to_cfg is actually a child of from_cfg and target_cfg is somewhere between them
|
// Check that to_cfg is actually a child of from_cfg and target_cfg is somewhere between them
|
||||||
std::vector<inode_t> chain_list;
|
std::vector<inode_t> chain_list;
|
||||||
inode_config_t *cur = to_cfg;
|
inode_config_t *cur = to_cfg;
|
||||||
@@ -452,7 +451,7 @@ struct snap_merger_t
|
|||||||
{
|
{
|
||||||
cluster_op_t *op = &rwo->op;
|
cluster_op_t *op = &rwo->op;
|
||||||
op->opcode = OSD_OP_READ;
|
op->opcode = OSD_OP_READ;
|
||||||
op->inode = to_num;
|
op->inode = target;
|
||||||
op->offset = rwo->offset;
|
op->offset = rwo->offset;
|
||||||
op->len = target_block_size;
|
op->len = target_block_size;
|
||||||
op->iov.push_back(rwo->buf, target_block_size);
|
op->iov.push_back(rwo->buf, target_block_size);
|
||||||
@@ -484,7 +483,7 @@ struct snap_merger_t
|
|||||||
{
|
{
|
||||||
// write start->end
|
// write start->end
|
||||||
rwo->todo++;
|
rwo->todo++;
|
||||||
write_subop(rwo, rwo->start*gran, rwo->end*gran, use_cas && to_num == target ? 1+rwo->op.version : 0);
|
write_subop(rwo, rwo->start*gran, rwo->end*gran, use_cas ? 1+rwo->op.version : 0);
|
||||||
rwo->start = rwo->end;
|
rwo->start = rwo->end;
|
||||||
if (use_cas)
|
if (use_cas)
|
||||||
{
|
{
|
||||||
@@ -503,7 +502,7 @@ struct snap_merger_t
|
|||||||
{
|
{
|
||||||
// write start->end
|
// write start->end
|
||||||
rwo->todo++;
|
rwo->todo++;
|
||||||
write_subop(rwo, rwo->start*gran, rwo->end*gran, use_cas && to_num == target ? 1+rwo->op.version : 0);
|
write_subop(rwo, rwo->start*gran, rwo->end*gran, use_cas ? 1+rwo->op.version : 0);
|
||||||
rwo->start = rwo->end;
|
rwo->start = rwo->end;
|
||||||
if (use_cas)
|
if (use_cas)
|
||||||
{
|
{
|
||||||
@@ -533,7 +532,7 @@ struct snap_merger_t
|
|||||||
if (use_cas && subop->retval == -EINTR)
|
if (use_cas && subop->retval == -EINTR)
|
||||||
{
|
{
|
||||||
// CAS failure - reread and repeat optimistically
|
// CAS failure - reread and repeat optimistically
|
||||||
rwo->start = rwo->end = 0;
|
rwo->start = subop->offset - rwo->offset;
|
||||||
rwo_read(rwo);
|
rwo_read(rwo);
|
||||||
delete subop;
|
delete subop;
|
||||||
return;
|
return;
|
||||||
@@ -543,7 +542,7 @@ struct snap_merger_t
|
|||||||
rwo->error_read = false;
|
rwo->error_read = false;
|
||||||
}
|
}
|
||||||
// Increment CAS version
|
// Increment CAS version
|
||||||
rwo->op.version = subop->version;
|
rwo->op.version++;
|
||||||
if (use_cas)
|
if (use_cas)
|
||||||
next_write(rwo);
|
next_write(rwo);
|
||||||
else
|
else
|
||||||
|
|||||||
+8
-58
@@ -65,9 +65,6 @@ struct snap_remover_t
|
|||||||
int current_child = 0;
|
int current_child = 0;
|
||||||
std::function<bool(cli_result_t &)> cb;
|
std::function<bool(cli_result_t &)> cb;
|
||||||
|
|
||||||
std::vector<std::string> rebased_images, deleted_images;
|
|
||||||
std::vector<uint64_t> deleted_ids;
|
|
||||||
std::string inverse_child_name, inverse_parent_name;
|
|
||||||
cli_result_t result;
|
cli_result_t result;
|
||||||
|
|
||||||
bool is_done()
|
bool is_done()
|
||||||
@@ -125,7 +122,6 @@ resume_1:
|
|||||||
{
|
{
|
||||||
if (merge_children[current_child] == inverse_child)
|
if (merge_children[current_child] == inverse_child)
|
||||||
continue;
|
continue;
|
||||||
rebased_images.push_back(parent->cli->st_cli.inode_config.at(merge_children[current_child]).name);
|
|
||||||
start_merge_child(merge_children[current_child], merge_children[current_child]);
|
start_merge_child(merge_children[current_child], merge_children[current_child]);
|
||||||
if (state == 100)
|
if (state == 100)
|
||||||
return;
|
return;
|
||||||
@@ -138,12 +134,9 @@ resume_2:
|
|||||||
cb = NULL;
|
cb = NULL;
|
||||||
if (result.err)
|
if (result.err)
|
||||||
{
|
{
|
||||||
result.data = my_result(result.data);
|
|
||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (parent->progress)
|
|
||||||
printf("%s\n", result.text.c_str());
|
|
||||||
parent->change_parent(merge_children[current_child], new_parent, &result);
|
parent->change_parent(merge_children[current_child], new_parent, &result);
|
||||||
state = 3;
|
state = 3;
|
||||||
resume_3:
|
resume_3:
|
||||||
@@ -151,7 +144,6 @@ resume_3:
|
|||||||
return;
|
return;
|
||||||
if (result.err)
|
if (result.err)
|
||||||
{
|
{
|
||||||
result.data = my_result(result.data);
|
|
||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -173,12 +165,9 @@ resume_4:
|
|||||||
cb = NULL;
|
cb = NULL;
|
||||||
if (result.err)
|
if (result.err)
|
||||||
{
|
{
|
||||||
result.data = my_result(result.data);
|
|
||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (parent->progress)
|
|
||||||
printf("%s\n", result.text.c_str());
|
|
||||||
// Delete "inverse" child data
|
// Delete "inverse" child data
|
||||||
start_delete_source(inverse_child);
|
start_delete_source(inverse_child);
|
||||||
if (state == 100)
|
if (state == 100)
|
||||||
@@ -192,12 +181,9 @@ resume_5:
|
|||||||
cb = NULL;
|
cb = NULL;
|
||||||
if (result.err)
|
if (result.err)
|
||||||
{
|
{
|
||||||
result.data = my_result(result.data);
|
|
||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (parent->progress)
|
|
||||||
printf("%s\n", result.text.c_str());
|
|
||||||
// Delete "inverse" child metadata, rename parent over it,
|
// Delete "inverse" child metadata, rename parent over it,
|
||||||
// and also change parent links of the previous "inverse" child
|
// and also change parent links of the previous "inverse" child
|
||||||
rename_inverse_parent();
|
rename_inverse_parent();
|
||||||
@@ -213,12 +199,6 @@ resume_6:
|
|||||||
{
|
{
|
||||||
if (chain_list[current_child] == inverse_parent)
|
if (chain_list[current_child] == inverse_parent)
|
||||||
continue;
|
continue;
|
||||||
{
|
|
||||||
auto parent_it = parent->cli->st_cli.inode_config.find(chain_list[current_child]);
|
|
||||||
if (parent_it != parent->cli->st_cli.inode_config.end())
|
|
||||||
deleted_images.push_back(parent_it->second.name);
|
|
||||||
deleted_ids.push_back(chain_list[current_child]);
|
|
||||||
}
|
|
||||||
start_delete_source(chain_list[current_child]);
|
start_delete_source(chain_list[current_child]);
|
||||||
resume_7:
|
resume_7:
|
||||||
while (!cb(result))
|
while (!cb(result))
|
||||||
@@ -229,12 +209,9 @@ resume_7:
|
|||||||
cb = NULL;
|
cb = NULL;
|
||||||
if (result.err)
|
if (result.err)
|
||||||
{
|
{
|
||||||
result.data = my_result(result.data);
|
|
||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (parent->progress)
|
|
||||||
printf("%s\n", result.text.c_str());
|
|
||||||
delete_inode_config(chain_list[current_child]);
|
delete_inode_config(chain_list[current_child]);
|
||||||
if (state == 100)
|
if (state == 100)
|
||||||
return;
|
return;
|
||||||
@@ -244,26 +221,11 @@ resume_8:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state = 100;
|
state = 100;
|
||||||
result = (cli_result_t){
|
|
||||||
.text = "",
|
|
||||||
.data = my_result(result.data),
|
|
||||||
};
|
|
||||||
resume_100:
|
resume_100:
|
||||||
// Done
|
// Done
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
json11::Json my_result(json11::Json src)
|
|
||||||
{
|
|
||||||
auto obj = src.object_items();
|
|
||||||
obj["deleted_ids"] = deleted_ids;
|
|
||||||
obj["deleted_images"] = deleted_images;
|
|
||||||
obj["rebased_images"] = rebased_images;
|
|
||||||
obj["renamed_from"] = inverse_parent_name;
|
|
||||||
obj["renamed_to"] = inverse_child_name;
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_merge_children()
|
void get_merge_children()
|
||||||
{
|
{
|
||||||
// Get all children of from..to
|
// Get all children of from..to
|
||||||
@@ -376,11 +338,7 @@ resume_100:
|
|||||||
}
|
}
|
||||||
for (auto inode_result: data["responses"].array_items())
|
for (auto inode_result: data["responses"].array_items())
|
||||||
{
|
{
|
||||||
if (inode_result["response_range"]["kvs"].array_items().size() == 0)
|
auto kv = parent->cli->st_cli.parse_etcd_kv(inode_result["kvs"][0]);
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto kv = parent->cli->st_cli.parse_etcd_kv(inode_result["response_range"]["kvs"][0]);
|
|
||||||
pool_id_t pool_id = 0;
|
pool_id_t pool_id = 0;
|
||||||
inode_t inode = 0;
|
inode_t inode = 0;
|
||||||
char null_byte = 0;
|
char null_byte = 0;
|
||||||
@@ -419,7 +377,7 @@ resume_100:
|
|||||||
inode_t child = cp.first;
|
inode_t child = cp.first;
|
||||||
uint64_t child_used = inode_used[child];
|
uint64_t child_used = inode_used[child];
|
||||||
int rank = cp.second;
|
int rank = cp.second;
|
||||||
for (int i = chain_list.size()-1-rank; i < chain_list.size(); i++)
|
for (int i = chain_list.size()-rank; i < chain_list.size(); i++)
|
||||||
{
|
{
|
||||||
inode_t parent = chain_list[i];
|
inode_t parent = chain_list[i];
|
||||||
uint64_t parent_used = inode_used[parent];
|
uint64_t parent_used = inode_used[parent];
|
||||||
@@ -455,8 +413,8 @@ resume_100:
|
|||||||
}
|
}
|
||||||
inode_config_t *child_cfg = &child_it->second;
|
inode_config_t *child_cfg = &child_it->second;
|
||||||
inode_config_t *target_cfg = &target_it->second;
|
inode_config_t *target_cfg = &target_it->second;
|
||||||
inverse_child_name = child_cfg->name;
|
std::string child_name = child_cfg->name;
|
||||||
inverse_parent_name = target_cfg->name;
|
std::string target_name = target_cfg->name;
|
||||||
std::string child_cfg_key = base64_encode(
|
std::string child_cfg_key = base64_encode(
|
||||||
parent->cli->st_cli.etcd_prefix+
|
parent->cli->st_cli.etcd_prefix+
|
||||||
"/config/inode/"+std::to_string(INODE_POOL(inverse_child))+
|
"/config/inode/"+std::to_string(INODE_POOL(inverse_child))+
|
||||||
@@ -467,9 +425,6 @@ resume_100:
|
|||||||
"/config/inode/"+std::to_string(INODE_POOL(inverse_parent))+
|
"/config/inode/"+std::to_string(INODE_POOL(inverse_parent))+
|
||||||
"/"+std::to_string(INODE_NO_POOL(inverse_parent))
|
"/"+std::to_string(INODE_NO_POOL(inverse_parent))
|
||||||
);
|
);
|
||||||
std::string target_idx_key = base64_encode(
|
|
||||||
parent->cli->st_cli.etcd_prefix+"/index/image/"+inverse_parent_name
|
|
||||||
);
|
|
||||||
// Fill new configuration
|
// Fill new configuration
|
||||||
inode_config_t new_cfg = *child_cfg;
|
inode_config_t new_cfg = *child_cfg;
|
||||||
new_cfg.num = target_cfg->num;
|
new_cfg.num = target_cfg->num;
|
||||||
@@ -494,11 +449,6 @@ resume_100:
|
|||||||
{ "key", child_cfg_key },
|
{ "key", child_cfg_key },
|
||||||
} },
|
} },
|
||||||
},
|
},
|
||||||
json11::Json::object {
|
|
||||||
{ "request_delete_range", json11::Json::object {
|
|
||||||
{ "key", target_idx_key },
|
|
||||||
} },
|
|
||||||
},
|
|
||||||
json11::Json::object {
|
json11::Json::object {
|
||||||
{ "request_put", json11::Json::object {
|
{ "request_put", json11::Json::object {
|
||||||
{ "key", target_cfg_key },
|
{ "key", target_cfg_key },
|
||||||
@@ -545,12 +495,12 @@ resume_100:
|
|||||||
parent->cli->st_cli.etcd_txn_slow(json11::Json::object {
|
parent->cli->st_cli.etcd_txn_slow(json11::Json::object {
|
||||||
{ "compare", cmp },
|
{ "compare", cmp },
|
||||||
{ "success", txn },
|
{ "success", txn },
|
||||||
}, [this](std::string err, json11::Json res)
|
}, [this, target_name, child_name](std::string err, json11::Json res)
|
||||||
{
|
{
|
||||||
parent->waiting--;
|
parent->waiting--;
|
||||||
if (err != "")
|
if (err != "")
|
||||||
{
|
{
|
||||||
result = (cli_result_t){ .err = EIO, .text = "Error renaming "+inverse_parent_name+" to "+inverse_child_name+": "+err };
|
result = (cli_result_t){ .err = EIO, .text = "Error renaming "+target_name+" to "+child_name+": "+err };
|
||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -558,14 +508,14 @@ resume_100:
|
|||||||
{
|
{
|
||||||
result = (cli_result_t){
|
result = (cli_result_t){
|
||||||
.err = EAGAIN,
|
.err = EAGAIN,
|
||||||
.text = "Parent ("+inverse_parent_name+"), child ("+inverse_child_name+"), or one of its children"
|
.text = "Parent ("+target_name+"), child ("+child_name+"), or one of its children"
|
||||||
" configuration was modified during rename",
|
" configuration was modified during rename",
|
||||||
};
|
};
|
||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent->progress)
|
if (parent->progress)
|
||||||
printf("Layer %s renamed to %s\n", inverse_parent_name.c_str(), inverse_child_name.c_str());
|
printf("Layer %s renamed to %s\n", target_name.c_str(), child_name.c_str());
|
||||||
parent->ringloop->wakeup();
|
parent->ringloop->wakeup();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-29
@@ -28,7 +28,6 @@ struct rm_inode_t
|
|||||||
cli_tool_t *parent = NULL;
|
cli_tool_t *parent = NULL;
|
||||||
inode_list_t *lister = NULL;
|
inode_list_t *lister = NULL;
|
||||||
std::vector<rm_pg_t*> lists;
|
std::vector<rm_pg_t*> lists;
|
||||||
std::vector<osd_num_t> inactive_osds;
|
|
||||||
uint64_t total_count = 0, total_done = 0, total_prev_pct = 0;
|
uint64_t total_count = 0, total_done = 0, total_prev_pct = 0;
|
||||||
uint64_t pgs_to_list = 0;
|
uint64_t pgs_to_list = 0;
|
||||||
bool lists_done = false;
|
bool lists_done = false;
|
||||||
@@ -87,16 +86,6 @@ struct rm_inode_t
|
|||||||
state = 100;
|
state = 100;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inactive_osds = parent->cli->list_inode_get_inactive_osds(lister);
|
|
||||||
if (inactive_osds.size() && !parent->json_output)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Some data may remain after delete on OSDs which are currently down: ");
|
|
||||||
for (int i = 0; i < inactive_osds.size(); i++)
|
|
||||||
{
|
|
||||||
fprintf(stderr, i > 0 ? ", %lu" : "%lu", inactive_osds[i]);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
pgs_to_list = parent->cli->list_pg_count(lister);
|
pgs_to_list = parent->cli->list_pg_count(lister);
|
||||||
parent->cli->list_inode_next(lister, parent->parallel_osds);
|
parent->cli->list_inode_next(lister, parent->parallel_osds);
|
||||||
}
|
}
|
||||||
@@ -178,33 +167,16 @@ struct rm_inode_t
|
|||||||
}
|
}
|
||||||
if (parent->progress && total_count > 0 && total_done*1000/total_count != total_prev_pct)
|
if (parent->progress && total_count > 0 && total_done*1000/total_count != total_prev_pct)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\rRemoved %lu/%lu objects, %lu more PGs to list...", total_done, total_count, pgs_to_list);
|
printf("\rRemoved %lu/%lu objects, %lu more PGs to list...", total_done, total_count, pgs_to_list);
|
||||||
total_prev_pct = total_done*1000/total_count;
|
total_prev_pct = total_done*1000/total_count;
|
||||||
}
|
}
|
||||||
if (lists_done && !lists.size())
|
if (lists_done && !lists.size())
|
||||||
{
|
{
|
||||||
if (parent->progress && total_count > 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
if (parent->progress && (total_done < total_count || inactive_osds.size() > 0))
|
|
||||||
{
|
|
||||||
fprintf(
|
|
||||||
stderr, "Warning: Pool:%u,ID:%lu inode data may not have been fully removed.\n"
|
|
||||||
" Use `vitastor-cli rm-data --pool %u --inode %lu` if you encounter it in listings.\n",
|
|
||||||
pool_id, INODE_NO_POOL(inode), pool_id, INODE_NO_POOL(inode)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
result = (cli_result_t){
|
result = (cli_result_t){
|
||||||
.err = error_count > 0 ? EIO : 0,
|
.err = error_count > 0 ? EIO : 0,
|
||||||
.text = error_count > 0 ? "Some blocks were not removed" : (
|
.text = error_count > 0 ? "Some blocks were not removed" : (
|
||||||
"Done, inode "+std::to_string(INODE_NO_POOL(inode))+" from pool "+
|
"Done, inode "+std::to_string(INODE_NO_POOL(inode))+" from pool "+
|
||||||
std::to_string(pool_id)+" removed"),
|
std::to_string(pool_id)+" removed"),
|
||||||
.data = json11::Json::object {
|
|
||||||
{ "removed_objects", total_done },
|
|
||||||
{ "total_objects", total_count },
|
|
||||||
{ "inactive_osds", inactive_osds },
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
state = 100;
|
state = 100;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-18
@@ -12,7 +12,7 @@ static const char *obj_states[] = { "clean", "misplaced", "degraded", "incomplet
|
|||||||
// Print cluster status:
|
// Print cluster status:
|
||||||
// etcd, mon, osd states
|
// etcd, mon, osd states
|
||||||
// raw/used space, object states, pool states, pg states
|
// raw/used space, object states, pool states, pg states
|
||||||
// client io, recovery io, rebalance io, scrub io
|
// client io, recovery io, rebalance io
|
||||||
struct status_printer_t
|
struct status_printer_t
|
||||||
{
|
{
|
||||||
cli_tool_t *parent;
|
cli_tool_t *parent;
|
||||||
@@ -252,25 +252,18 @@ resume_2:
|
|||||||
}
|
}
|
||||||
more_states.resize(more_states.size()-2);
|
more_states.resize(more_states.size()-2);
|
||||||
std::string recovery_io;
|
std::string recovery_io;
|
||||||
int io_indent = 0;
|
|
||||||
{
|
{
|
||||||
uint64_t deg_bps = agg_stats["recovery_stats"]["degraded"]["bps"].uint64_value();
|
uint64_t deg_bps = agg_stats["recovery_stats"]["degraded"]["bps"].uint64_value();
|
||||||
uint64_t deg_iops = agg_stats["recovery_stats"]["degraded"]["iops"].uint64_value();
|
uint64_t deg_iops = agg_stats["recovery_stats"]["degraded"]["iops"].uint64_value();
|
||||||
uint64_t misp_bps = agg_stats["recovery_stats"]["misplaced"]["bps"].uint64_value();
|
uint64_t misp_bps = agg_stats["recovery_stats"]["misplaced"]["bps"].uint64_value();
|
||||||
uint64_t misp_iops = agg_stats["recovery_stats"]["misplaced"]["iops"].uint64_value();
|
uint64_t misp_iops = agg_stats["recovery_stats"]["misplaced"]["iops"].uint64_value();
|
||||||
uint64_t scrub_bps = agg_stats["op_stats"]["scrub"]["bps"].uint64_value();
|
|
||||||
uint64_t scrub_iops = agg_stats["op_stats"]["scrub"]["iops"].uint64_value();
|
|
||||||
if (misp_iops > 0 || misp_bps > 0 || no_rebalance)
|
|
||||||
io_indent = 3;
|
|
||||||
else if (deg_iops > 0 || deg_bps > 0 || no_recovery)
|
|
||||||
io_indent = 2;
|
|
||||||
if (deg_iops > 0 || deg_bps > 0)
|
if (deg_iops > 0 || deg_bps > 0)
|
||||||
{
|
{
|
||||||
recovery_io += " recovery: "+str_repeat(" ", io_indent-2)+std::string(no_recovery ? "disabled, " : "")+
|
recovery_io += " recovery: "+std::string(no_recovery ? "disabled, " : "")+
|
||||||
format_size(deg_bps)+"/s, "+format_size(deg_iops, true)+" op/s\n";
|
format_size(deg_bps)+"/s, "+format_size(deg_iops, true)+" op/s\n";
|
||||||
}
|
}
|
||||||
else if (no_recovery)
|
else if (no_recovery)
|
||||||
recovery_io += " recovery: disabled\n";
|
recovery_io += " recovery: disabled\n";
|
||||||
if (misp_iops > 0 || misp_bps > 0)
|
if (misp_iops > 0 || misp_bps > 0)
|
||||||
{
|
{
|
||||||
recovery_io += " rebalance: "+std::string(no_rebalance ? "disabled, " : "")+
|
recovery_io += " rebalance: "+std::string(no_rebalance ? "disabled, " : "")+
|
||||||
@@ -278,13 +271,6 @@ resume_2:
|
|||||||
}
|
}
|
||||||
else if (no_rebalance)
|
else if (no_rebalance)
|
||||||
recovery_io += " rebalance: disabled\n";
|
recovery_io += " rebalance: disabled\n";
|
||||||
if (scrub_iops > 0 || scrub_bps > 0)
|
|
||||||
{
|
|
||||||
recovery_io += " scrub: "+str_repeat(" ", io_indent+1)+std::string(no_scrub ? "disabled, " : "")+
|
|
||||||
format_size(scrub_bps)+"/s, "+format_size(scrub_iops, true)+" op/s\n";
|
|
||||||
}
|
|
||||||
else if (no_scrub)
|
|
||||||
recovery_io += " scrub: "+str_repeat(" ", io_indent+1)+"disabled\n";
|
|
||||||
}
|
}
|
||||||
printf(
|
printf(
|
||||||
" cluster:\n"
|
" cluster:\n"
|
||||||
@@ -312,7 +298,7 @@ resume_2:
|
|||||||
pools_active, pool_count,
|
pools_active, pool_count,
|
||||||
pgs_by_state_str.c_str(),
|
pgs_by_state_str.c_str(),
|
||||||
readonly ? " (read-only mode)" : "",
|
readonly ? " (read-only mode)" : "",
|
||||||
str_repeat(" ", io_indent).c_str(),
|
recovery_io.size() > 0 ? " " : "",
|
||||||
format_size(agg_stats["op_stats"]["primary_read"]["bps"].uint64_value()).c_str(),
|
format_size(agg_stats["op_stats"]["primary_read"]["bps"].uint64_value()).c_str(),
|
||||||
format_size(agg_stats["op_stats"]["primary_read"]["iops"].uint64_value(), true).c_str(),
|
format_size(agg_stats["op_stats"]["primary_read"]["iops"].uint64_value(), true).c_str(),
|
||||||
format_size(agg_stats["op_stats"]["primary_write"]["bps"].uint64_value()).c_str(),
|
format_size(agg_stats["op_stats"]["primary_write"]["bps"].uint64_value()).c_str(),
|
||||||
|
|||||||
@@ -1209,10 +1209,6 @@ void cluster_client_t::handle_op_part(cluster_op_part_t *part)
|
|||||||
copy_part_bitmap(op, part);
|
copy_part_bitmap(op, part);
|
||||||
op->version = op->parts.size() == 1 ? part->op.reply.rw.version : 0;
|
op->version = op->parts.size() == 1 ? part->op.reply.rw.version : 0;
|
||||||
}
|
}
|
||||||
else if (op->opcode == OSD_OP_WRITE)
|
|
||||||
{
|
|
||||||
op->version = op->parts.size() == 1 ? part->op.reply.rw.version : 0;
|
|
||||||
}
|
|
||||||
if (op->inflight_count == 0)
|
if (op->inflight_count == 0)
|
||||||
{
|
{
|
||||||
if (op->opcode == OSD_OP_SYNC)
|
if (op->opcode == OSD_OP_SYNC)
|
||||||
|
|||||||
@@ -130,7 +130,6 @@ public:
|
|||||||
inode_list_t *list_inode_start(inode_t inode,
|
inode_list_t *list_inode_start(inode_t inode,
|
||||||
std::function<void(inode_list_t* lst, std::set<object_id>&& objects, pg_num_t pg_num, osd_num_t primary_osd, int status)> callback);
|
std::function<void(inode_list_t* lst, std::set<object_id>&& objects, pg_num_t pg_num, osd_num_t primary_osd, int status)> callback);
|
||||||
int list_pg_count(inode_list_t *lst);
|
int list_pg_count(inode_list_t *lst);
|
||||||
const std::vector<osd_num_t> & list_inode_get_inactive_osds(inode_list_t *lst);
|
|
||||||
void list_inode_next(inode_list_t *lst, int next_pgs);
|
void list_inode_next(inode_list_t *lst, int next_pgs);
|
||||||
//inline uint32_t get_bs_bitmap_granularity() { return st_cli.global_bitmap_granularity; }
|
//inline uint32_t get_bs_bitmap_granularity() { return st_cli.global_bitmap_granularity; }
|
||||||
//inline uint64_t get_bs_block_size() { return st_cli.global_block_size; }
|
//inline uint64_t get_bs_block_size() { return st_cli.global_block_size; }
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ struct inode_list_t
|
|||||||
inode_t inode = 0;
|
inode_t inode = 0;
|
||||||
int done_pgs = 0;
|
int done_pgs = 0;
|
||||||
int want = 0;
|
int want = 0;
|
||||||
std::vector<osd_num_t> inactive_osds;
|
|
||||||
std::vector<inode_list_pg_t*> pgs;
|
std::vector<inode_list_pg_t*> pgs;
|
||||||
std::function<void(inode_list_t* lst, std::set<object_id>&& objects, pg_num_t pg_num, osd_num_t primary_osd, int status)> callback;
|
std::function<void(inode_list_t* lst, std::set<object_id>&& objects, pg_num_t pg_num, osd_num_t primary_osd, int status)> callback;
|
||||||
};
|
};
|
||||||
@@ -61,7 +60,6 @@ inode_list_t* cluster_client_t::list_inode_start(inode_t inode,
|
|||||||
lst->inode = inode;
|
lst->inode = inode;
|
||||||
lst->callback = callback;
|
lst->callback = callback;
|
||||||
auto pool_cfg = st_cli.pool_config[pool_id];
|
auto pool_cfg = st_cli.pool_config[pool_id];
|
||||||
std::set<osd_num_t> inactive_osd_set;
|
|
||||||
for (auto & pg_item: pool_cfg.pg_config)
|
for (auto & pg_item: pool_cfg.pg_config)
|
||||||
{
|
{
|
||||||
auto & pg = pg_item.second;
|
auto & pg = pg_item.second;
|
||||||
@@ -108,18 +106,11 @@ inode_list_t* cluster_client_t::list_inode_start(inode_t inode,
|
|||||||
}
|
}
|
||||||
for (osd_num_t peer_osd: all_peers)
|
for (osd_num_t peer_osd: all_peers)
|
||||||
{
|
{
|
||||||
if (st_cli.peer_states.find(peer_osd) != st_cli.peer_states.end())
|
r->list_osds.push_back((inode_list_osd_t){
|
||||||
{
|
.pg = r,
|
||||||
r->list_osds.push_back((inode_list_osd_t){
|
.osd_num = peer_osd,
|
||||||
.pg = r,
|
.sent = false,
|
||||||
.osd_num = peer_osd,
|
});
|
||||||
.sent = false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inactive_osd_set.insert(peer_osd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -141,7 +132,6 @@ inode_list_t* cluster_client_t::list_inode_start(inode_t inode,
|
|||||||
{
|
{
|
||||||
lst->pgs[i]->pos = i;
|
lst->pgs[i]->pos = i;
|
||||||
}
|
}
|
||||||
lst->inactive_osds.insert(lst->inactive_osds.end(), inactive_osd_set.begin(), inactive_osd_set.end());
|
|
||||||
lists.push_back(lst);
|
lists.push_back(lst);
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
@@ -151,11 +141,6 @@ int cluster_client_t::list_pg_count(inode_list_t *lst)
|
|||||||
return lst->pgs.size();
|
return lst->pgs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<osd_num_t> & cluster_client_t::list_inode_get_inactive_osds(inode_list_t *lst)
|
|
||||||
{
|
|
||||||
return lst->inactive_osds;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cluster_client_t::list_inode_next(inode_list_t *lst, int next_pgs)
|
void cluster_client_t::list_inode_next(inode_list_t *lst, int next_pgs)
|
||||||
{
|
{
|
||||||
if (next_pgs >= 0)
|
if (next_pgs >= 0)
|
||||||
|
|||||||
+1
-4
@@ -132,7 +132,6 @@ protected:
|
|||||||
uint64_t rdma_max_msg = 0;
|
uint64_t rdma_max_msg = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool has_send_loop = false;
|
|
||||||
std::vector<int> read_ready_clients;
|
std::vector<int> read_ready_clients;
|
||||||
std::vector<int> write_ready_clients;
|
std::vector<int> write_ready_clients;
|
||||||
// We don't use ringloop->set_immediate here because we may have no ringloop in client :)
|
// We don't use ringloop->set_immediate here because we may have no ringloop in client :)
|
||||||
@@ -160,7 +159,6 @@ public:
|
|||||||
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();
|
||||||
bool can_send();
|
|
||||||
void accept_connections(int listen_fd);
|
void accept_connections(int listen_fd);
|
||||||
~osd_messenger_t();
|
~osd_messenger_t();
|
||||||
|
|
||||||
@@ -175,8 +173,6 @@ public:
|
|||||||
bool connect_rdma(int peer_fd, std::string rdma_address, uint64_t client_max_msg);
|
bool connect_rdma(int peer_fd, std::string rdma_address, uint64_t client_max_msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void measure_exec(osd_op_t *cur_op);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void try_connect_peer(uint64_t osd_num);
|
void try_connect_peer(uint64_t osd_num);
|
||||||
void try_connect_peer_addr(osd_num_t peer_osd, const char *peer_host, int peer_port);
|
void try_connect_peer_addr(osd_num_t peer_osd, const char *peer_host, int peer_port);
|
||||||
@@ -188,6 +184,7 @@ protected:
|
|||||||
void cancel_op(osd_op_t *op);
|
void cancel_op(osd_op_t *op);
|
||||||
|
|
||||||
bool try_send(osd_client_t *cl);
|
bool try_send(osd_client_t *cl);
|
||||||
|
void measure_exec(osd_op_t *cur_op);
|
||||||
void handle_send(int result, osd_client_t *cl);
|
void handle_send(int result, osd_client_t *cl);
|
||||||
|
|
||||||
bool handle_read(int result, osd_client_t *cl);
|
bool handle_read(int result, osd_client_t *cl);
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ osd_op_t::~osd_op_t()
|
|||||||
{
|
{
|
||||||
assert(!bs_op);
|
assert(!bs_op);
|
||||||
assert(!op_data);
|
assert(!op_data);
|
||||||
if (bitmap_buf)
|
|
||||||
{
|
|
||||||
free(bitmap_buf);
|
|
||||||
}
|
|
||||||
if (rmw_buf)
|
if (rmw_buf)
|
||||||
{
|
{
|
||||||
free(rmw_buf);
|
free(rmw_buf);
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ struct osd_op_t
|
|||||||
void *bitmap = NULL;
|
void *bitmap = NULL;
|
||||||
unsigned bitmap_len = 0;
|
unsigned bitmap_len = 0;
|
||||||
unsigned bmp_data = 0;
|
unsigned bmp_data = 0;
|
||||||
void *bitmap_buf = NULL;
|
|
||||||
void *rmw_buf = NULL;
|
void *rmw_buf = NULL;
|
||||||
osd_primary_op_data_t* op_data = NULL;
|
osd_primary_op_data_t* op_data = NULL;
|
||||||
std::function<void(osd_op_t*)> callback;
|
std::function<void(osd_op_t*)> callback;
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ bool osd_messenger_t::handle_reply_hdr(osd_client_t *cl)
|
|||||||
op->buf = malloc_or_die(op->reply.hdr.retval);
|
op->buf = malloc_or_die(op->reply.hdr.retval);
|
||||||
cl->recv_list.push_back(op->buf, op->reply.hdr.retval);
|
cl->recv_list.push_back(op->buf, op->reply.hdr.retval);
|
||||||
}
|
}
|
||||||
else if (op->reply.hdr.opcode == OSD_OP_DESCRIBE && op->reply.describe.result_bytes > 0)
|
else if (op->reply.hdr.opcode == OSD_OP_DESCRIBE && op->reply.hdr.retval > 0)
|
||||||
{
|
{
|
||||||
delete cl->read_op;
|
delete cl->read_op;
|
||||||
cl->read_op = op;
|
cl->read_op = op;
|
||||||
|
|||||||
+8
-25
@@ -84,12 +84,9 @@ void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < cur_op->iov.count; i++)
|
for (int i = 0; i < cur_op->iov.count; i++)
|
||||||
{
|
{
|
||||||
if (cur_op->iov.buf[i].iov_len > 0)
|
assert(cur_op->iov.buf[i].iov_base);
|
||||||
{
|
to_send_list.push_back(cur_op->iov.buf[i]);
|
||||||
assert(cur_op->iov.buf[i].iov_base);
|
to_outbox.push_back((msgr_sendp_t){ .op = cur_op, .flags = 0 });
|
||||||
to_send_list.push_back(cur_op->iov.buf[i]);
|
|
||||||
to_outbox.push_back((msgr_sendp_t){ .op = cur_op, .flags = 0 });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cur_op->req.hdr.opcode == OSD_OP_SEC_READ_BMP)
|
if (cur_op->req.hdr.opcode == OSD_OP_SEC_READ_BMP)
|
||||||
@@ -111,28 +108,22 @@ void osd_messenger_t::outbox_push(osd_op_t *cur_op)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!ringloop && !has_send_loop)
|
if (!ringloop)
|
||||||
{
|
{
|
||||||
// "Send loop" should be used, like in QEMU driver, or performance will suffer
|
// FIXME: It's worse because it doesn't allow batching
|
||||||
// due to a large number of sendmsg() syscalls where they can be avoided.
|
|
||||||
// "Send loop" increases 4k T1Q128 randread from ~55k iops to ~90k on a 1 OSD.
|
|
||||||
// The difference is smaller when there are more OSDs though...
|
|
||||||
while (cl->outbox.size())
|
while (cl->outbox.size())
|
||||||
{
|
{
|
||||||
try_send(cl);
|
try_send(cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cl->write_msg.msg_iovlen > 0 || has_send_loop || !try_send(cl))
|
else if (cl->write_msg.msg_iovlen > 0 || !try_send(cl))
|
||||||
{
|
{
|
||||||
if (cl->write_state == 0)
|
if (cl->write_state == 0)
|
||||||
{
|
{
|
||||||
cl->write_state = CL_WRITE_READY;
|
cl->write_state = CL_WRITE_READY;
|
||||||
write_ready_clients.push_back(cur_op->peer_fd);
|
write_ready_clients.push_back(cur_op->peer_fd);
|
||||||
}
|
}
|
||||||
if (ringloop)
|
ringloop->wakeup();
|
||||||
{
|
|
||||||
ringloop->wakeup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,10 +150,8 @@ void osd_messenger_t::measure_exec(osd_op_t *cur_op)
|
|||||||
(cur_op->tv_end.tv_nsec - cur_op->tv_begin.tv_nsec)/1000
|
(cur_op->tv_end.tv_nsec - cur_op->tv_begin.tv_nsec)/1000
|
||||||
);
|
);
|
||||||
if (cur_op->req.hdr.opcode == OSD_OP_READ ||
|
if (cur_op->req.hdr.opcode == OSD_OP_READ ||
|
||||||
cur_op->req.hdr.opcode == OSD_OP_WRITE ||
|
cur_op->req.hdr.opcode == OSD_OP_WRITE)
|
||||||
cur_op->req.hdr.opcode == OSD_OP_SCRUB)
|
|
||||||
{
|
{
|
||||||
// req.rw.len is internally set to the full object size for scrubs
|
|
||||||
stats.op_stat_bytes[cur_op->req.hdr.opcode] += cur_op->req.rw.len;
|
stats.op_stat_bytes[cur_op->req.hdr.opcode] += cur_op->req.rw.len;
|
||||||
}
|
}
|
||||||
else if (cur_op->req.hdr.opcode == OSD_OP_SEC_READ ||
|
else if (cur_op->req.hdr.opcode == OSD_OP_SEC_READ ||
|
||||||
@@ -224,12 +213,6 @@ void osd_messenger_t::send_replies()
|
|||||||
write_ready_clients.clear();
|
write_ready_clients.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool osd_messenger_t::can_send()
|
|
||||||
{
|
|
||||||
has_send_loop = true;
|
|
||||||
return write_ready_clients.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void osd_messenger_t::handle_send(int result, osd_client_t *cl)
|
void osd_messenger_t::handle_send(int result, osd_client_t *cl)
|
||||||
{
|
{
|
||||||
cl->write_msg.msg_iovlen = 0;
|
cl->write_msg.msg_iovlen = 0;
|
||||||
|
|||||||
+1
-1
@@ -149,7 +149,7 @@ public:
|
|||||||
" --dev_num N\n"
|
" --dev_num N\n"
|
||||||
" Use the specified device /dev/nbdN instead of automatic selection.\n"
|
" Use the specified device /dev/nbdN instead of automatic selection.\n"
|
||||||
" --foreground 1\n"
|
" --foreground 1\n"
|
||||||
" Stay in foreground, do not daemonize.\n",
|
" Stay in foreground, do not daemonize.n",
|
||||||
exe_name, exe_name, exe_name
|
exe_name, exe_name, exe_name
|
||||||
);
|
);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|||||||
+1
-1
@@ -220,7 +220,7 @@ struct __attribute__((__packed__)) osd_reply_rw_t
|
|||||||
// for reads: bitmap length
|
// for reads: bitmap length
|
||||||
uint32_t bitmap_len;
|
uint32_t bitmap_len;
|
||||||
uint32_t pad0;
|
uint32_t pad0;
|
||||||
// for reads and writes: object version
|
// for reads: object version
|
||||||
uint64_t version;
|
uint64_t version;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+7
-8
@@ -240,20 +240,21 @@ void osd_t::start_pg_peering(pg_t & pg)
|
|||||||
// (PG history is kept up to the latest active+clean state)
|
// (PG history is kept up to the latest active+clean state)
|
||||||
for (auto & history_set: pg.target_history)
|
for (auto & history_set: pg.target_history)
|
||||||
{
|
{
|
||||||
int nonzero = 0, found = 0;
|
bool found = true;
|
||||||
for (auto history_osd: history_set)
|
for (auto history_osd: history_set)
|
||||||
{
|
{
|
||||||
if (history_osd != 0)
|
if (history_osd != 0)
|
||||||
{
|
{
|
||||||
nonzero++;
|
found = false;
|
||||||
if (history_osd == this->osd_num ||
|
if (history_osd == this->osd_num ||
|
||||||
msgr.osd_peer_fds.find(history_osd) != msgr.osd_peer_fds.end())
|
msgr.osd_peer_fds.find(history_osd) != msgr.osd_peer_fds.end())
|
||||||
{
|
{
|
||||||
found++;
|
found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found < (nonzero >= pg.pg_data_size ? pg.pg_data_size : 1))
|
if (!found)
|
||||||
{
|
{
|
||||||
pg.state = PG_INCOMPLETE;
|
pg.state = PG_INCOMPLETE;
|
||||||
report_pg_state(pg);
|
report_pg_state(pg);
|
||||||
@@ -485,10 +486,6 @@ void osd_t::report_pg_state(pg_t & pg)
|
|||||||
{
|
{
|
||||||
pg.print_state();
|
pg.print_state();
|
||||||
this->pg_state_dirty.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
|
this->pg_state_dirty.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
|
||||||
if (pg.state & PG_ACTIVE)
|
|
||||||
{
|
|
||||||
plan_scrub(pg, false);
|
|
||||||
}
|
|
||||||
if (pg.state == PG_ACTIVE && (pg.target_history.size() > 0 || pg.all_peers.size() > pg.target_set.size()))
|
if (pg.state == PG_ACTIVE && (pg.target_history.size() > 0 || pg.all_peers.size() > pg.target_set.size()))
|
||||||
{
|
{
|
||||||
// Clear history of active+clean PGs
|
// Clear history of active+clean PGs
|
||||||
@@ -497,6 +494,7 @@ void osd_t::report_pg_state(pg_t & pg)
|
|||||||
pg.all_peers = pg.target_set;
|
pg.all_peers = pg.target_set;
|
||||||
std::sort(pg.all_peers.begin(), pg.all_peers.end());
|
std::sort(pg.all_peers.begin(), pg.all_peers.end());
|
||||||
pg.cur_peers = pg.target_set;
|
pg.cur_peers = pg.target_set;
|
||||||
|
plan_scrub(pg, false);
|
||||||
// Change pg_config at the same time, otherwise our PG reconciling loop may try to apply the old metadata
|
// Change pg_config at the same time, otherwise our PG reconciling loop may try to apply the old metadata
|
||||||
auto & pg_cfg = st_cli.pool_config[pg.pool_id].pg_config[pg.pg_num];
|
auto & pg_cfg = st_cli.pool_config[pg.pool_id].pg_config[pg.pg_num];
|
||||||
pg_cfg.target_history = pg.target_history;
|
pg_cfg.target_history = pg.target_history;
|
||||||
@@ -540,6 +538,7 @@ void osd_t::report_pg_state(pg_t & pg)
|
|||||||
pg.cur_peers.push_back(pg_osd);
|
pg.cur_peers.push_back(pg_osd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
plan_scrub(pg, false);
|
||||||
auto & pg_cfg = st_cli.pool_config[pg.pool_id].pg_config[pg.pg_num];
|
auto & pg_cfg = st_cli.pool_config[pg.pool_id].pg_config[pg.pg_num];
|
||||||
pg_cfg.target_history = pg.target_history;
|
pg_cfg.target_history = pg.target_history;
|
||||||
pg_cfg.all_peers = pg.all_peers;
|
pg_cfg.all_peers = pg.all_peers;
|
||||||
|
|||||||
+14
-11
@@ -87,7 +87,8 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
|
|||||||
// - op_data
|
// - op_data
|
||||||
1, sizeof(osd_primary_op_data_t) +
|
1, sizeof(osd_primary_op_data_t) +
|
||||||
// - stripes
|
// - stripes
|
||||||
stripe_count * sizeof(osd_rmw_stripe_t) +
|
// - resulting bitmap buffers
|
||||||
|
stripe_count * (clean_entry_bitmap_size + sizeof(osd_rmw_stripe_t)) +
|
||||||
chain_size * (
|
chain_size * (
|
||||||
// - copy of the chain
|
// - copy of the chain
|
||||||
sizeof(inode_t) +
|
sizeof(inode_t) +
|
||||||
@@ -109,12 +110,11 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
|
|||||||
op_data->pg_size = pg_it->second.pg_size;
|
op_data->pg_size = pg_it->second.pg_size;
|
||||||
cur_op->op_data = op_data;
|
cur_op->op_data = op_data;
|
||||||
split_stripes(pg_data_size, bs_block_size, (uint32_t)(cur_op->req.rw.offset - oid.stripe), cur_op->req.rw.len, op_data->stripes);
|
split_stripes(pg_data_size, bs_block_size, (uint32_t)(cur_op->req.rw.offset - oid.stripe), cur_op->req.rw.len, op_data->stripes);
|
||||||
// Resulting bitmaps have to survive op_data and be freed with the op itself
|
// Allocate bitmaps along with stripes to avoid extra allocations and fragmentation
|
||||||
assert(!cur_op->bitmap_buf);
|
|
||||||
cur_op->bitmap_buf = calloc_or_die(1, clean_entry_bitmap_size * stripe_count);
|
|
||||||
for (int i = 0; i < stripe_count; i++)
|
for (int i = 0; i < stripe_count; i++)
|
||||||
{
|
{
|
||||||
op_data->stripes[i].bmp_buf = (uint8_t*)cur_op->bitmap_buf + clean_entry_bitmap_size * i;
|
op_data->stripes[i].bmp_buf = data_buf;
|
||||||
|
data_buf = (uint8_t*)data_buf + clean_entry_bitmap_size;
|
||||||
}
|
}
|
||||||
op_data->chain_size = chain_size;
|
op_data->chain_size = chain_size;
|
||||||
if (chain_size > 0)
|
if (chain_size > 0)
|
||||||
@@ -129,19 +129,16 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
|
|||||||
data_buf = (uint8_t*)data_buf + chain_size * (pool_cfg.scheme == POOL_SCHEME_REPLICATED ? 0 : pg_it->second.pg_size);
|
data_buf = (uint8_t*)data_buf + chain_size * (pool_cfg.scheme == POOL_SCHEME_REPLICATED ? 0 : pg_it->second.pg_size);
|
||||||
// Copy chain
|
// Copy chain
|
||||||
int chain_num = 0;
|
int chain_num = 0;
|
||||||
op_data->read_chain[chain_num] = cur_op->req.rw.inode;
|
op_data->read_chain[chain_num++] = cur_op->req.rw.inode;
|
||||||
op_data->chain_states[chain_num] = NULL;
|
|
||||||
chain_num++;
|
|
||||||
auto inode_it = st_cli.inode_config.find(cur_op->req.rw.inode);
|
auto inode_it = st_cli.inode_config.find(cur_op->req.rw.inode);
|
||||||
while (inode_it != st_cli.inode_config.end() && inode_it->second.parent_id &&
|
while (inode_it != st_cli.inode_config.end() && inode_it->second.parent_id &&
|
||||||
INODE_POOL(inode_it->second.parent_id) == pg_it->second.pool_id &&
|
INODE_POOL(inode_it->second.parent_id) == pg_it->second.pool_id &&
|
||||||
// Check for loops
|
// Check for loops
|
||||||
inode_it->second.parent_id != cur_op->req.rw.inode)
|
inode_it->second.parent_id != cur_op->req.rw.inode)
|
||||||
{
|
{
|
||||||
op_data->read_chain[chain_num] = inode_it->second.parent_id;
|
op_data->read_chain[chain_num++] = inode_it->second.parent_id;
|
||||||
op_data->chain_states[chain_num] = NULL;
|
op_data->chain_states[chain_num++] = NULL;
|
||||||
inode_it = st_cli.inode_config.find(inode_it->second.parent_id);
|
inode_it = st_cli.inode_config.find(inode_it->second.parent_id);
|
||||||
chain_num++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pg_it->second.inflight++;
|
pg_it->second.inflight++;
|
||||||
@@ -647,6 +644,12 @@ void osd_t::continue_primary_del(osd_op_t *cur_op)
|
|||||||
else if (op_data->st == 4) goto resume_4;
|
else if (op_data->st == 4) goto resume_4;
|
||||||
else if (op_data->st == 5) goto resume_5;
|
else if (op_data->st == 5) goto resume_5;
|
||||||
assert(op_data->st == 0);
|
assert(op_data->st == 0);
|
||||||
|
// Delete is forbidden even in active PGs if they're also degraded or have previous dead OSDs
|
||||||
|
if (pg.state & (PG_DEGRADED | PG_LEFT_ON_DEAD))
|
||||||
|
{
|
||||||
|
finish_op(cur_op, -EBUSY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!check_write_queue(cur_op, pg))
|
if (!check_write_queue(cur_op, pg))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ void osd_t::finish_op(osd_op_t *cur_op, int retval)
|
|||||||
cur_op->reply.hdr.retval = retval;
|
cur_op->reply.hdr.retval = retval;
|
||||||
if (cur_op->peer_fd == -1)
|
if (cur_op->peer_fd == -1)
|
||||||
{
|
{
|
||||||
msgr.measure_exec(cur_op);
|
|
||||||
// Copy lambda to be unaffected by `delete op`
|
// Copy lambda to be unaffected by `delete op`
|
||||||
std::function<void(osd_op_t*)>(cur_op->callback)(cur_op);
|
std::function<void(osd_op_t*)>(cur_op->callback)(cur_op);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,13 +83,11 @@ retry_1:
|
|||||||
// Object is degraded/misplaced and will be moved to <write_osd_set>
|
// Object is degraded/misplaced and will be moved to <write_osd_set>
|
||||||
op_data->stripes[0].read_start = 0;
|
op_data->stripes[0].read_start = 0;
|
||||||
op_data->stripes[0].read_end = bs_block_size;
|
op_data->stripes[0].read_end = bs_block_size;
|
||||||
assert(!cur_op->rmw_buf);
|
|
||||||
cur_op->rmw_buf = op_data->stripes[0].read_buf = memalign_or_die(MEM_ALIGNMENT, bs_block_size);
|
cur_op->rmw_buf = op_data->stripes[0].read_buf = memalign_or_die(MEM_ALIGNMENT, bs_block_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(!cur_op->rmw_buf);
|
|
||||||
cur_op->rmw_buf = calc_rmw(cur_op->buf, op_data->stripes, op_data->prev_set,
|
cur_op->rmw_buf = calc_rmw(cur_op->buf, op_data->stripes, op_data->prev_set,
|
||||||
pg.pg_size, op_data->pg_data_size, pg.pg_cursize, pg.cur_set.data(), bs_block_size, clean_entry_bitmap_size);
|
pg.pg_size, op_data->pg_data_size, pg.pg_cursize, pg.cur_set.data(), bs_block_size, clean_entry_bitmap_size);
|
||||||
if (!cur_op->rmw_buf)
|
if (!cur_op->rmw_buf)
|
||||||
|
|||||||
+2
-7
@@ -115,10 +115,6 @@ int osd_t::pick_next_scrub(object_id & next_oid)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (scrub_list_op)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
timespec tv_now;
|
timespec tv_now;
|
||||||
clock_gettime(CLOCK_REALTIME, &tv_now);
|
clock_gettime(CLOCK_REALTIME, &tv_now);
|
||||||
bool rescan = scrub_last_pg.pool_id != 0 || scrub_last_pg.pg_num != 0;
|
bool rescan = scrub_last_pg.pool_id != 0 || scrub_last_pg.pg_num != 0;
|
||||||
@@ -131,7 +127,7 @@ int osd_t::pick_next_scrub(object_id & next_oid)
|
|||||||
}
|
}
|
||||||
while (pg_it != pgs.end())
|
while (pg_it != pgs.end())
|
||||||
{
|
{
|
||||||
if ((pg_it->second.state & PG_ACTIVE) && pg_it->second.next_scrub && pg_it->second.next_scrub <= tv_now.tv_sec)
|
if ((pg_it->second.state & PG_ACTIVE) && pg_it->second.next_scrub && pg_it->second.next_scrub < tv_now.tv_sec)
|
||||||
{
|
{
|
||||||
// Continue scrubbing from the next object
|
// Continue scrubbing from the next object
|
||||||
if (scrub_last_pg == pg_it->first)
|
if (scrub_last_pg == pg_it->first)
|
||||||
@@ -350,7 +346,7 @@ void osd_t::schedule_scrub(pg_t & pg)
|
|||||||
tfd->clear_timer(scrub_timer_id);
|
tfd->clear_timer(scrub_timer_id);
|
||||||
scrub_timer_id = -1;
|
scrub_timer_id = -1;
|
||||||
}
|
}
|
||||||
if (tv_now.tv_sec >= scrub_nearest_ts)
|
if (tv_now.tv_sec > scrub_nearest_ts)
|
||||||
{
|
{
|
||||||
scrub_nearest_ts = 0;
|
scrub_nearest_ts = 0;
|
||||||
peering_state = peering_state | OSD_SCRUBBING;
|
peering_state = peering_state | OSD_SCRUBBING;
|
||||||
@@ -380,7 +376,6 @@ void osd_t::continue_primary_scrub(osd_op_t *cur_op)
|
|||||||
goto resume_2;
|
goto resume_2;
|
||||||
{
|
{
|
||||||
auto & pg = pgs.at({ .pool_id = INODE_POOL(op_data->oid.inode), .pg_num = op_data->pg_num });
|
auto & pg = pgs.at({ .pool_id = INODE_POOL(op_data->oid.inode), .pg_num = op_data->pg_num });
|
||||||
cur_op->req.rw.len = bs_block_size * pg.pg_data_size;
|
|
||||||
// Determine version
|
// Determine version
|
||||||
auto vo_it = pg.ver_override.find(op_data->oid);
|
auto vo_it = pg.ver_override.find(op_data->oid);
|
||||||
op_data->target_ver = vo_it != pg.ver_override.end() ? vo_it->second : UINT64_MAX;
|
op_data->target_ver = vo_it != pg.ver_override.end() ? vo_it->second : UINT64_MAX;
|
||||||
|
|||||||
+13
-174
@@ -35,11 +35,6 @@
|
|||||||
#define qdict_put_str(options, name, value) qdict_put_obj(options, name, QOBJECT(qstring_from_str(value)))
|
#define qdict_put_str(options, name, value) qdict_put_obj(options, name, QOBJECT(qstring_from_str(value)))
|
||||||
#define qobject_unref QDECREF
|
#define qobject_unref QDECREF
|
||||||
#endif
|
#endif
|
||||||
#if QEMU_VERSION_MAJOR == 4 && QEMU_VERSION_MINOR >= 2 || QEMU_VERSION_MAJOR > 4
|
|
||||||
#include "sysemu/replay.h"
|
|
||||||
#else
|
|
||||||
#include "sysemu/sysemu.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "vitastor_c.h"
|
#include "vitastor_c.h"
|
||||||
|
|
||||||
@@ -53,8 +48,6 @@ void DSO_STAMP_FUN(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct VitastorFdData VitastorFdData;
|
|
||||||
|
|
||||||
typedef struct VitastorClient
|
typedef struct VitastorClient
|
||||||
{
|
{
|
||||||
void *proxy;
|
void *proxy;
|
||||||
@@ -74,24 +67,12 @@ typedef struct VitastorClient
|
|||||||
int rdma_gid_index;
|
int rdma_gid_index;
|
||||||
int rdma_mtu;
|
int rdma_mtu;
|
||||||
QemuMutex mutex;
|
QemuMutex mutex;
|
||||||
AioContext *ctx;
|
|
||||||
VitastorFdData **fds;
|
|
||||||
int fd_count, fd_alloc;
|
|
||||||
int bh_send_all_scheduled;
|
|
||||||
|
|
||||||
uint64_t last_bitmap_inode, last_bitmap_offset, last_bitmap_len;
|
uint64_t last_bitmap_inode, last_bitmap_offset, last_bitmap_len;
|
||||||
uint32_t last_bitmap_granularity;
|
uint32_t last_bitmap_granularity;
|
||||||
uint8_t *last_bitmap;
|
uint8_t *last_bitmap;
|
||||||
} VitastorClient;
|
} VitastorClient;
|
||||||
|
|
||||||
typedef struct VitastorFdData
|
|
||||||
{
|
|
||||||
VitastorClient *cli;
|
|
||||||
int fd;
|
|
||||||
IOHandler *fd_read, *fd_write;
|
|
||||||
void *opaque;
|
|
||||||
} VitastorFdData;
|
|
||||||
|
|
||||||
typedef struct VitastorRPC
|
typedef struct VitastorRPC
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
@@ -102,21 +83,10 @@ typedef struct VitastorRPC
|
|||||||
uint64_t inode, offset, len;
|
uint64_t inode, offset, len;
|
||||||
uint32_t bitmap_granularity;
|
uint32_t bitmap_granularity;
|
||||||
uint8_t *bitmap;
|
uint8_t *bitmap;
|
||||||
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 8
|
|
||||||
QEMUBH *bh;
|
|
||||||
#endif
|
|
||||||
} VitastorRPC;
|
} VitastorRPC;
|
||||||
|
|
||||||
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 8
|
|
||||||
typedef struct VitastorBH
|
|
||||||
{
|
|
||||||
VitastorClient *cli;
|
|
||||||
QEMUBH *bh;
|
|
||||||
} VitastorBH;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void vitastor_co_init_task(BlockDriverState *bs, VitastorRPC *task);
|
static void vitastor_co_init_task(BlockDriverState *bs, VitastorRPC *task);
|
||||||
static void vitastor_co_generic_cb(void *opaque, long retval);
|
static void vitastor_co_generic_bh_cb(void *opaque, long retval);
|
||||||
static void vitastor_co_read_cb(void *opaque, long retval, uint64_t version);
|
static void vitastor_co_read_cb(void *opaque, long retval, uint64_t version);
|
||||||
static void vitastor_close(BlockDriverState *bs);
|
static void vitastor_close(BlockDriverState *bs);
|
||||||
|
|
||||||
@@ -232,49 +202,6 @@ out:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
|
|
||||||
static void vitastor_bh_send_all(void *opaque)
|
|
||||||
{
|
|
||||||
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 8
|
|
||||||
VitastorBH *vbh = opaque;
|
|
||||||
VitastorClient *client = vbh->cli;
|
|
||||||
#else
|
|
||||||
VitastorClient *client = opaque;
|
|
||||||
#endif
|
|
||||||
qemu_mutex_lock(&client->mutex);
|
|
||||||
client->bh_send_all_scheduled = 0;
|
|
||||||
vitastor_c_qemu_send_all(client->proxy);
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
|
||||||
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR < 8
|
|
||||||
qemu_bh_delete(vbh->bh);
|
|
||||||
free(vbh);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void vitastor_schedule_send_all(VitastorClient *client)
|
|
||||||
{
|
|
||||||
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
|
|
||||||
if (!client->bh_send_all_scheduled)
|
|
||||||
{
|
|
||||||
client->bh_send_all_scheduled = 1;
|
|
||||||
#if QEMU_VERSION_MAJOR > 4 || QEMU_VERSION_MAJOR == 4 && QEMU_VERSION_MINOR >= 2
|
|
||||||
replay_bh_schedule_oneshot_event(client->ctx, vitastor_bh_send_all, client);
|
|
||||||
#elif QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 8
|
|
||||||
aio_bh_schedule_oneshot(client->ctx, vitastor_bh_send_all, client);
|
|
||||||
#elif QEMU_VERSION_MAJOR >= 2
|
|
||||||
VitastorBH *vbh = (VitastorBH*)malloc(sizeof(VitastorBH));
|
|
||||||
vbh->cli = client;
|
|
||||||
vbh->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_bh_send_all, vbh);
|
|
||||||
qemu_bh_schedule(vbh->bh);
|
|
||||||
#else
|
|
||||||
client->bh_send_all_scheduled = 0;
|
|
||||||
vitastor_c_qemu_send_all(client->proxy);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void coroutine_fn vitastor_co_get_metadata(VitastorRPC *task)
|
static void coroutine_fn vitastor_co_get_metadata(VitastorRPC *task)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = task->bs;
|
BlockDriverState *bs = task->bs;
|
||||||
@@ -282,8 +209,7 @@ static void coroutine_fn vitastor_co_get_metadata(VitastorRPC *task)
|
|||||||
task->co = qemu_coroutine_self();
|
task->co = qemu_coroutine_self();
|
||||||
|
|
||||||
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_bh_cb, task);
|
||||||
vitastor_schedule_send_all(client);
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
|
|
||||||
while (!task->complete)
|
while (!task->complete)
|
||||||
@@ -292,72 +218,14 @@ static void coroutine_fn vitastor_co_get_metadata(VitastorRPC *task)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vitastor_aio_fd_read(void *fddv)
|
// FIXME: Fix thread safety of the driver - now it segfaults when iothread is enabled in QEMU
|
||||||
|
static void vitastor_aio_set_fd_handler(void *ctx, int fd, int unused1, IOHandler *fd_read, IOHandler *fd_write, void *unused2, void *opaque)
|
||||||
{
|
{
|
||||||
VitastorFdData *fdd = (VitastorFdData*)fddv;
|
aio_set_fd_handler(ctx, fd,
|
||||||
qemu_mutex_lock(&fdd->cli->mutex);
|
|
||||||
fdd->fd_read(fdd->opaque);
|
|
||||||
vitastor_schedule_send_all(fdd->cli);
|
|
||||||
qemu_mutex_unlock(&fdd->cli->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vitastor_aio_fd_write(void *fddv)
|
|
||||||
{
|
|
||||||
VitastorFdData *fdd = (VitastorFdData*)fddv;
|
|
||||||
qemu_mutex_lock(&fdd->cli->mutex);
|
|
||||||
fdd->fd_write(fdd->opaque);
|
|
||||||
vitastor_schedule_send_all(fdd->cli);
|
|
||||||
qemu_mutex_unlock(&fdd->cli->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vitastor_aio_set_fd_handler(void *vcli, int fd, int unused1, IOHandler *fd_read, IOHandler *fd_write, void *unused2, void *opaque)
|
|
||||||
{
|
|
||||||
VitastorClient *client = (VitastorClient*)vcli;
|
|
||||||
VitastorFdData *fdd = NULL;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < client->fd_count; i++)
|
|
||||||
{
|
|
||||||
if (client->fds[i]->fd == fd)
|
|
||||||
{
|
|
||||||
if (fd_read || fd_write)
|
|
||||||
{
|
|
||||||
fdd = client->fds[i];
|
|
||||||
fdd->opaque = opaque;
|
|
||||||
fdd->fd_read = fd_read;
|
|
||||||
fdd->fd_write = fd_write;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int j = i+1; j < client->fd_count; j++)
|
|
||||||
client->fds[j-1] = client->fds[j];
|
|
||||||
client->fd_count--;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((fd_read || fd_write) && !fdd)
|
|
||||||
{
|
|
||||||
fdd = (VitastorFdData*)malloc(sizeof(VitastorFdData));
|
|
||||||
fdd->cli = client;
|
|
||||||
fdd->fd = fd;
|
|
||||||
fdd->fd_read = fd_read;
|
|
||||||
fdd->fd_write = fd_write;
|
|
||||||
fdd->opaque = opaque;
|
|
||||||
if (client->fd_count >= client->fd_alloc)
|
|
||||||
{
|
|
||||||
client->fd_alloc = client->fd_alloc*2;
|
|
||||||
if (client->fd_alloc < 16)
|
|
||||||
client->fd_alloc = 16;
|
|
||||||
client->fds = (VitastorFdData**)realloc(client->fds, sizeof(VitastorFdData*) * client->fd_alloc);
|
|
||||||
}
|
|
||||||
client->fds[client->fd_count++] = fdd;
|
|
||||||
}
|
|
||||||
aio_set_fd_handler(client->ctx, fd,
|
|
||||||
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 5 || QEMU_VERSION_MAJOR >= 3
|
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 5 || QEMU_VERSION_MAJOR >= 3
|
||||||
0 /*is_external*/,
|
0 /*is_external*/,
|
||||||
#endif
|
#endif
|
||||||
fd_read ? vitastor_aio_fd_read : NULL,
|
fd_read, fd_write,
|
||||||
fd_write ? vitastor_aio_fd_write : NULL,
|
|
||||||
#if QEMU_VERSION_MAJOR == 1 && QEMU_VERSION_MINOR <= 6 || QEMU_VERSION_MAJOR < 1
|
#if QEMU_VERSION_MAJOR == 1 && QEMU_VERSION_MINOR <= 6 || QEMU_VERSION_MAJOR < 1
|
||||||
NULL /*io_flush*/,
|
NULL /*io_flush*/,
|
||||||
#endif
|
#endif
|
||||||
@@ -367,7 +235,7 @@ static void vitastor_aio_set_fd_handler(void *vcli, int fd, int unused1, IOHandl
|
|||||||
#if QEMU_VERSION_MAJOR >= 7
|
#if QEMU_VERSION_MAJOR >= 7
|
||||||
NULL /*io_poll_ready*/,
|
NULL /*io_poll_ready*/,
|
||||||
#endif
|
#endif
|
||||||
fdd);
|
opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
|
static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
|
||||||
@@ -387,9 +255,8 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
|
|||||||
client->rdma_port_num = qdict_get_try_int(options, "rdma-port-num", 0);
|
client->rdma_port_num = qdict_get_try_int(options, "rdma-port-num", 0);
|
||||||
client->rdma_gid_index = qdict_get_try_int(options, "rdma-gid-index", 0);
|
client->rdma_gid_index = qdict_get_try_int(options, "rdma-gid-index", 0);
|
||||||
client->rdma_mtu = qdict_get_try_int(options, "rdma-mtu", 0);
|
client->rdma_mtu = qdict_get_try_int(options, "rdma-mtu", 0);
|
||||||
client->ctx = bdrv_get_aio_context(bs);
|
|
||||||
client->proxy = vitastor_c_create_qemu(
|
client->proxy = vitastor_c_create_qemu(
|
||||||
vitastor_aio_set_fd_handler, client, client->config_path, client->etcd_host, client->etcd_prefix,
|
vitastor_aio_set_fd_handler, bdrv_get_aio_context(bs), client->config_path, client->etcd_host, client->etcd_prefix,
|
||||||
client->use_rdma, client->rdma_device, client->rdma_port_num, client->rdma_gid_index, client->rdma_mtu, 0
|
client->use_rdma, client->rdma_device, client->rdma_port_num, client->rdma_gid_index, client->rdma_mtu, 0
|
||||||
);
|
);
|
||||||
image = client->image = g_strdup(qdict_get_try_str(options, "image"));
|
image = client->image = g_strdup(qdict_get_try_str(options, "image"));
|
||||||
@@ -471,12 +338,6 @@ static void vitastor_close(BlockDriverState *bs)
|
|||||||
{
|
{
|
||||||
VitastorClient *client = bs->opaque;
|
VitastorClient *client = bs->opaque;
|
||||||
vitastor_c_destroy(client->proxy);
|
vitastor_c_destroy(client->proxy);
|
||||||
if (client->fds)
|
|
||||||
{
|
|
||||||
free(client->fds);
|
|
||||||
client->fds = NULL;
|
|
||||||
client->fd_alloc = client->fd_count = 0;
|
|
||||||
}
|
|
||||||
qemu_mutex_destroy(&client->mutex);
|
qemu_mutex_destroy(&client->mutex);
|
||||||
if (client->config_path)
|
if (client->config_path)
|
||||||
g_free(client->config_path);
|
g_free(client->config_path);
|
||||||
@@ -593,43 +454,25 @@ static void vitastor_co_init_task(BlockDriverState *bs, VitastorRPC *task)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vitastor_co_generic_bh_cb(void *opaque)
|
static void vitastor_co_generic_bh_cb(void *opaque, long retval)
|
||||||
{
|
{
|
||||||
VitastorRPC *task = opaque;
|
VitastorRPC *task = opaque;
|
||||||
|
task->ret = retval;
|
||||||
task->complete = 1;
|
task->complete = 1;
|
||||||
if (qemu_coroutine_self() != task->co)
|
if (qemu_coroutine_self() != task->co)
|
||||||
{
|
{
|
||||||
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 8
|
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 8
|
||||||
aio_co_wake(task->co);
|
aio_co_wake(task->co);
|
||||||
#else
|
#else
|
||||||
#if QEMU_VERSION_MAJOR == 2
|
|
||||||
qemu_bh_delete(task->bh);
|
|
||||||
#endif
|
|
||||||
qemu_coroutine_enter(task->co, NULL);
|
qemu_coroutine_enter(task->co, NULL);
|
||||||
qemu_aio_release(task);
|
qemu_aio_release(task);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vitastor_co_generic_cb(void *opaque, long retval)
|
|
||||||
{
|
|
||||||
VitastorRPC *task = opaque;
|
|
||||||
task->ret = retval;
|
|
||||||
#if QEMU_VERSION_MAJOR > 4 || QEMU_VERSION_MAJOR == 4 && QEMU_VERSION_MINOR >= 2
|
|
||||||
replay_bh_schedule_oneshot_event(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
||||||
#elif QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 8
|
|
||||||
aio_bh_schedule_oneshot(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
||||||
#elif QEMU_VERSION_MAJOR >= 2
|
|
||||||
task->bh = aio_bh_new(bdrv_get_aio_context(task->bs), vitastor_co_generic_bh_cb, opaque);
|
|
||||||
qemu_bh_schedule(task->bh);
|
|
||||||
#else
|
|
||||||
vitastor_co_generic_bh_cb(opaque);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vitastor_co_read_cb(void *opaque, long retval, uint64_t version)
|
static void vitastor_co_read_cb(void *opaque, long retval, uint64_t version)
|
||||||
{
|
{
|
||||||
vitastor_co_generic_cb(opaque, retval);
|
vitastor_co_generic_bh_cb(opaque, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn vitastor_co_preadv(BlockDriverState *bs,
|
static int coroutine_fn vitastor_co_preadv(BlockDriverState *bs,
|
||||||
@@ -648,7 +491,6 @@ 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);
|
||||||
vitastor_schedule_send_all(client);
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
|
|
||||||
while (!task.complete)
|
while (!task.complete)
|
||||||
@@ -681,8 +523,7 @@ 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_bh_cb, &task);
|
||||||
vitastor_schedule_send_all(client);
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
|
|
||||||
while (!task.complete)
|
while (!task.complete)
|
||||||
@@ -761,7 +602,6 @@ 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);
|
||||||
vitastor_schedule_send_all(client);
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
while (!task.complete)
|
while (!task.complete)
|
||||||
{
|
{
|
||||||
@@ -847,8 +687,7 @@ static int coroutine_fn vitastor_co_flush(BlockDriverState *bs)
|
|||||||
vitastor_co_init_task(bs, &task);
|
vitastor_co_init_task(bs, &task);
|
||||||
|
|
||||||
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_bh_cb, &task);
|
||||||
vitastor_schedule_send_all(client);
|
|
||||||
qemu_mutex_unlock(&client->mutex);
|
qemu_mutex_unlock(&client->mutex);
|
||||||
|
|
||||||
while (!task.complete)
|
while (!task.complete)
|
||||||
|
|||||||
@@ -300,11 +300,3 @@ std::string read_all_fd(int fd)
|
|||||||
res.resize(res_size);
|
res.resize(res_size);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string str_repeat(const std::string & str, int times)
|
|
||||||
{
|
|
||||||
std::string r;
|
|
||||||
for (int i = 0; i < times; i++)
|
|
||||||
r += str;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,4 +17,3 @@ std::string format_size(uint64_t size, bool nobytes = false);
|
|||||||
void print_help(const char *help_text, std::string exe_name, std::string cmd, bool all);
|
void print_help(const char *help_text, std::string exe_name, std::string cmd, bool all);
|
||||||
uint64_t parse_time(std::string time_str, bool *ok = NULL);
|
uint64_t parse_time(std::string time_str, bool *ok = NULL);
|
||||||
std::string read_all_fd(int fd);
|
std::string read_all_fd(int fd);
|
||||||
std::string str_repeat(const std::string & str, int times);
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
|||||||
|
|
||||||
Name: Vitastor
|
Name: Vitastor
|
||||||
Description: Vitastor client library
|
Description: Vitastor client library
|
||||||
Version: 0.9.2
|
Version: 0.9.0
|
||||||
Libs: -L${libdir} -lvitastor_client
|
Libs: -L${libdir} -lvitastor_client
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
|
||||||
|
|||||||
@@ -166,14 +166,6 @@ void vitastor_c_uring_wait_events(vitastor_c *client)
|
|||||||
client->ringloop->wait();
|
client->ringloop->wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void vitastor_c_qemu_send_all(vitastor_c *client)
|
|
||||||
{
|
|
||||||
while (client->cli->msgr.can_send())
|
|
||||||
{
|
|
||||||
client->cli->msgr.send_replies();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void vitastor_c_read(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len,
|
void vitastor_c_read(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len,
|
||||||
struct iovec *iov, int iovcnt, VitastorReadHandler cb, void *opaque)
|
struct iovec *iov, int iovcnt, VitastorReadHandler cb, void *opaque)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-2
@@ -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 2
|
#define VITASTOR_C_API_VERSION 1
|
||||||
|
|
||||||
#ifndef POOL_ID_BITS
|
#ifndef POOL_ID_BITS
|
||||||
#define POOL_ID_BITS 16
|
#define POOL_ID_BITS 16
|
||||||
@@ -42,7 +42,6 @@ int vitastor_c_is_ready(vitastor_c *client);
|
|||||||
void vitastor_c_uring_wait_ready(vitastor_c *client);
|
void vitastor_c_uring_wait_ready(vitastor_c *client);
|
||||||
void vitastor_c_uring_handle_events(vitastor_c *client);
|
void vitastor_c_uring_handle_events(vitastor_c *client);
|
||||||
void vitastor_c_uring_wait_events(vitastor_c *client);
|
void vitastor_c_uring_wait_events(vitastor_c *client);
|
||||||
void vitastor_c_qemu_send_all(vitastor_c *client);
|
|
||||||
void vitastor_c_read(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len,
|
void vitastor_c_read(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len,
|
||||||
struct iovec *iov, int iovcnt, VitastorReadHandler cb, void *opaque);
|
struct iovec *iov, int iovcnt, VitastorReadHandler cb, void *opaque);
|
||||||
void vitastor_c_write(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len, uint64_t check_version,
|
void vitastor_c_write(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len, uint64_t check_version,
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ for i in $(seq 1 $OSD_COUNT); do
|
|||||||
start_osd $i
|
start_osd $i
|
||||||
done
|
done
|
||||||
|
|
||||||
|
cd mon
|
||||||
|
npm install
|
||||||
|
cd ..
|
||||||
(while true; do node mon/mon-main.js --etcd_url $ETCD_URL --etcd_prefix "/vitastor" --verbose 1 || true; done) &>./testdata/mon.log &
|
(while true; do node mon/mon-main.js --etcd_url $ETCD_URL --etcd_prefix "/vitastor" --verbose 1 || true; done) &>./testdata/mon.log &
|
||||||
MON_PID=$!
|
MON_PID=$!
|
||||||
|
|
||||||
|
|||||||
+10
-15
@@ -16,35 +16,29 @@ SCHEME=ec ./test_change_pg_count.sh
|
|||||||
|
|
||||||
./test_etcd_fail.sh
|
./test_etcd_fail.sh
|
||||||
|
|
||||||
|
./test_failure_domain.sh
|
||||||
|
|
||||||
./test_interrupted_rebalance.sh
|
./test_interrupted_rebalance.sh
|
||||||
IMMEDIATE_COMMIT=1 ./test_interrupted_rebalance.sh
|
IMMEDIATE_COMMIT=1 ./test_interrupted_rebalance.sh
|
||||||
SCHEME=ec ./test_interrupted_rebalance.sh
|
SCHEME=ec ./test_interrupted_rebalance.sh
|
||||||
SCHEME=ec IMMEDIATE_COMMIT=1 ./test_interrupted_rebalance.sh
|
SCHEME=ec IMMEDIATE_COMMIT=1 ./test_interrupted_rebalance.sh
|
||||||
|
|
||||||
./test_failure_domain.sh
|
|
||||||
|
|
||||||
./test_snapshot.sh
|
|
||||||
SCHEME=ec ./test_snapshot.sh
|
|
||||||
|
|
||||||
./test_minsize_1.sh
|
./test_minsize_1.sh
|
||||||
|
|
||||||
./test_move_reappear.sh
|
./test_move_reappear.sh
|
||||||
|
|
||||||
./test_rm.sh
|
|
||||||
|
|
||||||
./test_snapshot_chain.sh
|
|
||||||
SCHEME=ec ./test_snapshot_chain.sh
|
|
||||||
|
|
||||||
./test_snapshot_down.sh
|
|
||||||
SCHEME=ec ./test_snapshot_down.sh
|
|
||||||
|
|
||||||
./test_splitbrain.sh
|
|
||||||
|
|
||||||
./test_rebalance_verify.sh
|
./test_rebalance_verify.sh
|
||||||
IMMEDIATE_COMMIT=1 ./test_rebalance_verify.sh
|
IMMEDIATE_COMMIT=1 ./test_rebalance_verify.sh
|
||||||
SCHEME=ec ./test_rebalance_verify.sh
|
SCHEME=ec ./test_rebalance_verify.sh
|
||||||
SCHEME=ec IMMEDIATE_COMMIT=1 ./test_rebalance_verify.sh
|
SCHEME=ec IMMEDIATE_COMMIT=1 ./test_rebalance_verify.sh
|
||||||
|
|
||||||
|
./test_rm.sh
|
||||||
|
|
||||||
|
./test_snapshot.sh
|
||||||
|
SCHEME=ec ./test_snapshot.sh
|
||||||
|
|
||||||
|
./test_splitbrain.sh
|
||||||
|
|
||||||
./test_write.sh
|
./test_write.sh
|
||||||
SCHEME=xor ./test_write.sh
|
SCHEME=xor ./test_write.sh
|
||||||
|
|
||||||
@@ -52,6 +46,7 @@ SCHEME=xor ./test_write.sh
|
|||||||
|
|
||||||
PG_SIZE=2 ./test_heal.sh
|
PG_SIZE=2 ./test_heal.sh
|
||||||
SCHEME=ec ./test_heal.sh
|
SCHEME=ec ./test_heal.sh
|
||||||
|
IMMEDIATE_COMMIT=1 SCHEME=ec ./test_heal.sh
|
||||||
|
|
||||||
./test_scrub.sh
|
./test_scrub.sh
|
||||||
ZERO_OSD=2 ./test_scrub.sh
|
ZERO_OSD=2 ./test_scrub.sh
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ try_change 16
|
|||||||
|
|
||||||
# Monitor should report non-zero overall statistics at least once
|
# Monitor should report non-zero overall statistics at least once
|
||||||
|
|
||||||
if ! (grep /vitastor/stats ./testdata/mon.log | jq -s -e '[ .[] | select((.kv.value.op_stats.primary_write.count // 0 | tonumber) > 0) ] | length > 0'); then
|
if ! (grep /vitastor/stats ./testdata/mon.log | jq -s -e '[ .[] | select((.kv.value.op_stats.primary_write.count | tonumber) > 0) ] | length > 0'); then
|
||||||
format_error "FAILED: monitor doesn't aggregate stats"
|
format_error "FAILED: monitor doesn't aggregate stats"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ $ETCDCTL put /vitastor/osd/stats/7 '{"host":"host4","size":1073741824,"time":"'$
|
|||||||
$ETCDCTL put /vitastor/osd/stats/8 '{"host":"host4","size":1073741824,"time":"'$TIME'"}'
|
$ETCDCTL put /vitastor/osd/stats/8 '{"host":"host4","size":1073741824,"time":"'$TIME'"}'
|
||||||
$ETCDCTL put /vitastor/config/pools '{"1":{"name":"testpool","scheme":"replicated","pg_size":2,"pg_minsize":1,"pg_count":4,"failure_domain":"rack"}}'
|
$ETCDCTL put /vitastor/config/pools '{"1":{"name":"testpool","scheme":"replicated","pg_size":2,"pg_minsize":1,"pg_count":4,"failure_domain":"rack"}}'
|
||||||
|
|
||||||
|
cd mon
|
||||||
|
npm install
|
||||||
|
cd ..
|
||||||
node mon/mon-main.js --etcd_url $ETCD_URL --etcd_prefix "/vitastor" &>./testdata/mon.log &
|
node mon/mon-main.js --etcd_url $ETCD_URL --etcd_prefix "/vitastor" &>./testdata/mon.log &
|
||||||
MON_PID=$!
|
MON_PID=$!
|
||||||
|
|
||||||
|
|||||||
+17
-21
@@ -12,7 +12,7 @@ PG_COUNT=32
|
|||||||
. `dirname $0`/run_3osds.sh
|
. `dirname $0`/run_3osds.sh
|
||||||
check_qemu
|
check_qemu
|
||||||
|
|
||||||
IMG_SIZE=960
|
IMG_SIZE=128
|
||||||
|
|
||||||
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
|
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
|
||||||
|
|
||||||
@@ -22,32 +22,28 @@ LD_PRELOAD="build/src/libfio_vitastor.so" \
|
|||||||
|
|
||||||
kill_osds()
|
kill_osds()
|
||||||
{
|
{
|
||||||
sleep 5
|
for i in {1..60}; do
|
||||||
|
sleep 5
|
||||||
kill -9 $OSD1_PID
|
K=$((1 + RANDOM % OSD_COUNT))
|
||||||
$ETCDCTL del /vitastor/osd/state/1
|
eval "kill -9 \$OSD${K}_PID"
|
||||||
|
$ETCDCTL del /vitastor/osd/state/$K
|
||||||
for i in 2 3 4 5 6 7; do
|
start_osd $K
|
||||||
sleep 15
|
|
||||||
echo Killing OSD $i and starting OSD $((i-1))
|
|
||||||
p=OSD${i}_PID
|
|
||||||
kill -9 ${!p}
|
|
||||||
$ETCDCTL del /vitastor/osd/state/$i
|
|
||||||
start_osd $((i-1))
|
|
||||||
sleep 15
|
|
||||||
done
|
done
|
||||||
|
|
||||||
sleep 5
|
|
||||||
start_osd 7
|
|
||||||
|
|
||||||
sleep 5
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kill_osds &
|
kill_osds &
|
||||||
|
|
||||||
LD_PRELOAD="build/src/libfio_vitastor.so" \
|
LD_PRELOAD="build/src/libfio_vitastor.so" \
|
||||||
fio -thread -name=test -ioengine=build/src/libfio_vitastor.so -bsrange=4k-128k -direct=1 -iodepth=32 -fsync=256 -rw=randrw \
|
fio -thread -name=test -ioengine=build/src/libfio_vitastor.so -bs=512k -direct=1 -iodepth=8 -fsync=256 -rw=write \
|
||||||
-randrepeat=0 -refill_buffers=1 -mirror_file=./testdata/mirror.bin -etcd=$ETCD_URL -image=testimg -loops=10 -runtime=120
|
-refill_buffers=1 -mirror_file=./testdata/mirror.bin -etcd=$ETCD_URL -image=testimg -loops=1000 -runtime=120 &>/dev/null &
|
||||||
|
|
||||||
|
LD_PRELOAD="build/src/libfio_vitastor.so" \
|
||||||
|
fio -thread -name=test -ioengine=build/src/libfio_vitastor.so -bs=512k -direct=1 -iodepth=8 -fsync=256 -rw=write \
|
||||||
|
-refill_buffers=1 -mirror_file=./testdata/mirror.bin -etcd=$ETCD_URL -image=testimg -loops=1000 -runtime=120 &>/dev/null &
|
||||||
|
|
||||||
|
LD_PRELOAD="build/src/libfio_vitastor.so" \
|
||||||
|
fio -thread -name=test -ioengine=build/src/libfio_vitastor.so -bs=512k -direct=1 -iodepth=8 -fsync=256 -rw=write \
|
||||||
|
-refill_buffers=1 -mirror_file=./testdata/mirror.bin -etcd=$ETCD_URL -image=testimg -loops=1000 -runtime=120
|
||||||
|
|
||||||
qemu-img convert -S 4096 -p \
|
qemu-img convert -S 4096 -p \
|
||||||
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
|
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
#!/bin/bash -ex
|
|
||||||
|
|
||||||
. `dirname $0`/run_3osds.sh
|
|
||||||
check_qemu
|
|
||||||
|
|
||||||
# Test multiple snapshots
|
|
||||||
|
|
||||||
build/src/vitastor-cli --etcd_address $ETCD_URL create -s 32M testchain
|
|
||||||
|
|
||||||
LD_PRELOAD="build/src/libfio_vitastor.so" \
|
|
||||||
fio -thread -name=test -ioengine=build/src/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
|
|
||||||
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/mirror.bin
|
|
||||||
|
|
||||||
for i in {1..10}; do
|
|
||||||
# Create a snapshot
|
|
||||||
build/src/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@$i
|
|
||||||
# Check that the new snapshot is see-through
|
|
||||||
qemu-img convert -p \
|
|
||||||
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
|
|
||||||
-O raw ./testdata/check.bin
|
|
||||||
cmp ./testdata/check.bin ./testdata/mirror.bin
|
|
||||||
# Write something to it
|
|
||||||
LD_PRELOAD="build/src/libfio_vitastor.so" \
|
|
||||||
fio -thread -name=test -ioengine=build/src/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=32 -rw=randwrite \
|
|
||||||
-randrepeat=$((i <= 2)) -buffer_pattern=0x$((10+i))$((10+i))$((10+i))$((10+i)) \
|
|
||||||
-etcd=$ETCD_URL -image=testchain -number_ios=1024 -mirror_file=./testdata/mirror.bin
|
|
||||||
# Check the new content
|
|
||||||
qemu-img convert -p \
|
|
||||||
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
|
|
||||||
-O raw ./testdata/layer1.bin
|
|
||||||
cmp ./testdata/layer1.bin ./testdata/mirror.bin
|
|
||||||
done
|
|
||||||
|
|
||||||
build/src/vitastor-cli --etcd_address $ETCD_URL rm testchain@1 testchain@9
|
|
||||||
|
|
||||||
# Check the final image
|
|
||||||
qemu-img convert -p \
|
|
||||||
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
|
|
||||||
-O raw ./testdata/layer1.bin
|
|
||||||
cmp ./testdata/layer1.bin ./testdata/mirror.bin
|
|
||||||
|
|
||||||
# Check the last remaining snapshot
|
|
||||||
qemu-img convert -p \
|
|
||||||
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain@10" \
|
|
||||||
-O raw ./testdata/layer0.bin
|
|
||||||
cmp ./testdata/layer0.bin ./testdata/check.bin
|
|
||||||
|
|
||||||
format_green OK
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#!/bin/bash -ex
|
|
||||||
|
|
||||||
. `dirname $0`/run_3osds.sh
|
|
||||||
check_qemu
|
|
||||||
|
|
||||||
# Test merge to child (without "inverse rename" optimisation)
|
|
||||||
|
|
||||||
build/src/vitastor-cli --etcd_address $ETCD_URL create -s 128M testchain
|
|
||||||
|
|
||||||
LD_PRELOAD="build/src/libfio_vitastor.so" \
|
|
||||||
fio -thread -name=test -ioengine=build/src/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
|
|
||||||
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/mirror.bin
|
|
||||||
|
|
||||||
# Create a snapshot
|
|
||||||
build/src/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@0
|
|
||||||
|
|
||||||
# Write something to it
|
|
||||||
LD_PRELOAD="build/src/libfio_vitastor.so" \
|
|
||||||
fio -thread -name=test -ioengine=build/src/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 -rw=randwrite \
|
|
||||||
-randrepeat=0 -etcd=$ETCD_URL -image=testchain -number_ios=8 -mirror_file=./testdata/mirror.bin
|
|
||||||
|
|
||||||
# Check the new content
|
|
||||||
qemu-img convert -p \
|
|
||||||
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
|
|
||||||
-O raw ./testdata/layer1.bin
|
|
||||||
cmp ./testdata/layer1.bin ./testdata/mirror.bin
|
|
||||||
|
|
||||||
# Merge
|
|
||||||
build/src/vitastor-cli --etcd_address $ETCD_URL rm testchain@0
|
|
||||||
|
|
||||||
# Check the final image
|
|
||||||
qemu-img convert -p \
|
|
||||||
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
|
|
||||||
-O raw ./testdata/layer1.bin
|
|
||||||
cmp ./testdata/layer1.bin ./testdata/mirror.bin
|
|
||||||
|
|
||||||
format_green OK
|
|
||||||
Reference in New Issue
Block a user