Compare commits

..

2 Commits

Author SHA1 Message Date
Vitaliy Filippov 26ee963b3e WIP "Heap" metadata storage scheme 2025-01-12 02:28:29 +03:00
Vitaliy Filippov 13ed3b63e4 Pass clean_bitmap explicitly 2025-01-12 02:23:37 +03:00
179 changed files with 1915 additions and 4830 deletions

View File

@ -2,6 +2,6 @@ cmake_minimum_required(VERSION 2.8.12)
project(vitastor) project(vitastor)
set(VITASTOR_VERSION "2.1.0") set(VITASTOR_VERSION "1.10.1")
add_subdirectory(src) add_subdirectory(src)

View File

@ -6,7 +6,7 @@
Вернём былую скорость кластерному блочному хранилищу! Вернём былую скорость кластерному блочному хранилищу!
Vitastor - распределённая блочная, файловая и объектная SDS (программная СХД), прямой аналог Ceph RBD, CephFS и RGW, Vitastor - распределённая блочная и файловая SDS (программная СХД), прямой аналог Ceph RBD и CephFS,
а также внутренних СХД популярных облачных провайдеров. Однако, в отличие от них, Vitastor а также внутренних СХД популярных облачных провайдеров. Однако, в отличие от них, Vitastor
быстрый и при этом простой. Только пока маленький :-). быстрый и при этом простой. Только пока маленький :-).
@ -41,12 +41,10 @@ Vitastor поддерживает QEMU-драйвер, протоколы NBD и
- [Автор и лицензия](docs/intro/author.ru.md) - [Автор и лицензия](docs/intro/author.ru.md)
- Установка - Установка
- [Пакеты](docs/installation/packages.ru.md) - [Пакеты](docs/installation/packages.ru.md)
- [Docker](docs/installation/docker.ru.md)
- [Proxmox](docs/installation/proxmox.ru.md) - [Proxmox](docs/installation/proxmox.ru.md)
- [OpenNebula](docs/installation/opennebula.ru.md) - [OpenNebula](docs/installation/opennebula.ru.md)
- [OpenStack](docs/installation/openstack.ru.md) - [OpenStack](docs/installation/openstack.ru.md)
- [Kubernetes CSI](docs/installation/kubernetes.ru.md) - [Kubernetes CSI](docs/installation/kubernetes.ru.md)
- [S3](docs/installation/s3.ru.md)
- [Сборка из исходных кодов](docs/installation/source.ru.md) - [Сборка из исходных кодов](docs/installation/source.ru.md)
- Конфигурация - Конфигурация
- [Обзор](docs/config.ru.md) - [Обзор](docs/config.ru.md)

View File

@ -6,7 +6,7 @@
Make Clustered Block Storage Fast Again. Make Clustered Block Storage Fast Again.
Vitastor is a distributed block, file and object SDS, direct replacement of Ceph RBD, CephFS and RGW, Vitastor is a distributed block and file SDS, direct replacement of Ceph RBD and CephFS,
and also internal SDS's of public clouds. However, in contrast to them, Vitastor is fast and also internal SDS's of public clouds. However, in contrast to them, Vitastor is fast
and simple at the same time. The only thing is it's slightly young :-). and simple at the same time. The only thing is it's slightly young :-).
@ -41,12 +41,10 @@ Read more details in the documentation. You can start from here: [Quick Start](d
- [Author and license](docs/intro/author.en.md) - [Author and license](docs/intro/author.en.md)
- Installation - Installation
- [Packages](docs/installation/packages.en.md) - [Packages](docs/installation/packages.en.md)
- [Docker](docs/installation/docker.en.md)
- [Proxmox](docs/installation/proxmox.en.md) - [Proxmox](docs/installation/proxmox.en.md)
- [OpenNebula](docs/installation/opennebula.en.md) - [OpenNebula](docs/installation/opennebula.en.md)
- [OpenStack](docs/installation/openstack.en.md) - [OpenStack](docs/installation/openstack.en.md)
- [Kubernetes CSI](docs/installation/kubernetes.en.md) - [Kubernetes CSI](docs/installation/kubernetes.en.md)
- [S3](docs/installation/s3.en.md)
- [Building from Source](docs/installation/source.en.md) - [Building from Source](docs/installation/source.en.md)
- Configuration - Configuration
- [Overview](docs/config.en.md) - [Overview](docs/config.en.md)

@ -1 +1 @@
Subproject commit 8de8b467acbca50cfd8835c20e0e379110f3b32b Subproject commit a21350e484cefa5728f23c227323b4b0822e738f

View File

@ -37,8 +37,8 @@ RUN (echo deb http://vitastor.io/debian bookworm main > /etc/apt/sources.list.d/
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 && \
apt-get update && \ apt-get update && \
apt-get install -y vitastor-client && \ apt-get install -y vitastor-client && \
wget https://vitastor.io/archive/qemu/qemu-bookworm-9.2.2%2Bds-1%2Bvitastor4/qemu-utils_9.2.2%2Bds-1%2Bvitastor4_amd64.deb && \ wget https://vitastor.io/archive/qemu/qemu-bookworm-8.1.2%2Bds-1%2Bvitastor1/qemu-utils_8.1.2%2Bds-1%2Bvitastor1_amd64.deb && \
wget https://vitastor.io/archive/qemu/qemu-bookworm-9.2.2%2Bds-1%2Bvitastor4/qemu-block-extra_9.2.2%2Bds-1%2Bvitastor4_amd64.deb && \ wget https://vitastor.io/archive/qemu/qemu-bookworm-8.1.2%2Bds-1%2Bvitastor1/qemu-block-extra_8.1.2%2Bds-1%2Bvitastor1_amd64.deb && \
dpkg -x qemu-utils*.deb tmp1 && \ dpkg -x qemu-utils*.deb tmp1 && \
dpkg -x qemu-block-extra*.deb tmp1 && \ dpkg -x qemu-block-extra*.deb tmp1 && \
cp -a tmp1/usr/bin/qemu-storage-daemon /usr/bin/ && \ cp -a tmp1/usr/bin/qemu-storage-daemon /usr/bin/ && \

View File

@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v2.1.0 VITASTOR_VERSION ?= v1.10.1
all: build push all: build push

View File

@ -49,7 +49,7 @@ spec:
capabilities: capabilities:
add: ["SYS_ADMIN"] add: ["SYS_ADMIN"]
allowPrivilegeEscalation: true allowPrivilegeEscalation: true
image: vitalif/vitastor-csi:v2.1.0 image: vitalif/vitastor-csi:v1.10.1
args: args:
- "--node=$(NODE_ID)" - "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"

View File

@ -121,7 +121,7 @@ spec:
privileged: true privileged: true
capabilities: capabilities:
add: ["SYS_ADMIN"] add: ["SYS_ADMIN"]
image: vitalif/vitastor-csi:v2.1.0 image: vitalif/vitastor-csi:v1.10.1
args: args:
- "--node=$(NODE_ID)" - "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"

View File

@ -5,7 +5,7 @@ package vitastor
const ( const (
vitastorCSIDriverName = "csi.vitastor.io" vitastorCSIDriverName = "csi.vitastor.io"
vitastorCSIDriverVersion = "2.1.0" vitastorCSIDriverVersion = "1.10.1"
) )
// Config struct fills the parameters of request or user input // Config struct fills the parameters of request or user input

2
debian/changelog vendored
View File

@ -1,4 +1,4 @@
vitastor (2.1.0-1) unstable; urgency=medium vitastor (1.10.1-1) unstable; urgency=medium
* Bugfixes * Bugfixes

11
debian/control vendored
View File

@ -2,10 +2,7 @@ Source: vitastor
Section: admin Section: admin
Priority: optional Priority: optional
Maintainer: Vitaliy Filippov <vitalif@yourcmc.ru> Maintainer: Vitaliy Filippov <vitalif@yourcmc.ru>
Build-Depends: debhelper, liburing-dev (>= 0.6), g++ (>= 8), libstdc++6 (>= 8), Build-Depends: debhelper, liburing-dev (>= 0.6), g++ (>= 8), libstdc++6 (>= 8), linux-libc-dev, libgoogle-perftools-dev, libjerasure-dev, libgf-complete-dev, libibverbs-dev, libisal-dev, cmake, pkg-config, libnl-3-dev, libnl-genl-3-dev
linux-libc-dev, libgoogle-perftools-dev, libjerasure-dev, libgf-complete-dev,
libibverbs-dev, libisal-dev, cmake, pkg-config, libnl-3-dev, libnl-genl-3-dev,
node-bindings <!nocheck>, node-gyp, node-nan
Standards-Version: 4.5.0 Standards-Version: 4.5.0
Homepage: https://vitastor.io/ Homepage: https://vitastor.io/
Rules-Requires-Root: no Rules-Requires-Root: no
@ -62,9 +59,3 @@ Architecture: amd64
Depends: ${shlibs:Depends}, ${misc:Depends}, vitastor-client, patch, python3, jq Depends: ${shlibs:Depends}, ${misc:Depends}, vitastor-client, patch, python3, jq
Description: Vitastor OpenNebula storage plugin Description: Vitastor OpenNebula storage plugin
Vitastor storage plugin for OpenNebula. Vitastor storage plugin for OpenNebula.
Package: node-vitastor
Architecture: amd64
Depends: ${shlibs:Depends}, ${misc:Depends}, node-bindings
Description: Node.js bindings for Vitastor client
Node.js native bindings for the Vitastor client library (vitastor-client).

View File

@ -1 +0,0 @@
usr/lib/x86_64-linux-gnu/nodejs/vitastor

View File

@ -1,23 +1,17 @@
# Build patched QEMU for Debian inside a container # Build patched QEMU for Debian 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 DISTRO=debian
ARG REL= ARG REL=
FROM $DISTRO:$REL FROM debian:$REL
ARG DISTRO=debian
ARG REL= ARG REL=
WORKDIR /root WORKDIR /root
RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" -o "$REL" = "bookworm" ]; then \ RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" -o "$REL" = "bookworm" ]; then \
if [ "$REL" = "buster" ]; then \ echo "deb http://deb.debian.org/debian $REL-backports main" >> /etc/apt/sources.list; \
echo "deb http://archive.debian.org/debian $REL-backports main" >> /etc/apt/sources.list; \
else \
echo "deb http://deb.debian.org/debian $REL-backports main" >> /etc/apt/sources.list; \
fi; \
echo >> /etc/apt/preferences; \ echo >> /etc/apt/preferences; \
echo 'Package: *' >> /etc/apt/preferences; \ echo 'Package: *' >> /etc/apt/preferences; \
echo "Pin: release n=$REL-backports" >> /etc/apt/preferences; \ echo "Pin: release a=$REL-backports" >> /etc/apt/preferences; \
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; \
@ -26,8 +20,8 @@ RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" -o "$REL" = "bookworm" ]; then
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 DEBIAN_FRONTEND=noninteractive TZ=Europe/Moscow apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts RUN apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts
RUN DEBIAN_FRONTEND=noninteractive TZ=Europe/Moscow 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
@ -44,9 +38,9 @@ ADD src/client/qemu_driver.c /root/qemu_driver.c
# apt-get install -y vitastor-client vitastor-client-dev quilt # apt-get install -y vitastor-client vitastor-client-dev quilt
RUN set -e; \ RUN set -e; \
DEBIAN_FRONTEND=noninteractive TZ=Europe/Moscow apt-get -y install /root/packages/vitastor-$REL/vitastor-client_*.deb /root/packages/vitastor-$REL/vitastor-client-dev_*.deb; \ dpkg -i /root/packages/vitastor-$REL/vitastor-client_*.deb /root/packages/vitastor-$REL/vitastor-client-dev_*.deb; \
apt-get update; \ apt-get update; \
DEBIAN_FRONTEND=noninteractive TZ=Europe/Moscow apt-get -y install quilt; \ apt-get install -y quilt; \
mkdir -p /root/packages/qemu-$REL; \ mkdir -p /root/packages/qemu-$REL; \
rm -rf /root/packages/qemu-$REL/*; \ rm -rf /root/packages/qemu-$REL/*; \
cd /root/packages/qemu-$REL; \ cd /root/packages/qemu-$REL; \
@ -60,7 +54,7 @@ RUN set -e; \
quilt add block/vitastor.c; \ quilt add block/vitastor.c; \
cp /root/qemu_driver.c block/vitastor.c; \ cp /root/qemu_driver.c block/vitastor.c; \
quilt refresh; \ quilt refresh; \
V=$(head -n1 debian/changelog | perl -pe 's/5\.2\+dfsg-9/5.2+dfsg-11/; s/^.*\((.*?)(\+deb\d+u\d+)?(~bpo[\d\+]*)?\).*$/$1/')+vitastor5; \ V=$(head -n1 debian/changelog | perl -pe 's/5\.2\+dfsg-9/5.2+dfsg-11/; s/^.*\((.*?)(~bpo[\d\+]*)?\).*$/$1/')+vitastor4; \
if [ "$REL" = bullseye ]; then V=${V}bullseye; fi; \ if [ "$REL" = bullseye ]; then V=${V}bullseye; fi; \
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'; \
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \ DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \

8
debian/rules vendored
View File

@ -4,14 +4,6 @@ export DH_VERBOSE = 1
%: %:
dh $@ dh $@
override_dh_install:
perl -pe 's!prefix=/usr!prefix='`pwd`'/debian/tmp/usr!' < obj-x86_64-linux-gnu/src/client/vitastor.pc > node-binding/vitastor.pc
cd node-binding && PKG_CONFIG_PATH=./ PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 npm install --unsafe-perm || exit 1
mkdir -p debian/tmp/usr/lib/x86_64-linux-gnu/nodejs/vitastor/build/Release
cp -v node-binding/package.json node-binding/index.js node-binding/addon.cc node-binding/addon.h node-binding/client.cc node-binding/client.h debian/tmp/usr/lib/x86_64-linux-gnu/nodejs/vitastor
cp -v node-binding/build/Release/addon.node debian/tmp/usr/lib/x86_64-linux-gnu/nodejs/vitastor/build/Release
dh_install
override_dh_installdeb: override_dh_installdeb:
cat debian/fio_version >> debian/vitastor-fio.substvars cat debian/fio_version >> debian/vitastor-fio.substvars
[ -f debian/qemu_version ] && (cat debian/qemu_version >> debian/vitastor-qemu.substvars) || true [ -f debian/qemu_version ] && (cat debian/qemu_version >> debian/vitastor-qemu.substvars) || true

View File

@ -22,8 +22,7 @@ RUN set -e -x; \
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 && \
apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts libjerasure-dev cmake \ apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts libjerasure-dev cmake libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl && \
libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl nodejs npm node-nan node-bindings && \
apt-get -y build-dep fio && \ apt-get -y build-dep fio && \
apt-get --download-only source fio apt-get --download-only source fio

View File

@ -1,11 +1,9 @@
# Build Docker image with Vitastor packages # Build Docker image with Vitastor packages
FROM debian:bookworm FROM debian:bullseye
ADD etc/apt /etc/apt/ ADD vitastor.list /etc/apt/sources.list.d
RUN apt-get update && apt-get -y install vitastor udev systemd qemu-system-x86 qemu-system-common qemu-block-extra qemu-utils jq nfs-common && apt-get clean ADD vitastor.gpg /etc/apt/trusted.gpg.d
ADD sleep.sh /usr/bin/ ADD vitastor.pref /etc/apt/preferences.d
ADD install.sh /usr/bin/ ADD apt.conf /etc/apt/
ADD scripts /opt/scripts/ RUN apt-get update && apt-get -y install vitastor qemu-system-x86 qemu-system-common && apt-get clean
ADD etc /etc/
RUN ln -s /usr/lib/vitastor/mon/make-etcd /usr/bin/make-etcd

View File

@ -1,9 +0,0 @@
VITASTOR_VERSION ?= v2.1.0
all: build push
build:
@docker build --no-cache --rm -t vitalif/vitastor:$(VITASTOR_VERSION) .
push:
@docker push vitalif/vitastor:$(VITASTOR_VERSION)

View File

@ -1,2 +0,0 @@
deb http://vitastor.io/debian bookworm main
deb http://http.debian.net/debian/ bookworm-backports main

View File

@ -1,27 +0,0 @@
[Unit]
Description=Containerized etcd for Vitastor
After=network-online.target local-fs.target time-sync.target docker.service vitastor-host.service
Wants=network-online.target local-fs.target time-sync.target docker.service vitastor-host.service
PartOf=vitastor.target
[Service]
Restart=always
Environment=GOGC=50
EnvironmentFile=/etc/vitastor/docker.conf
EnvironmentFile=/etc/vitastor/etcd.conf
SyslogIdentifier=etcd
ExecStart=bash -c 'docker run --rm -i -v /var/lib/vitastor/etcd:/data \
--log-driver none --network host $CONTAINER_OPTIONS --name vitastor-etcd \
$ETCD_IMAGE /usr/local/bin/etcd --name "$ETCD_NAME" --data-dir /data \
--snapshot-count 10000 --advertise-client-urls http://$ETCD_IP:2379 --listen-client-urls http://$ETCD_IP:2379 \
--initial-advertise-peer-urls http://$ETCD_IP:2380 --listen-peer-urls http://$ETCD_IP:2380 \
--initial-cluster-token vitastor-etcd-1 --initial-cluster "$ETCD_INITIAL_CLUSTER" \
--initial-cluster-state new --max-txn-ops=100000 --max-request-bytes=104857600 \
--auto-compaction-retention=10 --auto-compaction-mode=revision'
ExecStop=docker stop vitastor-etcd
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target

View File

@ -1,23 +0,0 @@
[Unit]
Description=Empty container for running Vitastor commands
After=network-online.target local-fs.target time-sync.target docker.service
Wants=network-online.target local-fs.target time-sync.target docker.service
PartOf=vitastor.target
[Service]
Restart=always
EnvironmentFile=/etc/vitastor/docker.conf
ExecStart=bash -c 'docker run --rm -i -v /etc/vitastor:/etc/vitastor -v /dev:/dev -v /run:/run \
--security-opt seccomp=unconfined --privileged --pid=host --log-driver none --network host --name vitastor vitastor:$VITASTOR_VERSION \
sleep.sh'
ExecStartPost=udevadm trigger
ExecStop=docker stop vitastor
WorkingDirectory=/
PrivateTmp=false
TasksMax=infinity
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target

View File

@ -1,23 +0,0 @@
[Unit]
Description=Containerized Vitastor monitor
After=network-online.target local-fs.target time-sync.target docker.service
Wants=network-online.target local-fs.target time-sync.target docker.service
PartOf=vitastor.target
[Service]
Restart=always
EnvironmentFile=/etc/vitastor/docker.conf
SyslogIdentifier=vitastor-mon
ExecStart=bash -c 'docker run --rm -i -v /etc/vitastor:/etc/vitastor -v /var/lib/vitastor:/var/lib/vitastor -v /dev:/dev \
--log-driver none --network host $CONTAINER_OPTIONS --name vitastor-mon vitastor:$VITASTOR_VERSION \
node /usr/lib/vitastor/mon/mon-main.js'
ExecStop=docker stop vitastor-mon
WorkingDirectory=/
PrivateTmp=false
TasksMax=infinity
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target

View File

@ -1,28 +0,0 @@
[Unit]
Description=Containerized Vitastor object storage daemon osd.%i
After=network-online.target local-fs.target time-sync.target docker.service vitastor-host.service
Wants=network-online.target local-fs.target time-sync.target docker.service vitastor-host.service
PartOf=vitastor.target
[Service]
LimitNOFILE=1048576
LimitNPROC=1048576
LimitMEMLOCK=infinity
EnvironmentFile=/etc/vitastor/docker.conf
SyslogIdentifier=vitastor-osd%i
ExecStart=bash -c 'docker run --rm -i -v /etc/vitastor:/etc/vitastor -v /dev:/dev \
$(for i in $(ls /dev/vitastor/osd%i-*); do echo --device $i:$i; done) \
--log-driver none --network host --ulimit nofile=1048576 --ulimit memlock=-1 \
--security-opt seccomp=unconfined $CONTAINER_OPTIONS --name vitastor-osd%i \
vitastor:$VITASTOR_VERSION vitastor-disk exec-osd /dev/vitastor/osd%i-data'
ExecStartPre=+docker exec vitastor vitastor-disk pre-exec /dev/vitastor/osd%i-data
ExecStop=docker stop vitastor-etcd%i
WorkingDirectory=/
PrivateTmp=false
TasksMax=infinity
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=vitastor.target

View File

@ -1,4 +0,0 @@
[Unit]
Description=vitastor target
[Install]
WantedBy=multi-user.target

View File

@ -1,7 +0,0 @@
SUBSYSTEM=="block", ENV{ID_PART_ENTRY_TYPE}=="e7009fac-a5a1-4d72-af72-53de13059903", \
OWNER="vitastor", GROUP="vitastor", \
IMPORT{program}="/usr/bin/docker exec vitastor vitastor-disk udev $devnode", \
SYMLINK+="vitastor/$env{VITASTOR_ALIAS}"
ENV{VITASTOR_OSD_NUM}!="", ACTION=="add", RUN{program}+="/usr/bin/systemctl enable --now --no-block vitastor-osd@$env{VITASTOR_OSD_NUM}"
ENV{VITASTOR_OSD_NUM}!="", ACTION=="remove", RUN{program}+="/usr/bin/systemctl disable --now --no-block vitastor-osd@$env{VITASTOR_OSD_NUM}"

View File

@ -1,11 +0,0 @@
#
# Configuration file for containerized Vitastor installation
# (non-Kubernetes, with systemd and udev-based orchestration)
#
# Desired Vitastor version
VITASTOR_VERSION=v2.1.0
# Additional arguments for all containers
# For example, you may want to specify a custom logging driver here
CONTAINER_OPTIONS=""

View File

@ -1,4 +0,0 @@
ETCD_IMAGE=quay.io/coreos/etcd:v3.5.18
ETCD_NAME=""
ETCD_IP=""
ETCD_INITIAL_CLUSTER=""

View File

@ -1,2 +0,0 @@
{
}

View File

@ -1,9 +0,0 @@
#!/bin/bash
set -e
cp -urv /etc/default /host-etc/
cp -urv /etc/systemd /host-etc/
cp -urv /etc/udev /host-etc/
cp -urnv /etc/vitastor /host-etc/
cp -urnv /opt/scripts/* /host-bin/

View File

@ -1,3 +0,0 @@
#!/bin/bash
docker exec -it vitastor vitastor-cli "$@"

View File

@ -1,3 +0,0 @@
#!/bin/bash
docker exec -it vitastor vitastor-disk "$@"

View File

@ -1,3 +0,0 @@
#!/bin/bash
docker exec -it vitastor fio "$@"

View File

@ -1,3 +0,0 @@
#!/bin/bash
docker exec -it vitastor vitastor-nbd "$@"

View File

@ -1,3 +0,0 @@
#!/bin/bash
while :; do sleep infinity; done

1
docker/vitastor.list Normal file
View File

@ -0,0 +1 @@
deb http://vitastor.io/debian bullseye main

View File

@ -13,7 +13,7 @@ Vitastor configuration consists of:
- [Separate OSD settings](config/pool.en.md#osd-settings) - [Separate OSD settings](config/pool.en.md#osd-settings)
- [Inode configuration](config/inode.en.md) i.e. image metadata like name, size and parent reference - [Inode configuration](config/inode.en.md) i.e. image metadata like name, size and parent reference
Configuration parameters can be set in 4 places: Configuration parameters can be set in 3 places:
- Configuration file (`/etc/vitastor/vitastor.conf` or other path) - Configuration file (`/etc/vitastor/vitastor.conf` or other path)
- etcd key `/vitastor/config/global`. Most variables can be set there, but etcd - etcd key `/vitastor/config/global`. Most variables can be set there, but etcd
connection parameters should obviously be set in the configuration file. connection parameters should obviously be set in the configuration file.

View File

@ -14,7 +14,7 @@
- [Настроек инодов](config/inode.ru.md), т.е. метаданных образов, таких, как имя, размер и ссылки на - [Настроек инодов](config/inode.ru.md), т.е. метаданных образов, таких, как имя, размер и ссылки на
родительский образ родительский образ
Параметры конфигурации могут задаваться в 4 местах: Параметры конфигурации могут задаваться в 3 местах:
- Файле конфигурации (`/etc/vitastor/vitastor.conf` или по другому пути) - Файле конфигурации (`/etc/vitastor/vitastor.conf` или по другому пути)
- Ключе в etcd `/vitastor/config/global`. Большая часть параметров может - Ключе в etcd `/vitastor/config/global`. Большая часть параметров может
задаваться там, кроме, естественно, самих параметров соединения с etcd, задаваться там, кроме, естественно, самих параметров соединения с etcd,

View File

@ -13,7 +13,6 @@ affect their interaction with the cluster.
- [client_retry_interval](#client_retry_interval) - [client_retry_interval](#client_retry_interval)
- [client_eio_retry_interval](#client_eio_retry_interval) - [client_eio_retry_interval](#client_eio_retry_interval)
- [client_retry_enospc](#client_retry_enospc) - [client_retry_enospc](#client_retry_enospc)
- [client_wait_up_timeout](#client_wait_up_timeout)
- [client_max_dirty_bytes](#client_max_dirty_bytes) - [client_max_dirty_bytes](#client_max_dirty_bytes)
- [client_max_dirty_ops](#client_max_dirty_ops) - [client_max_dirty_ops](#client_max_dirty_ops)
- [client_enable_writeback](#client_enable_writeback) - [client_enable_writeback](#client_enable_writeback)
@ -71,19 +70,6 @@ and clients are not blocked and just get EIO error code instead.
Retry writes on out of space errors to wait until some space is freed on Retry writes on out of space errors to wait until some space is freed on
OSDs. OSDs.
## client_wait_up_timeout
- Type: seconds
- Default: 16
- Can be changed online: yes
Wait for this number of seconds until PGs are up when doing operations
which require all PGs to be up. Currently only used by object listings
in delete and merge-based commands ([vitastor-cli rm](../usage/cli.en.md#rm), merge and so on).
The default value is calculated as `1 + OSD lease timeout`, which is
`1 + etcd_report_interval + max_etcd_attempts*2*etcd_quick_timeout`.
## client_max_dirty_bytes ## client_max_dirty_bytes
- Type: integer - Type: integer

View File

@ -13,7 +13,6 @@
- [client_retry_interval](#client_retry_interval) - [client_retry_interval](#client_retry_interval)
- [client_eio_retry_interval](#client_eio_retry_interval) - [client_eio_retry_interval](#client_eio_retry_interval)
- [client_retry_enospc](#client_retry_enospc) - [client_retry_enospc](#client_retry_enospc)
- [client_wait_up_timeout](#client_wait_up_timeout)
- [client_max_dirty_bytes](#client_max_dirty_bytes) - [client_max_dirty_bytes](#client_max_dirty_bytes)
- [client_max_dirty_ops](#client_max_dirty_ops) - [client_max_dirty_ops](#client_max_dirty_ops)
- [client_enable_writeback](#client_enable_writeback) - [client_enable_writeback](#client_enable_writeback)
@ -73,19 +72,6 @@ RDMA и хотите повысить пиковую производитель
Повторять запросы записи, завершившиеся с ошибками нехватки места, т.е. Повторять запросы записи, завершившиеся с ошибками нехватки места, т.е.
ожидать, пока на OSD не освободится место. ожидать, пока на OSD не освободится место.
## client_wait_up_timeout
- Тип: секунды
- Значение по умолчанию: 16
- Можно менять на лету: да
Время ожидания поднятия PG при операциях, требующих активности всех PG.
В данный момент используется листингами объектов в командах, использующих
удаление и слияние ([vitastor-cli rm](../usage/cli.ru.md#rm), merge и подобные).
Значение по умолчанию вычисляется как `1 + время lease OSD`, равное
`1 + etcd_report_interval + max_etcd_attempts*2*etcd_quick_timeout`.
## client_max_dirty_bytes ## client_max_dirty_bytes
- Тип: целое число - Тип: целое число

View File

@ -74,13 +74,13 @@ Grafana dashboard suitable for this exporter is here: [Vitastor-Grafana-6+.json]
- Type: integer - Type: integer
- Default: 8060 - Default: 8060
HTTP port for monitors to listen to (including metrics exporter) HTTP port for monitors to listen on (including metrics exporter)
## mon_http_ip ## mon_http_ip
- Type: string - Type: string
IP address for monitors to listen to (all addresses by default) IP address for monitors to listen on (all addresses by default)
## mon_https_cert ## mon_https_cert

View File

@ -9,11 +9,9 @@
These parameters apply to clients and OSDs and affect network connection logic These parameters apply to clients and OSDs and affect network connection logic
between clients, OSDs and etcd. between clients, OSDs and etcd.
- [osd_network](#osd_network) - [tcp_header_buffer_size](#tcp_header_buffer_size)
- [osd_cluster_network](#osd_cluster_network) - [use_sync_send_recv](#use_sync_send_recv)
- [use_rdma](#use_rdma) - [use_rdma](#use_rdma)
- [use_rdmacm](#use_rdmacm)
- [disable_tcp](#disable_tcp)
- [rdma_device](#rdma_device) - [rdma_device](#rdma_device)
- [rdma_port_num](#rdma_port_num) - [rdma_port_num](#rdma_port_num)
- [rdma_gid_index](#rdma_gid_index) - [rdma_gid_index](#rdma_gid_index)
@ -32,62 +30,38 @@ between clients, OSDs and etcd.
- [etcd_slow_timeout](#etcd_slow_timeout) - [etcd_slow_timeout](#etcd_slow_timeout)
- [etcd_keepalive_timeout](#etcd_keepalive_timeout) - [etcd_keepalive_timeout](#etcd_keepalive_timeout)
- [etcd_ws_keepalive_interval](#etcd_ws_keepalive_interval) - [etcd_ws_keepalive_interval](#etcd_ws_keepalive_interval)
- [etcd_min_reload_interval](#etcd_min_reload_interval)
- [tcp_header_buffer_size](#tcp_header_buffer_size)
- [use_sync_send_recv](#use_sync_send_recv)
## osd_network ## tcp_header_buffer_size
- Type: string or array of strings - Type: integer
- Default: 65536
Network mask of public OSD network(s) (IPv4 or IPv6). Each OSD listens to all Size of the buffer used to read data using an additional copy. Vitastor
addresses of UP + RUNNING interfaces matching one of these networks, on the packet headers are 128 bytes, payload is always at least 4 KB, so it is
same port. Port is auto-selected except if [bind_port](osd.en.md#bind_port) is usually beneficial to try to read multiple packets at once even though
explicitly specified. Bind address(es) may also be overridden manually by it requires to copy the data an additional time. The rest of each packet
specifying [bind_address](osd.en.md#bind_address). If OSD networks are not specified is received without an additional copy. You can try to play with this
at all, OSD just listens to a wildcard address (0.0.0.0). parameter and see how it affects random iops and linear bandwidth if you
want.
## osd_cluster_network ## use_sync_send_recv
- Type: string or array of strings - Type: boolean
- Default: false
Network mask of separate network(s) (IPv4 or IPv6) to use for OSD If true, synchronous send/recv syscalls are used instead of io_uring for
cluster connections. I.e. OSDs will always attempt to use these networks socket communication. Useless for OSDs because they require io_uring anyway,
to connect to other OSDs, while clients will attempt to use networks from but may be required for clients with old kernel versions.
[osd_network](#osd_network).
## use_rdma ## use_rdma
- Type: boolean - Type: boolean
- Default: true - Default: true
Try to use RDMA through libibverbs for communication if it's available. Try to use RDMA for communication if it's available. Disable if you don't
Disable if you don't want Vitastor to use RDMA. TCP-only clients can also want Vitastor to use RDMA. TCP-only clients can also talk to an RDMA-enabled
talk to an RDMA-enabled cluster, so disabling RDMA may be needed if clients cluster, so disabling RDMA may be needed if clients have RDMA devices,
have RDMA devices, but they are not connected to the cluster. but they are not connected to the cluster.
`use_rdma` works with RoCEv1/RoCEv2 networks, but not with iWARP and,
maybe, with some Infiniband configurations which require RDMA-CM.
Consider `use_rdmacm` for such networks.
## use_rdmacm
- Type: boolean
- Default: true
Use an alternative implementation of RDMA through RDMA-CM (Connection
Manager). Works with all RDMA networks: Infiniband, iWARP and
RoCEv1/RoCEv2, and even allows to disable TCP and run only with RDMA.
OSDs always use random port numbers for RDMA-CM listeners, different
from their TCP ports. `use_rdma` is automatically disabled when
`use_rdmacm` is enabled.
## disable_tcp
- Type: boolean
- Default: true
Fully disable TCP and only use RDMA-CM for OSD communication.
## rdma_device ## rdma_device
@ -118,13 +92,12 @@ PFC (Priority Flow Control) and ECN (Explicit Congestion Notification).
## rdma_port_num ## rdma_port_num
- Type: integer - Type: integer
- Default: 1
RDMA device port number to use. Only for devices that have more than 1 port. RDMA device port number to use. Only for devices that have more than 1 port.
See `phys_port_cnt` in `ibv_devinfo -v` output to determine how many ports See `phys_port_cnt` in `ibv_devinfo -v` output to determine how many ports
your device has. your device has.
Not relevant for RDMA-CM (use_rdmacm).
## rdma_gid_index ## rdma_gid_index
- Type: integer - Type: integer
@ -140,14 +113,13 @@ GID auto-selection is unsupported with libibverbs < v32.
A correct rdma_gid_index for RoCEv2 is usually 1 (IPv6) or 3 (IPv4). A correct rdma_gid_index for RoCEv2 is usually 1 (IPv6) or 3 (IPv4).
Not relevant for RDMA-CM (use_rdmacm).
## rdma_mtu ## rdma_mtu
- Type: integer - Type: integer
- Default: 4096
RDMA Path MTU to use. Must be 1024, 2048 or 4096. Default is to use the RDMA Path MTU to use. Must be 1024, 2048 or 4096. There is usually no
RDMA device's MTU. sense to change it from the default 4096.
## rdma_max_sge ## rdma_max_sge
@ -289,35 +261,3 @@ etcd_report_interval to guarantee that keepalive actually works.
etcd websocket ping interval required to keep the connection alive and etcd websocket ping interval required to keep the connection alive and
detect disconnections quickly. detect disconnections quickly.
## etcd_min_reload_interval
- Type: milliseconds
- Default: 1000
- Can be changed online: yes
Minimum interval for full etcd state reload. Introduced to prevent
excessive load on etcd during outages when etcd can't keep up with event
streams and cancels them.
## tcp_header_buffer_size
- Type: integer
- Default: 65536
Size of the buffer used to read data using an additional copy. Vitastor
packet headers are 128 bytes, payload is always at least 4 KB, so it is
usually beneficial to try to read multiple packets at once even though
it requires to copy the data an additional time. The rest of each packet
is received without an additional copy. You can try to play with this
parameter and see how it affects random iops and linear bandwidth if you
want.
## use_sync_send_recv
- Type: boolean
- Default: false
If true, synchronous send/recv syscalls are used instead of io_uring for
socket communication. Useless for OSDs because they require io_uring anyway,
but may be required for clients with old kernel versions.

View File

@ -9,11 +9,9 @@
Данные параметры используются клиентами и OSD и влияют на логику сетевого Данные параметры используются клиентами и OSD и влияют на логику сетевого
взаимодействия между клиентами, OSD, а также etcd. взаимодействия между клиентами, OSD, а также etcd.
- [osd_network](#osd_network) - [tcp_header_buffer_size](#tcp_header_buffer_size)
- [osd_cluster_network](#osd_cluster_network) - [use_sync_send_recv](#use_sync_send_recv)
- [use_rdma](#use_rdma) - [use_rdma](#use_rdma)
- [use_rdmacm](#use_rdmacm)
- [disable_tcp](#disable_tcp)
- [rdma_device](#rdma_device) - [rdma_device](#rdma_device)
- [rdma_port_num](#rdma_port_num) - [rdma_port_num](#rdma_port_num)
- [rdma_gid_index](#rdma_gid_index) - [rdma_gid_index](#rdma_gid_index)
@ -32,62 +30,41 @@
- [etcd_slow_timeout](#etcd_slow_timeout) - [etcd_slow_timeout](#etcd_slow_timeout)
- [etcd_keepalive_timeout](#etcd_keepalive_timeout) - [etcd_keepalive_timeout](#etcd_keepalive_timeout)
- [etcd_ws_keepalive_interval](#etcd_ws_keepalive_interval) - [etcd_ws_keepalive_interval](#etcd_ws_keepalive_interval)
- [etcd_min_reload_interval](#etcd_min_reload_interval)
- [tcp_header_buffer_size](#tcp_header_buffer_size)
- [use_sync_send_recv](#use_sync_send_recv)
## osd_network ## tcp_header_buffer_size
- Тип: строка или массив строк - Тип: целое число
- Значение по умолчанию: 65536
Маски подсетей (IPv4 или IPv6) публичной сети или сетей OSD. Каждый OSD слушает Размер буфера для чтения данных с дополнительным копированием. Пакеты
один и тот же порт на всех адресах поднятых (UP + RUNNING) сетевых интерфейсов, Vitastor содержат 128-байтные заголовки, за которыми следуют данные размером
соответствующих одной из указанных сетей. Порт выбирается автоматически, если от 4 КБ и для мелких операций ввода-вывода обычно выгодно за 1 вызов читать
только [bind_port](osd.ru.md#bind_port) не задан явно. Адреса для подключений можно сразу несколько пакетов, даже не смотря на то, что это требует лишний раз
также переопределить явно, задав [bind_address](osd.ru.md#bind_address). Если сети OSD скопировать данные. Часть каждого пакета за пределами значения данного
не заданы вообще, OSD слушает все адреса (0.0.0.0). параметра читается без дополнительного копирования. Вы можете попробовать
поменять этот параметр и посмотреть, как он влияет на производительность
случайного и линейного доступа.
## osd_cluster_network ## use_sync_send_recv
- Тип: строка или массив строк - Тип: булево (да/нет)
- Значение по умолчанию: false
Маски подсетей (IPv4 или IPv6) отдельной кластерной сети или сетей OSD. Если установлено в истину, то вместо io_uring для передачи данных по сети
То есть, OSD будут всегда стараться использовать эти сети для соединений будут использоваться обычные синхронные системные вызовы send/recv. Для OSD
с другими OSD, а клиенты будут стараться использовать сети из [osd_network](#osd_network). это бессмысленно, так как OSD в любом случае нуждается в io_uring, но, в
принципе, это может применяться для клиентов со старыми версиями ядра.
## use_rdma ## use_rdma
- Тип: булево (да/нет) - Тип: булево (да/нет)
- Значение по умолчанию: true - Значение по умолчанию: true
Попробовать использовать RDMA через libibverbs для связи при наличии Пытаться использовать RDMA для связи при наличии доступных устройств.
доступных устройств. Отключите, если вы не хотите, чтобы Vitastor Отключите, если вы не хотите, чтобы Vitastor использовал RDMA.
использовал RDMA. TCP-клиенты также могут работать с RDMA-кластером, TCP-клиенты также могут работать с RDMA-кластером, так что отключать
так что отключать RDMA может быть нужно, только если у клиентов есть RDMA может быть нужно только если у клиентов есть RDMA-устройства,
RDMA-устройства, но они не имеют соединения с кластером Vitastor. но они не имеют соединения с кластером Vitastor.
`use_rdma` работает с RoCEv1/RoCEv2 сетями, но не работает с iWARP и
может не работать с частью конфигураций Infiniband, требующих RDMA-CM.
Рассмотрите включение `use_rdmacm` для таких сетей.
## use_rdmacm
- Тип: булево (да/нет)
- Значение по умолчанию: true
Использовать альтернативную реализацию RDMA на основе RDMA-CM (Connection
Manager). Работает со всеми типами RDMA-сетей: Infiniband, iWARP и
RoCEv1/RoCEv2, и даже позволяет полностью отключить TCP и работать
только на RDMA. OSD используют случайные номера портов для ожидания
соединений через RDMA-CM, отличающиеся от их TCP-портов. Также при
включении `use_rdmacm` автоматически отключается опция `use_rdma`.
## disable_tcp
- Тип: булево (да/нет)
- Значение по умолчанию: true
Полностью отключить TCP и использовать только RDMA-CM для соединений с OSD.
## rdma_device ## rdma_device
@ -119,14 +96,13 @@ Control) и ECN (Explicit Congestion Notification).
## rdma_port_num ## rdma_port_num
- Тип: целое число - Тип: целое число
- Значение по умолчанию: 1
Номер порта RDMA-устройства, который следует использовать. Имеет смысл Номер порта RDMA-устройства, который следует использовать. Имеет смысл
только для устройств, у которых более 1 порта. Чтобы узнать, сколько портов только для устройств, у которых более 1 порта. Чтобы узнать, сколько портов
у вашего адаптера, посмотрите `phys_port_cnt` в выводе команды у вашего адаптера, посмотрите `phys_port_cnt` в выводе команды
`ibv_devinfo -v`. `ibv_devinfo -v`.
Опция неприменима к RDMA-CM (use_rdmacm).
## rdma_gid_index ## rdma_gid_index
- Тип: целое число - Тип: целое число
@ -143,14 +119,13 @@ libibverbs < v32.
Правильный rdma_gid_index для RoCEv2, как правило, 1 (IPv6) или 3 (IPv4). Правильный rdma_gid_index для RoCEv2, как правило, 1 (IPv6) или 3 (IPv4).
Опция неприменима к RDMA-CM (use_rdmacm).
## rdma_mtu ## rdma_mtu
- Тип: целое число - Тип: целое число
- Значение по умолчанию: 4096
Максимальная единица передачи (Path MTU) для RDMA. Должно быть равно 1024, Максимальная единица передачи (Path MTU) для RDMA. Должно быть равно 1024,
2048 или 4096. По умолчанию используется значение MTU RDMA-устройства. 2048 или 4096. Обычно нет смысла менять значение по умолчанию, равное 4096.
## rdma_max_sge ## rdma_max_sge
@ -296,37 +271,3 @@ etcd_report_interval, чтобы keepalive гарантированно рабо
- Можно менять на лету: да - Можно менять на лету: да
Интервал проверки живости вебсокет-подключений к etcd. Интервал проверки живости вебсокет-подключений к etcd.
## etcd_min_reload_interval
- Тип: миллисекунды
- Значение по умолчанию: 1000
- Можно менять на лету: да
Минимальный интервал полной перезагрузки состояния из etcd. Добавлено для
предотвращения избыточной нагрузки на etcd во время отказов, когда etcd не
успевает рассылать потоки событий и отменяет их.
## tcp_header_buffer_size
- Тип: целое число
- Значение по умолчанию: 65536
Размер буфера для чтения данных с дополнительным копированием. Пакеты
Vitastor содержат 128-байтные заголовки, за которыми следуют данные размером
от 4 КБ и для мелких операций ввода-вывода обычно выгодно за 1 вызов читать
сразу несколько пакетов, даже не смотря на то, что это требует лишний раз
скопировать данные. Часть каждого пакета за пределами значения данного
параметра читается без дополнительного копирования. Вы можете попробовать
поменять этот параметр и посмотреть, как он влияет на производительность
случайного и линейного доступа.
## use_sync_send_recv
- Тип: булево (да/нет)
- Значение по умолчанию: false
Если установлено в истину, то вместо io_uring для передачи данных по сети
будут использоваться обычные синхронные системные вызовы send/recv. Для OSD
это бессмысленно, так как OSD в любом случае нуждается в io_uring, но, в
принципе, это может применяться для клиентов со старыми версиями ядра.

View File

@ -7,15 +7,16 @@
# Runtime OSD Parameters # Runtime OSD Parameters
These parameters only apply to OSDs, are not fixed at the moment of OSD drive These parameters only apply to OSDs, are not fixed at the moment of OSD drive
initialization and can be changed - in /etc/vitastor/vitastor.conf or [vitastor-disk update-sb](../usage/disk.en.md#update-sb) initialization and can be changed - either with an OSD restart or, for some of
with an OSD restart or, for some of them, even without restarting by updating configuration in etcd. them, even without restarting by updating configuration in etcd.
- [bind_address](#bind_address)
- [bind_port](#bind_port)
- [osd_iothread_count](#osd_iothread_count) - [osd_iothread_count](#osd_iothread_count)
- [etcd_report_interval](#etcd_report_interval) - [etcd_report_interval](#etcd_report_interval)
- [etcd_stats_interval](#etcd_stats_interval) - [etcd_stats_interval](#etcd_stats_interval)
- [run_primary](#run_primary) - [run_primary](#run_primary)
- [osd_network](#osd_network)
- [bind_address](#bind_address)
- [bind_port](#bind_port)
- [autosync_interval](#autosync_interval) - [autosync_interval](#autosync_interval)
- [autosync_writes](#autosync_writes) - [autosync_writes](#autosync_writes)
- [recovery_queue_depth](#recovery_queue_depth) - [recovery_queue_depth](#recovery_queue_depth)
@ -60,26 +61,6 @@ with an OSD restart or, for some of them, even without restarting by updating co
- [recovery_tune_agg_interval](#recovery_tune_agg_interval) - [recovery_tune_agg_interval](#recovery_tune_agg_interval)
- [recovery_tune_sleep_min_us](#recovery_tune_sleep_min_us) - [recovery_tune_sleep_min_us](#recovery_tune_sleep_min_us)
- [recovery_tune_sleep_cutoff_us](#recovery_tune_sleep_cutoff_us) - [recovery_tune_sleep_cutoff_us](#recovery_tune_sleep_cutoff_us)
- [discard_on_start](#discard_on_start)
- [min_discard_size](#min_discard_size)
- [allow_net_split](#allow_net_split)
## bind_address
- Type: string or array of strings
Instead of the network masks ([osd_network](network.en.md#osd_network) and
[osd_cluster_network](network.en.md#osd_cluster_network)), you can also set
OSD listen addresses explicitly using this parameter. May be useful if you
want to start OSDs on interfaces that are not UP + RUNNING.
## bind_port
- Type: integer
By default, OSDs pick random ports to use for incoming connections
automatically. With this option you can set a specific port for a specific
OSD by hand.
## osd_iothread_count ## osd_iothread_count
@ -123,6 +104,34 @@ debugging purposes. It's possible to implement additional feature for the
monitor which may allow to separate primary and secondary OSDs, but it's monitor which may allow to separate primary and secondary OSDs, but it's
unclear why anyone could need it, so it's not implemented. unclear why anyone could need it, so it's not implemented.
## osd_network
- Type: string or array of strings
Network mask of the network (IPv4 or IPv6) to use for OSDs. Note that
although it's possible to specify multiple networks here, this does not
mean that OSDs will create multiple listening sockets - they'll only
pick the first matching address of an UP + RUNNING interface. Separate
networks for cluster and client connections are also not implemented, but
they are mostly useless anyway, so it's not a big deal.
## bind_address
- Type: string
- Default: 0.0.0.0
Instead of the network mask, you can also set OSD listen address explicitly
using this parameter. May be useful if you want to start OSDs on interfaces
that are not UP + RUNNING.
## bind_port
- Type: integer
By default, OSDs pick random ports to use for incoming connections
automatically. With this option you can set a specific port for a specific
OSD by hand.
## autosync_interval ## autosync_interval
- Type: seconds - Type: seconds
@ -307,7 +316,7 @@ for hot data and slower disks - HDDs and maybe SATA SSDs - but will slightly
decrease write performance for fast disks because page cache is an overhead decrease write performance for fast disks because page cache is an overhead
itself. itself.
Choose "directsync" to use [immediate_commit](layout-cluster.en.md#immediate_commit) Choose "directsync" to use [immediate_commit](layout-cluster.ru.md#immediate_commit)
(which requires disable_data_fsync) with drives having write-back cache (which requires disable_data_fsync) with drives having write-back cache
which can't be turned off, for example, Intel Optane. Also note that *some* which can't be turned off, for example, Intel Optane. Also note that *some*
desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making
@ -620,30 +629,3 @@ are changed to 0.
Maximum possible value for auto-tuned recovery_sleep_us. Higher values Maximum possible value for auto-tuned recovery_sleep_us. Higher values
are treated as outliers and ignored in aggregation. are treated as outliers and ignored in aggregation.
## discard_on_start
- Type: boolean
Discard (SSD TRIM) unused data device blocks on every OSD startup.
## min_discard_size
- Type: integer
- Default: 1048576
Minimum consecutive block size to TRIM it.
## allow_net_split
- Type: boolean
- Default: false
Allow "safe" cases of network splits/partitions - allow to start PGs without
connections to some OSDs currently registered as alive in etcd, if the number
of actually connected PG OSDs is at least pg_minsize. That is, allow some OSDs to lose
connectivity with some other OSDs as long as it doesn't break pg_minsize guarantees.
The downside is that it increases the probability of writing data into just pg_minsize
OSDs during failover which can lead to PGs becoming incomplete after additional outages.
The old behaviour in versions up to 2.0.0 was equal to enabled allow_net_split.

View File

@ -8,15 +8,16 @@
Данные параметры используются только OSD, но, в отличие от дисковых параметров, Данные параметры используются только OSD, но, в отличие от дисковых параметров,
не фиксируются в момент инициализации дисков OSD и могут быть изменены в любой не фиксируются в момент инициализации дисков OSD и могут быть изменены в любой
момент с перезапуском OSD в /etc/vitastor/vitastor.conf или [vitastor-disk update-sb](../usage/disk.ru.md#update-sb), момент с помощью перезапуска OSD, а некоторые и без перезапуска, с помощью
а некоторые и без перезапуска, с помощью изменения конфигурации в etcd. изменения конфигурации в etcd.
- [bind_address](#bind_address)
- [bind_port](#bind_port)
- [osd_iothread_count](#osd_iothread_count) - [osd_iothread_count](#osd_iothread_count)
- [etcd_report_interval](#etcd_report_interval) - [etcd_report_interval](#etcd_report_interval)
- [etcd_stats_interval](#etcd_stats_interval) - [etcd_stats_interval](#etcd_stats_interval)
- [run_primary](#run_primary) - [run_primary](#run_primary)
- [osd_network](#osd_network)
- [bind_address](#bind_address)
- [bind_port](#bind_port)
- [autosync_interval](#autosync_interval) - [autosync_interval](#autosync_interval)
- [autosync_writes](#autosync_writes) - [autosync_writes](#autosync_writes)
- [recovery_queue_depth](#recovery_queue_depth) - [recovery_queue_depth](#recovery_queue_depth)
@ -61,26 +62,6 @@
- [recovery_tune_agg_interval](#recovery_tune_agg_interval) - [recovery_tune_agg_interval](#recovery_tune_agg_interval)
- [recovery_tune_sleep_min_us](#recovery_tune_sleep_min_us) - [recovery_tune_sleep_min_us](#recovery_tune_sleep_min_us)
- [recovery_tune_sleep_cutoff_us](#recovery_tune_sleep_cutoff_us) - [recovery_tune_sleep_cutoff_us](#recovery_tune_sleep_cutoff_us)
- [discard_on_start](#discard_on_start)
- [min_discard_size](#min_discard_size)
- [allow_net_split](#allow_net_split)
## bind_address
- Тип: строка или массив строк
Вместо использования масок подсети ([osd_network](network.ru.md#osd_network) и
[osd_cluster_network](network.ru.md#osd_cluster_network)), вы также можете явно
задать адрес(а), на которых будут ожидать соединений OSD, с помощью данного
параметра. Это может быть полезно, например, чтобы запускать OSD на неподнятых
интерфейсах (не UP + RUNNING).
## bind_port
- Тип: целое число
По умолчанию OSD сами выбирают случайные порты для входящих подключений.
С помощью данной опции вы можете задать порт для отдельного OSD вручную.
## osd_iothread_count ## osd_iothread_count
@ -126,6 +107,34 @@ max_etcd_attempts * etcd_quick_timeout.
первичные OSD от вторичных, но пока не понятно, зачем это может кому-то первичные OSD от вторичных, но пока не понятно, зачем это может кому-то
понадобиться, поэтому это не реализовано. понадобиться, поэтому это не реализовано.
## osd_network
- Тип: строка или массив строк
Маска подсети (IPv4 или IPv6) для использования для соединений с OSD.
Имейте в виду, что хотя сейчас и можно передать в этот параметр несколько
подсетей, это не означает, что OSD будут создавать несколько слушающих
сокетов - они лишь будут выбирать адрес первого поднятого (состояние UP +
RUNNING), подходящий под заданную маску. Также не реализовано разделение
кластерной и публичной сетей OSD. Правда, от него обычно всё равно довольно
мало толку, так что особенной проблемы в этом нет.
## bind_address
- Тип: строка
- Значение по умолчанию: 0.0.0.0
Этим параметром можно явным образом задать адрес, на котором будет ожидать
соединений OSD (вместо использования маски подсети). Может быть полезно,
например, чтобы запускать OSD на неподнятых интерфейсах (не UP + RUNNING).
## bind_port
- Тип: целое число
По умолчанию OSD сами выбирают случайные порты для входящих подключений.
С помощью данной опции вы можете задать порт для отдельного OSD вручную.
## autosync_interval ## autosync_interval
- Тип: секунды - Тип: секунды
@ -651,31 +660,3 @@ EC (кодов коррекции ошибок) с более, чем 1 диск
Максимальное возможное значение авто-подстроенного recovery_sleep_us. Максимальное возможное значение авто-подстроенного recovery_sleep_us.
Большие значения считаются случайными выбросами и игнорируются в Большие значения считаются случайными выбросами и игнорируются в
усреднении. усреднении.
## discard_on_start
- Тип: булево (да/нет)
Освобождать (SSD TRIM) неиспользуемые блоки диска данных при каждом запуске OSD.
## min_discard_size
- Тип: целое число
- Значение по умолчанию: 1048576
Минимальный размер последовательного блока данных, чтобы освобождать его через TRIM.
## allow_net_split
- Тип: булево (да/нет)
- Значение по умолчанию: false
Разрешить "безопасные" случаи разделений сети - разрешить активировать PG без
соединений к некоторым OSD, помеченным активными в etcd, если общее число активных
OSD в PG составляет как минимум pg_minsize. То есть, разрешать некоторым OSD терять
соединения с некоторыми другими OSD, если это не нарушает гарантий pg_minsize.
Минус такого разрешения в том, что оно повышает вероятность записи данных ровно в
pg_minsize OSD во время переключений, что может потом привести к тому, что PG станут
неполными (incomplete), если упадут ещё какие-то OSD.
Старое поведение в версиях до 2.0.0 было идентично включённому allow_net_split.

View File

@ -43,7 +43,7 @@ Parameters:
- [osd_tags](#osd_tags) - [osd_tags](#osd_tags)
- [primary_affinity_tags](#primary_affinity_tags) - [primary_affinity_tags](#primary_affinity_tags)
- [scrub_interval](#scrub_interval) - [scrub_interval](#scrub_interval)
- [used_for_app](#used_for_app) - [used_for_fs](#used_for_fs)
Examples: Examples:
@ -189,9 +189,6 @@ So, pg_minsize regulates the number of failures that a pool can tolerate
without temporary downtime for [osd_out_time](monitor.en.md#osd_out_time), without temporary downtime for [osd_out_time](monitor.en.md#osd_out_time),
but at a cost of slightly reduced storage reliability. but at a cost of slightly reduced storage reliability.
See also [allow_net_split](osd.en.md#allow_net_split) and
[PG state descriptions](../usage/admin.en.md#pg-states).
FIXME: pg_minsize behaviour may be changed in the future to only make PGs FIXME: pg_minsize behaviour may be changed in the future to only make PGs
read-only instead of deactivating them. read-only instead of deactivating them.
@ -380,37 +377,24 @@ of the OSDs containing a data chunk for a PG.
Automatic scrubbing interval for this pool. Overrides Automatic scrubbing interval for this pool. Overrides
[global scrub_interval setting](osd.en.md#scrub_interval). [global scrub_interval setting](osd.en.md#scrub_interval).
## used_for_app ## used_for_fs
- Type: string - Type: string
If non-empty, the pool is marked as used for a separate application, for example, If non-empty, the pool is marked as used for VitastorFS with metadata stored
VitastorFS or S3, which allocates Vitastor volume IDs by itself and does not use in block image (regular Vitastor volume) named as the value of this pool parameter.
image/inode metadata in etcd.
When a pool is marked as used for such app, regular block volume creation in it When a pool is marked as used for VitastorFS, regular block volume creation in it
is disabled (vitastor-cli refuses to create images without --force) to protect is disabled (vitastor-cli refuses to create images without --force) to protect
the user from block volume and FS/S3 volume ID collisions and data loss. the user from block volume and FS file ID collisions and data loss.
Also such pools do not calculate per-inode space usage statistics in etcd because [vitastor-nfs](../usage/nfs.ru.md), in its turn, refuses to use pools not marked
using it for an external application implies that it may contain a very large
number of volumes and their statistics may take too much space in etcd.
Setting used_for_app to `fs:<name>` tells Vitastor that the pool is used for VitastorFS
with VitastorKV metadata base stored in a block image (regular Vitastor volume) named
`<name>`.
[vitastor-nfs](../usage/nfs.en.md), in its turn, refuses to use pools not marked
for the corresponding FS when starting. This also implies that you can use one for the corresponding FS when starting. This also implies that you can use one
pool only for one VitastorFS. pool only for one VitastorFS.
If you plan to use the pool for S3, set its used_for_app to `s3:<name>`. `<name>` may The second thing that is disabled for VitastorFS pools is reporting per-inode space
be basically anything you want (for example, `s3:standard`) - it's not validated usage statistics in etcd because a FS pool may store a very large number of files
by Vitastor S3 components in any way. and statistics for them all would take a lot of space in etcd.
All other values except prefixed with `fs:` or `s3:` may be used freely and don't
mean anything special for Vitastor core components. For now, you can use them as
you wish.
# Examples # Examples

View File

@ -42,7 +42,7 @@
- [osd_tags](#osd_tags) - [osd_tags](#osd_tags)
- [primary_affinity_tags](#primary_affinity_tags) - [primary_affinity_tags](#primary_affinity_tags)
- [scrub_interval](#scrub_interval) - [scrub_interval](#scrub_interval)
- [used_for_app](#used_for_app) - [used_for_fs](#used_for_fs)
Примеры: Примеры:
@ -256,7 +256,7 @@ PG в Vitastor эферемерны, то есть вы можете менят
## raw_placement ## raw_placement
- Тип: строка - Type: string
Низкоуровневые правила генерации PG в форме DSL (доменно-специфичного языка). Низкоуровневые правила генерации PG в форме DSL (доменно-специфичного языка).
Используйте, только если действительно знаете, зачем вам это надо :) Используйте, только если действительно знаете, зачем вам это надо :)
@ -383,42 +383,26 @@ OSD с "all".
Интервал скраба, то есть, автоматической фоновой проверки данных для данного пула. Интервал скраба, то есть, автоматической фоновой проверки данных для данного пула.
Переопределяет [глобальную настройку scrub_interval](osd.ru.md#scrub_interval). Переопределяет [глобальную настройку scrub_interval](osd.ru.md#scrub_interval).
## used_for_app ## used_for_fs
- Тип: строка - Type: string
Если непусто, пул помечается как используемый для отдельного приложения, например, Если непусто, пул помечается как используемый для файловой системы VitastorFS с
для VitastorFS или S3, которое распределяет ID образов в пуле само и не использует метаданными, хранимыми в блочном образе Vitastor с именем, равным значению
метаданные образов/инодов в etcd. этого параметра.
Когда пул помечается используемым для такого приложения, создание обычных блочных Когда пул помечается как используемый для VitastorFS, создание обычных блочных
образов в нём запрещается (vitastor-cli отказывается создавать образы без --force), образов в нём отключается (vitastor-cli отказывается создавать образы без --force),
чтобы защитить пользователя от коллизий ID блочных образов и томов ФС/S3, и, чтобы защитить пользователя от коллизий ID файлов и блочных образов и, таким
таким образом, от потери данных. образом, от потери данных.
Также для таких пулов отключается передача статистики в etcd по отдельным инодам,
так как использование для внешнего приложения подразумевает, что пул может содержать
очень много томов и их статистика может занять слишком много места в etcd.
Установка used_for_app в значение `fs:<name>` сообщает о том, что пул используется
для VitastorFS с базой метаданных VitastorKV, хранимой в блочном образе с именем
`<name>`.
[vitastor-nfs](../usage/nfs.ru.md), в свою очередь, при запуске отказывается [vitastor-nfs](../usage/nfs.ru.md), в свою очередь, при запуске отказывается
использовать для ФС пулы, не помеченные, как используемые для неё. Это также использовать для ФС пулы, не выделенные для неё. Это также означает, что один
означает, что один пул может использоваться только для одной VitastorFS. пул может использоваться только для одной VitastorFS.
Если же вы планируете использовать пул для данных S3, установите его used_for_app Также для ФС-пулов отключается передача статистики в etcd по отдельным инодам,
в значение `s3:<name>`, где `<name>` - любое название по вашему усмотрению так как ФС-пул может содержать очень много файлов и статистика по ним всем
(например, `s3:standard`) - конкретное содержимое `<name>` пока никак не проверяется заняла бы очень много места в etcd.
компонентами Vitastor S3.
Смотрите также [allow_net_split](osd.ru.md#allow_net_split) и
[документацию по состояниям PG](../usage/admin.ru.md#состояния-pg).
Все остальные значения used_for_app, кроме начинающихся на `fs:` или `s3:`, не
означают ничего особенного для основных компонентов Vitastor. Поэтому сейчас вы
можете использовать их свободно любым желаемым способом.
# Примеры # Примеры

View File

@ -14,12 +14,8 @@
{{../../installation/packages.en.md}} {{../../installation/packages.en.md}}
{{../../installation/docker.en.md}}
{{../../installation/proxmox.en.md}} {{../../installation/proxmox.en.md}}
{{../../installation/opennebula.en.md}}
{{../../installation/openstack.en.md}} {{../../installation/openstack.en.md}}
{{../../installation/kubernetes.en.md}} {{../../installation/kubernetes.en.md}}

View File

@ -14,12 +14,8 @@
{{../../installation/packages.ru.md}} {{../../installation/packages.ru.md}}
{{../../installation/docker.ru.md}}
{{../../installation/proxmox.ru.md}} {{../../installation/proxmox.ru.md}}
{{../../installation/opennebula.ru.md}}
{{../../installation/openstack.ru.md}} {{../../installation/openstack.ru.md}}
{{../../installation/kubernetes.ru.md}} {{../../installation/kubernetes.ru.md}}

View File

@ -75,11 +75,11 @@
- name: mon_http_port - name: mon_http_port
type: int type: int
default: 8060 default: 8060
info: HTTP port for monitors to listen to (including metrics exporter) info: HTTP port for monitors to listen on (including metrics exporter)
info_ru: Порт, на котором мониторы принимают HTTP-соединения (в том числе для отдачи метрик) info_ru: Порт, на котором мониторы принимают HTTP-соединения (в том числе для отдачи метрик)
- name: mon_http_ip - name: mon_http_ip
type: string type: string
info: IP address for monitors to listen to (all addresses by default) info: IP address for monitors to listen on (all addresses by default)
info_ru: IP-адрес, на котором мониторы принимают HTTP-соединения (по умолчанию все адреса) info_ru: IP-адрес, на котором мониторы принимают HTTP-соединения (по умолчанию все адреса)
- name: mon_https_cert - name: mon_https_cert
type: string type: string

View File

@ -1,78 +1,49 @@
- name: osd_network - name: tcp_header_buffer_size
type: string or array of strings type: int
type_ru: строка или массив строк default: 65536
info: | info: |
Network mask of public OSD network(s) (IPv4 or IPv6). Each OSD listens to all Size of the buffer used to read data using an additional copy. Vitastor
addresses of UP + RUNNING interfaces matching one of these networks, on the packet headers are 128 bytes, payload is always at least 4 KB, so it is
same port. Port is auto-selected except if [bind_port](osd.en.md#bind_port) is usually beneficial to try to read multiple packets at once even though
explicitly specified. Bind address(es) may also be overridden manually by it requires to copy the data an additional time. The rest of each packet
specifying [bind_address](osd.en.md#bind_address). If OSD networks are not specified is received without an additional copy. You can try to play with this
at all, OSD just listens to a wildcard address (0.0.0.0). parameter and see how it affects random iops and linear bandwidth if you
want.
info_ru: | info_ru: |
Маски подсетей (IPv4 или IPv6) публичной сети или сетей OSD. Каждый OSD слушает Размер буфера для чтения данных с дополнительным копированием. Пакеты
один и тот же порт на всех адресах поднятых (UP + RUNNING) сетевых интерфейсов, Vitastor содержат 128-байтные заголовки, за которыми следуют данные размером
соответствующих одной из указанных сетей. Порт выбирается автоматически, если от 4 КБ и для мелких операций ввода-вывода обычно выгодно за 1 вызов читать
только [bind_port](osd.ru.md#bind_port) не задан явно. Адреса для подключений можно сразу несколько пакетов, даже не смотря на то, что это требует лишний раз
также переопределить явно, задав [bind_address](osd.ru.md#bind_address). Если сети OSD скопировать данные. Часть каждого пакета за пределами значения данного
не заданы вообще, OSD слушает все адреса (0.0.0.0). параметра читается без дополнительного копирования. Вы можете попробовать
- name: osd_cluster_network поменять этот параметр и посмотреть, как он влияет на производительность
type: string or array of strings случайного и линейного доступа.
type_ru: строка или массив строк - name: use_sync_send_recv
type: bool
default: false
info: | info: |
Network mask of separate network(s) (IPv4 or IPv6) to use for OSD If true, synchronous send/recv syscalls are used instead of io_uring for
cluster connections. I.e. OSDs will always attempt to use these networks socket communication. Useless for OSDs because they require io_uring anyway,
to connect to other OSDs, while clients will attempt to use networks from but may be required for clients with old kernel versions.
[osd_network](#osd_network).
info_ru: | info_ru: |
Маски подсетей (IPv4 или IPv6) отдельной кластерной сети или сетей OSD. Если установлено в истину, то вместо io_uring для передачи данных по сети
То есть, OSD будут всегда стараться использовать эти сети для соединений будут использоваться обычные синхронные системные вызовы send/recv. Для OSD
с другими OSD, а клиенты будут стараться использовать сети из [osd_network](#osd_network). это бессмысленно, так как OSD в любом случае нуждается в io_uring, но, в
принципе, это может применяться для клиентов со старыми версиями ядра.
- name: use_rdma - name: use_rdma
type: bool type: bool
default: true default: true
info: | info: |
Try to use RDMA through libibverbs for communication if it's available. Try to use RDMA for communication if it's available. Disable if you don't
Disable if you don't want Vitastor to use RDMA. TCP-only clients can also want Vitastor to use RDMA. TCP-only clients can also talk to an RDMA-enabled
talk to an RDMA-enabled cluster, so disabling RDMA may be needed if clients cluster, so disabling RDMA may be needed if clients have RDMA devices,
have RDMA devices, but they are not connected to the cluster. but they are not connected to the cluster.
`use_rdma` works with RoCEv1/RoCEv2 networks, but not with iWARP and,
maybe, with some Infiniband configurations which require RDMA-CM.
Consider `use_rdmacm` for such networks.
info_ru: | info_ru: |
Попробовать использовать RDMA через libibverbs для связи при наличии Пытаться использовать RDMA для связи при наличии доступных устройств.
доступных устройств. Отключите, если вы не хотите, чтобы Vitastor Отключите, если вы не хотите, чтобы Vitastor использовал RDMA.
использовал RDMA. TCP-клиенты также могут работать с RDMA-кластером, TCP-клиенты также могут работать с RDMA-кластером, так что отключать
так что отключать RDMA может быть нужно, только если у клиентов есть RDMA может быть нужно только если у клиентов есть RDMA-устройства,
RDMA-устройства, но они не имеют соединения с кластером Vitastor. но они не имеют соединения с кластером Vitastor.
`use_rdma` работает с RoCEv1/RoCEv2 сетями, но не работает с iWARP и
может не работать с частью конфигураций Infiniband, требующих RDMA-CM.
Рассмотрите включение `use_rdmacm` для таких сетей.
- name: use_rdmacm
type: bool
default: true
info: |
Use an alternative implementation of RDMA through RDMA-CM (Connection
Manager). Works with all RDMA networks: Infiniband, iWARP and
RoCEv1/RoCEv2, and even allows to disable TCP and run only with RDMA.
OSDs always use random port numbers for RDMA-CM listeners, different
from their TCP ports. `use_rdma` is automatically disabled when
`use_rdmacm` is enabled.
info_ru: |
Использовать альтернативную реализацию RDMA на основе RDMA-CM (Connection
Manager). Работает со всеми типами RDMA-сетей: Infiniband, iWARP и
RoCEv1/RoCEv2, и даже позволяет полностью отключить TCP и работать
только на RDMA. OSD используют случайные номера портов для ожидания
соединений через RDMA-CM, отличающиеся от их TCP-портов. Также при
включении `use_rdmacm` автоматически отключается опция `use_rdma`.
- name: disable_tcp
type: bool
default: true
info: |
Fully disable TCP and only use RDMA-CM for OSD communication.
info_ru: |
Полностью отключить TCP и использовать только RDMA-CM для соединений с OSD.
- name: rdma_device - name: rdma_device
type: string type: string
info: | info: |
@ -122,19 +93,16 @@
Control) и ECN (Explicit Congestion Notification). Control) и ECN (Explicit Congestion Notification).
- name: rdma_port_num - name: rdma_port_num
type: int type: int
default: 1
info: | info: |
RDMA device port number to use. Only for devices that have more than 1 port. RDMA device port number to use. Only for devices that have more than 1 port.
See `phys_port_cnt` in `ibv_devinfo -v` output to determine how many ports See `phys_port_cnt` in `ibv_devinfo -v` output to determine how many ports
your device has. your device has.
Not relevant for RDMA-CM (use_rdmacm).
info_ru: | info_ru: |
Номер порта RDMA-устройства, который следует использовать. Имеет смысл Номер порта RDMA-устройства, который следует использовать. Имеет смысл
только для устройств, у которых более 1 порта. Чтобы узнать, сколько портов только для устройств, у которых более 1 порта. Чтобы узнать, сколько портов
у вашего адаптера, посмотрите `phys_port_cnt` в выводе команды у вашего адаптера, посмотрите `phys_port_cnt` в выводе команды
`ibv_devinfo -v`. `ibv_devinfo -v`.
Опция неприменима к RDMA-CM (use_rdmacm).
- name: rdma_gid_index - name: rdma_gid_index
type: int type: int
info: | info: |
@ -148,8 +116,6 @@
GID auto-selection is unsupported with libibverbs < v32. GID auto-selection is unsupported with libibverbs < v32.
A correct rdma_gid_index for RoCEv2 is usually 1 (IPv6) or 3 (IPv4). A correct rdma_gid_index for RoCEv2 is usually 1 (IPv6) or 3 (IPv4).
Not relevant for RDMA-CM (use_rdmacm).
info_ru: | info_ru: |
Номер глобального идентификатора адреса RDMA-устройства, который следует Номер глобального идентификатора адреса RDMA-устройства, который следует
использовать. Разным gid_index могут соответствовать разные протоколы связи: использовать. Разным gid_index могут соответствовать разные протоколы связи:
@ -162,16 +128,15 @@
libibverbs < v32. libibverbs < v32.
Правильный rdma_gid_index для RoCEv2, как правило, 1 (IPv6) или 3 (IPv4). Правильный rdma_gid_index для RoCEv2, как правило, 1 (IPv6) или 3 (IPv4).
Опция неприменима к RDMA-CM (use_rdmacm).
- name: rdma_mtu - name: rdma_mtu
type: int type: int
default: 4096
info: | info: |
RDMA Path MTU to use. Must be 1024, 2048 or 4096. Default is to use the RDMA Path MTU to use. Must be 1024, 2048 or 4096. There is usually no
RDMA device's MTU. sense to change it from the default 4096.
info_ru: | info_ru: |
Максимальная единица передачи (Path MTU) для RDMA. Должно быть равно 1024, Максимальная единица передачи (Path MTU) для RDMA. Должно быть равно 1024,
2048 или 4096. По умолчанию используется значение MTU RDMA-устройства. 2048 или 4096. Обычно нет смысла менять значение по умолчанию, равное 4096.
- name: rdma_max_sge - name: rdma_max_sge
type: int type: int
default: 128 default: 128
@ -341,47 +306,3 @@
detect disconnections quickly. detect disconnections quickly.
info_ru: | info_ru: |
Интервал проверки живости вебсокет-подключений к etcd. Интервал проверки живости вебсокет-подключений к etcd.
- name: etcd_min_reload_interval
type: ms
default: 1000
online: true
info: |
Minimum interval for full etcd state reload. Introduced to prevent
excessive load on etcd during outages when etcd can't keep up with event
streams and cancels them.
info_ru: |
Минимальный интервал полной перезагрузки состояния из etcd. Добавлено для
предотвращения избыточной нагрузки на etcd во время отказов, когда etcd не
успевает рассылать потоки событий и отменяет их.
- name: tcp_header_buffer_size
type: int
default: 65536
info: |
Size of the buffer used to read data using an additional copy. Vitastor
packet headers are 128 bytes, payload is always at least 4 KB, so it is
usually beneficial to try to read multiple packets at once even though
it requires to copy the data an additional time. The rest of each packet
is received without an additional copy. You can try to play with this
parameter and see how it affects random iops and linear bandwidth if you
want.
info_ru: |
Размер буфера для чтения данных с дополнительным копированием. Пакеты
Vitastor содержат 128-байтные заголовки, за которыми следуют данные размером
от 4 КБ и для мелких операций ввода-вывода обычно выгодно за 1 вызов читать
сразу несколько пакетов, даже не смотря на то, что это требует лишний раз
скопировать данные. Часть каждого пакета за пределами значения данного
параметра читается без дополнительного копирования. Вы можете попробовать
поменять этот параметр и посмотреть, как он влияет на производительность
случайного и линейного доступа.
- name: use_sync_send_recv
type: bool
default: false
info: |
If true, synchronous send/recv syscalls are used instead of io_uring for
socket communication. Useless for OSDs because they require io_uring anyway,
but may be required for clients with old kernel versions.
info_ru: |
Если установлено в истину, то вместо io_uring для передачи данных по сети
будут использоваться обычные синхронные системные вызовы send/recv. Для OSD
это бессмысленно, так как OSD в любом случае нуждается в io_uring, но, в
принципе, это может применяться для клиентов со старыми версиями ядра.

View File

@ -1,5 +1,5 @@
# Runtime OSD Parameters # Runtime OSD Parameters
These parameters only apply to OSDs, are not fixed at the moment of OSD drive These parameters only apply to OSDs, are not fixed at the moment of OSD drive
initialization and can be changed - in /etc/vitastor/vitastor.conf or [vitastor-disk update-sb](../usage/disk.en.md#update-sb) initialization and can be changed - either with an OSD restart or, for some of
with an OSD restart or, for some of them, even without restarting by updating configuration in etcd. them, even without restarting by updating configuration in etcd.

View File

@ -2,5 +2,5 @@
Данные параметры используются только OSD, но, в отличие от дисковых параметров, Данные параметры используются только OSD, но, в отличие от дисковых параметров,
не фиксируются в момент инициализации дисков OSD и могут быть изменены в любой не фиксируются в момент инициализации дисков OSD и могут быть изменены в любой
момент с перезапуском OSD в /etc/vitastor/vitastor.conf или [vitastor-disk update-sb](../usage/disk.ru.md#update-sb), момент с помощью перезапуска OSD, а некоторые и без перезапуска, с помощью
а некоторые и без перезапуска, с помощью изменения конфигурации в etcd. изменения конфигурации в etcd.

View File

@ -1,26 +1,3 @@
- name: bind_address
type: string or array of strings
type_ru: строка или массив строк
info: |
Instead of the network masks ([osd_network](network.en.md#osd_network) and
[osd_cluster_network](network.en.md#osd_cluster_network)), you can also set
OSD listen addresses explicitly using this parameter. May be useful if you
want to start OSDs on interfaces that are not UP + RUNNING.
info_ru: |
Вместо использования масок подсети ([osd_network](network.ru.md#osd_network) и
[osd_cluster_network](network.ru.md#osd_cluster_network)), вы также можете явно
задать адрес(а), на которых будут ожидать соединений OSD, с помощью данного
параметра. Это может быть полезно, например, чтобы запускать OSD на неподнятых
интерфейсах (не UP + RUNNING).
- name: bind_port
type: int
info: |
By default, OSDs pick random ports to use for incoming connections
automatically. With this option you can set a specific port for a specific
OSD by hand.
info_ru: |
По умолчанию OSD сами выбирают случайные порты для входящих подключений.
С помощью данной опции вы можете задать порт для отдельного OSD вручную.
- name: osd_iothread_count - name: osd_iothread_count
type: int type: int
default: 0 default: 0
@ -79,6 +56,44 @@
реализовать дополнительный режим для монитора, который позволит отделять реализовать дополнительный режим для монитора, который позволит отделять
первичные OSD от вторичных, но пока не понятно, зачем это может кому-то первичные OSD от вторичных, но пока не понятно, зачем это может кому-то
понадобиться, поэтому это не реализовано. понадобиться, поэтому это не реализовано.
- name: osd_network
type: string or array of strings
type_ru: строка или массив строк
info: |
Network mask of the network (IPv4 or IPv6) to use for OSDs. Note that
although it's possible to specify multiple networks here, this does not
mean that OSDs will create multiple listening sockets - they'll only
pick the first matching address of an UP + RUNNING interface. Separate
networks for cluster and client connections are also not implemented, but
they are mostly useless anyway, so it's not a big deal.
info_ru: |
Маска подсети (IPv4 или IPv6) для использования для соединений с OSD.
Имейте в виду, что хотя сейчас и можно передать в этот параметр несколько
подсетей, это не означает, что OSD будут создавать несколько слушающих
сокетов - они лишь будут выбирать адрес первого поднятого (состояние UP +
RUNNING), подходящий под заданную маску. Также не реализовано разделение
кластерной и публичной сетей OSD. Правда, от него обычно всё равно довольно
мало толку, так что особенной проблемы в этом нет.
- name: bind_address
type: string
default: "0.0.0.0"
info: |
Instead of the network mask, you can also set OSD listen address explicitly
using this parameter. May be useful if you want to start OSDs on interfaces
that are not UP + RUNNING.
info_ru: |
Этим параметром можно явным образом задать адрес, на котором будет ожидать
соединений OSD (вместо использования маски подсети). Может быть полезно,
например, чтобы запускать OSD на неподнятых интерфейсах (не UP + RUNNING).
- name: bind_port
type: int
info: |
By default, OSDs pick random ports to use for incoming connections
automatically. With this option you can set a specific port for a specific
OSD by hand.
info_ru: |
По умолчанию OSD сами выбирают случайные порты для входящих подключений.
С помощью данной опции вы можете задать порт для отдельного OSD вручную.
- name: autosync_interval - name: autosync_interval
type: sec type: sec
default: 5 default: 5
@ -300,7 +315,7 @@
decrease write performance for fast disks because page cache is an overhead decrease write performance for fast disks because page cache is an overhead
itself. itself.
Choose "directsync" to use [immediate_commit](layout-cluster.en.md#immediate_commit) Choose "directsync" to use [immediate_commit](layout-cluster.ru.md#immediate_commit)
(which requires disable_data_fsync) with drives having write-back cache (which requires disable_data_fsync) with drives having write-back cache
which can't be turned off, for example, Intel Optane. Also note that *some* which can't be turned off, for example, Intel Optane. Also note that *some*
desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making
@ -750,34 +765,3 @@
Максимальное возможное значение авто-подстроенного recovery_sleep_us. Максимальное возможное значение авто-подстроенного recovery_sleep_us.
Большие значения считаются случайными выбросами и игнорируются в Большие значения считаются случайными выбросами и игнорируются в
усреднении. усреднении.
- name: discard_on_start
type: bool
info: Discard (SSD TRIM) unused data device blocks on every OSD startup.
info_ru: Освобождать (SSD TRIM) неиспользуемые блоки диска данных при каждом запуске OSD.
- name: min_discard_size
type: int
default: 1048576
info: Minimum consecutive block size to TRIM it.
info_ru: Минимальный размер последовательного блока данных, чтобы освобождать его через TRIM.
- name: allow_net_split
type: bool
default: false
info: |
Allow "safe" cases of network splits/partitions - allow to start PGs without
connections to some OSDs currently registered as alive in etcd, if the number
of actually connected PG OSDs is at least pg_minsize. That is, allow some OSDs to lose
connectivity with some other OSDs as long as it doesn't break pg_minsize guarantees.
The downside is that it increases the probability of writing data into just pg_minsize
OSDs during failover which can lead to PGs becoming incomplete after additional outages.
The old behaviour in versions up to 2.0.0 was equal to enabled allow_net_split.
info_ru: |
Разрешить "безопасные" случаи разделений сети - разрешить активировать PG без
соединений к некоторым OSD, помеченным активными в etcd, если общее число активных
OSD в PG составляет как минимум pg_minsize. То есть, разрешать некоторым OSD терять
соединения с некоторыми другими OSD, если это не нарушает гарантий pg_minsize.
Минус такого разрешения в том, что оно повышает вероятность записи данных ровно в
pg_minsize OSD во время переключений, что может потом привести к тому, что PG станут
неполными (incomplete), если упадут ещё какие-то OSD.
Старое поведение в версиях до 2.0.0 было идентично включённому allow_net_split.

View File

@ -1,60 +0,0 @@
[Documentation](../../README.md#documentation) → Installation → Dockerized Installation
-----
[Читать на русском](docker.ru.md)
# Dockerized Installation
Vitastor may be installed in Docker/Podman. In such setups etcd, monitors and OSD
all run in containers, but everything else looks as close as possible to a usual
setup with packages:
- host network is used
- auto-start is implemented through udev and systemd
- logs are written to journald (not docker json log files)
- command-line wrapper scripts are installed to the host system to call vitastor-disk,
vitastor-cli and others through the container
Such installations may be useful when it's impossible or inconvenient to install
Vitastor from packages, for example, in exotic Linux distributions.
If you don't want just a simple containerized installation, you can also take a look
at Vitastor Kubernetes operator: https://github.com/Antilles7227/vitastor-operator
## Installing Containers
The instruction is very simple.
1. Download a Docker image of the desired version: \
`docker pull vitastor:2.1.0`
2. Install scripts to the host system: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitastor:2.1.0 install.sh`
3. Reload udev rules: \
`udevadm control --reload-rules`
And you can return to [Quick Start](../intro/quickstart.en.md).
## Upgrading Containers
First make sure to check the topic [Upgrading Vitastor](../usage/admin.en.md#upgrading-vitastor)
to figure out if you need any additional steps.
Then, to upgrade a containerized installation, you just need to change the `VITASTOR_VERSION`
option in `/etc/vitastor/docker.conf` and restart all Vitastor services:
`systemctl restart vitastor.target`
## QEMU
Vitastor Docker image also contains QEMU, qemu-img and qemu-storage-daemon built with Vitastor support.
However, running QEMU in Docker is harder to setup and it depends on the used virtualization UI
(OpenNebula, Proxmox and so on). Some of them also required patched Libvirt.
That's why containerized installation of Vitastor doesn't contain a ready-made QEMU setup and it's
recommended to install QEMU from packages or build it manually.
## fio
Vitastor Docker image also contains fio and installs a wrapper called `vitastor-fio` to use it from
the host system.

View File

@ -1,60 +0,0 @@
[Документация](../../README-ru.md#документация) → Установка → Установка в Docker
-----
[Read in English](docker.en.md)
# Установка в Docker
Vitastor можно установить в Docker/Podman. При этом etcd, мониторы и OSD запускаются
в контейнерах, но всё остальное выглядит максимально приближенно к установке из пакетов:
- используется сеть хост-системы
- для автозапуска используются udev и systemd
- журналы записываются в journald (не в json-файлы журналов docker)
- в хост-систему устанавливаются обёртки для вызова консольных инструментов vitastor-disk,
vitastor-cli и других через контейнер
Такая установка полезна тогда, когда установка из пакетов невозможна или неудобна,
например, в нестандартных Linux-дистрибутивах.
Если вам нужна не просто контейнеризованная инсталляция, вы также можете обратить внимание
на Vitastor Kubernetes-оператор: https://github.com/Antilles7227/vitastor-operator
## Установка контейнеров
Инструкция по установке максимально простая.
1. Скачайте Docker-образ желаемой версии: \
`docker pull vitastor:2.1.0`
2. Установите скрипты в хост-систему командой: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitastor:2.1.0 install.sh`
3. Перезагрузите правила udev: \
`udevadm control --reload-rules`
После этого вы можете возвращаться к разделу [Быстрый старт](../intro/quickstart.ru.md).
## Обновление контейнеров
Сначала обязательно проверьте раздел [Обновление Vitastor](../usage/admin.ru.md#обновление-vitastor),
чтобы понять, не требуются ли вам какие-то дополнительные действия.
После этого для обновления Docker-инсталляции вам нужно просто поменять опцию `VITASTOR_VERSION`
в файле `/etc/vitastor/docker.conf` и перезапустить все сервисы Vitastor командой:
`systemctl restart vitastor.target`
## QEMU
В Docker-образ также входят QEMU, qemu-img и qemu-storage-daemon, собранные с поддержкой Vitastor.
Однако настроить запуск QEMU в Docker сложнее и способ запуска зависит от используемого интерфейса
виртуализации (OpenNebula, Proxmox и т.п.). Также для OpenNebula, например, требуется патченый
Libvirt.
Поэтому по умолчанию Docker-сборка пока что не включает в себя готового способа запуска QEMU
и QEMU рекомендуется устанавливать из пакетов или собирать самостоятельно.
## fio
fio также входит в Docker-контейнер vitastor, и в хост-систему устанавливается обёртка `vitastor-fio`
для запуска fio в контейнер.

View File

@ -14,7 +14,6 @@
- Debian 12 (Bookworm/Sid): `deb https://vitastor.io/debian bookworm main` - Debian 12 (Bookworm/Sid): `deb https://vitastor.io/debian bookworm main`
- Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main` - Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main`
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main` - Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
- Ubuntu 22.04 (Jammy): `deb https://vitastor.io/debian jammy main`
- Add `-oldstable` to bookworm/bullseye/buster in this line to install the last - Add `-oldstable` to bookworm/bullseye/buster in this line to install the last
stable version from 0.9.x branch instead of 1.x stable version from 0.9.x branch instead of 1.x
- Install packages: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86` - Install packages: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86`

View File

@ -14,7 +14,6 @@
- Debian 12 (Bookworm/Sid): `deb https://vitastor.io/debian bookworm main` - Debian 12 (Bookworm/Sid): `deb https://vitastor.io/debian bookworm main`
- Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main` - Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main`
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main` - Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
- Ubuntu 22.04 (Jammy): `deb https://vitastor.io/debian jammy main`
- Добавьте `-oldstable` к слову bookworm/bullseye/buster в этой строке, чтобы - Добавьте `-oldstable` к слову bookworm/bullseye/buster в этой строке, чтобы
установить последнюю стабильную версию из ветки 0.9.x вместо 1.x установить последнюю стабильную версию из ветки 0.9.x вместо 1.x
- Установите пакеты: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86` - Установите пакеты: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86`

View File

@ -1,191 +0,0 @@
[Documentation](../../README.md#documentation) → Installation → S3 for Vitastor
-----
[Читать на русском](s3.ru.md)
# S3 for Vitastor
The moment has come - Vitastor S3 implementation based on Zenko CloudServer is released.
## Highlights
- Zenko CloudServer is implemented in node.js.
- Object metadata is stored in MongoDB.
- Modified Zenko CloudServer version is used for Vitastor. It is slightly different from
the original, has an optimised build and unneeded dependencies are stripped off.
- Object data is stored in Vitastor block volumes, but the volume metadata is stored in
the same MongoDB, not in Vitastor etcd.
- Objects are written to volumes sequentially one after another. The space is allocated
with rounding to the sector size (4 KB), so each object takes at least 4 KB.
- An important property of such storage scheme is that small objects aren't chunked into
parts in Vitastor EC N+K pools and thus don't require reads from all N disks when
downloading.
- Deleted objects are marked as deleted, but the space is only actually freed during
asynchronously executed "defragmentation" process. Defragmentation runs automatically
in the background when a volume reaches configured amount of "garbage" (20% by default).
Defragmentation copies actual objects to new volume(s) and then removes the old volume.
Defragmentation can be configured in locationConfig.json.
## Plans for future development
- User account storage in the DB instead of a static file. Original Zenko uses
a separate closed-source "Scality Vault" service for it, that's why we use
a static file for now.
- More detailed documentation.
- Support for other (and faster) key-value DBMS for object metadata storage.
- Other performance optimisations, for example, related to the used hash function -
MD5 used for Amazon compatibility purposes is relatively slow.
- Object Lifecycle support. There is a Lifecycle implementation for Zenko called
[Backbeat](https://github.com/scality/backbeat) but it's not adapted for Vitastor yet.
- Quota support. Original Zenko uses a separate "SCUBA" service for quotas, but
it's also proprietary and not available publicly.
## Installation
In a few words:
- Install MongoDB, create a user for S3 metadata DB.
- Create a Vitastor pool for S3 data.
- Download and setup the Docker container `vitalif/vitastor-zenko`.
### Setup MongoDB
You can setup MongoDB yourself, following the [MongoDB manual](https://www.mongodb.com/docs/manual/installation/).
Or you can follow the instructions below - it describes a simple example of MongoDB setup
in Docker (through docker-compose) with 3 replicas.
1. On each host, create a file `docker-compose.yml` with the content listed below.
Replace `<YOUR_PASSWORD>` with your future mongodb administrator password, and optionally
replace `0.0.0.0` with `localhost,<server_IP>`. It's recommended to either use a private IP
or [setup TLS](https://www.mongodb.com/docs/manual/tutorial/configure-ssl/) afterwards.
```
version: '3.1'
services:
mongo:
container_name: mongo
image: mongo:7-jammy
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: <YOUR_PASSWORD>
network_mode: host
volumes:
- ./keyfile:/opt/keyfile
- ./mongo-data/db:/data/db
- ./mongo-data/configdb:/data/configdb
entrypoint: /bin/bash -c
command: [ "chown mongodb /opt/keyfile && chmod 600 /opt/keyfile && . /usr/local/bin/docker-entrypoint.sh mongod --replSet rs0 --keyFile /opt/keyfile --bind_ip 0.0.0.0" ]
```
2. Generate a shared cluster key using `openssl rand -base64 756 > ./keyfile` and copy
that `keyfile` to all hosts.
3. Start MongoDB on all hosts with `docker compose up -d mongo`.
4. Enter Mongo Shell with `docker exec -it mongo mongosh -u root -p <YOUR_PASSWORD> localhost/admin`
and execute the following command (replace IP addresses `10.10.10.{1,2,3}` with your host IPs):
`rs.initiate({ _id: 'rs0', members: [
{ _id: 1, host: '10.10.10.1:27017' },
{ _id: 2, host: '10.10.10.2:27017' },
{ _id: 3, host: '10.10.10.3:27017' }
] })`
5. Stay in Mongo Shell and create a user for the future S3 database:
`db.createUser({ user: 's3', pwd: '<YOUR_S3_PASSWORD>', roles: [
{ role: 'readWrite', db: 's3' },
{ role: 'dbAdmin', db: 's3' },
{ role: 'readWrite', db: 'vitastor' },
{ role: 'dbAdmin', db: 'vitastor' }
] })`
### Setup Vitastor
Create a pool in Vitastor for S3 object data, for example:
`vitastor-cli create-pool --ec 2+1 -n 512 s3-data --used_for_app s3:standard`
The `--used_for_app` options works as fool-proofing and prevents you from
accidentally creating a regular block volume in the S3 pool and overwriting some S3 data.
Also it hides inode space statistics from Vitastor etcd.
Retrieve the ID of your pool with `vitastor-cli ls-pools s3-data --detail`.
### Setup Vitastor S3
1. Add the following lines to `docker-compose.yml` (instead of `network_mode: host`,
you can use `ports: [ "8000:8000", "8002:8002" ]`):
```
zenko:
container_name: zenko
image: vitalif/vitastor-zenko
restart: always
security_opt:
- seccomp:unconfined
ulimits:
memlock: -1
network_mode: host
volumes:
- /etc/vitastor:/etc/vitastor
- /etc/vitastor/s3:/conf
```
2. Download Docker image: `docker pull vitalif/vitastor-zenko`
3. Extract configuration file examples from the Docker image:
```
docker run --rm -it -v /etc/vitastor:/etc/vitastor -v /etc/vitastor/s3:/conf vitalif/vitastor-zenko configure.sh
```
4. Edit configuration files in `/etc/vitastor/s3/`:
- `config.json` - common settings.
- `authdata.json` - user accounts and access keys.
- `locationConfig.json` - S3 storage class list with placement settings.
Note: it actually contains storage classes (like STANDARD, COLD, etc)
instead of "locations" (zones like us-east-1) as in the original Zenko CloudServer.
- Put your MongoDB connection data into `config.json` and `locationConfig.json`.
- Put your Vitastor pool ID into `locationConfig.json`.
- For now, the complete list of Vitastor backend settings is only available [in the code](https://git.yourcmc.ru/vitalif/zenko-arsenal/src/branch/master/lib/storage/data/vitastor/VitastorBackend.ts#L94).
### Start Zenko
Start the S3 server with:
```
docker run --restart always --security-opt seccomp:unconfined --ulimit memlock=-1 --network=host \
-v /etc/vitastor:/etc/vitastor -v /etc/vitastor/s3:/conf --name zenko vitalif/vitastor-zenko
```
If you use default settings, Zenko CloudServer starts on port 8000.
The default access key is `accessKey1` with a secret key of `verySecretKey1`.
Now you can access your S3 with, for example, [s3cmd](https://s3tools.org/s3cmd):
```
s3cmd --access_key=accessKey1 --secret_key=verySecretKey1 --host=http://localhost:8000 mb s3://testbucket
```
Or even mount it with [GeeseFS](https://github.com/yandex-cloud/geesefs):
```
AWS_ACCESS_KEY_ID=accessKey1 \
AWS_SECRET_ACCESS_KEY=verySecretKey1 \
geesefs --endpoint http://localhost:8000 testbucket mountdir
```
## Author & License
- [Zenko CloudServer](https://s3-server.readthedocs.io/en/latest/) author is Scality,
licensed under [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
- [Vitastor](https://git.yourcmc.ru/vitalif/vitastor/) and Zenko Vitastor backend author is
Vitaliy Filippov, licensed under [VNPL-1.1](https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/VNPL-1.1.txt)
(a "network copyleft" license based on AGPL/SSPL, but worded in a better way)
- Vitastor S3 repository: https://git.yourcmc.ru/vitalif/zenko-cloudserver-vitastor
- Vitastor S3 backend code: https://git.yourcmc.ru/vitalif/zenko-arsenal/src/branch/master/lib/storage/data/vitastor/VitastorBackend.ts

View File

@ -1,171 +0,0 @@
[Документация](../../README-ru.md#документация) → Установка → S3 на базе Vitastor
-----
[Read in English](s3.en.md)
# S3 на базе Vitastor
Итак, свершилось - реализация Vitastor S3 на базе Zenko CloudServer достигла
состояния готовности к публикации и использованию.
## Ключевые особенности
- Zenko CloudServer реализован на node.js.
- Метаданные объектов хранятся в MongoDB.
- Поставляется модифицированная версия Zenko CloudServer, отвязанная от лишних зависимостей,
с оптимизированной сборкой и немного отличающаяся от оригинала.
- Данные объектов хранятся в блочных томах Vitastor, однако информация о самих томах
сохраняется не в etcd Vitastor, а тоже в БД на основе MongoDB.
- Объекты записываются в тома последовательно друг за другом. Место выделяется с округлением
до размера сектора (до 4 килобайт), поэтому каждый объект занимает как минимум 4 КБ.
- Благодаря такой схеме записи объектов мелкие объекты не нарезаются на части и поэтому не
требуют чтения с N дисков данных в EC N+K пулах Vitastor.
- При удалении объекты помечаются удалёнными, но место освобождается не сразу, а при
запускаемой асинхронно "дефрагментации". Дефрагментация запускается автоматически в фоне
при достижении заданного объёма "мусора" в томе (по умолчанию 20%), копирует актуальные
объекты в новые тома, после чего очищает старый том полностью. Дефрагментацию можно
настраивать в locationConfig.json.
## Планы развития
- Хранение учётных записей в БД, а не в статическом файле (в оригинальном Zenko для
этого используется отдельный закрытый сервис "Scality Vault").
- Более подробная документация.
- Поддержка других (и более производительных) key-value СУБД для хранения метаданных.
- Другие оптимизации производительности, например, в области используемой хеш-функции
(хеш MD5, используемый в целях совместимости, относительно медленный).
- Поддержка Object Lifecycle. Реализация Lifecycle для Zenko существует и называется
[Backbeat](https://github.com/scality/backbeat), но она ещё не адаптирована для Vitastor.
- Квоты. В оригинальном Zenko для этого используется отдельный сервис "SCUBA", однако
он тоже является закрытым и недоступен для публичного использования.
## Установка
Кратко:
- Установите MongoDB, создайте пользователя для БД метаданных S3.
- Создайте в Vitastor пул для хранения данных объектов.
- Скачайте и настройте Docker-контейнер `vitalif/vitastor-zenko`.
### Установка MongoDB
Вы можете установить MongoDB сами, следуя [официальному руководству MongoDB](https://www.mongodb.com/docs/manual/installation/).
Либо вы можете последовать инструкции, приведённой ниже - здесь описан простейший пример
установки MongoDB в Docker (docker-compose) в конфигурации с 3 репликами.
1. На всех 3 серверах создайте файл `docker-compose.yml`, заменив `<ВАШ_ПАРОЛЬ>`
на собственный будущий пароль администратора mongodb, а `0.0.0.0` по желанию
заменив на на `localhost,<IP_сервера>` - желательно либо использовать публично не доступный IP,
либо потом [настроить TLS](https://www.mongodb.com/docs/manual/tutorial/configure-ssl/).
```
version: '3.1'
services:
mongo:
container_name: mongo
image: mongo:7-jammy
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: <ВАШ_ПАРОЛЬ>
network_mode: host
volumes:
- ./keyfile:/opt/keyfile
- ./mongo-data/db:/data/db
- ./mongo-data/configdb:/data/configdb
entrypoint: /bin/bash -c
command: [ "chown mongodb /opt/keyfile && chmod 600 /opt/keyfile && . /usr/local/bin/docker-entrypoint.sh mongod --replSet rs0 --keyFile /opt/keyfile --bind_ip 0.0.0.0" ]
```
2. В той же директории сгенерируйте общий ключ кластера командой `openssl rand -base64 756 > ./keyfile`
и скопируйте этот файл на все 3 сервера.
3. На всех 3 серверах запустите MongoDB командой `docker compose up -d mongo`.
4. Зайдите в Mongo Shell с помощью команды `docker exec -it mongo mongosh -u root -p <ВАШ_ПАРОЛЬ> localhost/admin`
и там выполните команду (заменив IP-адреса `10.10.10.{1,2,3}` на адреса своих серверов):
`rs.initiate({ _id: 'rs0', members: [
{ _id: 1, host: '10.10.10.1:27017' },
{ _id: 2, host: '10.10.10.2:27017' },
{ _id: 3, host: '10.10.10.3:27017' }
] })`
5. Находясь там же, в Mongo Shell, создайте пользователя с доступом к будущей базе данных S3:
`db.createUser({ user: 's3', pwd: '<ВАШ_ПАРОЛЬ_S3>', roles: [
{ role: 'readWrite', db: 's3' },
{ role: 'dbAdmin', db: 's3' },
{ role: 'readWrite', db: 'vitastor' },
{ role: 'dbAdmin', db: 'vitastor' }
] })`
### Настройка Vitastor
Создайте в Vitastor отдельный пул для данных объектов S3, например:
`vitastor-cli create-pool --ec 2+1 -n 512 s3-data --used_for_app s3:standard`
Опция `--used_for_app` работает как "защита от дурака" и не даёт вам случайно создать
в этом пуле обычный блочный том и перезаписать им какие-то данные S3, а также скрывает
статистику занятого места по томам S3 из etcd.
Получите ID своего пула с помощью команды `vitastor-cli ls-pools --detail`.
### Установка Vitastor S3
1. Добавьте в `docker-compose.yml` строки (альтернативно вместо `network_mode: host`
можно использовать `ports: [ "8000:8000", "8002:8002" ]`):
```
zenko:
container_name: zenko
image: vitalif/vitastor-zenko
restart: always
security_opt:
- seccomp:unconfined
ulimits:
memlock: -1
network_mode: host
volumes:
- /etc/vitastor:/etc/vitastor
- /etc/vitastor/s3:/conf
```
2. Извлеките из Docker-образа Vitastor примеры файлов конфигурации:
`docker run --rm -it -v /etc/vitastor:/etc/vitastor -v /etc/vitastor/s3:/conf vitalif/vitastor-zenko configure.sh`
3. Отредактируйте файлы конфигурации в `/etc/vitastor/s3/`:
- `config.json` - общие настройки.
- `authdata.json` - учётные записи и ключи доступа.
- `locationConfig.json` - список классов хранения S3 с настройками расположения.
Внимание: в данной версии это именно список S3 storage class-ов (STANDARD, COLD и т.п.),
а не зон (подобных us-east-1), как в оригинальном Zenko CloudServer.
- В `config.json` и в `locationConfig.json` пропишите свои данные подключения к MongoDB.
- В `locationConfig.json` укажите ID пула Vitastor для хранения данных.
- Полный перечень настроек Vitastor-бэкенда пока можно посмотреть [в коде](https://git.yourcmc.ru/vitalif/zenko-arsenal/src/branch/master/lib/storage/data/vitastor/VitastorBackend.ts#L94).
### Запуск
Запустите S3-сервер: `docker-compose up -d zenko`
Готово! Вы получили S3-сервер, работающий на порту 8000.
Можете попробовать обратиться к нему с помощью, например, [s3cmd](https://s3tools.org/s3cmd):
`s3cmd --host-bucket= --no-ssl --access_key=accessKey1 --secret_key=verySecretKey1 --host=http://localhost:8000 mb s3://testbucket`
Или смонтировать его с помощью [GeeseFS](https://github.com/yandex-cloud/geesefs):
`AWS_ACCESS_KEY_ID=accessKey1 AWS_SECRET_ACCESS_KEY=verySecretKey1 geesefs --endpoint http://localhost:8000 testbucket /mnt/geesefs`
## Лицензия
- Автор [Zenko CloudServer](https://s3-server.readthedocs.io/en/latest/) - Scality, лицензия [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0)
- Vitastor-бэкенд для S3, как и сам Vitastor, лицензируется на условиях [VNPL 1.1](https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/VNPL-1.1.txt)
- Репозиторий сборки: https://git.yourcmc.ru/vitalif/zenko-cloudserver-vitastor
- Бэкенд хранения данных: https://git.yourcmc.ru/vitalif/zenko-arsenal/src/branch/master/lib/storage/data/vitastor/VitastorBackend.ts

View File

@ -16,7 +16,7 @@
designated initializers support from C++20 designated initializers support from C++20
- CMake - CMake
- liburing, jerasure headers and libraries - liburing, jerasure headers and libraries
- ISA-L, libibverbs and librdmacm headers and libraries (optional) - ISA-L, libibverbs headers and libraries (optional)
- tcmalloc (google-perftools-dev) - tcmalloc (google-perftools-dev)
## Basic instructions ## Basic instructions

View File

@ -16,7 +16,7 @@
назначенных инициализаторов (designated initializers) из C++20 назначенных инициализаторов (designated initializers) из C++20
- CMake - CMake
- Заголовки и библиотеки liburing, jerasure - Заголовки и библиотеки liburing, jerasure
- Опционально - заголовки и библиотеки ISA-L, libibverbs, librdmacm - Опционально - заголовки и библиотеки ISA-L, libibverbs
- tcmalloc (google-perftools-dev) - tcmalloc (google-perftools-dev)
## Базовая инструкция ## Базовая инструкция

View File

@ -28,7 +28,7 @@
- Per-OSD and per-image I/O and space usage statistics in etcd - Per-OSD and per-image I/O and space usage statistics in etcd
- Snapshots and copy-on-write image clones - Snapshots and copy-on-write image clones
- [Write throttling to smooth random write workloads in SSD+HDD configurations](../config/osd.en.md#throttle_small_writes) - [Write throttling to smooth random write workloads in SSD+HDD configurations](../config/osd.en.md#throttle_small_writes)
- RDMA/RoCEv2 support [via libibverbs](../config/network.en.md#use_rdma) or [RDMA-CM](../config/network.en.md#use_rdmacm) - [RDMA/RoCEv2 support via libibverbs](../config/network.en.md#rdma_device)
- [Scrubbing](../config/osd.en.md#auto_scrub) (verification of copies) - [Scrubbing](../config/osd.en.md#auto_scrub) (verification of copies)
- [Checksums](../config/layout-osd.en.md#data_csum_type) - [Checksums](../config/layout-osd.en.md#data_csum_type)
- [Client write-back cache](../config/client.en.md#client_enable_writeback) - [Client write-back cache](../config/client.en.md#client_enable_writeback)
@ -37,7 +37,6 @@
- [Experimental internal etcd replacement - antietcd](../config/monitor.en.md#use_antietcd) - [Experimental internal etcd replacement - antietcd](../config/monitor.en.md#use_antietcd)
- [Built-in Prometheus metric exporter](../config/monitor.en.md#enable_prometheus) - [Built-in Prometheus metric exporter](../config/monitor.en.md#enable_prometheus)
- [NFS RDMA support](../usage/nfs.en.md#rdma) (probably also usable for GPUDirect) - [NFS RDMA support](../usage/nfs.en.md#rdma) (probably also usable for GPUDirect)
- [S3](../installation/s3.en.md)
## Plugins and tools ## Plugins and tools
@ -64,6 +63,7 @@ The following features are planned for the future:
- iSCSI and NVMeoF gateways - iSCSI and NVMeoF gateways
- Multi-threaded client - Multi-threaded client
- Faster failover - Faster failover
- S3
- Tiered storage (SSD caching) - Tiered storage (SSD caching)
- NVDIMM support - NVDIMM support
- Compression (possibly) - Compression (possibly)

View File

@ -30,7 +30,7 @@
- Именование инодов через хранение их метаданных в etcd - Именование инодов через хранение их метаданных в etcd
- Снапшоты и copy-on-write клоны - Снапшоты и copy-on-write клоны
- [Сглаживание производительности случайной записи в SSD+HDD конфигурациях](../config/osd.ru.md#throttle_small_writes) - [Сглаживание производительности случайной записи в SSD+HDD конфигурациях](../config/osd.ru.md#throttle_small_writes)
- Поддержка RDMA/RoCEv2 [через libibverbs](../config/network.ru.md#use_rdma) или [RDMA-CM](../config/network.ru.md#use_rdmacm) - [Поддержка RDMA/RoCEv2 через libibverbs](../config/network.ru.md#rdma_device)
- [Фоновая проверка целостности](../config/osd.ru.md#auto_scrub) (сверка копий) - [Фоновая проверка целостности](../config/osd.ru.md#auto_scrub) (сверка копий)
- [Контрольные суммы](../config/layout-osd.ru.md#data_csum_type) - [Контрольные суммы](../config/layout-osd.ru.md#data_csum_type)
- [Буферизация записи на стороне клиента](../config/client.ru.md#client_enable_writeback) - [Буферизация записи на стороне клиента](../config/client.ru.md#client_enable_writeback)
@ -39,7 +39,6 @@
- [Экспериментальная встроенная замена etcd - antietcd](../config/monitor.ru.md#use_antietcd) - [Экспериментальная встроенная замена etcd - antietcd](../config/monitor.ru.md#use_antietcd)
- [Встроенный Prometheus-экспортер метрик](../config/monitor.ru.md#enable_prometheus) - [Встроенный Prometheus-экспортер метрик](../config/monitor.ru.md#enable_prometheus)
- [Поддержка NFS RDMA](../usage/nfs.ru.md#rdma) (вероятно, также подходящая для GPUDirect) - [Поддержка NFS RDMA](../usage/nfs.ru.md#rdma) (вероятно, также подходящая для GPUDirect)
- [S3](../installation/s3.ru.md)
## Драйверы и инструменты ## Драйверы и инструменты
@ -64,6 +63,7 @@
- iSCSI и NVMeoF прокси - iSCSI и NVMeoF прокси
- Многопоточный клиент - Многопоточный клиент
- Более быстрое переключение при отказах - Более быстрое переключение при отказах
- S3
- Поддержка SSD-кэширования (tiered storage) - Поддержка SSD-кэширования (tiered storage)
- Поддержка NVDIMM - Поддержка NVDIMM
- Возможно, сжатие - Возможно, сжатие

View File

@ -26,13 +26,13 @@
you also need small SSDs for journal and metadata (even 2 GB per 1 TB of HDD space is enough). you also need small SSDs for journal and metadata (even 2 GB per 1 TB of HDD space is enough).
- Get a fast network (at least 10 Gbit/s). Something like Mellanox ConnectX-4 with RoCEv2 is ideal. - Get a fast network (at least 10 Gbit/s). Something like Mellanox ConnectX-4 with RoCEv2 is ideal.
- Disable CPU powersaving: `cpupower idle-set -D 0 && cpupower frequency-set -g performance`. - Disable CPU powersaving: `cpupower idle-set -D 0 && cpupower frequency-set -g performance`.
- Either [install Vitastor packages](../installation/packages.en.md) or [install Vitastor in Docker](../installation/docker.en.md). - [Install Vitastor packages](../installation/packages.en.md).
## Recommended drives ## Recommended drives
- SATA SSD: Micron 5100/5200/5300/5400, Samsung PM863/PM883/PM893, Intel D3-S4510/4520/4610/4620, Kingston DC500M - SATA SSD: Micron 5100/5200/5300/5400, Samsung PM863/PM883/PM893, Intel D3-S4510/4520/4610/4620, Kingston DC500M
- NVMe: Micron 9100/9200/9300/9400, Micron 7300/7450, Samsung PM983/PM9A3, Samsung PM1723/1735/1743, - NVMe: Micron 9100/9200/9300/9400, Micron 7300/7450, Samsung PM983/PM9A3, Samsung PM1723/1735/1743,
Intel DC-P3700/P4500/P4600, Intel D5-P4320/P5530, Intel D7-P5500/P5600, Intel Optane, Kingston DC1000B/DC1500M Intel DC-P3700/P4500/P4600, Intel D5-P4320, Intel D7-P5500/P5600, Intel Optane, Kingston DC1000B/DC1500M
- HDD: HGST Ultrastar, Toshiba MG, Seagate EXOS - HDD: HGST Ultrastar, Toshiba MG, Seagate EXOS
## Configure monitors ## Configure monitors
@ -45,12 +45,11 @@ On the monitor hosts:
} }
``` ```
- Create systemd units for etcd by running: `/usr/lib/vitastor/mon/make-etcd` - Create systemd units for etcd by running: `/usr/lib/vitastor/mon/make-etcd`
Or, if you installed Vitastor in Docker, run `systemctl start vitastor-host; docker exec vitastor make-etcd`. - Start etcd and monitors: `systemctl enable --now etcd vitastor-mon`
- Start etcd and monitors: `systemctl enable --now vitastor-etcd vitastor-mon`
## Configure OSDs ## Configure OSDs
- Put etcd_address and [osd_network](../config/network.en.md#osd_network) into `/etc/vitastor/vitastor.conf`. Example: - Put etcd_address and osd_network into `/etc/vitastor/vitastor.conf`. Example:
``` ```
{ {
"etcd_address": ["10.200.1.10:2379","10.200.1.11:2379","10.200.1.12:2379"], "etcd_address": ["10.200.1.10:2379","10.200.1.11:2379","10.200.1.12:2379"],

View File

@ -26,13 +26,13 @@
обязательно возьмите SSD под метаданные и журнал (маленькие, буквально 2 ГБ на 1 ТБ HDD-места). обязательно возьмите SSD под метаданные и журнал (маленькие, буквально 2 ГБ на 1 ТБ HDD-места).
- Возьмите быструю сеть, минимум 10 гбит/с. Идеал - что-то вроде Mellanox ConnectX-4 с RoCEv2. - Возьмите быструю сеть, минимум 10 гбит/с. Идеал - что-то вроде Mellanox ConnectX-4 с RoCEv2.
- Для лучшей производительности отключите энергосбережение CPU: `cpupower idle-set -D 0 && cpupower frequency-set -g performance`. - Для лучшей производительности отключите энергосбережение CPU: `cpupower idle-set -D 0 && cpupower frequency-set -g performance`.
- Либо [установите пакеты Vitastor](../installation/packages.ru.md), либо [установите Vitastor в Docker](../installation/docker.ru.md). - [Установите пакеты Vitastor](../installation/packages.ru.md).
## Рекомендуемые диски ## Рекомендуемые диски
- SATA SSD: Micron 5100/5200/5300/5400, Samsung PM863/PM883/PM893, Intel D3-S4510/4520/4610/4620, Kingston DC500M - SATA SSD: Micron 5100/5200/5300/5400, Samsung PM863/PM883/PM893, Intel D3-S4510/4520/4610/4620, Kingston DC500M
- NVMe: Micron 9100/9200/9300/9400, Micron 7300/7450, Samsung PM983/PM9A3, Samsung PM1723/1735/1743, - NVMe: Micron 9100/9200/9300/9400, Micron 7300/7450, Samsung PM983/PM9A3, Samsung PM1723/1735/1743,
Intel DC-P3700/P4500/P4600, Intel D5-P4320/P5530, Intel D7-P5500/P5600, Intel Optane, Kingston DC1000B/DC1500M Intel DC-P3700/P4500/P4600, Intel D5-P4320, Intel D7-P5500/P5600, Intel Optane, Kingston DC1000B/DC1500M
- HDD: HGST Ultrastar, Toshiba MG, Seagate EXOS - HDD: HGST Ultrastar, Toshiba MG, Seagate EXOS
## Настройте мониторы ## Настройте мониторы
@ -44,13 +44,12 @@
"etcd_address": ["10.200.1.10:2379","10.200.1.11:2379","10.200.1.12:2379"] "etcd_address": ["10.200.1.10:2379","10.200.1.11:2379","10.200.1.12:2379"]
} }
``` ```
- Инициализируйте сервисы etcd, запустив `/usr/lib/vitastor/mon/make-etcd`.\ - Инициализируйте сервисы etcd, запустив `/usr/lib/vitastor/mon/make-etcd`
Либо, если вы установили Vitastor в Docker, запустите `systemctl start vitastor-host; docker exec vitastor make-etcd`. - Запустите etcd и мониторы: `systemctl enable --now etcd vitastor-mon`
- Запустите etcd и мониторы: `systemctl enable --now vitastor-etcd vitastor-mon`
## Настройте OSD ## Настройте OSD
- Пропишите etcd_address и [osd_network](../config/network.ru.md#osd_network) в `/etc/vitastor/vitastor.conf`. Например: - Пропишите etcd_address и osd_network в `/etc/vitastor/vitastor.conf`. Например:
``` ```
{ {
"etcd_address": ["10.200.1.10:2379","10.200.1.11:2379","10.200.1.12:2379"], "etcd_address": ["10.200.1.10:2379","10.200.1.11:2379","10.200.1.12:2379"],

View File

@ -35,19 +35,10 @@ PG state consists of exactly 1 base state and an arbitrary number of additional
PG state always includes exactly 1 of the following base states: PG state always includes exactly 1 of the following base states:
- **active** — PG is active and handles user I/O. - **active** — PG is active and handles user I/O.
- **incomplete** — Not enough OSDs are available to activate this PG. More exactly, that - **incomplete** — Not enough OSDs are available to activate this PG. That is, more disks
means one of the following: are lost than it's allowed by the pool's redundancy scheme. For example, if the pool has
- Less than pg_minsize current target OSDs are available for the PG. I.e. more disks pg_size=3 and pg_minsize=1, part of the data may be written only to 1 OSD. If that exact
are lost than allowed by the pool's redundancy scheme. OSD is lost, PG will become **incomplete**.
- All OSDs of some of PG's history records are unavailable, or, for EC pools, less
than (pg_size-parity_chunks) OSDs are available in one of the history records.
In other words it means that some data in this PG was written to an OSD set such that
it's currently impossible to read it back because these OSDs are down. For example,
if the pool has pg_size=3 and pg_minsize=1, part of the data may be written only to
1 OSD. If that exact OSD is lost, PG becomes **incomplete**.
- [allow_net_split](../config/osd.en.md#allow_net_split) is disabled (default) and
primary OSD of the PG can't connect to some secondary OSDs marked as alive in etcd.
I.e. a network partition happened: OSDs can talk to etcd, but not to some other OSDs.
- **offline** — PG isn't activated by any OSD at all. Either primary OSD isn't set for - **offline** — PG isn't activated by any OSD at all. Either primary OSD isn't set for
this PG at all (if the pool is just created), or an unavailable OSD is set as primary, this PG at all (if the pool is just created), or an unavailable OSD is set as primary,
or the primary OSD refuses to start this PG (for example, because of wrong block_size), or the primary OSD refuses to start this PG (for example, because of wrong block_size),

View File

@ -35,20 +35,10 @@
Состояние PG включает в себя ровно 1 флаг из следующих: Состояние PG включает в себя ровно 1 флаг из следующих:
- **active** — PG активна и обрабатывает запросы ввода-вывода от пользователей. - **active** — PG активна и обрабатывает запросы ввода-вывода от пользователей.
- **incomplete** — Недостаточно живых OSD, чтобы включить эту PG. Если точнее, то это - **incomplete** — Недостаточно живых OSD, чтобы включить эту PG.
означает один из следующих вариантов: То есть, дисков потеряно больше, чем разрешено схемой отказоустойчивости пула и pg_minsize.
- Доступно менее, чем pg_minsize текущих целевых OSD данной PG. Иными словами, потеряно Например, если у пула pg_size=3 и pg_minsize=1, то часть данных может записаться всего на 1 OSD.
больше дисков, чем это разрешает схема отказоустойчивости пула. Если потом конкретно этот OSD упадёт, PG окажется **incomplete**.
- Все OSD одной из исторических записей PG недоступны, или, для EC-пулов, в одной
из исторических записей PG доступно менее, чем (pg_size-parity_chunks) OSD. Другими
словами это означает, что часть данных этой PG была записана в такой набор OSD, из
которого их сейчас невозможно прочитать обратно, так как OSD не включены. Например,
если у пула pg_size=3 и pg_minsize=1, то часть данных может записаться всего на 1 OSD.
Если потом конкретно этот OSD упадёт, PG окажется **incomplete**.
- [allow_net_split](../config/osd.ru.md#allow_net_split) отключено (по умолчанию) и
первичный OSD данной PG не может соединиться с частью вторичных OSD этой PG, помеченных
как живых в etcd. Это означает, что произошло разделение сети: OSD могут общаться с etcd,
но не могут общаться с частью других OSD.
- **offline** — PG вообще не активирована ни одним OSD. Либо первичный OSD не назначен вообще - **offline** — PG вообще не активирована ни одним OSD. Либо первичный OSD не назначен вообще
(если пул только создан), либо в качестве первичного назначен недоступный OSD, либо (если пул только создан), либо в качестве первичного назначен недоступный OSD, либо
назначенный OSD отказывается запускать эту PG (например, из-за несовпадения block_size), назначенный OSD отказывается запускать эту PG (например, из-за несовпадения block_size),

View File

@ -37,7 +37,7 @@ It supports the following commands:
Global options: Global options:
``` ```
--config_path FILE Path to Vitastor configuration file --config_file FILE Path to Vitastor configuration file
--etcd_address URL Etcd connection address --etcd_address URL Etcd connection address
--iodepth N Send N operations in parallel to each OSD when possible (default 32) --iodepth N Send N operations in parallel to each OSD when possible (default 32)
--parallel_osds M Work with M osds in parallel when possible (default 4) --parallel_osds M Work with M osds in parallel when possible (default 4)
@ -355,7 +355,7 @@ Set OSD reweight, tags or noout flag. See detail description in [OSD config docu
## pg-list ## pg-list
`vitastor-cli pg-list|pg-ls|list-pg|ls-pg|ls-pgs|pgs [OPTIONS] [state1+state2] [^state3] [...]` `vitastor-cli pg-list|pg-ls|list-pg|ls-pg|ls-pgs [OPTIONS] [state1+state2] [^state3] [...]`
List PGs with any of listed state filters (^ or ! in the beginning is negation). Options: List PGs with any of listed state filters (^ or ! in the beginning is negation). Options:
@ -363,7 +363,6 @@ List PGs with any of listed state filters (^ or ! in the beginning is negation).
--pool <pool name or number> Only list PGs of the given pool. --pool <pool name or number> Only list PGs of the given pool.
--min <min pg number> Only list PGs with number >= min. --min <min pg number> Only list PGs with number >= min.
--max <max pg number> Only list PGs with number <= max. --max <max pg number> Only list PGs with number <= max.
--osd 1,2,... Only list PGs with some data on specified OSD(s).
``` ```
Examples: Examples:
@ -378,11 +377,11 @@ Examples:
Create a pool. Required parameters: Create a pool. Required parameters:
| <!-- --> | <!-- --> | | <!-- --> | <!-- --> |
|--------------------------|-----------------------------------------------------------------------------------------| |--------------------------|---------------------------------------------------------------------------------------|
| `-s R` or `--pg_size R` | Number of replicas for replicated pools | | `-s R` or `--pg_size R` | Number of replicas for replicated pools |
| `--ec N+K` | Number of data (N) and parity (K) chunks for erasure-coded pools | | `--ec N+K` | Number of data (N) and parity (K) chunks for erasure-coded pools |
| `-n N` or `--pg_count N` | PG count for the new pool (start with 10*\<OSD count\>/pg_size rounded to a power of 2) | | `-n N` or `--pg_count N` | PG count for the new pool (start with 10*<OSD count>/pg_size rounded to a power of 2) |
Optional parameters: Optional parameters:
@ -399,8 +398,7 @@ Optional parameters:
| `--raw_placement <rules>` | Specify raw PG generation rules ([details](../config/pool.en.md#raw_placement)) | | `--raw_placement <rules>` | Specify raw PG generation rules ([details](../config/pool.en.md#raw_placement)) |
| `--primary_affinity_tags tags` | Prefer to put primary copies on OSDs with all specified tags | | `--primary_affinity_tags tags` | Prefer to put primary copies on OSDs with all specified tags |
| `--scrub_interval <time>` | Enable regular scrubbing for this pool. Format: number + unit s/m/h/d/M/y | | `--scrub_interval <time>` | Enable regular scrubbing for this pool. Format: number + unit s/m/h/d/M/y |
| `--used_for_app fs:<name>` | Mark pool as used for VitastorFS with metadata in image `<name>` | | `--used_for_fs <name>` | Mark pool as used for VitastorFS with metadata in image <name> |
| `--used_for_app s3:<name>` | Mark pool as used for S3 location with name `<name>` |
| `--pg_stripe_size <number>` | Increase object grouping stripe | | `--pg_stripe_size <number>` | Increase object grouping stripe |
| `--max_osd_combinations 10000` | Maximum number of random combinations for LP solver input | | `--max_osd_combinations 10000` | Maximum number of random combinations for LP solver input |
| `--wait` | Wait for the new pool to come online | | `--wait` | Wait for the new pool to come online |

View File

@ -22,8 +22,6 @@ vitastor-cli - интерфейс командной строки для адм
- [flatten](#flatten) - [flatten](#flatten)
- [rm-data](#rm-data) - [rm-data](#rm-data)
- [merge-data](#merge-data) - [merge-data](#merge-data)
- [describe](#describe)
- [fix](#fix)
- [alloc-osd](#alloc-osd) - [alloc-osd](#alloc-osd)
- [rm-osd](#rm-osd) - [rm-osd](#rm-osd)
- [osd-tree](#osd-tree) - [osd-tree](#osd-tree)
@ -38,7 +36,7 @@ vitastor-cli - интерфейс командной строки для адм
Глобальные опции: Глобальные опции:
``` ```
--config_path FILE Путь к файлу конфигурации Vitastor --config_file FILE Путь к файлу конфигурации Vitastor
--etcd_address URL Адрес соединения с etcd --etcd_address URL Адрес соединения с etcd
--iodepth N Отправлять параллельно N операций на каждый OSD (по умолчанию 32) --iodepth N Отправлять параллельно N операций на каждый OSD (по умолчанию 32)
--parallel_osds M Работать параллельно с M OSD (по умолчанию 4) --parallel_osds M Работать параллельно с M OSD (по умолчанию 4)
@ -377,10 +375,9 @@ OSD PARENT UP SIZE USED% TAGS WEIGHT BLOCK BITMAP
в начале фильтра означает отрицание). Опции: в начале фильтра означает отрицание). Опции:
``` ```
--pool <pool name or number> Вывести только PG в заданном пуле. --pool <pool name or number> Only list PGs of the given pool.
--min <min pg number> Вывести только PG с номерами >= min. --min <min pg number> Only list PGs with number >= min.
--max <max pg number> Вывести только PG с номерами <= max. --max <max pg number> Only list PGs with number <= max.
--osd 1,2,... Вывести только PG с данными на заданных OSD.
``` ```
Примеры: Примеры:
@ -395,11 +392,11 @@ OSD PARENT UP SIZE USED% TAGS WEIGHT BLOCK BITMAP
Создать пул. Обязательные параметры: Создать пул. Обязательные параметры:
| <!-- --> | <!-- --> | | <!-- --> | <!-- --> |
|---------------------------|-----------------------------------------------------------------------------------------------| |---------------------------|---------------------------------------------------------------------------------------------|
| `-s R` или `--pg_size R` | Число копий данных для реплицированных пулов | | `-s R` или `--pg_size R` | Число копий данных для реплицированных пулов |
| `--ec N+K` | Число частей данных (N) и чётности (K) для пулов с кодами коррекции ошибок | | `--ec N+K` | Число частей данных (N) и чётности (K) для пулов с кодами коррекции ошибок |
| `-n N` или `--pg_count N` | Число PG для нового пула (начните с 10*\<число OSD\>/pg_size, округлённого до степени двойки) | | `-n N` или `--pg_count N` | Число PG для нового пула (начните с 10*<число OSD>/pg_size, округлённого до степени двойки) |
Необязательные параметры: Необязательные параметры:

View File

@ -14,7 +14,6 @@ It supports the following commands:
- [upgrade-simple](#upgrade-simple) - [upgrade-simple](#upgrade-simple)
- [resize](#resize) - [resize](#resize)
- [raw-resize](#raw-resize) - [raw-resize](#raw-resize)
- [trim](#trim)
- [start/stop/restart/enable/disable](#start/stop/restart/enable/disable) - [start/stop/restart/enable/disable](#start/stop/restart/enable/disable)
- [purge](#purge) - [purge](#purge)
- [read-sb](#read-sb) - [read-sb](#read-sb)
@ -98,9 +97,6 @@ Options (both modes):
--data_device_block 4k Override data device block size --data_device_block 4k Override data device block size
--meta_device_block 4k Override metadata device block size --meta_device_block 4k Override metadata device block size
--journal_device_block 4k Override journal device block size --journal_device_block 4k Override journal device block size
--discard_on_start 0 TRIM unused data device blocks every OSD start (default off)
--min_discard_size 1M Minimum TRIM block size
--json Enable JSON output
``` ```
[immediate_commit](../config/layout-cluster.en.md#immediate_commit) setting is [immediate_commit](../config/layout-cluster.en.md#immediate_commit) setting is
@ -183,19 +179,6 @@ parameters from OSD command line (i.e. from systemd unit or superblock).
SIZE may include k/m/g/t suffixes. If any of the new layout parameter SIZE may include k/m/g/t suffixes. If any of the new layout parameter
options are not specified, old values will be used. options are not specified, old values will be used.
## trim
`vitastor-disk trim <osd_num>|<osd_device> [<osd_num>|<osd_device>...]`
Try to discard unused blocks (SSD TRIM) on the data device of each of the OSD(s).
May only be used on stopped OSDs. Options:
```
--min_discard_size 1M Minimum TRIM block size
--discard_granularity 0 Override device's discard granularity
```
## start/stop/restart/enable/disable ## start/stop/restart/enable/disable
`vitastor-disk start|stop|restart|enable|disable [--now] <device> [device2 device3 ...]` `vitastor-disk start|stop|restart|enable|disable [--now] <device> [device2 device3 ...]`

View File

@ -99,9 +99,6 @@ vitastor-disk - инструмент командной строки для уп
--data_device_block 4k Задать размер блока устройства данных --data_device_block 4k Задать размер блока устройства данных
--meta_device_block 4k Задать размер блока метаданных --meta_device_block 4k Задать размер блока метаданных
--journal_device_block 4k Задать размер блока журнала --journal_device_block 4k Задать размер блока журнала
--discard_on_start 0 Выполнять TRIM пустых блоков данных при запуске OSD (по умолчанию нет)
--min_discard_size 1M Минимальный размер блока для TRIM
--json Включить JSON-вывод
``` ```
Настройка [immediate_commit](../config/layout-cluster.ru.md#immediate_commit) Настройка [immediate_commit](../config/layout-cluster.ru.md#immediate_commit)
@ -185,20 +182,6 @@ throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
`РАЗМЕР` может быть указан с суффиксами k/m/g/t. Если любой из новых параметров `РАЗМЕР` может быть указан с суффиксами k/m/g/t. Если любой из новых параметров
расположения не указан, он принимается равным старому значению. расположения не указан, он принимается равным старому значению.
## trim
`vitastor-disk trim <osd_num>|<osd_device> [<osd_num>|<osd_device>...]`
Попробовать пометить пустые блоки дисков данных всех указанных OSD неиспользуемыми
(выполнить команду SSD TRIM).
Можно использовать только с остановленными OSD. Опции:
```
--min_discard_size 1M Минимальный размер блока для TRIM
--discard_granularity 0 Кратность размера блока для TRIM
```
## start/stop/restart/enable/disable ## start/stop/restart/enable/disable
`vitastor-disk start|stop|restart|enable|disable [--now] <device> [device2 device3 ...]` `vitastor-disk start|stop|restart|enable|disable [--now] <device> [device2 device3 ...]`

View File

@ -36,7 +36,7 @@ It will output a block device name like /dev/nbd0 which you can then use as a no
You can also use `--pool <POOL> --inode <INODE> --size <SIZE>` instead of `--image <IMAGE>` if you want. You can also use `--pool <POOL> --inode <INODE> --size <SIZE>` instead of `--image <IMAGE>` if you want.
vitastor-nbd supports all usual Vitastor configuration options like `--config_path <path_to_config>` plus NBD-specific: vitastor-nbd supports all usual Vitastor configuration options like `--config_file <path_to_config>` plus NBD-specific:
* `--nbd_timeout 0` \ * `--nbd_timeout 0` \
Timeout for I/O operations in seconds after exceeding which the kernel stops the device. Timeout for I/O operations in seconds after exceeding which the kernel stops the device.
@ -54,18 +54,16 @@ vitastor-nbd supports all usual Vitastor configuration options like `--config_pa
Stay in foreground, do not daemonize. Stay in foreground, do not daemonize.
Note that `nbd_timeout`, `nbd_max_devices` and `nbd_max_part` options may also be specified Note that `nbd_timeout`, `nbd_max_devices` and `nbd_max_part` options may also be specified
in `/etc/vitastor/vitastor.conf` or in other configuration file specified with `--config_path`. in `/etc/vitastor/vitastor.conf` or in other configuration file specified with `--config_file`.
## unmap ## unmap
To unmap the device run: To unmap the device run:
``` ```
vitastor-nbd unmap [--force] /dev/nbd0 vitastor-nbd unmap /dev/nbd0
``` ```
If `--force` is specified, `vitastor-nbd` doesn't check if the device is actually mapped.
## ls ## ls
``` ```

View File

@ -41,7 +41,7 @@ vitastor-nbd map [/dev/nbdN] --image testimg
Для обращения по номеру инода, аналогично другим командам, можно использовать опции Для обращения по номеру инода, аналогично другим командам, можно использовать опции
`--pool <POOL> --inode <INODE> --size <SIZE>` вместо `--image testimg`. `--pool <POOL> --inode <INODE> --size <SIZE>` вместо `--image testimg`.
vitastor-nbd поддерживает все обычные опции Vitastor, например, `--config_path <path_to_config>`, vitastor-nbd поддерживает все обычные опции Vitastor, например, `--config_file <path_to_config>`,
плюс специфичные для NBD: плюс специфичные для NBD:
* `--nbd_timeout 0` \ * `--nbd_timeout 0` \
@ -62,19 +62,16 @@ vitastor-nbd поддерживает все обычные опции Vitastor,
Обратите внимание, что опции `nbd_timeout`, `nbd_max_devices` и `nbd_max_part` можно Обратите внимание, что опции `nbd_timeout`, `nbd_max_devices` и `nbd_max_part` можно
также задавать в `/etc/vitastor/vitastor.conf` или в другом файле конфигурации, также задавать в `/etc/vitastor/vitastor.conf` или в другом файле конфигурации,
заданном опцией `--config_path`. заданном опцией `--config_file`.
## unmap ## unmap
Для отключения устройства выполните: Для отключения устройства выполните:
``` ```
vitastor-nbd unmap [--force] /dev/nbd0 vitastor-nbd unmap /dev/nbd0
``` ```
Если задана опция `--force`, `vitastor-nbd` не проверяет, подключено ли устройство,
перед попыткой его отключить.
## ls ## ls
``` ```

View File

@ -58,7 +58,7 @@ To use VitastorFS:
2. Create an image for FS metadata, preferably in a faster (SSD or replica-HDD) pool, 2. Create an image for FS metadata, preferably in a faster (SSD or replica-HDD) pool,
but you can create it in the data pool too if you want (image size doesn't matter): but you can create it in the data pool too if you want (image size doesn't matter):
`vitastor-cli create -s 10G -p fastpool testfs` `vitastor-cli create -s 10G -p fastpool testfs`
3. Mark data pool as an FS pool: `vitastor-cli modify-pool --used-for-app fs:testfs data-pool` 3. Mark data pool as an FS pool: `vitastor-cli modify-pool --used-for-fs testfs data-pool`
4. Either mount the FS: `vitastor-nfs mount --fs testfs --pool data-pool /mnt/vita` 4. Either mount the FS: `vitastor-nfs mount --fs testfs --pool data-pool /mnt/vita`
5. Or start the NFS server: `vitastor-nfs start --fs testfs --pool data-pool` 5. Or start the NFS server: `vitastor-nfs start --fs testfs --pool data-pool`

View File

@ -60,7 +60,7 @@ JSON-формате :-). Для инспекции содержимого БД
или по крайней мере на HDD, но без EC), но можно и в том же пуле, что данные или по крайней мере на HDD, но без EC), но можно и в том же пуле, что данные
(размер образа значения не имеет): (размер образа значения не имеет):
`vitastor-cli create -s 10G -p fastpool testfs` `vitastor-cli create -s 10G -p fastpool testfs`
3. Пометьте пул данных как ФС-пул: `vitastor-cli modify-pool --used-for-app fs:testfs data-pool` 3. Пометьте пул данных как ФС-пул: `vitastor-cli modify-pool --used-for-fs testfs data-pool`
4. Либо примонтируйте ФС: `vitastor-nfs mount --fs testfs --pool data-pool /mnt/vita` 4. Либо примонтируйте ФС: `vitastor-nfs mount --fs testfs --pool data-pool /mnt/vita`
5. Либо запустите сетевой NFS-сервер: `vitastor-nfs start --fs testfs --pool data-pool` 5. Либо запустите сетевой NFS-сервер: `vitastor-nfs start --fs testfs --pool data-pool`

View File

@ -773,27 +773,23 @@ class Mon
} }
} }
} }
if (!this.recheck_pgs_active) for (const pool_id in this.state.pool.stats)
{ {
// PG recheck also modifies /pool/stats, so don't touch it here if it's active if (!seen_pools[pool_id])
for (const pool_id in this.state.pool.stats)
{ {
if (!seen_pools[pool_id]) txn.push({ requestDeleteRange: {
{ key: b64(this.config.etcd_prefix+'/pool/stats/'+pool_id),
txn.push({ requestDeleteRange: { } });
key: b64(this.config.etcd_prefix+'/pool/stats/'+pool_id), delete this.state.pool.stats[pool_id];
} }); }
delete this.state.pool.stats[pool_id]; else
} {
else const pool_stats = { ...this.state.pool.stats[pool_id] };
{ serialize_bigints(pool_stats);
const pool_stats = { ...this.state.pool.stats[pool_id] }; txn.push({ requestPut: {
serialize_bigints(pool_stats); key: b64(this.config.etcd_prefix+'/pool/stats/'+pool_id),
txn.push({ requestPut: { value: b64(JSON.stringify(pool_stats)),
key: b64(this.config.etcd_prefix+'/pool/stats/'+pool_id), } });
value: b64(JSON.stringify(pool_stats)),
} });
}
} }
} }
if (txn.length) if (txn.length)

View File

@ -15,7 +15,7 @@ function get_osd_tree(global_config, state)
const stat = state.osd.stats[osd_num]; const stat = state.osd.stats[osd_num];
const osd_cfg = state.config.osd[osd_num]; const osd_cfg = state.config.osd[osd_num];
let reweight = osd_cfg == null ? 1 : Number(osd_cfg.reweight); let reweight = osd_cfg == null ? 1 : Number(osd_cfg.reweight);
if (isNaN(reweight) || reweight < 0 || reweight > 0) if (reweight < 0 || isNaN(reweight))
reweight = 1; reweight = 1;
if (stat && stat.size && reweight && (state.osd.state[osd_num] || Number(stat.time) >= down_time || if (stat && stat.size && reweight && (state.osd.state[osd_num] || Number(stat.time) >= down_time ||
osd_cfg && osd_cfg.noout)) osd_cfg && osd_cfg.noout))

View File

@ -1,6 +1,6 @@
{ {
"name": "vitastor-mon", "name": "vitastor-mon",
"version": "2.1.0", "version": "1.10.1",
"description": "Vitastor SDS monitor service", "description": "Vitastor SDS monitor service",
"main": "mon-main.js", "main": "mon-main.js",
"scripts": { "scripts": {
@ -19,6 +19,6 @@
"eslint-plugin-node": "^11.1.0" "eslint-plugin-node": "^11.1.0"
}, },
"engines": { "engines": {
"node": ">=12.1.0" "node": ">=12.0.0"
} }
} }

View File

@ -8,9 +8,23 @@ const LPOptimizer = require('./lp_optimizer/lp_optimizer.js');
const { scale_pg_count } = require('./pg_utils.js'); const { scale_pg_count } = require('./pg_utils.js');
const { make_hier_tree, filter_osds_by_root_node, const { make_hier_tree, filter_osds_by_root_node,
filter_osds_by_tags, filter_osds_by_block_layout, get_affinity_osds } = require('./osd_tree.js'); filter_osds_by_tags, filter_osds_by_block_layout, get_affinity_osds } = require('./osd_tree.js');
const { select_murmur3 } = require('./lp_optimizer/murmur3.js');
function pick_primary(pool_id, pg_num, pool_config, osd_set, up_osds, aff_osds) let seed;
function reset_rng()
{
seed = 0x5f020e43;
}
function rng()
{
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
return seed + 2147483648;
}
function pick_primary(pool_config, osd_set, up_osds, aff_osds)
{ {
let alive_set; let alive_set;
if (pool_config.scheme === 'replicated') if (pool_config.scheme === 'replicated')
@ -38,7 +52,7 @@ function pick_primary(pool_id, pg_num, pool_config, osd_set, up_osds, aff_osds)
{ {
return 0; return 0;
} }
return alive_set[select_murmur3(alive_set.length, osd_num => pool_id+'/'+pg_num+'/'+osd_num)]; return alive_set[rng() % alive_set.length];
} }
function recheck_primary(state, global_config, up_osds, osd_tree) function recheck_primary(state, global_config, up_osds, osd_tree)
@ -52,6 +66,7 @@ function recheck_primary(state, global_config, up_osds, osd_tree)
continue; continue;
} }
const aff_osds = get_affinity_osds(pool_cfg, up_osds, osd_tree); const aff_osds = get_affinity_osds(pool_cfg, up_osds, osd_tree);
reset_rng();
for (let pg_num = 1; pg_num <= pool_cfg.pg_count; pg_num++) for (let pg_num = 1; pg_num <= pool_cfg.pg_count; pg_num++)
{ {
if (!state.pg.config.items[pool_id]) if (!state.pg.config.items[pool_id])
@ -61,7 +76,7 @@ function recheck_primary(state, global_config, up_osds, osd_tree)
const pg_cfg = state.pg.config.items[pool_id][pg_num]; const pg_cfg = state.pg.config.items[pool_id][pg_num];
if (pg_cfg) if (pg_cfg)
{ {
const new_primary = pick_primary(pool_id, pg_num, state.config.pools[pool_id], pg_cfg.osd_set, up_osds, aff_osds); const new_primary = pick_primary(state.config.pools[pool_id], pg_cfg.osd_set, up_osds, aff_osds);
if (pg_cfg.primary != new_primary) if (pg_cfg.primary != new_primary)
{ {
if (!new_pg_config) if (!new_pg_config)
@ -84,12 +99,13 @@ function save_new_pgs_txn(save_to, request, state, etcd_prefix, etcd_watch_revis
{ {
const aff_osds = get_affinity_osds(state.config.pools[pool_id] || {}, up_osds, osd_tree); const aff_osds = get_affinity_osds(state.config.pools[pool_id] || {}, up_osds, osd_tree);
const pg_items = {}; const pg_items = {};
reset_rng();
new_pgs.map((osd_set, i) => new_pgs.map((osd_set, i) =>
{ {
osd_set = osd_set.map(osd_num => osd_num === LPOptimizer.NO_OSD ? 0 : osd_num); osd_set = osd_set.map(osd_num => osd_num === LPOptimizer.NO_OSD ? 0 : osd_num);
pg_items[i+1] = { pg_items[i+1] = {
osd_set, osd_set,
primary: pick_primary(pool_id, i+1, state.config.pools[pool_id], osd_set, up_osds, aff_osds), primary: pick_primary(state.config.pools[pool_id], osd_set, up_osds, aff_osds),
}; };
if (prev_pgs[i] && prev_pgs[i].join(' ') != osd_set.join(' ') && if (prev_pgs[i] && prev_pgs[i].join(' ') != osd_set.join(' ') &&
prev_pgs[i].filter(osd_num => osd_num).length > 0) prev_pgs[i].filter(osd_num => osd_num).length > 0)

View File

@ -33,11 +33,9 @@ async function run()
console.log(config_path+' is missing'); console.log(config_path+' is missing');
process.exit(1); process.exit(1);
} }
const in_docker = fs.existsSync("/etc/vitastor/etcd.conf") && if (fs.existsSync("/etc/systemd/system/etcd.service"))
fs.existsSync("/etc/vitastor/docker.conf");
if (!in_docker && fs.existsSync("/etc/systemd/system/vitastor-etcd.service"))
{ {
console.log("/etc/systemd/system/vitastor-etcd.service already exists"); console.log("/etc/systemd/system/etcd.service already exists");
process.exit(1); process.exit(1);
} }
const config = JSON.parse(fs.readFileSync(config_path, { encoding: 'utf-8' })); const config = JSON.parse(fs.readFileSync(config_path, { encoding: 'utf-8' }));
@ -54,21 +52,10 @@ async function run()
console.log('No matching IPs in etcd_address from '+config_path); console.log('No matching IPs in etcd_address from '+config_path);
process.exit(0); process.exit(0);
} }
const etcd_name = 'etcd'+etcds[num].replace(/[^0-9a-z_]/ig, '_'); const etcd_cluster = etcds.map((e, i) => `etcd${i}=http://${e}:2380`).join(',');
const etcd_cluster = etcds.map(e => `etcd${e.replace(/[^0-9a-z_]/ig, '_')}=http://${e}:2380`).join(','); await system(`mkdir -p /var/lib/etcd${num}.etcd`);
if (in_docker)
{
let etcd_conf = fs.readFileSync("/etc/vitastor/etcd.conf", { encoding: 'utf-8' });
etcd_conf = replace_env(etcd_conf, 'ETCD_NAME', etcd_name);
etcd_conf = replace_env(etcd_conf, 'ETCD_IP', etcds[num]);
etcd_conf = replace_env(etcd_conf, 'ETCD_INITIAL_CLUSTER', etcd_cluster);
fs.writeFileSync("/etc/vitastor/etcd.conf", etcd_conf);
console.log('etcd for Vitastor configured. Run `systemctl enable --now vitastor-etcd` to start etcd');
process.exit(0);
}
await system(`mkdir -p /var/lib/etcd`);
fs.writeFileSync( fs.writeFileSync(
"/etc/systemd/system/vitastor-etcd.service", "/etc/systemd/system/etcd.service",
`[Unit] `[Unit]
Description=etcd for vitastor Description=etcd for vitastor
After=network-online.target local-fs.target time-sync.target After=network-online.target local-fs.target time-sync.target
@ -77,14 +64,14 @@ Wants=network-online.target local-fs.target time-sync.target
[Service] [Service]
Restart=always Restart=always
Environment=GOGC=50 Environment=GOGC=50
ExecStart=etcd --name ${etcd_name} --data-dir /var/lib/etcd \\ ExecStart=etcd -name etcd${num} --data-dir /var/lib/etcd${num}.etcd \\
--snapshot-count 10000 --advertise-client-urls http://${etcds[num]}:2379 --listen-client-urls http://${etcds[num]}:2379 \\ --snapshot-count 10000 --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} \\
--initial-cluster-state new --max-txn-ops=100000 --max-request-bytes=104857600 \\ --initial-cluster-state new --max-txn-ops=100000 --max-request-bytes=104857600 \\
--auto-compaction-retention=10 --auto-compaction-mode=revision --auto-compaction-retention=10 --auto-compaction-mode=revision
WorkingDirectory=/var/lib/etcd WorkingDirectory=/var/lib/etcd${num}.etcd
ExecStartPre=+chown -R etcd /var/lib/etcd ExecStartPre=+chown -R etcd /var/lib/etcd${num}.etcd
User=etcd User=etcd
PrivateTmp=false PrivateTmp=false
TasksMax=infinity TasksMax=infinity
@ -102,13 +89,6 @@ WantedBy=multi-user.target
process.exit(0); process.exit(0);
} }
function replace_env(text, key, value)
{
let found = false;
text = text.replace(new RegExp('^'+key+'\\s*=.*', 'm'), () => { found = true; return key+'='+value; });
return found ? text : text.replace(/\s*$/, '\n')+key+'='+value+'\n';
}
function select_local_etcd(etcds) function select_local_etcd(etcds)
{ {
const ifaces = os.networkInterfaces(); const ifaces = os.networkInterfaces();

View File

@ -5,7 +5,6 @@ Wants=network-online.target local-fs.target time-sync.target
[Service] [Service]
Restart=always Restart=always
SyslogIdentifier=vitastor-mon
ExecStart=node /usr/lib/vitastor/mon/mon-main.js ExecStart=node /usr/lib/vitastor/mon/mon-main.js
WorkingDirectory=/ WorkingDirectory=/
User=vitastor User=vitastor

View File

@ -8,7 +8,6 @@ PartOf=vitastor.target
LimitNOFILE=1048576 LimitNOFILE=1048576
LimitNPROC=1048576 LimitNPROC=1048576
LimitMEMLOCK=infinity LimitMEMLOCK=infinity
SyslogIdentifier=vitastor-osd%i
# Use the following for direct logs to files # Use the following for direct logs to files
#ExecStart=bash -c 'exec vitastor-disk exec-osd /dev/vitastor/osd%i-data >>/var/log/vitastor/osd%i.log 2>&1' #ExecStart=bash -c 'exec vitastor-disk exec-osd /dev/vitastor/osd%i-data >>/var/log/vitastor/osd%i.log 2>&1'
ExecStart=vitastor-disk exec-osd /dev/vitastor/osd%i-data ExecStart=vitastor-disk exec-osd /dev/vitastor/osd%i-data

View File

@ -14,13 +14,8 @@ NAN_MODULE_INIT(InitAddon)
Nan::SetPrototypeMethod(tpl, "read", NodeVitastor::Read); Nan::SetPrototypeMethod(tpl, "read", NodeVitastor::Read);
Nan::SetPrototypeMethod(tpl, "write", NodeVitastor::Write); Nan::SetPrototypeMethod(tpl, "write", NodeVitastor::Write);
Nan::SetPrototypeMethod(tpl, "delete", NodeVitastor::Delete);
Nan::SetPrototypeMethod(tpl, "sync", NodeVitastor::Sync); Nan::SetPrototypeMethod(tpl, "sync", NodeVitastor::Sync);
Nan::SetPrototypeMethod(tpl, "read_bitmap", NodeVitastor::ReadBitmap); Nan::SetPrototypeMethod(tpl, "read_bitmap", NodeVitastor::ReadBitmap);
Nan::SetPrototypeMethod(tpl, "on_ready", NodeVitastor::OnReady);
Nan::SetPrototypeMethod(tpl, "get_min_io_size", NodeVitastor::GetMinIoSize);
Nan::SetPrototypeMethod(tpl, "get_max_atomic_write_size", NodeVitastor::GetMaxAtomicWriteSize);
Nan::SetPrototypeMethod(tpl, "get_immediate_commit", NodeVitastor::GetImmediateCommit);
//Nan::SetPrototypeMethod(tpl, "destroy", NodeVitastor::Destroy); //Nan::SetPrototypeMethod(tpl, "destroy", NodeVitastor::Destroy);
Nan::Set(target, Nan::New("Client").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked()); Nan::Set(target, Nan::New("Client").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());
@ -68,10 +63,6 @@ NAN_MODULE_INIT(InitAddon)
Nan::Set(target, Nan::New("ENOSYS").ToLocalChecked(), Nan::New<v8::Int32>(-ENOSYS)); Nan::Set(target, Nan::New("ENOSYS").ToLocalChecked(), Nan::New<v8::Int32>(-ENOSYS));
Nan::Set(target, Nan::New("EAGAIN").ToLocalChecked(), Nan::New<v8::Int32>(-EAGAIN)); Nan::Set(target, Nan::New("EAGAIN").ToLocalChecked(), Nan::New<v8::Int32>(-EAGAIN));
Nan::Set(target, Nan::New("IMMEDIATE_NONE").ToLocalChecked(), Nan::New<v8::Int32>(IMMEDIATE_NONE));
Nan::Set(target, Nan::New("IMMEDIATE_SMALL").ToLocalChecked(), Nan::New<v8::Int32>(IMMEDIATE_SMALL));
Nan::Set(target, Nan::New("IMMEDIATE_ALL").ToLocalChecked(), Nan::New<v8::Int32>(IMMEDIATE_ALL));
// Listing handle // Listing handle
tpl = Nan::New<v8::FunctionTemplate>(NodeVitastorKVListing::Create); tpl = Nan::New<v8::FunctionTemplate>(NodeVitastorKVListing::Create);

View File

@ -5,10 +5,9 @@
#define NODE_VITASTOR_READ 1 #define NODE_VITASTOR_READ 1
#define NODE_VITASTOR_WRITE 2 #define NODE_VITASTOR_WRITE 2
#define NODE_VITASTOR_DELETE 3 #define NODE_VITASTOR_SYNC 3
#define NODE_VITASTOR_SYNC 4 #define NODE_VITASTOR_READ_BITMAP 4
#define NODE_VITASTOR_READ_BITMAP 5 #define NODE_VITASTOR_GET_INFO 5
#define NODE_VITASTOR_GET_INFO 6
#ifndef INODE_POOL #ifndef INODE_POOL
#define INODE_POOL(inode) (uint32_t)((inode) >> (64 - POOL_ID_BITS)) #define INODE_POOL(inode) (uint32_t)((inode) >> (64 - POOL_ID_BITS))
@ -19,16 +18,11 @@
class NodeVitastorRequest: public Nan::AsyncResource class NodeVitastorRequest: public Nan::AsyncResource
{ {
public: public:
NodeVitastorRequest(NodeVitastor *cli, const v8::Local<v8::Function> & cb): Nan::AsyncResource("NodeVitastorRequest") NodeVitastorRequest(NodeVitastor *cli, v8::Local<v8::Function> cb): Nan::AsyncResource("NodeVitastorRequest")
{ {
this->cli = cli; this->cli = cli;
callback.Reset(cb); callback.Reset(cb);
} }
~NodeVitastorRequest()
{
callback.Reset();
buffer_ref.Reset();
}
iovec iov; iovec iov;
std::vector<iovec> iov_list; std::vector<iovec> iov_list;
@ -38,7 +32,6 @@ public:
uint64_t offset = 0, len = 0, version = 0; uint64_t offset = 0, len = 0, version = 0;
bool with_parents = false; bool with_parents = false;
Nan::Persistent<v8::Function> callback; Nan::Persistent<v8::Function> callback;
Nan::Persistent<v8::Value> buffer_ref;
}; };
static uint64_t get_ui64(const v8::Local<v8::Value> & val) static uint64_t get_ui64(const v8::Local<v8::Value> & val)
@ -87,11 +80,6 @@ NAN_METHOD(NodeVitastor::Create)
NodeVitastor* cli = new NodeVitastor(); NodeVitastor* cli = new NodeVitastor();
cli->c = vitastor_c_create_uring_json(c_cfg, cfg.size()); cli->c = vitastor_c_create_uring_json(c_cfg, cfg.size());
delete[] c_cfg; delete[] c_cfg;
if (!cli->c)
{
Nan::ThrowError("failed to initialize io_uring (old kernel or insufficient ulimit -l?)");
return;
}
int res = vitastor_c_uring_register_eventfd(cli->c); int res = vitastor_c_uring_register_eventfd(cli->c);
if (res >= 0) if (res >= 0)
@ -135,8 +123,8 @@ NodeVitastorRequest* NodeVitastor::get_read_request(const Nan::FunctionCallbackI
Nan::ThrowError("failed to allocate memory"); Nan::ThrowError("failed to allocate memory");
return NULL; return NULL;
} }
v8::Local<v8::Function> callback = info[argpos+2].As<v8::Function>();
auto req = new NodeVitastorRequest(this, info[argpos+2].As<v8::Function>()); auto req = new NodeVitastorRequest(this, callback);
req->offset = offset; req->offset = offset;
req->len = len; req->len = len;
@ -145,12 +133,12 @@ NodeVitastorRequest* NodeVitastor::get_read_request(const Nan::FunctionCallbackI
return req; return req;
} }
// read(pool, inode, offset, length, callback(err, buffer, version)) // read(pool, inode, offset, len, callback(err, buffer, version))
NAN_METHOD(NodeVitastor::Read) NAN_METHOD(NodeVitastor::Read)
{ {
TRACE("NodeVitastor::Read"); TRACE("NodeVitastor::Read");
if (info.Length() < 5) if (info.Length() < 5)
Nan::ThrowError("Not enough arguments to read(pool, inode, offset, length, callback(err, buffer, version))"); Nan::ThrowError("Not enough arguments to read(pool, inode, offset, len, callback(err, buffer, version))");
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This()); NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
@ -161,9 +149,6 @@ NAN_METHOD(NodeVitastor::Read)
self->Ref(); self->Ref();
vitastor_c_read(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, &req->iov, 1, on_read_finish, req); vitastor_c_read(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, &req->iov, 1, on_read_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c);
#endif
} }
NodeVitastorRequest* NodeVitastor::get_write_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos) NodeVitastorRequest* NodeVitastor::get_write_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos)
@ -183,11 +168,11 @@ NodeVitastorRequest* NodeVitastor::get_write_request(const Nan::FunctionCallback
argpos++; argpos++;
} }
auto req = new NodeVitastorRequest(this, info[argpos+2].As<v8::Function>()); v8::Local<v8::Function> callback = info[argpos+2].As<v8::Function>();
auto req = new NodeVitastorRequest(this, callback);
req->offset = offset; req->offset = offset;
req->version = version; req->version = version;
req->buffer_ref.Reset(bufarg);
if (bufarg->IsArray()) if (bufarg->IsArray())
{ {
@ -232,57 +217,6 @@ NAN_METHOD(NodeVitastor::Write)
req->iov_list.size() ? req->iov_list.data() : &req->iov, req->iov_list.size() ? req->iov_list.data() : &req->iov,
req->iov_list.size() ? req->iov_list.size() : 1, req->iov_list.size() ? req->iov_list.size() : 1,
on_write_finish, req); on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c);
#endif
}
NodeVitastorRequest* NodeVitastor::get_delete_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos)
{
uint64_t offset = get_ui64(info[argpos+0]);
uint64_t len = get_ui64(info[argpos+1]);
uint64_t version = 0;
if (!info[argpos+2].IsEmpty() &&
!info[argpos+2]->IsFunction() &&
info[argpos+2]->IsObject())
{
auto key = Nan::New<v8::String>("version").ToLocalChecked();
auto params = info[argpos+2].As<v8::Object>();
auto versionObj = Nan::Get(params, key).ToLocalChecked();
if (!versionObj.IsEmpty())
version = get_ui64(versionObj);
argpos++;
}
auto req = new NodeVitastorRequest(this, info[argpos+2].As<v8::Function>());
req->offset = offset;
req->len = len;
req->version = version;
return req;
}
// delete(pool, inode, offset, length, { version }?, callback(err))
NAN_METHOD(NodeVitastor::Delete)
{
TRACE("NodeVitastor::Delete");
if (info.Length() < 5)
Nan::ThrowError("Not enough arguments to delete(pool, inode, offset, length, { version }?, callback(err))");
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
uint64_t pool = get_ui64(info[0]);
uint64_t inode = get_ui64(info[1]);
auto req = self->get_delete_request(info, 2);
self->Ref();
vitastor_c_delete(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, req->version,
on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c);
#endif
} }
// sync(callback(err)) // sync(callback(err))
@ -294,21 +228,19 @@ NAN_METHOD(NodeVitastor::Sync)
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This()); NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
auto req = new NodeVitastorRequest(self, info[0].As<v8::Function>()); v8::Local<v8::Function> callback = info[0].As<v8::Function>();
auto req = new NodeVitastorRequest(self, callback);
self->Ref(); self->Ref();
vitastor_c_sync(self->c, on_write_finish, req); vitastor_c_sync(self->c, on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c);
#endif
} }
// read_bitmap(pool, inode, offset, length, with_parents, callback(err, bitmap_buffer)) // read_bitmap(pool, inode, offset, len, with_parents, callback(err, bitmap_buffer))
NAN_METHOD(NodeVitastor::ReadBitmap) NAN_METHOD(NodeVitastor::ReadBitmap)
{ {
TRACE("NodeVitastor::ReadBitmap"); TRACE("NodeVitastor::ReadBitmap");
if (info.Length() < 6) if (info.Length() < 6)
Nan::ThrowError("Not enough arguments to read_bitmap(pool, inode, offset, length, with_parents, callback(err, bitmap_buffer))"); Nan::ThrowError("Not enough arguments to read_bitmap(pool, inode, offset, len, with_parents, callback(err, bitmap_buffer))");
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This()); NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
@ -317,13 +249,11 @@ NAN_METHOD(NodeVitastor::ReadBitmap)
uint64_t offset = get_ui64(info[2]); uint64_t offset = get_ui64(info[2]);
uint64_t len = get_ui64(info[3]); uint64_t len = get_ui64(info[3]);
bool with_parents = Nan::To<bool>(info[4]).FromJust(); bool with_parents = Nan::To<bool>(info[4]).FromJust();
v8::Local<v8::Function> callback = info[5].As<v8::Function>();
auto req = new NodeVitastorRequest(self, info[5].As<v8::Function>()); auto req = new NodeVitastorRequest(self, callback);
self->Ref(); self->Ref();
vitastor_c_read_bitmap(self->c, ((pool << (64-POOL_ID_BITS)) | inode), offset, len, with_parents, on_read_bitmap_finish, req); vitastor_c_read_bitmap(self->c, ((pool << (64-POOL_ID_BITS)) | inode), offset, len, with_parents, on_read_bitmap_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c);
#endif
} }
static void on_error(NodeVitastorRequest *req, Nan::Callback & nanCallback, long retval) static void on_error(NodeVitastorRequest *req, Nan::Callback & nanCallback, long retval)
@ -337,66 +267,6 @@ static void on_error(NodeVitastorRequest *req, Nan::Callback & nanCallback, long
nanCallback.Call(1, args, req); nanCallback.Call(1, args, req);
} }
// on_ready(callback(err))
NAN_METHOD(NodeVitastor::OnReady)
{
TRACE("NodeVitastor::OnReady");
if (info.Length() < 1)
Nan::ThrowError("Not enough arguments to on_ready(callback(err))");
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
auto req = new NodeVitastorRequest(self, info[0].As<v8::Function>());
self->Ref();
vitastor_c_on_ready(self->c, on_ready_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c);
#endif
}
void NodeVitastor::on_ready_finish(void *opaque, long retval)
{
TRACE("NodeVitastor::on_ready_finish");
auto req = (NodeVitastorRequest*)opaque;
auto self = req->cli;
Nan::HandleScope scope;
Nan::Callback nanCallback(Nan::New(req->callback));
nanCallback.Call(0, NULL, req);
self->Unref();
delete req;
}
// get_min_io_size(pool_id)
NAN_METHOD(NodeVitastor::GetMinIoSize)
{
TRACE("NodeVitastor::GetMinIoSize");
if (info.Length() < 1)
Nan::ThrowError("Not enough arguments to get_min_io_size(pool_id)");
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
uint64_t pool = get_ui64(info[0]);
info.GetReturnValue().Set(Nan::New<v8::Number>(vitastor_c_inode_get_bitmap_granularity(self->c, INODE_WITH_POOL(pool, 1))));
}
// get_max_atomic_write_size(pool_id)
NAN_METHOD(NodeVitastor::GetMaxAtomicWriteSize)
{
TRACE("NodeVitastor::GetMaxAtomicWriteSize");
if (info.Length() < 1)
Nan::ThrowError("Not enough arguments to get_max_atomic_write_size(pool_id)");
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
uint64_t pool = get_ui64(info[0]);
info.GetReturnValue().Set(Nan::New<v8::Number>(vitastor_c_inode_get_block_size(self->c, INODE_WITH_POOL(pool, 1))));
}
// get_immediate_commit(pool_id)
NAN_METHOD(NodeVitastor::GetImmediateCommit)
{
TRACE("NodeVitastor::GetImmediateCommit");
if (info.Length() < 1)
Nan::ThrowError("Not enough arguments to get_immediate_commit(pool_id)");
NodeVitastor* self = Nan::ObjectWrap::Unwrap<NodeVitastor>(info.This());
uint64_t pool = get_ui64(info[0]);
info.GetReturnValue().Set(Nan::New<v8::Number>(vitastor_c_inode_get_immediate_commit(self->c, INODE_WITH_POOL(pool, 1))));
}
void NodeVitastor::on_read_finish(void *opaque, long retval, uint64_t version) void NodeVitastor::on_read_finish(void *opaque, long retval, uint64_t version)
{ {
TRACE("NodeVitastor::on_read_finish"); TRACE("NodeVitastor::on_read_finish");
@ -494,9 +364,6 @@ NAN_METHOD(NodeVitastorImage::Create)
img->Ref(); img->Ref();
cli->Ref(); cli->Ref();
vitastor_c_watch_inode(cli->c, (char*)img->name.c_str(), on_watch_start, img); vitastor_c_watch_inode(cli->c, (char*)img->name.c_str(), on_watch_start, img);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c);
#endif
info.GetReturnValue().Set(info.This()); info.GetReturnValue().Set(info.This());
} }
@ -511,12 +378,12 @@ NodeVitastorImage::~NodeVitastorImage()
cli->Unref(); cli->Unref();
} }
// read(offset, length, callback(err, buffer, version)) // read(offset, len, callback(err, buffer, version))
NAN_METHOD(NodeVitastorImage::Read) NAN_METHOD(NodeVitastorImage::Read)
{ {
TRACE("NodeVitastorImage::Read"); TRACE("NodeVitastorImage::Read");
if (info.Length() < 3) if (info.Length() < 3)
Nan::ThrowError("Not enough arguments to read(offset, length, callback(err, buffer, version))"); Nan::ThrowError("Not enough arguments to read(offset, len, callback(err, buffer, version))");
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This()); NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
@ -527,12 +394,12 @@ NAN_METHOD(NodeVitastorImage::Read)
img->exec_or_wait(req); img->exec_or_wait(req);
} }
// write(offset, buf: Buffer | Buffer[], { version }?, callback(err)) // write(offset, buffer, { version }?, callback(err))
NAN_METHOD(NodeVitastorImage::Write) NAN_METHOD(NodeVitastorImage::Write)
{ {
TRACE("NodeVitastorImage::Write"); TRACE("NodeVitastorImage::Write");
if (info.Length() < 3) if (info.Length() < 3)
Nan::ThrowError("Not enough arguments to write(offset, buf: Buffer | Buffer[], { version }?, callback(err))"); Nan::ThrowError("Not enough arguments to write(offset, buffer, { version }?, callback(err))");
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This()); NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
@ -543,22 +410,6 @@ NAN_METHOD(NodeVitastorImage::Write)
img->exec_or_wait(req); img->exec_or_wait(req);
} }
// delete(offset, length, { version }?, callback(err))
NAN_METHOD(NodeVitastorImage::Delete)
{
TRACE("NodeVitastorImage::Delete");
if (info.Length() < 3)
Nan::ThrowError("Not enough arguments to delete(offset, length, { version }?, callback(err))");
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
auto req = img->cli->get_delete_request(info, 0);
req->img = img;
req->op = NODE_VITASTOR_DELETE;
img->exec_or_wait(req);
}
// sync(callback(err)) // sync(callback(err))
NAN_METHOD(NodeVitastorImage::Sync) NAN_METHOD(NodeVitastorImage::Sync)
{ {
@ -568,27 +419,29 @@ NAN_METHOD(NodeVitastorImage::Sync)
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This()); NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
auto req = new NodeVitastorRequest(img->cli, info[0].As<v8::Function>()); v8::Local<v8::Function> callback = info[0].As<v8::Function>();
auto req = new NodeVitastorRequest(img->cli, callback);
req->img = img; req->img = img;
req->op = NODE_VITASTOR_SYNC; req->op = NODE_VITASTOR_SYNC;
img->exec_or_wait(req); img->exec_or_wait(req);
} }
// read_bitmap(offset, length, with_parents, callback(err, bitmap_buffer)) // read_bitmap(offset, len, with_parents, callback(err, bitmap_buffer))
NAN_METHOD(NodeVitastorImage::ReadBitmap) NAN_METHOD(NodeVitastorImage::ReadBitmap)
{ {
TRACE("NodeVitastorImage::ReadBitmap"); TRACE("NodeVitastorImage::ReadBitmap");
if (info.Length() < 4) if (info.Length() < 4)
Nan::ThrowError("Not enough arguments to read_bitmap(offset, length, with_parents, callback(err, bitmap_buffer))"); Nan::ThrowError("Not enough arguments to read_bitmap(offset, len, with_parents, callback(err, bitmap_buffer))");
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This()); NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
uint64_t offset = get_ui64(info[0]); uint64_t offset = get_ui64(info[0]);
uint64_t len = get_ui64(info[1]); uint64_t len = get_ui64(info[1]);
bool with_parents = Nan::To<bool>(info[2]).FromJust(); bool with_parents = Nan::To<bool>(info[2]).FromJust();
v8::Local<v8::Function> callback = info[3].As<v8::Function>();
auto req = new NodeVitastorRequest(img->cli, info[3].As<v8::Function>()); auto req = new NodeVitastorRequest(img->cli, callback);
req->img = img; req->img = img;
req->op = NODE_VITASTOR_READ_BITMAP; req->op = NODE_VITASTOR_READ_BITMAP;
req->offset = offset; req->offset = offset;
@ -607,7 +460,8 @@ NAN_METHOD(NodeVitastorImage::GetInfo)
NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This()); NodeVitastorImage* img = Nan::ObjectWrap::Unwrap<NodeVitastorImage>(info.This());
auto req = new NodeVitastorRequest(img->cli, info[0].As<v8::Function>()); v8::Local<v8::Function> callback = info[0].As<v8::Function>();
auto req = new NodeVitastorRequest(img->cli, callback);
req->img = img; req->img = img;
req->op = NODE_VITASTOR_GET_INFO; req->op = NODE_VITASTOR_GET_INFO;
@ -634,9 +488,6 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
uint64_t ino = vitastor_c_inode_get_num(watch); uint64_t ino = vitastor_c_inode_get_num(watch);
cli->Ref(); cli->Ref();
vitastor_c_read(cli->c, ino, req->offset, req->len, &req->iov, 1, NodeVitastor::on_read_finish, req); vitastor_c_read(cli->c, ino, req->offset, req->len, &req->iov, 1, NodeVitastor::on_read_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c);
#endif
} }
else if (req->op == NODE_VITASTOR_WRITE) else if (req->op == NODE_VITASTOR_WRITE)
{ {
@ -646,19 +497,6 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
req->iov_list.size() ? req->iov_list.data() : &req->iov, req->iov_list.size() ? req->iov_list.data() : &req->iov,
req->iov_list.size() ? req->iov_list.size() : 1, req->iov_list.size() ? req->iov_list.size() : 1,
NodeVitastor::on_write_finish, req); NodeVitastor::on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c);
#endif
}
else if (req->op == NODE_VITASTOR_DELETE)
{
uint64_t ino = vitastor_c_inode_get_num(watch);
cli->Ref();
vitastor_c_delete(cli->c, ino, req->offset, req->len, req->version,
NodeVitastor::on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c);
#endif
} }
else if (req->op == NODE_VITASTOR_SYNC) else if (req->op == NODE_VITASTOR_SYNC)
{ {
@ -668,9 +506,6 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
if (imm != IMMEDIATE_ALL) if (imm != IMMEDIATE_ALL)
{ {
vitastor_c_sync(cli->c, NodeVitastor::on_write_finish, req); vitastor_c_sync(cli->c, NodeVitastor::on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c);
#endif
} }
else else
{ {
@ -682,9 +517,6 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
uint64_t ino = vitastor_c_inode_get_num(watch); uint64_t ino = vitastor_c_inode_get_num(watch);
cli->Ref(); cli->Ref();
vitastor_c_read_bitmap(cli->c, ino, req->offset, req->len, req->with_parents, NodeVitastor::on_read_bitmap_finish, req); vitastor_c_read_bitmap(cli->c, ino, req->offset, req->len, req->with_parents, NodeVitastor::on_read_bitmap_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c);
#endif
} }
else if (req->op == NODE_VITASTOR_GET_INFO) else if (req->op == NODE_VITASTOR_GET_INFO)
{ {
@ -802,7 +634,8 @@ NAN_METHOD(NodeVitastorKV::Open)
cfg[std::string(*Nan::Utf8String(key))] = std::string(*Nan::Utf8String(Nan::Get(jsParams, key).ToLocalChecked())); cfg[std::string(*Nan::Utf8String(key))] = std::string(*Nan::Utf8String(Nan::Get(jsParams, key).ToLocalChecked()));
} }
auto req = new NodeVitastorRequest(kv->cli, info[3].As<v8::Function>()); v8::Local<v8::Function> callback = info[3].As<v8::Function>();
auto req = new NodeVitastorRequest(kv->cli, callback);
kv->Ref(); kv->Ref();
kv->dbw->open(inode_id, cfg, [kv, req](int res) kv->dbw->open(inode_id, cfg, [kv, req](int res)
@ -815,9 +648,6 @@ NAN_METHOD(NodeVitastorKV::Open)
delete req; delete req;
kv->Unref(); kv->Unref();
}); });
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// close(callback(err)) // close(callback(err))
@ -829,7 +659,8 @@ NAN_METHOD(NodeVitastorKV::Close)
NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap<NodeVitastorKV>(info.This()); NodeVitastorKV* kv = Nan::ObjectWrap::Unwrap<NodeVitastorKV>(info.This());
auto req = new NodeVitastorRequest(kv->cli, info[0].As<v8::Function>()); v8::Local<v8::Function> callback = info[0].As<v8::Function>();
auto req = new NodeVitastorRequest(kv->cli, callback);
kv->Ref(); kv->Ref();
kv->dbw->close([kv, req]() kv->dbw->close([kv, req]()
@ -840,9 +671,6 @@ NAN_METHOD(NodeVitastorKV::Close)
delete req; delete req;
kv->Unref(); kv->Unref();
}); });
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// set_config({ ...config }) // set_config({ ...config })
@ -886,7 +714,8 @@ void NodeVitastorKV::get_impl(const Nan::FunctionCallbackInfo<v8::Value> & info,
// FIXME: Handle Buffer too // FIXME: Handle Buffer too
std::string key(*Nan::Utf8String(info[0].As<v8::String>())); std::string key(*Nan::Utf8String(info[0].As<v8::String>()));
auto req = new NodeVitastorRequest(kv->cli, info[1].As<v8::Function>()); v8::Local<v8::Function> callback = info[1].As<v8::Function>();
auto req = new NodeVitastorRequest(kv->cli, callback);
kv->Ref(); kv->Ref();
kv->dbw->get(key, [kv, req](int res, const std::string & value) kv->dbw->get(key, [kv, req](int res, const std::string & value)
@ -900,9 +729,6 @@ void NodeVitastorKV::get_impl(const Nan::FunctionCallbackInfo<v8::Value> & info,
delete req; delete req;
kv->Unref(); kv->Unref();
}, allow_cache); }, allow_cache);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// get(key, callback(err, value)) // get(key, callback(err, value))
@ -951,12 +777,14 @@ NAN_METHOD(NodeVitastorKV::Set)
std::string key(*Nan::Utf8String(info[0].As<v8::String>())); std::string key(*Nan::Utf8String(info[0].As<v8::String>()));
std::string value(*Nan::Utf8String(info[1].As<v8::String>())); std::string value(*Nan::Utf8String(info[1].As<v8::String>()));
NodeVitastorRequest *req = new NodeVitastorRequest(kv->cli, info[2].As<v8::Function>()), *cas_req = NULL; v8::Local<v8::Function> callback = info[2].As<v8::Function>();
NodeVitastorRequest *req = new NodeVitastorRequest(kv->cli, callback), *cas_req = NULL;
std::function<bool(int, const std::string &)> cas_cb; std::function<bool(int, const std::string &)> cas_cb;
if (info.Length() > 3 && info[3]->IsObject()) if (info.Length() > 3 && info[3]->IsObject())
{ {
cas_req = new NodeVitastorRequest(kv->cli, info[3].As<v8::Function>()); v8::Local<v8::Function> cas_callback = info[3].As<v8::Function>();
cas_req = new NodeVitastorRequest(kv->cli, cas_callback);
cas_cb = make_cas_callback(cas_req); cas_cb = make_cas_callback(cas_req);
} }
@ -973,9 +801,6 @@ NAN_METHOD(NodeVitastorKV::Set)
delete cas_req; delete cas_req;
kv->Unref(); kv->Unref();
}, cas_cb); }, cas_cb);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// del(key, callback(err), cas_compare(old_value)?) // del(key, callback(err), cas_compare(old_value)?)
@ -990,12 +815,14 @@ NAN_METHOD(NodeVitastorKV::Del)
// FIXME: Handle Buffer too // FIXME: Handle Buffer too
std::string key(*Nan::Utf8String(info[0].As<v8::String>())); std::string key(*Nan::Utf8String(info[0].As<v8::String>()));
NodeVitastorRequest *req = new NodeVitastorRequest(kv->cli, info[1].As<v8::Function>()), *cas_req = NULL; v8::Local<v8::Function> callback = info[1].As<v8::Function>();
NodeVitastorRequest *req = new NodeVitastorRequest(kv->cli, callback), *cas_req = NULL;
std::function<bool(int, const std::string &)> cas_cb; std::function<bool(int, const std::string &)> cas_cb;
if (info.Length() > 2 && info[2]->IsObject()) if (info.Length() > 2 && info[2]->IsObject())
{ {
cas_req = new NodeVitastorRequest(kv->cli, info[2].As<v8::Function>()); v8::Local<v8::Function> cas_callback = info[2].As<v8::Function>();
cas_req = new NodeVitastorRequest(kv->cli, cas_callback);
cas_cb = make_cas_callback(cas_req); cas_cb = make_cas_callback(cas_req);
} }
@ -1012,9 +839,6 @@ NAN_METHOD(NodeVitastorKV::Del)
delete cas_req; delete cas_req;
kv->Unref(); kv->Unref();
}, cas_cb); }, cas_cb);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// list(start_key?) // list(start_key?)
@ -1085,7 +909,7 @@ NodeVitastorKVListing::~NodeVitastorKVListing()
kv->Unref(); kv->Unref();
} }
// next(callback(err, key, value)?) // next(callback(err, value)?)
NAN_METHOD(NodeVitastorKVListing::Next) NAN_METHOD(NodeVitastorKVListing::Next)
{ {
TRACE("NodeVitastorKVListing::Next"); TRACE("NodeVitastorKVListing::Next");
@ -1094,11 +918,12 @@ NAN_METHOD(NodeVitastorKVListing::Next)
if (info.Length() > 0) if (info.Length() > 0)
{ {
v8::Local<v8::Function> callback = info[0].As<v8::Function>();
if (list->iter) if (list->iter)
{ {
delete list->iter; delete list->iter;
} }
list->iter = new NodeVitastorRequest(list->kv->cli, info[0].As<v8::Function>()); list->iter = new NodeVitastorRequest(list->kv->cli, callback);
} }
if (!list->handle) if (!list->handle)
{ {
@ -1134,9 +959,6 @@ NAN_METHOD(NodeVitastorKVListing::Next)
list->iter = req; list->iter = req;
list->kv->Unref(); list->kv->Unref();
}); });
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(list->kv->cli->c);
#endif
} }
// close() // close()

View File

@ -15,24 +15,14 @@ class NodeVitastor: public Nan::ObjectWrap
public: public:
// constructor({ ...config }) // constructor({ ...config })
static NAN_METHOD(Create); static NAN_METHOD(Create);
// read(pool_id, inode, offset, length, callback(err, buffer, version)) // read(pool, inode, offset, len, callback(err, buffer, version))
static NAN_METHOD(Read); static NAN_METHOD(Read);
// write(pool_id, inode, offset, buf: Buffer | Buffer[], { version }?, callback(err)) // write(pool, inode, offset, buf: Buffer | Buffer[], { version }?, callback(err))
static NAN_METHOD(Write); static NAN_METHOD(Write);
// delete(pool_id, inode, offset, length, { version }?, callback(err))
static NAN_METHOD(Delete);
// sync(callback(err)) // sync(callback(err))
static NAN_METHOD(Sync); static NAN_METHOD(Sync);
// read_bitmap(pool_id, inode, offset, length, with_parents, callback(err, bitmap_buffer)) // read_bitmap(pool, inode, offset, len, with_parents, callback(err, bitmap_buffer))
static NAN_METHOD(ReadBitmap); static NAN_METHOD(ReadBitmap);
// on_ready(callback(err))
static NAN_METHOD(OnReady);
// get_min_io_size(pool_id)
static NAN_METHOD(GetMinIoSize);
// get_max_atomic_write_size(pool_id)
static NAN_METHOD(GetMaxAtomicWriteSize);
// get_immediate_commit(pool_id)
static NAN_METHOD(GetImmediateCommit);
// // destroy() // // destroy()
// static NAN_METHOD(Destroy); // static NAN_METHOD(Destroy);
@ -47,13 +37,11 @@ private:
static void on_io_readable(uv_poll_t* handle, int status, int revents); static void on_io_readable(uv_poll_t* handle, int status, int revents);
static void on_read_finish(void *opaque, long retval, uint64_t version); static void on_read_finish(void *opaque, long retval, uint64_t version);
static void on_ready_finish(void *opaque, long retval);
static void on_write_finish(void *opaque, long retval); static void on_write_finish(void *opaque, long retval);
static void on_read_bitmap_finish(void *opaque, long retval, uint8_t *bitmap); static void on_read_bitmap_finish(void *opaque, long retval, uint8_t *bitmap);
NodeVitastorRequest* get_read_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos); NodeVitastorRequest* get_read_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos);
NodeVitastorRequest* get_write_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos); NodeVitastorRequest* get_write_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos);
NodeVitastorRequest* get_delete_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos);
friend class NodeVitastorImage; friend class NodeVitastorImage;
friend class NodeVitastorKV; friend class NodeVitastorKV;
@ -65,15 +53,13 @@ class NodeVitastorImage: public Nan::ObjectWrap
public: public:
// constructor(node_vitastor, name) // constructor(node_vitastor, name)
static NAN_METHOD(Create); static NAN_METHOD(Create);
// read(offset, length, callback(err, buffer, version)) // read(offset, len, callback(err, buffer, version))
static NAN_METHOD(Read); static NAN_METHOD(Read);
// write(offset, buf: Buffer | Buffer[], { version }?, callback(err)) // write(offset, buf: Buffer | Buffer[], { version }?, callback(err))
static NAN_METHOD(Write); static NAN_METHOD(Write);
// delete(offset, length, { version }?, callback(err))
static NAN_METHOD(Delete);
// sync(callback(err)) // sync(callback(err))
static NAN_METHOD(Sync); static NAN_METHOD(Sync);
// read_bitmap(offset, length, with_parents, callback(err, bitmap_buffer)) // read_bitmap(offset, len, with_parents, callback(err, bitmap_buffer))
static NAN_METHOD(ReadBitmap); static NAN_METHOD(ReadBitmap);
// get_info(callback({ num, name, size, parent_id?, readonly?, meta?, mod_revision, block_size, bitmap_granularity, immediate_commit })) // get_info(callback({ num, name, size, parent_id?, readonly?, meta?, mod_revision, block_size, bitmap_granularity, immediate_commit }))
static NAN_METHOD(GetInfo); static NAN_METHOD(GetInfo);
@ -134,7 +120,7 @@ class NodeVitastorKVListing: public Nan::ObjectWrap
public: public:
// constructor(node_vitastor_kv, start_key?) // constructor(node_vitastor_kv, start_key?)
static NAN_METHOD(Create); static NAN_METHOD(Create);
// next(callback(err, key, value)?) // next(callback(err, value)?)
static NAN_METHOD(Next); static NAN_METHOD(Next);
// close() // close()
static NAN_METHOD(Close); static NAN_METHOD(Close);

View File

@ -1,6 +1,6 @@
{ {
"name": "vitastor", "name": "vitastor",
"version": "2.1.0", "version": "1.7.0",
"description": "Low-level native bindings to Vitastor client library", "description": "Low-level native bindings to Vitastor client library",
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
@ -16,7 +16,7 @@
"build": "node-gyp rebuild" "build": "node-gyp rebuild"
}, },
"author": "Vitaliy Filippov", "author": "Vitaliy Filippov",
"license": "VNPL-1.1", "license": "VNPL-2.0",
"dependencies": { "dependencies": {
"bindings": "1.5.0", "bindings": "1.5.0",
"nan": "^2.19.0" "nan": "^2.19.0"

View File

@ -50,7 +50,7 @@ from cinder.volume import configuration
from cinder.volume import driver from cinder.volume import driver
from cinder.volume import volume_utils from cinder.volume import volume_utils
VITASTOR_VERSION = '2.1.0' VITASTOR_VERSION = '1.10.1'
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@ -1,172 +0,0 @@
Index: pve-qemu-kvm-9.2.0/block/meson.build
===================================================================
--- pve-qemu-kvm-9.2.0.orig/block/meson.build
+++ pve-qemu-kvm-9.2.0/block/meson.build
@@ -126,6 +126,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()
Index: pve-qemu-kvm-9.2.0/meson.build
===================================================================
--- pve-qemu-kvm-9.2.0.orig/meson.build
+++ pve-qemu-kvm-9.2.0/meson.build
@@ -1590,6 +1590,26 @@ if not get_option('rbd').auto() or have_
endif
endif
+vitastor = not_found
+if not get_option('vitastor').auto() or have_block
+ libvitastor_client = cc.find_library('vitastor_client', has_headers: ['vitastor_c.h'],
+ required: get_option('vitastor'))
+ if libvitastor_client.found()
+ if cc.links('''
+ #include <vitastor_c.h>
+ int main(void) {
+ vitastor_c_create_qemu(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return 0;
+ }''', dependencies: libvitastor_client)
+ vitastor = declare_dependency(dependencies: libvitastor_client)
+ elif get_option('vitastor').enabled()
+ error('could not link libvitastor_client')
+ else
+ warning('could not link libvitastor_client, disabling')
+ endif
+ endif
+endif
+
glusterfs = not_found
glusterfs_ftruncate_has_stat = false
glusterfs_iocb_has_stat = false
@@ -2478,6 +2498,7 @@ endif
config_host_data.set('CONFIG_OPENGL', opengl.found())
config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
config_host_data.set('CONFIG_RBD', rbd.found())
+config_host_data.set('CONFIG_VITASTOR', vitastor.found())
config_host_data.set('CONFIG_RDMA', rdma.found())
config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
@@ -4789,6 +4810,7 @@ summary_info += {'fdt support': fd
summary_info += {'libcap-ng support': libcap_ng}
summary_info += {'bpf support': libbpf}
summary_info += {'rbd support': rbd}
+summary_info += {'vitastor support': vitastor}
summary_info += {'smartcard support': cacard}
summary_info += {'U2F support': u2f}
summary_info += {'libusb': libusb}
Index: pve-qemu-kvm-9.2.0/meson_options.txt
===================================================================
--- pve-qemu-kvm-9.2.0.orig/meson_options.txt
+++ pve-qemu-kvm-9.2.0/meson_options.txt
@@ -200,6 +200,8 @@ option('lzo', type : 'feature', value :
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',
Index: pve-qemu-kvm-9.2.0/qapi/block-core.json
===================================================================
--- pve-qemu-kvm-9.2.0.orig/qapi/block-core.json
+++ pve-qemu-kvm-9.2.0/qapi/block-core.json
@@ -3481,7 +3481,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' },
@@ -4592,6 +4592,28 @@
'*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:
#
# An enumeration of replication modes.
@@ -5054,6 +5076,7 @@
'throttle': 'BlockdevOptionsThrottle',
'vdi': 'BlockdevOptionsGenericFormat',
'vhdx': 'BlockdevOptionsGenericFormat',
+ 'vitastor': 'BlockdevOptionsVitastor',
'virtio-blk-vfio-pci':
{ 'type': 'BlockdevOptionsVirtioBlkVfioPci',
'if': 'CONFIG_BLKIO' },
@@ -5501,6 +5524,20 @@
'*encrypt' : 'RbdEncryptionCreateOptions' } }
##
+# @BlockdevCreateOptionsVitastor:
+#
+# Driver specific image creation options for Vitastor.
+#
+# @location: Where to store the new image file. This location cannot
+# point to a snapshot.
+#
+# @size: Size of the virtual disk in bytes
+##
+{ 'struct': 'BlockdevCreateOptionsVitastor',
+ 'data': { 'location': 'BlockdevOptionsVitastor',
+ 'size': 'size' } }
+
+##
# @BlockdevVmdkSubformat:
#
# Subformat options for VMDK images
@@ -5722,6 +5759,7 @@
'ssh': 'BlockdevCreateOptionsSsh',
'vdi': 'BlockdevCreateOptionsVdi',
'vhdx': 'BlockdevCreateOptionsVhdx',
+ 'vitastor': 'BlockdevCreateOptionsVitastor',
'vmdk': 'BlockdevCreateOptionsVmdk',
'vpc': 'BlockdevCreateOptionsVpc'
} }
Index: pve-qemu-kvm-9.2.0/scripts/meson-buildoptions.sh
===================================================================
--- pve-qemu-kvm-9.2.0.orig/scripts/meson-buildoptions.sh
+++ pve-qemu-kvm-9.2.0/scripts/meson-buildoptions.sh
@@ -174,6 +174,7 @@ meson_options_help() {
printf "%s\n" ' qga-vss build QGA VSS support (broken with MinGW)'
printf "%s\n" ' qpl Query Processing Library support'
printf "%s\n" ' rbd Ceph block device driver'
+ printf "%s\n" ' vitastor Vitastor block device driver'
printf "%s\n" ' rdma Enable RDMA-based migration'
printf "%s\n" ' replication replication support'
printf "%s\n" ' rust Rust support'
@@ -455,6 +456,8 @@ _meson_option_parse() {
--disable-qpl) printf "%s" -Dqpl=disabled ;;
--enable-rbd) printf "%s" -Drbd=enabled ;;
--disable-rbd) printf "%s" -Drbd=disabled ;;
+ --enable-vitastor) printf "%s" -Dvitastor=enabled ;;
+ --disable-vitastor) printf "%s" -Dvitastor=disabled ;;
--enable-rdma) printf "%s" -Drdma=enabled ;;
--disable-rdma) printf "%s" -Drdma=disabled ;;
--enable-relocatable) printf "%s" -Drelocatable=true ;;

View File

@ -1,172 +0,0 @@
diff --git a/block/meson.build b/block/meson.build
index f1262ec2ba..3cf3e23f16 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 147097c652..2486b3aeb5 100644
--- a/meson.build
+++ b/meson.build
@@ -1590,6 +1590,26 @@ if not get_option('rbd').auto() or have_block
endif
endif
+vitastor = not_found
+if not get_option('vitastor').auto() or have_block
+ libvitastor_client = cc.find_library('vitastor_client', has_headers: ['vitastor_c.h'],
+ required: get_option('vitastor'))
+ if libvitastor_client.found()
+ if cc.links('''
+ #include <vitastor_c.h>
+ int main(void) {
+ vitastor_c_create_qemu(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return 0;
+ }''', dependencies: libvitastor_client)
+ vitastor = declare_dependency(dependencies: libvitastor_client)
+ elif get_option('vitastor').enabled()
+ error('could not link libvitastor_client')
+ else
+ warning('could not link libvitastor_client, disabling')
+ endif
+ endif
+endif
+
glusterfs = not_found
glusterfs_ftruncate_has_stat = false
glusterfs_iocb_has_stat = false
@@ -2474,6 +2494,7 @@ endif
config_host_data.set('CONFIG_OPENGL', opengl.found())
config_host_data.set('CONFIG_PLUGIN', get_option('plugins'))
config_host_data.set('CONFIG_RBD', rbd.found())
+config_host_data.set('CONFIG_VITASTOR', vitastor.found())
config_host_data.set('CONFIG_RDMA', rdma.found())
config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable'))
config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack'))
@@ -4778,6 +4799,7 @@ summary_info += {'fdt support': fdt_opt == 'internal' ? 'internal' : fdt}
summary_info += {'libcap-ng support': libcap_ng}
summary_info += {'bpf support': libbpf}
summary_info += {'rbd support': rbd}
+summary_info += {'vitastor support': vitastor}
summary_info += {'smartcard support': cacard}
summary_info += {'U2F support': u2f}
summary_info += {'libusb': libusb}
diff --git a/meson_options.txt b/meson_options.txt
index 5eeaf3eee5..b04eda29f9 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -200,6 +200,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 fd3bcc1c17..41571ac3f9 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3212,7 +3212,7 @@
'parallels', 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum',
'raw', 'rbd',
{ 'name': 'replication', 'if': 'CONFIG_REPLICATION' },
- 'ssh', 'throttle', 'vdi', 'vhdx',
+ 'ssh', 'throttle', 'vdi', 'vhdx', 'vitastor',
{ 'name': 'virtio-blk-vfio-pci', 'if': 'CONFIG_BLKIO' },
{ 'name': 'virtio-blk-vhost-user', 'if': 'CONFIG_BLKIO' },
{ 'name': 'virtio-blk-vhost-vdpa', 'if': 'CONFIG_BLKIO' },
@@ -4295,6 +4295,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:
#
@@ -4757,6 +4779,7 @@
'throttle': 'BlockdevOptionsThrottle',
'vdi': 'BlockdevOptionsGenericFormat',
'vhdx': 'BlockdevOptionsGenericFormat',
+ 'vitastor': 'BlockdevOptionsVitastor',
'virtio-blk-vfio-pci':
{ 'type': 'BlockdevOptionsVirtioBlkVfioPci',
'if': 'CONFIG_BLKIO' },
@@ -5198,6 +5221,20 @@
'*cluster-size' : 'size',
'*encrypt' : 'RbdEncryptionCreateOptions' } }
+##
+# @BlockdevCreateOptionsVitastor:
+#
+# Driver specific image creation options for Vitastor.
+#
+# @location: Where to store the new image file. This location cannot
+# point to a snapshot.
+#
+# @size: Size of the virtual disk in bytes
+##
+{ 'struct': 'BlockdevCreateOptionsVitastor',
+ 'data': { 'location': 'BlockdevOptionsVitastor',
+ 'size': 'size' } }
+
##
# @BlockdevVmdkSubformat:
#
@@ -5420,6 +5457,7 @@
'ssh': 'BlockdevCreateOptionsSsh',
'vdi': 'BlockdevCreateOptionsVdi',
'vhdx': 'BlockdevCreateOptionsVhdx',
+ 'vitastor': 'BlockdevCreateOptionsVitastor',
'vmdk': 'BlockdevCreateOptionsVmdk',
'vpc': 'BlockdevCreateOptionsVpc'
} }
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index a8066aab03..12e650e7d4 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -174,6 +174,7 @@ meson_options_help() {
printf "%s\n" ' qga-vss build QGA VSS support (broken with MinGW)'
printf "%s\n" ' qpl Query Processing Library support'
printf "%s\n" ' rbd Ceph block device driver'
+ printf "%s\n" ' vitastor Vitastor block device driver'
printf "%s\n" ' rdma Enable RDMA-based migration'
printf "%s\n" ' replication replication support'
printf "%s\n" ' rust Rust support'
@@ -455,6 +456,8 @@ _meson_option_parse() {
--disable-qpl) printf "%s" -Dqpl=disabled ;;
--enable-rbd) printf "%s" -Drbd=enabled ;;
--disable-rbd) printf "%s" -Drbd=disabled ;;
+ --enable-vitastor) printf "%s" -Dvitastor=enabled ;;
+ --disable-vitastor) printf "%s" -Dvitastor=disabled ;;
--enable-rdma) printf "%s" -Drdma=enabled ;;
--disable-rdma) printf "%s" -Drdma=disabled ;;
--enable-relocatable) printf "%s" -Drelocatable=true ;;

View File

@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 2.1.0 Version: 1.10.1
Release: 1%{?dist} Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1 License: Vitastor Network Public License 1.1
URL: https://vitastor.io/ URL: https://vitastor.io/
Source0: vitastor-2.1.0.el7.tar.gz Source0: vitastor-1.10.1.el7.tar.gz
BuildRequires: liburing-devel >= 0.6 BuildRequires: liburing-devel >= 0.6
BuildRequires: gperftools-devel BuildRequires: gperftools-devel

View File

@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 2.1.0 Version: 1.10.1
Release: 1%{?dist} Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1 License: Vitastor Network Public License 1.1
URL: https://vitastor.io/ URL: https://vitastor.io/
Source0: vitastor-2.1.0.el8.tar.gz Source0: vitastor-1.10.1.el8.tar.gz
BuildRequires: liburing-devel >= 0.6 BuildRequires: liburing-devel >= 0.6
BuildRequires: gperftools-devel BuildRequires: gperftools-devel

View File

@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 2.1.0 Version: 1.10.1
Release: 1%{?dist} Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1 License: Vitastor Network Public License 1.1
URL: https://vitastor.io/ URL: https://vitastor.io/
Source0: vitastor-2.1.0.el9.tar.gz Source0: vitastor-1.10.1.el9.tar.gz
BuildRequires: liburing-devel >= 0.6 BuildRequires: liburing-devel >= 0.6
BuildRequires: gperftools-devel BuildRequires: gperftools-devel

View File

@ -19,7 +19,7 @@ if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/local/?$")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
endif() endif()
add_definitions(-DVITASTOR_VERSION="2.1.0") add_definitions(-DVITASTOR_VERSION="1.10.1")
add_definitions(-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -fno-omit-frame-pointer -I ${CMAKE_SOURCE_DIR}/src) add_definitions(-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -fno-omit-frame-pointer -I ${CMAKE_SOURCE_DIR}/src)
add_link_options(-fno-omit-frame-pointer) add_link_options(-fno-omit-frame-pointer)
if (${WITH_ASAN}) if (${WITH_ASAN})

View File

@ -31,6 +31,7 @@
#define DEFAULT_DATA_BLOCK_ORDER 17 #define DEFAULT_DATA_BLOCK_ORDER 17
#define MIN_DATA_BLOCK_SIZE 4*1024 #define MIN_DATA_BLOCK_SIZE 4*1024
#define MAX_DATA_BLOCK_SIZE 128*1024*1024 #define MAX_DATA_BLOCK_SIZE 128*1024*1024
#define MAX_META_BLOCK_SIZE 64*1024
#define DEFAULT_BITMAP_GRANULARITY 4096 #define DEFAULT_BITMAP_GRANULARITY 4096
#define BS_OP_MIN 1 #define BS_OP_MIN 1

View File

@ -8,7 +8,6 @@
#include "blockstore_impl.h" #include "blockstore_impl.h"
#include "blockstore_disk.h" #include "blockstore_disk.h"
#include "str_util.h" #include "str_util.h"
#include "allocator.h"
static uint32_t is_power_of_two(uint64_t value) static uint32_t is_power_of_two(uint64_t value)
{ {
@ -84,12 +83,6 @@ void blockstore_disk_t::parse_config(std::map<std::string, std::string> & config
throw std::runtime_error("data_csum_type="+config["data_csum_type"]+" is unsupported, only \"crc32c\" and \"none\" are supported"); throw std::runtime_error("data_csum_type="+config["data_csum_type"]+" is unsupported, only \"crc32c\" and \"none\" are supported");
} }
csum_block_size = parse_size(config["csum_block_size"]); csum_block_size = parse_size(config["csum_block_size"]);
discard_on_start = config.find("discard_on_start") != config.end() &&
(config["discard_on_start"] == "true" || config["discard_on_start"] == "1" || config["discard_on_start"] == "yes");
min_discard_size = parse_size(config["min_discard_size"]);
if (!min_discard_size)
min_discard_size = 1024*1024;
discard_granularity = parse_size(config["discard_granularity"]);
// Validate // Validate
if (!data_block_size) if (!data_block_size)
{ {
@ -127,9 +120,9 @@ void blockstore_disk_t::parse_config(std::map<std::string, std::string> & config
{ {
throw std::runtime_error("meta_block_size must be a multiple of "+std::to_string(DIRECT_IO_ALIGNMENT)); throw std::runtime_error("meta_block_size must be a multiple of "+std::to_string(DIRECT_IO_ALIGNMENT));
} }
else if (meta_block_size > MAX_DATA_BLOCK_SIZE) else if (meta_block_size > MAX_META_BLOCK_SIZE)
{ {
throw std::runtime_error("meta_block_size must not exceed "+std::to_string(MAX_DATA_BLOCK_SIZE)); throw std::runtime_error("meta_block_size must not exceed "+std::to_string(MAX_META_BLOCK_SIZE));
} }
if (data_offset % disk_alignment) if (data_offset % disk_alignment)
{ {
@ -179,6 +172,10 @@ void blockstore_disk_t::parse_config(std::map<std::string, std::string> & config
{ {
throw std::runtime_error("journal_offset must be a multiple of journal_block_size = "+std::to_string(journal_block_size)); throw std::runtime_error("journal_offset must be a multiple of journal_block_size = "+std::to_string(journal_block_size));
} }
clean_entry_bitmap_size = data_block_size / bitmap_granularity / 8;
clean_dyn_size = clean_entry_bitmap_size*2 + (csum_block_size
? data_block_size/csum_block_size*(data_csum_type & 0xFF) : 0);
clean_entry_size = sizeof(clean_disk_entry) + clean_dyn_size + 4 /*entry_csum*/;
} }
void blockstore_disk_t::calc_lengths(bool skip_meta_check) void blockstore_disk_t::calc_lengths(bool skip_meta_check)
@ -227,13 +224,9 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check)
} }
// required metadata size // required metadata size
block_count = data_len / data_block_size; block_count = data_len / data_block_size;
clean_entry_bitmap_size = data_block_size / bitmap_granularity / 8;
clean_dyn_size = clean_entry_bitmap_size*2 + (csum_block_size
? data_block_size/csum_block_size*(data_csum_type & 0xFF) : 0);
clean_entry_size = sizeof(clean_disk_entry) + clean_dyn_size + 4 /*entry_csum*/;
meta_len = (1 + (block_count - 1 + meta_block_size / clean_entry_size) / (meta_block_size / clean_entry_size)) * meta_block_size; meta_len = (1 + (block_count - 1 + meta_block_size / clean_entry_size) / (meta_block_size / clean_entry_size)) * meta_block_size;
bool new_doesnt_fit = (!meta_format && !skip_meta_check && meta_area_size < meta_len && !data_csum_type); if (meta_format == BLOCKSTORE_META_FORMAT_V1 ||
if (meta_format == BLOCKSTORE_META_FORMAT_V1 || new_doesnt_fit) !meta_format && !skip_meta_check && meta_area_size < meta_len && !data_csum_type)
{ {
uint64_t clean_entry_v0_size = sizeof(clean_disk_entry) + 2*clean_entry_bitmap_size; uint64_t clean_entry_v0_size = sizeof(clean_disk_entry) + 2*clean_entry_bitmap_size;
uint64_t meta_v0_len = (1 + (block_count - 1 + meta_block_size / clean_entry_v0_size) uint64_t meta_v0_len = (1 + (block_count - 1 + meta_block_size / clean_entry_v0_size)
@ -241,11 +234,7 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check)
if (meta_format == BLOCKSTORE_META_FORMAT_V1 || meta_area_size >= meta_v0_len) if (meta_format == BLOCKSTORE_META_FORMAT_V1 || meta_area_size >= meta_v0_len)
{ {
// Old metadata fits. // Old metadata fits.
if (new_doesnt_fit) printf("Warning: Using old metadata format without checksums because the new format doesn't fit into provided area\n");
{
printf("Warning: Using old metadata format without checksums because the new format"
" doesn't fit into provided area (%ju bytes required, %ju bytes available)\n", meta_len, meta_area_size);
}
clean_entry_size = clean_entry_v0_size; clean_entry_size = clean_entry_v0_size;
meta_len = meta_v0_len; meta_len = meta_v0_len;
meta_format = BLOCKSTORE_META_FORMAT_V1; meta_format = BLOCKSTORE_META_FORMAT_V1;
@ -257,7 +246,7 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check)
meta_format = BLOCKSTORE_META_FORMAT_V2; meta_format = BLOCKSTORE_META_FORMAT_V2;
if (!skip_meta_check && meta_area_size < meta_len) if (!skip_meta_check && meta_area_size < meta_len)
{ {
throw std::runtime_error("Metadata area is too small, need at least "+std::to_string(meta_len)+" bytes, have only "+std::to_string(meta_area_size)+" bytes"); throw std::runtime_error("Metadata area is too small, need at least "+std::to_string(meta_len)+" bytes");
} }
// requested journal size // requested journal size
if (!skip_meta_check && cfg_journal_size > journal_len) if (!skip_meta_check && cfg_journal_size > journal_len)
@ -426,44 +415,3 @@ void blockstore_disk_t::close_all()
close(journal_fd); close(journal_fd);
data_fd = meta_fd = journal_fd = -1; data_fd = meta_fd = journal_fd = -1;
} }
// Sadly DISCARD only works through ioctl(), but it seems to always block the device queue,
// so it's not a big deal that we can only run it synchronously.
int blockstore_disk_t::trim_data(allocator_t *alloc)
{
int r = 0;
uint64_t j = 0, i = 0;
uint64_t discarded = 0;
for (; i <= block_count; i++)
{
if (i >= block_count || alloc->get(i))
{
if (i > j && (i-j)*data_block_size >= min_discard_size)
{
uint64_t range[2] = { data_offset + j*data_block_size, (i-j)*data_block_size };
if (discard_granularity)
{
range[1] += range[0];
if (range[1] % discard_granularity)
range[1] = range[1] - (range[1] % discard_granularity);
if (range[0] % discard_granularity)
range[0] = range[0] + discard_granularity - (range[0] % discard_granularity);
if (range[0] >= range[1])
continue;
range[1] -= range[0];
}
r = ioctl(data_fd, BLKDISCARD, &range);
if (r != 0)
{
fprintf(stderr, "Failed to execute BLKDISCARD %ju+%ju on %s: %s (code %d)\n",
range[0], range[1], data_device.c_str(), strerror(-r), r);
return -errno;
}
discarded += range[1];
}
j = i+1;
}
}
fprintf(stderr, "%s (%ju bytes) of unused data discarded on %s\n", format_size(discarded).c_str(), discarded, data_device.c_str());
return 0;
}

View File

@ -12,8 +12,6 @@
// Lower byte of checksum type is its length // Lower byte of checksum type is its length
#define BLOCKSTORE_CSUM_CRC32C 0x104 #define BLOCKSTORE_CSUM_CRC32C 0x104
class allocator_t;
struct blockstore_disk_t struct blockstore_disk_t
{ {
std::string data_device, meta_device, journal_device; std::string data_device, meta_device, journal_device;
@ -36,18 +34,14 @@ struct blockstore_disk_t
// I/O modes for data, metadata and journal: direct or "" = O_DIRECT, cached = O_SYNC, directsync = O_DIRECT|O_SYNC // I/O modes for data, metadata and journal: direct or "" = O_DIRECT, cached = O_SYNC, directsync = O_DIRECT|O_SYNC
// O_SYNC without O_DIRECT = use Linux page cache for reads and writes // O_SYNC without O_DIRECT = use Linux page cache for reads and writes
std::string data_io, meta_io, journal_io; std::string data_io, meta_io, journal_io;
// Data discard granularity and minimum size (for the sake of performance)
bool discard_on_start = false;
uint64_t min_discard_size = 1024*1024;
uint64_t discard_granularity = 0;
int meta_fd = -1, data_fd = -1, journal_fd = -1; int meta_fd = -1, data_fd = -1, journal_fd = -1;
uint64_t meta_offset, meta_device_sect, meta_device_size, meta_len, meta_format = 0; uint64_t meta_offset, meta_device_sect, meta_device_size, meta_len, meta_format = 0;
uint64_t data_offset, data_device_sect, data_device_size, data_len; uint64_t data_offset, data_device_sect, data_device_size, data_len;
uint64_t journal_offset, journal_device_sect, journal_device_size, journal_len; uint64_t journal_offset, journal_device_sect, journal_device_size, journal_len;
uint32_t block_order = 0; uint32_t block_order;
uint64_t block_count = 0; uint64_t block_count;
uint32_t clean_entry_bitmap_size = 0, clean_entry_size = 0, clean_dyn_size = 0; uint32_t clean_entry_bitmap_size = 0, clean_entry_size = 0, clean_dyn_size = 0;
void parse_config(std::map<std::string, std::string> & config); void parse_config(std::map<std::string, std::string> & config);
@ -56,7 +50,6 @@ struct blockstore_disk_t
void open_journal(); void open_journal();
void calc_lengths(bool skip_meta_check = false); void calc_lengths(bool skip_meta_check = false);
void close_all(); void close_all();
int trim_data(allocator_t *alloc);
inline uint64_t dirty_dyn_size(uint64_t offset, uint64_t len) inline uint64_t dirty_dyn_size(uint64_t offset, uint64_t len)
{ {

View File

@ -427,13 +427,6 @@ stop_flusher:
printf("Flushing %jx:%jx v%ju\n", cur.oid.inode, cur.oid.stripe, cur.version); printf("Flushing %jx:%jx v%ju\n", cur.oid.inode, cur.oid.stripe, cur.version);
#endif #endif
flusher->active_flushers++; flusher->active_flushers++;
// Find it in clean_db
{
auto & clean_db = bs->clean_db_shard(cur.oid);
auto clean_it = clean_db.find(cur.oid);
old_clean_ver = (clean_it != clean_db.end() ? clean_it->second.version : 0);
old_clean_loc = (clean_it != clean_db.end() ? clean_it->second.location : UINT64_MAX);
}
// Scan dirty versions of the object to determine what we need to read // Scan dirty versions of the object to determine what we need to read
scan_dirty(); scan_dirty();
// Writes and deletes shouldn't happen at the same time // Writes and deletes shouldn't happen at the same time
@ -912,6 +905,12 @@ void journal_flusher_co::calc_block_checksums(uint32_t *new_data_csums, bool ski
void journal_flusher_co::scan_dirty() void journal_flusher_co::scan_dirty()
{ {
// Find it in clean_db
auto & clean_db = bs->clean_db_shard(cur.oid);
auto clean_it = clean_db.find(cur.oid);
old_clean_ver = (clean_it != clean_db.end() ? clean_it->second.version : 0);
old_clean_loc = (clean_it != clean_db.end() ? clean_it->second.location : UINT64_MAX);
auto old_clean_bitmap = (clean_it != clean_db.end() ? bs->get_clean_entry_bitmap(clean_it, 0) : NULL);
dirty_it = dirty_start = dirty_end; dirty_it = dirty_start = dirty_end;
v.clear(); v.clear();
copy_count = 0; copy_count = 0;
@ -1037,13 +1036,12 @@ void journal_flusher_co::scan_dirty()
read_to_fill_incomplete = 0; read_to_fill_incomplete = 0;
return; return;
} }
uint8_t *bmp_ptr = bs->get_clean_entry_bitmap(old_clean_loc, 0);
uint64_t fulfilled = 0; uint64_t fulfilled = 0;
int last = v.size()-1; int last = v.size()-1;
while (last >= 0 && (v[last].copy_flags & COPY_BUF_CSUM_FILL)) while (last >= 0 && (v[last].copy_flags & COPY_BUF_CSUM_FILL))
last--; last--;
read_to_fill_incomplete = bs->fill_partial_checksum_blocks( read_to_fill_incomplete = bs->fill_partial_checksum_blocks(
v, fulfilled, bmp_ptr, NULL, false, NULL, v[0].offset/bs->dsk.csum_block_size * bs->dsk.csum_block_size, v, fulfilled, old_clean_bitmap, NULL, false, NULL, v[0].offset/bs->dsk.csum_block_size * bs->dsk.csum_block_size,
((v[last].offset+v[last].len-1) / bs->dsk.csum_block_size + 1) * bs->dsk.csum_block_size ((v[last].offset+v[last].len-1) / bs->dsk.csum_block_size + 1) * bs->dsk.csum_block_size
); );
} }

View File

@ -12,15 +12,15 @@ blockstore_impl_t::blockstore_impl_t(blockstore_config_t & config, ring_loop_t *
ringloop->register_consumer(&ring_consumer); ringloop->register_consumer(&ring_consumer);
initialized = 0; initialized = 0;
parse_config(config, true); parse_config(config, true);
zero_object = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.data_block_size);
alloc_dyn_data = dsk.clean_dyn_size > sizeof(void*) || dsk.csum_block_size > 0;
try try
{ {
dsk.open_data(); dsk.open_data();
dsk.open_meta(); dsk.open_meta();
dsk.open_journal(); dsk.open_journal();
calc_lengths(); calc_lengths();
alloc_dyn_data = dsk.clean_dyn_size > sizeof(void*) || dsk.csum_block_size > 0; data_alloc = new allocator(dsk.block_count);
zero_object = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.data_block_size);
data_alloc = new allocator_t(dsk.block_count);
} }
catch (std::exception & e) catch (std::exception & e)
{ {
@ -34,14 +34,15 @@ blockstore_impl_t::~blockstore_impl_t()
{ {
delete data_alloc; delete data_alloc;
delete flusher; delete flusher;
if (zero_object) free(zero_object);
free(zero_object);
ringloop->unregister_consumer(&ring_consumer); ringloop->unregister_consumer(&ring_consumer);
dsk.close_all(); dsk.close_all();
if (metadata_buffer) if (metadata_buffer)
free(metadata_buffer); free(metadata_buffer);
if (clean_bitmaps) if (clean_bitmaps)
free(clean_bitmaps); free(clean_bitmaps);
if (heap_meta.blocks)
delete[] heap_meta.blocks;
} }
bool blockstore_impl_t::is_started() bool blockstore_impl_t::is_started()
@ -84,20 +85,14 @@ void blockstore_impl_t::loop()
{ {
delete journal_init_reader; delete journal_init_reader;
journal_init_reader = NULL; journal_init_reader = NULL;
initialized = 3; if (journal.flush_journal)
initialized = 3;
else
initialized = 10;
ringloop->wakeup(); ringloop->wakeup();
} }
} }
if (initialized == 3) if (initialized == 3)
{
if (!readonly && dsk.discard_on_start)
dsk.trim_data(data_alloc);
if (journal.flush_journal)
initialized = 4;
else
initialized = 10;
}
if (initialized == 4)
{ {
if (readonly) if (readonly)
{ {
@ -431,13 +426,29 @@ blockstore_clean_db_t& blockstore_impl_t::clean_db_shard(object_id oid)
{ {
uint64_t pg_num = 0; uint64_t pg_num = 0;
uint64_t pool_id = (oid.inode >> (64-POOL_ID_BITS)); uint64_t pool_id = (oid.inode >> (64-POOL_ID_BITS));
auto sh_it = clean_db_settings.find(pool_id); auto sett_it = clean_db_settings.find(pool_id);
if (sh_it != clean_db_settings.end()) if (sett_it != clean_db_settings.end())
{ {
// like map_to_pg() // like map_to_pg()
pg_num = (oid.stripe / sh_it->second.pg_stripe_size) % sh_it->second.pg_count + 1; pg_num = (oid.stripe / sett_it->second.pg_stripe_size) % sett_it->second.pg_count + 1;
} }
return clean_db_shards[(pool_id << (64-POOL_ID_BITS)) | pg_num]; auto shard_id = (pool_id << (64-POOL_ID_BITS)) | pg_num;
if (dsk.meta_format == BLOCKSTORE_META_FORMAT_HEAP)
{
auto sh_it = clean_db_shards.find(shard_id);
if (sh_it == clean_db_shards.end())
{
// clean_db_t stores larger entries with heap_meta, but we disguise it as smaller clean_entry :)
// patched cpp-btree with extra_data
clean_db_shards[shard_id] = blockstore_clean_db_t(
sizeof(clean_entry_heap_t) - sizeof(clean_entry)
+ (inmemory_meta ? dsk.clean_dyn_size : 2*dsk.clean_entry_bitmap_size)
);
return clean_db_shards[shard_id];
}
return sh_it->second;
}
return clean_db_shards[shard_id];
} }
void blockstore_impl_t::reshard_clean_db(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size) void blockstore_impl_t::reshard_clean_db(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size)

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