Compare commits

...
40 Commits
Author SHA1 Message Date
Vitaliy Filippov facaa2cc6a Release 3.0.3
- Fix csum_block_size > 0 unusable with atomic writes in the new store
  (almost all atomic write requests generated invalid checksums with csum_block_size > 0)
- Fix monitor sometimes randomly failing to optimize PGs with the "problem is
  infeasible or unbounded" message due to not waiting to read full stdout of lp_solve
- Remove reshard_abort optimisation to fix chunked resharding introduced in 3.0.2 possibly
  corrupting in-memory OSD state when handling multiple rapid PG count change requests
- Fix removed inodes not disappearing from OSD statistics in the new store, leading to
  bloating of the statistics with old inodes
- Increase test coverage for the new store and fix several minor bugs:
  - Enabling/disabling of used_for_app was recalculating inode space statistics incorrectly
  - Fix object metadata validation on OSD startup rejecting some correct sequences of entries,
    possibly leading to OSD being unable to start
  - Fix PG activation with EC failing in rare cases with EBUSY when requesting to commit an
    already committed write
  - Fix a theoretically possible metadata writeback issue on ENOSPC during commit
- Fix monitor failing to optimize PGs in presence of a host with name convertible to
  js Number (like 04e278988710) :D
- Fix vitastor-cli dd sometimes (rarely) truncating the image when writing to stdout
- Fix a theoretically possible client connection object leak when io_uring is full
- Fix a leak of RDMA-CM connection objects
- Fix crashes with data_block_size < 32KB (useless setup, but anyway) (#113)
2026-02-08 01:39:57 +03:00
Vitaliy Filippov d2ac8e3827 Fix block writeback on enospc during commit 2026-02-07 16:27:26 +03:00
Vitaliy Filippov d6dacc67db Do not return EBUSY when already stable in the new store 2026-02-07 16:10:39 +03:00
Vitaliy Filippov cbe51595cb Remove reshard_abort 2026-02-07 16:05:40 +03:00
Vitaliy Filippov 6bd0830ab8 Add a test for chunked resharding 2026-02-07 16:02:17 +03:00
Vitaliy Filippov 796e82f34d Check get_compacted_count and get_compact_queue_size 2026-02-07 15:44:54 +03:00
Vitaliy Filippov db39283970 Add a test for complete_lsn_write 2026-02-07 15:36:46 +03:00
Vitaliy Filippov 9f8c686321 Add a test for redirect_intent 2026-02-07 15:09:58 +03:00
Vitaliy Filippov 2618e559d1 Add rollback tests, simplify rollback logic 2026-02-07 15:09:58 +03:00
Vitaliy Filippov 037d2bc162 Add a test for recalc_inode_stats in the new store and fix a bug in it 2026-02-07 14:00:10 +03:00
Vitaliy Filippov f0b64adb32 Fix removed inodes not disappearing from statistics in the new store 2026-02-07 02:48:49 +03:00
Vitaliy Filippov f06d64d879 Fix validate_object commit validation bug 2026-02-06 18:52:37 +03:00
Vitaliy Filippov d164499a1c Add more iterate_compaction test cases 2026-02-06 18:52:19 +03:00
Vitaliy Filippov 725e9aa8ae Remove unused read_locked_entry 2026-02-06 17:38:59 +03:00
Vitaliy Filippov 0715feffa1 Wait for finished read, not for process exit in lp_optimizer 2026-02-04 02:33:08 +03:00
Vitaliy Filippov e9f37e8dc3 Fix NaN PG optimisation error when a hostname has a name convertible to js Number... some shit like 04e278988710 2026-02-04 15:08:03 +03:00
Vitaliy Filippov 4fbe4b5654 Fix BIG_INTENT rechecks with enabled checksums 2026-02-04 02:33:50 +03:00
Vitaliy Filippov 9fb645693b Fix checksums with BIG_INTENT writes in the new store 2026-02-04 02:33:50 +03:00
Vitaliy Filippov 9e47828383 Add a test for big_intent with checksums 2026-02-04 02:33:50 +03:00
Vitaliy Filippov ac2ce48cb2 Fix missing wait for short writes in vitastor-cli dd 2026-02-03 01:28:13 +03:00
Vitaliy Filippov 9cc2beed95 Fix new compile warnings from merged PR 2026-01-30 00:47:58 +03:00
MoonBoi9001andVitaliy Filippov fb1c870f5c Fix: integer division bug with block_size < 32KB (#113)
Test scenarios:
- 128KB aligned I/O (may work despite bug)
- 4KB random I/O (triggers assertion failure)
- 4KB mixed read/write (triggers crash)
- 4KB sequential write (triggers crash)

I accept Vitastor CLA agreement: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md
2026-01-29 02:04:30 +03:00
ston3luandVitaliy Filippov 2d616d8058 Fix VLA init in test_heap
I accept Vitastor CLA agreement: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md
2026-01-29 02:01:21 +03:00
Vitaliy Filippov 3f7f6f442b Fix some compilation warnings 2026-01-29 02:00:25 +03:00
ston3luandVitaliy Filippov 7e7b95eeb4 Fix void* arithmetic in memset/memcpy
I accept Vitastor CLA agreement: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md
2026-01-29 01:59:35 +03:00
ston3luandVitaliy Filippov dd588a0783 Fix ref leak on read path when SQE allocation fails
I accept Vitastor CLA agreement: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md
2026-01-29 01:52:07 +03:00
ston3luandVitaliy Filippov 028a6cab68 Clean RDMA entry
I accept Vitastor CLA agreement: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md
2026-01-29 01:51:31 +03:00
Vitaliy Filippov d75334ddf0 Release 3.0.2
- Antietcd is now officially safe to use: the release includes a fixed version of antietcd
  which passes Jepsen transaction serializability tests.
- Fix a huge checksum bug in the old store: incorrect checksums for small initial writes.
  The bug affected writes of exactly csum_block_size (4k by default) into new (unallocated)
  objects and generated invalid checksums in the store for the written 4k block. Moreover,
  generation of these invalid checksums was very slow because it was calculating CRC32
  for 4 GB of zeroes. If the block wasn't then overwritten as a part of a larger write
  request it became unreadable even though the stored data was correct. The bug affected
  all versions since 1.0.0, or since 2.3.0 because vitastor-disk didn't allow to enable
  checksums prior to 2.3.0 because of another bug. O:-)
- Prevent OSD disconnections due to long blocking of event-loop caused by PG resharding
  (moving objects between old and new PGs in memory) when changing pool PG count or
  just on restart of an OSD with a large database (for example, with a filled 8 TB SSD).
  The issue should now be fixed because OSD now performs resharding in chunks with pauses
  between chunks.
- Prevent pools stuck in paused state on an aborted PG count change.
- Fix a possible OSD crash with "division by zero" when trying to handle an operation
  before pool PG count is applied to the in-memory store.
2026-01-25 16:08:02 +03:00
Vitaliy Filippov bf0875128e Prevent secondary ops execution on resharded pools 2026-01-25 16:07:51 +03:00
Vitaliy Filippov 9a6a7b7f75 Remove separate storage of PG counts in pg_counts 2026-01-25 12:26:49 +03:00
Vitaliy Filippov c4c17ee6fb Support chunked resharding in OSD 2026-01-25 10:42:48 +03:00
Vitaliy Filippov 2b801a7ffa Support chunked resharding in blockstores 2026-01-25 01:56:29 +03:00
Vitaliy Filippov 233d2b2a09 Resume pool on monitor restart if nothing changed 2026-01-25 01:56:29 +03:00
Vitaliy Filippov 8380d4c6a6 Fix possible FPE in osd_primary 2026-01-23 02:11:16 +03:00
Vitaliy Filippov 73f9c7293f Initialize blockstore after loading pool configuration to pre-shard the DB correctly on start 2026-01-23 01:45:13 +03:00
Vitaliy Filippov 1c66c3e5ba Update antietcd to 1.2.2 2026-01-23 01:45:00 +03:00
Vitaliy Filippov eddfa93c18 Refactor vitastor-cli & fio & qemu-img options in tests 2026-01-16 20:08:13 +03:00
Vitaliy Filippov ddd755a0e6 Fix incorrect checksums for small initial writes in the old store
Details:
- Write size should be exactly csum_block_size (4k by default)
- Write should be made into a new object (unallocated space)
- In this case, the checksum of the block was calculated as if the block was
  padded with extra (2^32 - size) zero bytes due to a simple integer overflow
- As a cherry on the cake, such calculation was 'slightly' slow because it
  was processing almost 4 GB of zeroes for a small write
2026-01-16 01:07:39 +03:00
Vitaliy Filippov 819f5b7ec9 Add a test for an idiotic checksum bug 2026-01-16 01:07:39 +03:00
Vitaliy Filippov 34d0a6d9b1 Allow -1 args 2026-01-16 01:07:34 +03:00
99 changed files with 1874 additions and 510 deletions
+18
View File
@@ -1818,6 +1818,24 @@ jobs:
echo ""
done
test_old_partwr_csum:
runs-on: ubuntu-latest
needs: build
container: ${{env.TEST_IMAGE}}:${{github.sha}}
steps:
- name: Run test
id: test
timeout-minutes: 3
run: OLD=1 /root/vitastor/tests/test_partwr_csum.sh
- name: Print logs
if: always() && steps.test.outcome == 'failure'
run: |
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
echo "-------- $i --------"
cat $i
echo ""
done
test_heal_old_csum_32k_dmj:
runs-on: ubuntu-latest
needs: build
+1 -1
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12)
project(vitastor)
set(VITASTOR_VERSION "3.0.1")
set(VITASTOR_VERSION "3.0.3")
include(CTest)
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.1
VITASTOR_VERSION ?= v3.0.3
all: build push
+1 -1
View File
@@ -49,7 +49,7 @@ spec:
capabilities:
add: ["SYS_ADMIN"]
allowPrivilegeEscalation: true
image: vitalif/vitastor-csi:v3.0.1
image: vitalif/vitastor-csi:v3.0.3
args:
- "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -121,7 +121,7 @@ spec:
privileged: true
capabilities:
add: ["SYS_ADMIN"]
image: vitalif/vitastor-csi:v3.0.1
image: vitalif/vitastor-csi:v3.0.3
args:
- "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -5,7 +5,7 @@ package vitastor
const (
vitastorCSIDriverName = "csi.vitastor.io"
vitastorCSIDriverVersion = "3.0.1"
vitastorCSIDriverVersion = "3.0.3"
)
// Config struct fills the parameters of request or user input
+1 -1
View File
@@ -1,4 +1,4 @@
vitastor (3.0.1-1) unstable; urgency=medium
vitastor (3.0.3-1) unstable; urgency=medium
* Bugfixes
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.1
VITASTOR_VERSION ?= v3.0.3
all: build push
+1 -1
View File
@@ -4,7 +4,7 @@
#
# Desired Vitastor version
VITASTOR_VERSION=v3.0.1
VITASTOR_VERSION=v3.0.3
# Additional arguments for all containers
# For example, you may want to specify a custom logging driver here
+20
View File
@@ -67,6 +67,8 @@ with an OSD restart or, for some of them, even without restarting by updating co
- [pg_lock_retry_interval_ms](#pg_lock_retry_interval_ms)
- [atomic_write_size](#atomic_write_size)
- [use_atomic_flag](#use_atomic_flag)
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
## bind_address
@@ -713,3 +715,21 @@ even though the NVMe specification allows them.
For NVMe disks with `scheduler=none` writes aren't fragmented anyway so it's not a big deal.
However, you can rebuild your kernel with [this patch](../../patches/linux-fix-atomic-write-checks.diff)
and turn this option on. It will make your atomic writes a bit safer.
## pg_reshard_chunk_size
- Type: integer
- Default: 100000
Pool PG count change is a CPU-intensive operation because OSDs store the full object database
in memory and have to move all entries between old and new PGs. Thus it's performed in chunks,
with pauses between chunks to prevent blocking OSD's event loop and other clients' operations.
This option sets the maximum number of object is a chunk. Moving 100k objects usually takes
50-100ms. Chunk size equal to 0 means unlimited.
## pg_reshard_chunk_pause_ms
- Type: milliseconds
- Default: 100
This option sets the interval between handling two PG count change chunks.
+21
View File
@@ -68,6 +68,8 @@
- [pg_lock_retry_interval_ms](#pg_lock_retry_interval_ms)
- [atomic_write_size](#atomic_write_size)
- [use_atomic_flag](#use_atomic_flag)
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
## bind_address
@@ -751,3 +753,22 @@ pg_minsize OSD во время переключений, что может по
Для NVMe-дисков с `scheduler=none` запросы записи и так не фрагментируются, так что это не так
уж и важно, однако вы можете пересобрать своё ядро с [этим патчем](../../patches/linux-fix-atomic-write-checks.diff)
и включить данную опцию. Это сделает вашу атомарную запись капельку безопаснее.
## pg_reshard_chunk_size
- Тип: целое число
- Значение по умолчанию: 100000
Изменение числа PG в пуле заметно загружает процессор, так как OSD хранят полную базу данных
объектов в памяти и им приходится перемещать все записи объектов между старыми и новыми PG.
Поэтому изменение применяется порциями, с паузами между порциями, чтобы не блокировать обработку
событий OSD и операции остальных клиентов. Данная опция задаёт максимальное число объектов
в порции. Перемещение 100 тысяч объектов (значение по умолчанию) обычно занимает порядка
50-100 миллисекунд. Значение опции 0 отключает лимит размера порции.
## pg_reshard_chunk_pause_ms
- Тип: миллисекунды
- Значение по умолчанию: 100
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
+23
View File
@@ -883,3 +883,26 @@
Для NVMe-дисков с `scheduler=none` запросы записи и так не фрагментируются, так что это не так
уж и важно, однако вы можете пересобрать своё ядро с [этим патчем](../../patches/linux-fix-atomic-write-checks.diff)
и включить данную опцию. Это сделает вашу атомарную запись капельку безопаснее.
- name: pg_reshard_chunk_size
type: int
default: 100000
info: |
Pool PG count change is a CPU-intensive operation because OSDs store the full object database
in memory and have to move all entries between old and new PGs. Thus it's performed in chunks,
with pauses between chunks to prevent blocking OSD's event loop and other clients' operations.
This option sets the maximum number of object is a chunk. Moving 100k objects usually takes
50-100ms. Chunk size equal to 0 means unlimited.
info_ru: |
Изменение числа PG в пуле заметно загружает процессор, так как OSD хранят полную базу данных
объектов в памяти и им приходится перемещать все записи объектов между старыми и новыми PG.
Поэтому изменение применяется порциями, с паузами между порциями, чтобы не блокировать обработку
событий OSD и операции остальных клиентов. Данная опция задаёт максимальное число объектов
в порции. Перемещение 100 тысяч объектов (значение по умолчанию) обычно занимает порядка
50-100 миллисекунд. Значение опции 0 отключает лимит размера порции.
- name: pg_reshard_chunk_pause_ms
type: ms
default: 100
info: |
This option sets the interval between handling two PG count change chunks.
info_ru: |
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
+2 -2
View File
@@ -26,9 +26,9 @@ at Vitastor Kubernetes operator: https://github.com/Antilles7227/vitastor-operat
The instruction is very simple.
1. Download a Docker image of the desired version: \
`docker pull vitalif/vitastor:v3.0.1`
`docker pull vitalif/vitastor:v3.0.3`
2. Install scripts to the host system: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.1 install.sh`
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.3 install.sh`
3. Reload udev rules: \
`udevadm control --reload-rules`
+2 -2
View File
@@ -25,9 +25,9 @@ Vitastor можно установить в Docker/Podman. При этом etcd,
Инструкция по установке максимально простая.
1. Скачайте Docker-образ желаемой версии: \
`docker pull vitalif/vitastor:v3.0.1`
`docker pull vitalif/vitastor:v3.0.3`
2. Установите скрипты в хост-систему командой: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.1 install.sh`
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.3 install.sh`
3. Перезагрузите правила udev: \
`udevadm control --reload-rules`
+8 -5
View File
@@ -10,16 +10,19 @@ const NO_OSD = 'Z';
async function lp_solve(text)
{
const cp = child_process.spawn('lp_solve');
let stdout = '', stderr = '', finish_cb;
let stdout = '', stderr = '', finish_cb, finished = 0;
cp.stdout.on('data', buf => stdout += buf.toString());
cp.stderr.on('data', buf => stderr += buf.toString());
cp.on('exit', () => finish_cb && finish_cb());
cp.stdout.on('end', () => finish_cb());
cp.stderr.on('end', () => finish_cb());
cp.stdin.write(text);
cp.stdin.end();
if (cp.exitCode == null)
await new Promise(ok => (finish_cb = () =>
{
await new Promise(ok => finish_cb = ok);
}
finished++;
if (finished == 2)
ok();
}));
if (!stdout.trim())
{
return null;
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "vitastor-mon",
"version": "3.0.1",
"version": "3.0.3",
"description": "Vitastor SDS monitor service",
"main": "mon-main.js",
"scripts": {
@@ -9,7 +9,7 @@
"author": "Vitaliy Filippov",
"license": "UNLICENSED",
"dependencies": {
"antietcd": "^1.1.3",
"antietcd": "^1.2.2",
"sprintf-js": "^1.1.2",
"ws": "^7.2.5"
},
+15 -1
View File
@@ -52,6 +52,7 @@ function recheck_primary(state, global_config, up_osds, osd_tree)
continue;
}
const aff_osds = get_affinity_osds(pool_cfg, up_osds, osd_tree);
let paused = false;
for (let pg_num = 1; pg_num <= pool_cfg.pg_count; pg_num++)
{
if (!state.pg.config.items[pool_id])
@@ -74,6 +75,19 @@ function recheck_primary(state, global_config, up_osds, osd_tree)
);
new_pg_config.items[pool_id][pg_num].primary = new_primary;
}
paused = paused || !!pg_cfg.pause;
}
}
if (paused)
{
if (!new_pg_config)
{
new_pg_config = JSON.parse(JSON.stringify(state.pg.config));
}
console.log(`Resuming paused pool ${pool_id}`);
for (const pg in new_pg_config.items[pool_id])
{
delete new_pg_config.items[pool_id][pg].pause;
}
}
}
@@ -181,7 +195,7 @@ async function generate_pool_pgs(state, global_config, pool_id, osd_tree, levels
const folded_tree = make_hier_tree(global_config, folded.nodes.reduce((a, c) => { a[c.id] = c; return a; }, {}));
const old_pg_count = prev_pgs.length;
const optimize_cfg = {
osd_weights: folded.nodes.reduce((a, c) => { if (Number(c.id)) { a[c.id] = c.size; } return a; }, {}),
osd_weights: folded.nodes.reduce((a, c) => { if (/^\d+$/.exec(c.id) && c.size != null) { a[c.id] = c.size||0; } return a; }, {}),
combinator: use_rules
// new algorithm:
? new RuleCombinator(folded_tree, rules, pool_cfg.max_osd_combinations)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vitastor",
"version": "3.0.1",
"version": "3.0.3",
"description": "Low-level native bindings to Vitastor client library",
"main": "index.js",
"keywords": [
+1 -1
View File
@@ -50,7 +50,7 @@ from cinder.volume import configuration
from cinder.volume import driver
from cinder.volume import volume_utils
VITASTOR_VERSION = '3.0.1'
VITASTOR_VERSION = '3.0.3'
LOG = logging.getLogger(__name__)
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor
Version: 3.0.1
Version: 3.0.3
Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1
URL: https://vitastor.io/
Source0: vitastor-3.0.1.el7.tar.gz
Source0: vitastor-3.0.3.el7.tar.gz
BuildRequires: gperftools-devel
BuildRequires: devtoolset-9-gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor
Version: 3.0.1
Version: 3.0.3
Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1
URL: https://vitastor.io/
Source0: vitastor-3.0.1.el8.tar.gz
Source0: vitastor-3.0.3.el8.tar.gz
BuildRequires: gperftools-devel
BuildRequires: gcc-toolset-9-gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor
Version: 3.0.1
Version: 3.0.3
Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1
URL: https://vitastor.io/
Source0: vitastor-3.0.1.el9.tar.gz
Source0: vitastor-3.0.3.el9.tar.gz
BuildRequires: gperftools-devel
BuildRequires: gcc-c++
+1 -1
View File
@@ -21,7 +21,7 @@ if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/local/?$")
endif()
set(ENABLE_COVERAGE false CACHE BOOL "Enable code coverage")
add_definitions(-DVITASTOR_VERSION="3.0.1")
add_definitions(-DVITASTOR_VERSION="3.0.3")
add_definitions(-D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -fno-omit-frame-pointer -fvisibility=hidden -I ${CMAKE_SOURCE_DIR}/src)
add_link_options(-fno-omit-frame-pointer)
if (${WITH_ASAN})
+5
View File
@@ -183,6 +183,11 @@ public:
// Update configuration
virtual void parse_config(blockstore_config_t & config) = 0;
// Reshard database for a pool in chunks
// MUST be called only when nobody makes any modifications to the DB for this pool
virtual void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit) = 0;
virtual bool reshard_continue(void *reshard_state, uint64_t chunk_limit) = 0;
// Event loop
virtual void loop() = 0;
+7 -1
View File
@@ -171,6 +171,12 @@ void blockstore_disk_t::parse_config(std::map<std::string, std::string> & config
{
throw std::runtime_error("Data block size must be a multiple of sparse write tracking granularity");
}
if (data_block_size / bitmap_granularity < 8)
{
fprintf(stderr, "Warning: block_size (%u) / bitmap_granularity (%u) = %u bits. "
"Consider using larger block_size or bitmap_granularity for better performance.\n",
data_block_size, bitmap_granularity, data_block_size / bitmap_granularity);
}
if (!data_csum_type)
{
csum_block_size = 0;
@@ -259,7 +265,7 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check)
}
// required metadata size
block_count = data_len / data_block_size;
clean_entry_bitmap_size = data_block_size / bitmap_granularity / 8;
clean_entry_bitmap_size = (data_block_size / bitmap_granularity + 7) / 8;
clean_dyn_size = clean_entry_bitmap_size*2 + (csum_block_size
? data_block_size/csum_block_size*(data_csum_type & 0xFF) : 0);
recalc:
-1
View File
@@ -58,7 +58,6 @@ class journal_flusher_co
int i, res;
bool read_to_fill_incomplete;
int copy_count;
bool do_repeat = false;
friend class journal_flusher_t;
+183 -89
View File
@@ -29,6 +29,15 @@
#define IMAP_MALLOC_LOW_BITS ((size_t)0x0F)
#define IMAP_MAX_LOW 16
void inode_map_put(void* & inode_idx, heap_list_item_t* li);
void inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_list_item_t* & li, uint64_t stripe);
void inode_map_free(void* inode_idx);
bool inode_map_is_big(void* & inode_idx);
void inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)> cb);
void inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* new_li);
void inode_map_erase(robin_hood::unordered_flat_map<inode_t, void*, i64hash_t> & pg_idx, void* & inode_idx,
const heap_inode_map_t::iterator & li_it, heap_list_item_t* li);
static inline heap_list_item_t *list_item(heap_entry_t *wr)
{
return (heap_list_item_t*)((uint8_t*)wr - offsetof(struct heap_list_item_t, entry));
@@ -449,19 +458,22 @@ bool blockstore_heap_t::validate_object(heap_entry_t *obj)
next_wr = wr;
if (wr->type() == BS_HEAP_ROLLBACK)
{
if (commit_wr && wr->version > commit_wr->version)
{
// rollback may not come before commit with a smaller version
fprintf(stderr, "Error: rollback entry %jx:%jx v%ju l%ju comes before a commit entry v%ju l%ju\n",
wr->inode, wr->stripe, wr->version, wr->lsn, commit_wr->version, commit_wr->lsn);
return false;
}
rollback_wr = wr;
continue;
}
if (wr->type() == BS_HEAP_COMMIT)
{
commit_wr = wr;
if (commit_wr && wr->version > commit_wr->version)
{
// commit may not come before commit with a smaller version
fprintf(stderr, "Error: commit entry %jx:%jx v%ju l%ju comes before a commit entry v%ju l%ju\n",
wr->inode, wr->stripe, wr->version, wr->lsn, commit_wr->version, commit_wr->lsn);
return false;
}
if (!commit_wr)
{
commit_wr = wr;
}
continue;
}
if (wr->entry_type & BS_HEAP_STABLE)
@@ -658,7 +670,8 @@ void blockstore_heap_t::recheck_buffer(heap_entry_t *cwr, uint8_t *buf)
else if (!calc_checksums(cwr, buf, false))
{
// write entry is invalid, erase it and mark newer entries with garbage bit
auto & inode_idx = block_index[get_pg_id(cwr->inode, cwr->stripe)][cwr->inode];
auto & pg_idx = block_index[get_pg_id(cwr->inode, cwr->stripe)];
auto & inode_idx = pg_idx[cwr->inode];
heap_inode_map_t::iterator li_it;
heap_list_item_t *li = NULL;
inode_map_get(inode_idx, li_it, li, cwr->stripe);
@@ -684,7 +697,7 @@ void blockstore_heap_t::recheck_buffer(heap_entry_t *cwr, uint8_t *buf)
{
fprintf(stderr, "Notice: the whole object %jx:%jx only has unfinished writes, rolling back\n",
cwr->inode, cwr->stripe);
inode_map_erase(inode_idx, li_it, li);
inode_map_erase(pg_idx, inode_idx, li_it, li);
}
free_entry(li);
}
@@ -827,7 +840,6 @@ bool blockstore_heap_t::calc_checksums(heap_entry_t *wr, uint8_t *data, bool set
{
return true;
}
uint32_t len = 0;
if (wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE)
len = wr->small().len;
else if (wr->type() == BS_HEAP_BIG_INTENT)
@@ -844,13 +856,14 @@ bool blockstore_heap_t::calc_checksums(heap_entry_t *wr, uint8_t *data, bool set
}
if (wr->type() == BS_HEAP_BIG_WRITE)
{
assert(offset != UINT32_MAX && len != UINT32_MAX);
return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)),
data, wr->get_int_bitmap(this), offset, offset+len, set, NULL);
}
if (wr->type() == BS_HEAP_BIG_INTENT)
{
auto & bi = wr->big_intent();
return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)),
return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + bi.offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)),
data, wr->get_int_bitmap(this), bi.offset, bi.offset+bi.len, set, NULL);
}
assert(wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE);
@@ -943,44 +956,128 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit
return res;
}
void blockstore_heap_t::reshard(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size)
struct heap_reshard_state_t
{
int state = 0;
uint64_t pool_id = 0;
uint32_t old_pg_count = 0;
uint32_t pg_count = 0;
uint32_t pg_stripe_size = 0;
uint64_t chunk_size = 0;
heap_block_index_t new_shards;
heap_block_index_t old_shards;
heap_block_index_t::iterator sh_it;
robin_hood::unordered_flat_map<inode_t, void*, i64hash_t>::iterator inode_it;
heap_inode_map_t *stripe_map = NULL;
heap_inode_map_t::iterator stripe_it;
void add(heap_list_item_t *li);
bool run(uint64_t chunk_limit);
};
void heap_reshard_state_t::add(heap_list_item_t *li)
{
// like map_to_pg()
uint64_t pg_num = (li->entry.stripe / pg_stripe_size) % pg_count + 1;
uint64_t shard_id = (pool_id << (64-POOL_ID_BITS)) | pg_num;
inode_map_put(new_shards[shard_id][li->entry.inode], li);
chunk_size++;
}
bool heap_reshard_state_t::run(uint64_t chunk_limit)
{
chunk_size = 0;
if (state == 1)
goto resume_1;
else if (state == 2)
goto resume_2;
sh_it = old_shards.begin();
for (; sh_it != old_shards.end(); sh_it++)
{
inode_it = sh_it->second.begin();
for (; inode_it != sh_it->second.end(); inode_it++)
{
if (!inode_map_is_big(inode_it->second))
{
if (chunk_limit > 0 && chunk_size >= chunk_limit)
{
state = 1;
return false;
}
resume_1:
inode_map_iterate(inode_it->second, [&](heap_list_item_t *li) { add(li); });
}
else
{
stripe_map = (heap_inode_map_t*)inode_it->second;
stripe_it = stripe_map->begin();
for (; stripe_it != stripe_map->end(); stripe_it++)
{
if (chunk_limit > 0 && chunk_size >= chunk_limit)
{
state = 2;
return false;
}
resume_2:
add(*stripe_it);
}
}
inode_map_free(inode_it->second);
}
}
return true;
}
void* blockstore_heap_t::reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit)
{
auto & pool_settings = pool_shard_settings[pool];
if (pool_settings.pg_count == pg_count && pool_settings.pg_stripe_size == pg_stripe_size)
{
return;
return NULL;
}
uint32_t old_pg_count = !pool_settings.pg_count ? 1 : pool_settings.pg_count;
uint64_t pool_id = (uint64_t)pool;
heap_block_index_t new_shards;
for (uint32_t pg_num = 0; pg_num <= old_pg_count; pg_num++)
heap_reshard_state_t *st = new heap_reshard_state_t;
st->pool_id = (uint64_t)pool;
st->pg_count = pg_count;
st->pg_stripe_size = pg_stripe_size;
st->old_pg_count = !pool_settings.pg_count ? 1 : pool_settings.pg_count;
for (uint32_t pg_num = 0; pg_num <= st->old_pg_count; pg_num++)
{
auto sh_it = block_index.find((pool_id << (64-POOL_ID_BITS)) | pg_num);
if (sh_it == block_index.end())
auto sh_it = block_index.find((st->pool_id << (64-POOL_ID_BITS)) | pg_num);
if (sh_it != block_index.end())
{
continue;
st->old_shards[pg_num] = std::move(sh_it->second);
block_index.erase(sh_it);
}
for (auto & inode_pair: sh_it->second)
{
inode_map_iterate(inode_pair.second, [&](heap_list_item_t *li)
{
// like map_to_pg()
uint64_t pg_num = (li->entry.stripe / pg_stripe_size) % pg_count + 1;
uint64_t shard_id = (pool_id << (64-POOL_ID_BITS)) | pg_num;
inode_map_put(new_shards[shard_id][li->entry.inode], li);
});
inode_map_free(inode_pair.second);
}
block_index.erase(sh_it);
}
for (auto sh_it = new_shards.begin(); sh_it != new_shards.end(); sh_it++)
bool finished = reshard_continue(st, chunk_limit);
return finished ? NULL : st;
}
bool blockstore_heap_t::reshard_continue(void *reshard_state, uint64_t chunk_limit)
{
heap_reshard_state_t *st = (heap_reshard_state_t*)reshard_state;
if (!st->run(chunk_limit))
{
return false;
}
for (auto sh_it = st->new_shards.begin(); sh_it != st->new_shards.end(); sh_it++)
{
block_index[sh_it->first] = std::move(sh_it->second);
}
pool_settings = (pool_shard_settings_t){
.pg_count = pg_count,
.pg_stripe_size = pg_stripe_size,
pool_shard_settings[st->pool_id] = (pool_shard_settings_t){
.pg_count = st->pg_count,
.pg_stripe_size = st->pg_stripe_size,
};
delete st;
return true;
}
bool blockstore_heap_t::reshard_check(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size)
{
auto set_it = pool_shard_settings.find(pool);
return (set_it != pool_shard_settings.end() &&
set_it->second.pg_count == pg_count &&
set_it->second.pg_stripe_size == pg_stripe_size);
}
heap_entry_t *blockstore_heap_t::lock_and_read_entry(object_id oid)
@@ -995,27 +1092,6 @@ heap_entry_t *blockstore_heap_t::lock_and_read_entry(object_id oid)
return obj;
}
heap_entry_t *blockstore_heap_t::read_locked_entry(object_id oid, uint64_t lsn)
{
auto obj = read_entry(oid);
assert(obj);
for (auto wr = obj; wr; wr = prev(wr))
{
if (wr->is_overwrite())
{
if (lsn == wr->lsn)
{
return obj;
}
else
{
obj = prev(wr);
}
}
}
return NULL;
}
bool blockstore_heap_t::unlock_entry(object_id oid)
{
auto mvcc_it = object_mvcc.find(oid);
@@ -1314,7 +1390,7 @@ int blockstore_heap_t::add_redirect_intent(object_id oid, heap_entry_t **obj_ptr
bitmap_set(wr->get_int_bitmap(this), offset, len, dsk->bitmap_granularity);
if (dsk->data_csum_type)
memset(wr->get_checksums(this), 0, get_csum_size(wr));
calc_checksums(wr, (uint8_t*)data, true, offset, len);
calc_checksums(wr, (uint8_t*)data, true);
*obj_ptr = wr;
});
}
@@ -1353,11 +1429,11 @@ int blockstore_heap_t::add_big_intent(object_id oid, heap_entry_t **obj_ptr, uin
if (dsk->data_csum_type)
{
if (checksums)
memcpy(wr->get_checksums(this), checksums, dsk->clean_entry_bitmap_size);
memcpy(wr->get_checksums(this), checksums, get_csum_size(wr));
else
{
memcpy(wr->get_checksums(this), obj->get_checksums(this), dsk->clean_entry_bitmap_size);
calc_checksums(wr, (uint8_t*)data, true, offset, len);
memcpy(wr->get_checksums(this), obj->get_checksums(this), get_csum_size(wr));
calc_checksums(wr, (uint8_t*)data, true);
}
}
else
@@ -1478,7 +1554,7 @@ int blockstore_heap_t::add_commit(heap_entry_t *obj, uint64_t version, uint32_t
}
if (!uncommitted)
{
return EBUSY;
return 0;
}
return add_simple(obj, version, modified_block, BS_HEAP_COMMIT);
}
@@ -1488,23 +1564,32 @@ int blockstore_heap_t::add_rollback(heap_entry_t *obj, uint64_t version, uint32_
heap_entry_t *wr = obj;
bool found_uncommitted = false;
uint64_t commit_version = 0;
while (wr && !wr->is_overwrite())
uint64_t rollback_version = UINT64_MAX;
while (wr)
{
if (wr->type() == BS_HEAP_ROLLBACK)
{
auto rollback_version = wr->version;
wr = prev(wr);
while (wr->version > rollback_version)
if (wr->version <= version)
{
assert(!(wr->entry_type & BS_HEAP_STABLE));
wr = prev(wr);
// All previous writes are already rolled back, stop
break;
}
rollback_version = wr->version;
wr = prev(wr);
continue;
}
if (wr->type() == BS_HEAP_COMMIT)
{
if (commit_version < wr->version)
{
commit_version = wr->version;
}
wr = prev(wr);
continue;
}
if (wr->version > rollback_version)
{
// Already rolled back, skip
wr = prev(wr);
continue;
}
@@ -1515,14 +1600,10 @@ int blockstore_heap_t::add_rollback(heap_entry_t *obj, uint64_t version, uint32_
{
return EBUSY;
}
else if (wr->version == version)
else
{
break;
}
else if (wr->version < version)
{
return ENOENT;
}
}
else if (wr->version > version)
{
@@ -1703,9 +1784,9 @@ void blockstore_heap_t::iterate_with_stable(heap_entry_t *obj, uint64_t max_lsn,
}
else
{
// 1) 1 2 3 ROLLBACK(2) COMMIT(3) -> impossible
// 1) 1 2 3 ROLLBACK(2) COMMIT(3) -> 3 is unstable
// 2) 1 2 3 4 ROLLBACK(3) COMMIT(2) -> OK
// 3) 1 2 3 ROLLBACK(2) 3 COMMIT(3) -> first 3 shouldn't be treated as stable
// 3) 1 2 3 ROLLBACK(2) 3 COMMIT(3) -> first 3 is unstable
// 4) 1 2 3 COMMIT(3) ROLLBACK(2) -> impossible
// I.e. a rollback always has version >= previous commit
// 5) 1 2 3 4 5 ROLLBACK(4) 5 ROLLBACK(3)
@@ -1941,7 +2022,13 @@ void blockstore_heap_t::free_data(inode_t inode, uint64_t location)
inode = (INODE_POOL(inode) << POOL_ID_BITS);
assert(data_alloc->get(location / dsk->data_block_size));
data_alloc->set(location / dsk->data_block_size, false);
inode_space_stats[inode] -= dsk->data_block_size;
auto sp_it = inode_space_stats.find(inode);
if (sp_it != inode_space_stats.end())
{
sp_it->second -= dsk->data_block_size;
if (sp_it->second == 0)
inode_space_stats.erase(sp_it);
}
data_used_space -= dsk->data_block_size;
}
@@ -2171,11 +2258,12 @@ void blockstore_heap_t::apply_inflight(heap_inflight_lsn_t & inflight)
if (!next)
{
assert(!prev);
auto & inode_idx = block_index[get_pg_id(wr->inode, wr->stripe)][wr->inode];
auto & pg_idx = block_index[get_pg_id(wr->inode, wr->stripe)];
auto & inode_idx = pg_idx[wr->inode];
heap_inode_map_t::iterator li_it;
heap_list_item_t *old_li = NULL;
inode_map_get(inode_idx, li_it, old_li, wr->stripe);
inode_map_erase(inode_idx, li_it, old_li);
inode_map_erase(pg_idx, inode_idx, li_it, old_li);
}
else
{
@@ -2223,7 +2311,7 @@ void blockstore_heap_t::set_no_inode_stats(const std::vector<uint64_t> & pool_id
{
// Recalculate if changed
if (ps.second.no_inode_stats == 2 || ps.second.no_inode_stats == 1)
recalc_inode_space_stats(ps.first, ps.second.no_inode_stats == 1);
recalc_inode_space_stats(ps.first, ps.second.no_inode_stats == 2);
ps.second.no_inode_stats &= 1;
}
}
@@ -2234,8 +2322,8 @@ void blockstore_heap_t::recalc_inode_space_stats(uint64_t pool_id, bool per_inod
auto sp_begin = inode_space_stats.lower_bound((pool_id << (64-POOL_ID_BITS)));
auto sp_end = inode_space_stats.lower_bound(((pool_id+1) << (64-POOL_ID_BITS)));
inode_space_stats.erase(sp_begin, sp_end);
uint32_t pg_count = ps.pg_count ? ps.pg_count : 1;
for (uint32_t pg_num = 1; pg_num <= pg_count; pg_num++)
uint32_t pg_count = ps.pg_count;
for (uint32_t pg_num = pg_count ? 1 : 0; pg_num <= pg_count; pg_num++)
{
auto & pg_idx = block_index[(pool_id << (64-POOL_ID_BITS)) | pg_num];
for (auto & ip: pg_idx)
@@ -2268,7 +2356,7 @@ void blockstore_heap_t::recalc_inode_space_stats(uint64_t pool_id, bool per_inod
// This is some really crazy shit but it seems to work well :)
// At the same time it has almost zero overhead and works just as fast for fat inodes.
void blockstore_heap_t::inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_list_item_t* & li, uint64_t stripe)
void inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_list_item_t* & li, uint64_t stripe)
{
size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!map_n)
@@ -2295,7 +2383,7 @@ void blockstore_heap_t::inode_map_get(void *inode_idx, heap_inode_map_t::iterato
}
}
void blockstore_heap_t::inode_map_free(void* inode_idx)
void inode_map_free(void* inode_idx)
{
size_t n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!n)
@@ -2308,7 +2396,12 @@ void blockstore_heap_t::inode_map_free(void* inode_idx)
}
}
void blockstore_heap_t::inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)> cb)
bool inode_map_is_big(void* & inode_idx)
{
return !((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
}
void inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)> cb)
{
size_t n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!n)
@@ -2335,7 +2428,7 @@ void blockstore_heap_t::inode_map_iterate(void* & inode_idx, std::function<void(
}
}
void blockstore_heap_t::inode_map_put(void* & inode_idx, heap_list_item_t* li)
void inode_map_put(void* & inode_idx, heap_list_item_t* li)
{
if (!inode_idx)
{
@@ -2404,7 +2497,7 @@ void blockstore_heap_t::inode_map_put(void* & inode_idx, heap_list_item_t* li)
}
}
void blockstore_heap_t::inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* new_li)
void inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* new_li)
{
size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!map_n)
@@ -2430,7 +2523,8 @@ void blockstore_heap_t::inode_map_replace(void* & inode_idx, const heap_inode_ma
}
}
void blockstore_heap_t::inode_map_erase(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* li)
void inode_map_erase(robin_hood::unordered_flat_map<inode_t, void*, i64hash_t> & pg_idx, void* & inode_idx,
const heap_inode_map_t::iterator & li_it, heap_list_item_t* li)
{
size_t map_n = ((size_t)inode_idx & IMAP_MALLOC_LOW_BITS);
if (!map_n)
@@ -2455,7 +2549,7 @@ void blockstore_heap_t::inode_map_erase(void* & inode_idx, const heap_inode_map_
else if (map_n == 1)
{
// Erase
block_index[get_pg_id(li->entry.inode, li->entry.stripe)].erase(li->entry.inode);
pg_idx.erase(li->entry.inode);
}
else
{
+8 -12
View File
@@ -137,6 +137,8 @@ struct heap_compact_t
bool do_delete;
};
struct heap_reshard_state_t;
struct heap_li_hash
{
size_t operator()(const heap_list_item_t* li) const noexcept
@@ -161,7 +163,7 @@ using heap_mvcc_map_t = robin_hood::unordered_flat_map<object_id, heap_object_mv
class blockstore_heap_t
{
friend class heap_entry_t;
friend struct heap_entry_t;
blockstore_disk_t *dsk = NULL;
uint8_t* buffer_area = NULL;
@@ -205,19 +207,13 @@ class blockstore_heap_t
std::function<void(bool is_data, uint64_t offset, uint64_t len, uint8_t* buf, std::function<void()>)> recheck_cb;
int recheck_queue_depth = 0;
void inode_map_put(void* & inode_idx, heap_list_item_t* li);
void inode_map_get(void *inode_idx, heap_inode_map_t::iterator & li_it, heap_list_item_t* & li, uint64_t stripe);
void inode_map_free(void* inode_idx);
void inode_map_iterate(void* & inode_idx, std::function<void(heap_list_item_t*)> cb);
void inode_map_replace(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* new_li);
void inode_map_erase(void* & inode_idx, const heap_inode_map_t::iterator & li_it, heap_list_item_t* li);
uint64_t get_pg_id(inode_t inode, uint64_t stripe);
bool validate_object(heap_entry_t *obj);
void fill_recheck_queue();
int mark_used_blocks();
void recheck_buffer(heap_entry_t *cwr, uint8_t *buf);
void defragment_block(uint32_t block_num);
void reshard_add(heap_reshard_state_t *st, heap_list_item_t *li);
int allocate_entry(uint32_t entry_size, uint32_t *block_num, bool allow_last_free);
void insert_list_item(heap_list_item_t *li);
@@ -249,20 +245,20 @@ public:
// recheck small write data after reading the database from disk
bool recheck_small_writes(std::function<void(bool is_data, uint64_t offset, uint64_t len, uint8_t* buf, std::function<void()>)> read_buffer, int queue_depth);
// reshard database according to the pool's PG count
void reshard(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size);
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
bool reshard_continue(void* reshard_state, uint64_t chunk_limit);
bool reshard_check(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size);
void set_no_inode_stats(const std::vector<uint64_t> & pool_ids);
void recalc_inode_space_stats(uint64_t pool_id, bool per_inode);
// read an object entry and lock it against removal
// in the future, may become asynchronous
heap_entry_t *lock_and_read_entry(object_id oid);
// re-read a locked object entry with the given lsn (pointer may be invalidated)
heap_entry_t *read_locked_entry(object_id oid, uint64_t lsn);
// read an object entry without locking it
heap_entry_t *read_entry(object_id oid);
// unlock an entry
bool unlock_entry(object_id oid);
// set or verify checksums in a write request
bool calc_checksums(heap_entry_t *wr, uint8_t *data, bool set, uint32_t offset = 0, uint32_t len = 0);
bool calc_checksums(heap_entry_t *wr, uint8_t *data, bool set, uint32_t offset = UINT32_MAX, uint32_t len = UINT32_MAX);
// set or verify raw block checksums
bool calc_block_checksums(uint32_t *block_csums, uint8_t *data, uint8_t *bitmap, uint32_t start, uint32_t end,
bool set, std::function<void(uint32_t, uint32_t, uint32_t)> bad_block_cb);
+19 -7
View File
@@ -23,6 +23,7 @@ blockstore_impl_t::blockstore_impl_t(blockstore_config_t & config, ring_loop_i *
dsk.open_meta();
dsk.open_journal();
dsk.calc_lengths();
dsk.check_lengths();
}
catch (std::exception & e)
{
@@ -31,16 +32,13 @@ blockstore_impl_t::blockstore_impl_t(blockstore_config_t & config, ring_loop_i *
}
meta_superblock = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.meta_block_size);
memset(meta_superblock, 0, dsk.meta_block_size);
}
void blockstore_impl_t::init()
{
flusher = new journal_flusher_t(this);
if (dsk.inmemory_journal)
{
buffer_area = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.journal_len);
}
heap = new blockstore_heap_t(&dsk, buffer_area, log_level);
ringloop->wakeup();
}
blockstore_impl_t::~blockstore_impl_t()
@@ -325,9 +323,13 @@ void blockstore_impl_t::process_list(blockstore_op_t *op)
FINISH_OP(op);
return;
}
// Check if the DB needs resharding
// (we don't know about PGs from the beginning, we only create "shards" here)
heap->reshard(INODE_POOL(min_inode), pg_count, pg_stripe_size);
// Check if the DB is sharded correctly
if (!heap->reshard_check(INODE_POOL(min_inode), pg_count, pg_stripe_size))
{
op->retval = -EAGAIN;
FINISH_OP(op);
return;
}
obj_ver_id *result = NULL;
size_t stable_count = 0, unstable_count = 0;
int res = heap->list_objects(list_pg, op->min_oid, op->max_oid, &result, &stable_count, &unstable_count);
@@ -394,3 +396,13 @@ std::string blockstore_impl_t::get_op_diag(blockstore_op_t *op)
snprintf(buf, sizeof(buf), "state=%d", priv->op_state);
return std::string(buf);
}
void* blockstore_impl_t::reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit)
{
return heap->reshard_start(pool, pg_count, pg_stripe_size, chunk_limit);
}
bool blockstore_impl_t::reshard_continue(void *reshard_state, uint64_t chunk_limit)
{
return heap->reshard_continue(reshard_state, chunk_limit);
}
+3 -1
View File
@@ -142,7 +142,6 @@ public:
int metadata_buf_size;
blockstore_init_meta* metadata_init_reader;
void init();
void check_wait(blockstore_op_t *op);
void init_op(blockstore_op_t *op);
@@ -190,6 +189,9 @@ public:
void parse_config(blockstore_config_t & config);
void parse_config(blockstore_config_t & config, bool init);
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
bool reshard_continue(void *reshard_state, uint64_t chunk_limit);
// Event loop
void loop();
+2 -11
View File
@@ -72,7 +72,6 @@ resume_1:
}
if (is_zero((uint64_t*)bs->meta_superblock, bs->dsk.meta_block_size))
{
bs->dsk.check_lengths();
{
blockstore_meta_header_v3_t *hdr = (blockstore_meta_header_v3_t *)bs->meta_superblock;
hdr->zero = 0;
@@ -141,7 +140,7 @@ resume_1:
hdr->bitmap_granularity != bs->dsk.bitmap_granularity ||
hdr->data_csum_type != bs->dsk.data_csum_type ||
hdr->csum_block_size != bs->dsk.csum_block_size ||
hdr->meta_area_size > bs->dsk.meta_area_size)
hdr->meta_area_size != bs->dsk.meta_area_size)
{
printf(
"Configuration stored in metadata superblock"
@@ -154,15 +153,7 @@ resume_1:
);
exit(1);
}
bs->dsk.meta_area_size = hdr->meta_area_size;
if (bs->dsk.meta_format != hdr->version)
{
bs->dsk.meta_format = hdr->version;
bs->dsk.calc_lengths();
}
bs->dsk.check_lengths();
}
bs->init();
bs->heap->start_load(((blockstore_meta_header_v3_t *)bs->meta_superblock)->completed_lsn);
if (bs->dsk.inmemory_journal)
{
@@ -278,7 +269,7 @@ resume_6:
}
GET_SQE();
data->iov = (iovec){ buf, len };
data->callback = [this, offset, cb](ring_data_t *data)
data->callback = [offset, cb](ring_data_t *data)
{
if (data->res < 0)
{
+1 -1
View File
@@ -57,9 +57,9 @@ int blockstore_impl_t::dequeue_stable(blockstore_op_t *op)
}
assert(res == 0);
}
resume_1:
if (priv->modified_block != UINT32_MAX && priv->modified_block2 != priv->modified_block)
{
resume_1:
BS_SUBMIT_CHECK_SQES(1);
prepare_meta_block_write(priv->modified_block);
resume_2:
+65 -17
View File
@@ -407,32 +407,77 @@ blockstore_clean_db_t& blockstore_impl_t::clean_db_shard(object_id oid)
return clean_db_shards[(pool_id << (64-POOL_ID_BITS)) | pg_num];
}
void blockstore_impl_t::reshard_clean_db(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size)
struct bs_reshard_state_t
{
uint64_t pool_id = (uint64_t)pool;
int state = 0;
uint64_t pool_id = 0;
uint32_t pg_count = 0;
uint32_t pg_stripe_size = 0;
uint64_t chunk_size = 0;
std::map<pool_pg_id_t, blockstore_clean_db_t> old_shards;
std::map<pool_pg_id_t, blockstore_clean_db_t> new_shards;
auto sh_it = clean_db_shards.lower_bound((pool_id << (64-POOL_ID_BITS)));
while (sh_it != clean_db_shards.end() &&
(sh_it->first >> (64-POOL_ID_BITS)) == pool_id)
std::map<pool_pg_id_t, blockstore_clean_db_t>::iterator sh_it;
blockstore_clean_db_t::iterator obj_it;
};
void* blockstore_impl_t::reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit)
{
auto & settings = clean_db_settings[pool];
if (settings.pg_count == pg_count && settings.pg_stripe_size == pg_stripe_size)
{
for (auto & pair: sh_it->second)
{
// like map_to_pg()
uint64_t pg_num = (pair.first.stripe / pg_stripe_size) % pg_count + 1;
uint64_t shard_id = (pool_id << (64-POOL_ID_BITS)) | pg_num;
new_shards[shard_id][pair.first] = pair.second;
}
return NULL;
}
bs_reshard_state_t *st = new bs_reshard_state_t;
st->state = 0;
st->pool_id = pool;
st->pg_count = pg_count;
st->pg_stripe_size = pg_stripe_size;
auto sh_it = clean_db_shards.lower_bound((st->pool_id << (64-POOL_ID_BITS)));
while (sh_it != clean_db_shards.end() &&
(sh_it->first >> (64-POOL_ID_BITS)) == st->pool_id)
{
st->old_shards[sh_it->first] = std::move(sh_it->second);
clean_db_shards.erase(sh_it++);
}
for (sh_it = new_shards.begin(); sh_it != new_shards.end(); sh_it++)
bool finished = reshard_continue(st, chunk_limit);
return finished ? NULL : st;
}
bool blockstore_impl_t::reshard_continue(void *reshard_state, uint64_t chunk_limit)
{
bs_reshard_state_t *st = (bs_reshard_state_t*)reshard_state;
uint64_t chunk_size = 0;
if (st->state == 1)
goto resume_1;
for (st->sh_it = st->old_shards.begin(); st->sh_it != st->old_shards.end(); )
{
for (st->obj_it = st->sh_it->second.begin(); st->obj_it != st->sh_it->second.end(); st->obj_it++)
{
if (chunk_limit > 0 && chunk_size >= chunk_limit)
{
st->state = 1;
return false;
}
resume_1:
// like map_to_pg()
uint64_t pg_num = (st->obj_it->first.stripe / st->pg_stripe_size) % st->pg_count + 1;
uint64_t shard_id = (st->pool_id << (64-POOL_ID_BITS)) | pg_num;
st->new_shards[shard_id][st->obj_it->first] = st->obj_it->second;
chunk_size++;
}
st->old_shards.erase(st->sh_it++);
}
for (auto sh_it = st->new_shards.begin(); sh_it != st->new_shards.end(); sh_it++)
{
auto & to = clean_db_shards[sh_it->first];
to.swap(sh_it->second);
}
clean_db_settings[pool_id] = (pool_shard_settings_t){
.pg_count = pg_count,
.pg_stripe_size = pg_stripe_size,
clean_db_settings[st->pool_id] = (pool_shard_settings_t){
.pg_count = st->pg_count,
.pg_stripe_size = st->pg_stripe_size,
};
delete st;
return true;
}
void blockstore_impl_t::process_list(blockstore_op_t *op)
@@ -465,7 +510,10 @@ void blockstore_impl_t::process_list(blockstore_op_t *op)
sh_it->second.pg_count != pg_count ||
sh_it->second.pg_stripe_size != pg_stripe_size)
{
reshard_clean_db(pool_id, pg_count, pg_stripe_size);
// Sharding mismatch
op->retval = -EAGAIN;
FINISH_OP(op);
return;
}
first_shard = last_shard = ((uint64_t)pool_id << (64-POOL_ID_BITS)) | list_pg;
}
+4 -1
View File
@@ -202,7 +202,6 @@ class blockstore_impl_t: public blockstore_i
uint8_t* get_clean_entry_bitmap(uint64_t block_loc, int offset);
blockstore_clean_db_t& clean_db_shard(object_id oid);
void reshard_clean_db(pool_id_t pool_id, uint32_t pg_count, uint32_t pg_stripe_size);
void recalc_inode_space_stats(uint64_t pool_id, bool per_inode);
// Journaling
@@ -288,6 +287,10 @@ public:
void parse_config(blockstore_config_t & config);
void parse_config(blockstore_config_t & config, bool init);
// Reshard database for a pool
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
bool reshard_continue(void *reshard_state, uint64_t chunk_limit);
// Event loop
void loop();
+1 -1
View File
@@ -183,7 +183,7 @@ bool blockstore_impl_t::enqueue_write(blockstore_op_t *op)
uint32_t end = (op->offset+op->len-1) / dsk.csum_block_size;
auto fn = state & BS_ST_BIG_WRITE ? crc32c_pad : crc32c_nopad;
if (start == end)
data_csums[0] = fn(0, op->buf, op->len, op->offset - start*dsk.csum_block_size, end*dsk.csum_block_size - (op->offset+op->len));
data_csums[0] = fn(0, op->buf, op->len, op->offset - start*dsk.csum_block_size, (end+1)*dsk.csum_block_size - (op->offset+op->len));
else
{
// First block
+2 -2
View File
@@ -898,7 +898,7 @@ void cluster_client_t::execute_cas(cluster_op_t *op)
.opcode = OSD_OP_SYNC,
},
},
.callback = [this, op](osd_op_t *part)
.callback = [op](osd_op_t *part)
{
if (part->reply.hdr.retval != 0)
{
@@ -1257,7 +1257,7 @@ void cluster_client_t::slice_rw(cluster_op_t *op)
{
op->bitmap_buf = realloc_or_die(op->bitmap_buf, bitmap_mem);
op->part_bitmaps = (uint8_t*)op->bitmap_buf + object_bitmap_size;
memset(op->bitmap_buf+op->bitmap_buf_size, 0, bitmap_mem-op->bitmap_buf_size);
memset((uint8_t*)op->bitmap_buf+op->bitmap_buf_size, 0, bitmap_mem-op->bitmap_buf_size);
op->bitmap_buf_size = bitmap_mem;
}
}
+28 -7
View File
@@ -568,9 +568,19 @@ void etcd_state_client_t::start_ws_keepalive()
void etcd_state_client_t::load_global_config()
{
etcd_call("/kv/range", json11::Json::object {
{ "key", base64_encode(etcd_prefix+"/config/global") }
}, etcd_quick_timeout, max_etcd_attempts, 0, [this](std::string err, json11::Json data)
json11::Json::object req = { { "success", json11::Json::array {
json11::Json::object {
{ "request_range", json11::Json::object {
{ "key", base64_encode(etcd_prefix+"/config/global") },
} }
},
json11::Json::object {
{ "request_range", json11::Json::object {
{ "key", base64_encode(etcd_prefix+"/config/pools") },
} }
},
} } };
etcd_txn(req, etcd_quick_timeout, max_etcd_attempts, 0, [this](std::string err, json11::Json data)
{
if (err != "")
{
@@ -588,10 +598,12 @@ void etcd_state_client_t::load_global_config()
}
return;
}
json11::Json config_kv = data["responses"][0]["response_range"]["kvs"][0];
json11::Json pools_kv = data["responses"][1]["response_range"]["kvs"][0];
json11::Json::object global_config;
if (data["kvs"].array_items().size() > 0)
if (!config_kv.is_null())
{
auto kv = parse_etcd_kv(data["kvs"][0]);
auto kv = parse_etcd_kv(config_kv);
if (kv.value.is_object())
{
global_config = kv.value.object_items();
@@ -608,6 +620,11 @@ void etcd_state_client_t::load_global_config()
global_bitmap_granularity = DEFAULT_BITMAP_GRANULARITY;
}
global_immediate_commit = parse_immediate_commit(global_config["immediate_commit"].string_value(), IMMEDIATE_ALL);
if (!pools_kv.is_null())
{
auto kv = parse_etcd_kv(pools_kv);
parse_state(kv);
}
on_load_config_hook(global_config);
});
}
@@ -945,8 +962,12 @@ void etcd_state_client_t::parse_state(const etcd_kv_t & kv)
if (pc.pg_stripe_size < min_stripe_size)
pc.pg_stripe_size = min_stripe_size;
// Save
pc.real_pg_count = this->pool_config[pool_id].real_pg_count;
std::swap(pc.pg_config, this->pool_config[pool_id].pg_config);
auto & old_pc = this->pool_config[pool_id];
pc.real_pg_count = old_pc.real_pg_count;
pc.applied_pg_count = old_pc.applied_pg_count;
pc.applied_pg_stripe_size = old_pc.applied_pg_stripe_size;
pc.reshard_state = old_pc.reshard_state;
std::swap(pc.pg_config, old_pc.pg_config);
std::swap(this->pool_config[pool_id], pc);
auto & parsed_cfg = this->pool_config[pool_id];
parsed_cfg.exists = true;
+5
View File
@@ -68,6 +68,11 @@ struct pool_config_t
std::string used_for_app;
int backfillfull = 0;
int local_reads = 0;
// runtime data, used only by OSD:
uint64_t applied_pg_count = 0;
uint64_t applied_pg_stripe_size = 0;
void *reshard_state = NULL;
};
struct inode_config_t
+1
View File
@@ -42,6 +42,7 @@ void osd_messenger_t::read_requests()
}
if (!sqe)
{
cl->refs--;
cl->read_msg.msg_iovlen = 0;
read_ready_clients.erase(read_ready_clients.begin(), read_ready_clients.begin() + i);
return;
+10
View File
@@ -85,6 +85,16 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
osd_peer_fds.erase(osd_it);
}
}
#ifdef WITH_RDMA
if (cl->rdma_conn && cl->rdma_conn->cmid)
{
auto rdma_it = rdmacm_connections.find(cl->rdma_conn->cmid);
if (rdma_it != rdmacm_connections.end() && rdma_it->second == cl)
{
rdmacm_connections.erase(rdma_it);
}
}
#endif
#ifndef __MOCK__
// Then remove FD from the eventloop so we don't accidentally read something
tfd->set_fd_handler(peer_fd, false, NULL);
+1 -1
View File
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: Vitastor
Description: Vitastor client library
Version: 3.0.1
Version: 3.0.3
Libs: -L${libdir} -lvitastor_client
Cflags: -I${includedir}
+1 -1
View File
@@ -245,7 +245,7 @@ static json11::Json::object parse_args(int narg, const char *args[])
cfg["progress"] = "1";
for (int i = 1; i < narg; i++)
{
bool argHasValue = (!(i == narg-1) && (args[i+1][0] != '-'));
bool argHasValue = (i < narg-1);
if (args[i][0] == '-' && args[i][1] == 'h' && args[i][2] == 0)
{
cfg["help"] = "1";
+3 -3
View File
@@ -890,12 +890,12 @@ resume_2:
clock_gettime(CLOCK_REALTIME, &tv_begin);
tv_progress = tv_begin;
resume_3:
while ((ignore_errors || !copy_error) && (!in_eof || read_buffers.size() || in_waiting > 0 || out_waiting > 0))
while ((ignore_errors || !copy_error) && (!in_eof || read_buffers.size() || in_waiting > 0 || out_waiting > 0 || short_writes.size()))
{
print_progress(false);
while ((ignore_errors || !copy_error) &&
(!in_eof && in_waiting < in_iodepth && read_buffers.size() < out_iodepth ||
read_buffers.size() && out_waiting < out_iodepth))
(read_buffers.size() || short_writes.size()) && out_waiting < out_iodepth))
{
if (!in_eof && in_waiting < in_iodepth && read_buffers.size() < out_iodepth)
{
@@ -904,7 +904,7 @@ resume_3:
break;
}
}
if (read_buffers.size() && out_waiting < out_iodepth)
if ((read_buffers.size() || short_writes.size()) && out_waiting < out_iodepth)
{
if (!add_write_op())
{
+1 -1
View File
@@ -54,7 +54,7 @@ int disk_tool_t::trim_data(std::string device)
fprintf(stderr, "Reading metadata\n");
data_alloc = new allocator_t(dsk.block_count);
r = process_meta(
[this](blockstore_meta_header_v3_t *hdr) {},
[](blockstore_meta_header_v3_t *hdr) {},
[this](blockstore_heap_t *heap, heap_entry_t *obj, uint32_t meta_block_num)
{
for (auto wr = obj; wr; wr = heap->prev(wr))
+44 -19
View File
@@ -31,25 +31,6 @@ osd_t::osd_t(const json11::Json & config, ring_loop_t *ringloop)
// FIXME: Use timerfd_interval based directly on io_uring
this->tfd = epmgr->tfd;
if (!json_is_true(this->config["disable_blockstore"]))
{
auto bs_cfg = json_to_string_map(this->config);
this->bs = blockstore_i::create(bs_cfg, ringloop, tfd);
// Wait for blockstore initialisation before actually starting OSD logic
// to prevent peering timeouts during restart with filled databases
while (!bs->is_started())
{
ringloop->loop();
if (bs->is_started())
break;
ringloop->wait();
}
// Autosync based on the number of unstable writes to prevent stalls due to insufficient journal space
uint64_t max_autosync = bs->get_journal_size() / bs->get_block_size() / 2;
if (autosync_writes > max_autosync)
autosync_writes = max_autosync;
}
if (json_is_true(this->config["osd_memlock"]))
{
// Lock all OSD memory if requested
@@ -117,6 +98,7 @@ osd_t::~osd_t()
autosync_timer_id = -1;
}
ringloop->unregister_consumer(&consumer);
ringloop->unregister_consumer(&init_consumer);
delete epmgr;
if (bs)
delete bs;
@@ -131,6 +113,43 @@ osd_t::~osd_t()
free(zero_buffer);
}
void osd_t::init_blockstore(std::function<void()> on_init)
{
if (!json_is_true(this->config["disable_blockstore"]))
{
auto bs_cfg = json_to_string_map(this->config);
this->bs = blockstore_i::create(bs_cfg, ringloop, tfd);
// Pre-configure pool PG shards
for (auto & pool_item: st_cli.pool_config)
{
auto st = bs->reshard_start(pool_item.first, pool_item.second.pg_count, pool_item.second.pg_stripe_size, 0);
assert(!st);
}
// Autosync based on the number of unstable writes to prevent stalls due to insufficient journal space
uint64_t max_autosync = bs->get_journal_size() / bs->get_block_size() / 2;
if (autosync_writes > max_autosync)
autosync_writes = max_autosync;
if (on_init)
{
init_consumer.loop = [this, on_init]()
{
// Wait for blockstore initialisation before actually starting OSD logic
// to prevent peering timeouts during restart with filled databases
if (bs->is_started())
{
ringloop->set_immediate([this, on_init] { init_consumer.loop = NULL; on_init(); });
ringloop->unregister_consumer(&init_consumer);
}
};
ringloop->register_consumer(&init_consumer);
}
}
else if (on_init)
{
on_init();
}
}
void osd_t::parse_config(bool init)
{
config = msgr.merge_configs(cli_config, file_config, etcd_global_config, etcd_osd_config);
@@ -292,6 +311,12 @@ void osd_t::parse_config(bool init)
scrub_list_limit = config["scrub_list_limit"].uint64_value();
if (!scrub_list_limit)
scrub_list_limit = 262144;
pg_reshard_chunk_size = config["pg_reshard_chunk_size"].uint64_value();
if (!pg_reshard_chunk_size)
pg_reshard_chunk_size = 100000;
pg_reshard_chunk_pause_ms = config["pg_reshard_chunk_pause_ms"].uint64_value();
if (!pg_reshard_chunk_pause_ms)
pg_reshard_chunk_pause_ms = 100;
if (!old_auto_scrub && auto_scrub)
{
// Schedule scrubbing
+15 -8
View File
@@ -148,6 +148,8 @@ class osd_t
bool enable_pg_locks = false;
bool pg_locks_localize_only = false;
uint64_t pg_lock_retry_interval_ms = 100;
uint64_t pg_reshard_chunk_size = 100000;
uint64_t pg_reshard_chunk_pause_ms = 100;
// cluster state
@@ -158,6 +160,7 @@ class osd_t
json11::Json self_state;
bool loading_peer_config = false;
std::set<pool_pg_num_t> pg_state_dirty;
bool etcd_global_config_loaded = false;
bool pg_config_applied = false;
bool etcd_reporting_pg_state = false;
bool etcd_reporting_stats = false;
@@ -168,10 +171,11 @@ class osd_t
// peers and PGs
std::map<pool_pg_num_t, osd_pg_lock_t> pg_locks;
std::map<pool_id_t, pg_num_t> pg_counts;
std::map<pool_pg_num_t, pg_t> pgs;
std::set<pool_pg_num_t> dirty_pgs;
std::set<osd_num_t> dirty_osds;
std::vector<pool_id_t> reshard_pools;
int reshard_timer_id = -1;
int copies_to_delete_after_sync_count = 0;
uint64_t misplaced_objects = 0, degraded_objects = 0, incomplete_objects = 0, inconsistent_objects = 0, corrupted_objects = 0;
int peering_state = 0;
@@ -206,7 +210,7 @@ class osd_t
void *zero_buffer = NULL;
uint64_t zero_buffer_size = 0;
uint32_t bs_block_size, bs_bitmap_granularity, clean_entry_bitmap_size;
ring_loop_t *ringloop;
ring_loop_t *ringloop = NULL;
timerfd_manager_t *tfd = NULL;
epoll_manager_t *epmgr = NULL;
@@ -218,6 +222,7 @@ class osd_t
int rdmacm_port = 0;
#endif
ring_consumer_t consumer;
ring_consumer_t init_consumer;
// op statistics
osd_op_stats_t prev_stats, prev_report_stats;
@@ -241,6 +246,7 @@ class osd_t
// cluster connection
void parse_config(bool init);
void init_blockstore(std::function<void()> on_init);
void init_cluster();
void on_change_osd_state_hook(osd_num_t peer_osd);
void on_change_backfillfull_hook(pool_id_t pool_id);
@@ -268,6 +274,7 @@ class osd_t
void apply_no_inode_stats();
void apply_pg_count();
void apply_pg_config();
void reshard_continue();
// event loop, socket read/write
void loop();
@@ -317,7 +324,7 @@ class osd_t
void finish_op(osd_op_t *cur_op, int retval);
// secondary ops
bool sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid);
bool sec_check_pg_lock(osd_num_t primary_osd, const object_id & oid, uint32_t flags);
void exec_show_config(osd_op_t *cur_op);
void exec_secondary(osd_op_t *cur_op);
void exec_secondary_real(osd_op_t *cur_op);
@@ -376,12 +383,12 @@ class osd_t
int submit_bitmap_subops(osd_op_t *cur_op, pg_t & pg);
int read_bitmaps(osd_op_t *cur_op, pg_t *pg, int base_state);
inline pg_num_t map_to_pg(object_id oid, uint64_t pg_stripe_size)
inline pg_num_t map_to_pg(object_id oid)
{
uint64_t pg_count = pg_counts[INODE_POOL(oid.inode)];
if (!pg_count)
pg_count = 1;
return (oid.stripe / pg_stripe_size) % pg_count + 1;
auto pool_it = st_cli.pool_config.find(INODE_POOL(oid.inode));
if (pool_it == st_cli.pool_config.end())
return 1;
return (oid.stripe / pool_it->second.applied_pg_stripe_size) % pool_it->second.applied_pg_count + 1;
}
public:
+114 -24
View File
@@ -18,6 +18,7 @@ void osd_t::init_cluster()
{
if (!st_cli.address_count())
{
init_blockstore(NULL);
if (run_primary)
{
// Test version of clustering code with 1 pool, 1 PG and 2 peers
@@ -54,9 +55,10 @@ void osd_t::init_cluster()
.pg_minsize = 2,
.pg_count = 1,
.real_pg_count = 1,
.applied_pg_count = 1,
.applied_pg_stripe_size = bs_block_size*2,
};
report_pg_state(pgs[{ 1, 1 }]);
pg_counts[1] = 1;
}
bind_socket();
}
@@ -422,7 +424,10 @@ void osd_t::on_change_osd_state_hook(osd_num_t peer_osd)
void osd_t::on_change_pool_config_hook()
{
apply_pg_locks_localize_only();
if (etcd_global_config_loaded)
{
apply_pg_locks_localize_only();
}
}
void osd_t::apply_pg_locks_localize_only()
@@ -484,9 +489,13 @@ void osd_t::on_load_config_hook(json11::Json::object & global_config)
{
etcd_global_config = global_config;
parse_config(true);
bind_socket();
acquire_lease();
st_cli.on_load_config_hook = [this](json11::Json::object & cfg) { on_reload_config_hook(cfg); };
etcd_global_config_loaded = true;
init_blockstore([this]()
{
bind_socket();
acquire_lease();
});
}
void osd_t::on_reload_config_hook(json11::Json::object & global_config)
@@ -719,8 +728,13 @@ void osd_t::apply_pg_count()
{
for (auto & pool_item: st_cli.pool_config)
{
if (pool_item.second.real_pg_count != 0 &&
pool_item.second.real_pg_count != pg_counts[pool_item.first])
auto & pool_cfg = pool_item.second;
if (pool_cfg.real_pg_count == 0)
{
continue;
}
if (pool_cfg.real_pg_count != pool_cfg.applied_pg_count ||
pool_cfg.pg_stripe_size != pool_cfg.applied_pg_stripe_size)
{
// Check that all pool PGs are offline. It is not allowed to change PG count when any PGs are online
// The external tool must wait for all PGs to come down before changing PG count
@@ -742,17 +756,87 @@ void osd_t::apply_pg_count()
}
if (still_active_primary > 0 || still_active_secondary > 0)
{
printf(
"[OSD %ju] PG count change detected for pool %u (new is %ju, old is %u),"
" but %u PG(s) are still active as primary and %u as secondary. This is not allowed. Exiting\n",
this->osd_num, pool_item.first, pool_item.second.real_pg_count, pg_counts[pool_item.first],
still_active_primary, still_active_secondary
);
if (pool_cfg.real_pg_count != pool_cfg.applied_pg_count)
{
printf(
"[OSD %ju] PG count change detected for pool %u (new is %ju, old is %ju),"
" but %u PG(s) are still active as primary and %u as secondary. This is not allowed. Exiting\n",
this->osd_num, pool_item.first, pool_cfg.real_pg_count, pool_cfg.applied_pg_count,
still_active_primary, still_active_secondary
);
}
else
{
printf(
"[OSD %ju] PG stripe change detected for pool %u (new is %ju, old is %ju),"
" but %u PG(s) are still active as primary and %u as secondary. This is not allowed. Exiting\n",
this->osd_num, pool_item.first, pool_cfg.pg_stripe_size, pool_cfg.applied_pg_stripe_size,
still_active_primary, still_active_secondary
);
}
force_stop(1);
return;
}
pool_cfg.applied_pg_count = pool_cfg.real_pg_count;
pool_cfg.applied_pg_stripe_size = pool_cfg.pg_stripe_size;
if (bs && !pool_cfg.reshard_state)
{
pool_cfg.reshard_state = bs->reshard_start(pool_item.first, pool_cfg.real_pg_count, pool_cfg.pg_stripe_size, pg_reshard_chunk_size);
if (pool_cfg.reshard_state)
{
reshard_pools.push_back(pool_item.first);
}
}
}
this->pg_counts[pool_item.first] = pool_item.second.real_pg_count;
}
if (reshard_pools.size() && reshard_timer_id < 0)
{
reshard_timer_id = tfd->set_timer(pg_reshard_chunk_pause_ms, false, [this](int)
{
reshard_continue();
});
}
}
void osd_t::reshard_continue()
{
again:
auto pool_id = reshard_pools[0];
auto pool_it = st_cli.pool_config.find(pool_id);
if (pool_it == st_cli.pool_config.end() || !pool_it->second.reshard_state)
{
reshard_pools.erase(reshard_pools.begin());
goto again;
}
auto & pool_cfg = pool_it->second;
bool done = bs->reshard_continue(pool_cfg.reshard_state, pg_reshard_chunk_size);
if (done &&
(pool_cfg.real_pg_count != pool_cfg.applied_pg_count ||
pool_cfg.pg_stripe_size != pool_cfg.applied_pg_stripe_size))
{
// PG count changed again, reshard again
pool_cfg.applied_pg_count = pool_cfg.real_pg_count;
pool_cfg.applied_pg_stripe_size = pool_cfg.pg_stripe_size;
pool_cfg.reshard_state = bs->reshard_start(pool_id, pool_cfg.real_pg_count, pool_cfg.pg_stripe_size, pg_reshard_chunk_size);
done = !pool_cfg.reshard_state;
}
if (done)
{
// Pool is resharded
pool_cfg.reshard_state = NULL;
reshard_pools.erase(reshard_pools.begin());
apply_pg_config();
}
if (reshard_pools.size())
{
reshard_timer_id = tfd->set_timer(pg_reshard_chunk_pause_ms, false, [this](int)
{
reshard_continue();
});
}
else
{
reshard_timer_id = -1;
}
}
@@ -761,9 +845,15 @@ void osd_t::apply_pg_config()
bool all_applied = true;
for (auto & pool_item: st_cli.pool_config)
{
auto & pool_cfg = pool_item.second;
if (pool_cfg.reshard_state)
{
// Can't apply anything for pools being resharded
continue;
}
bool warned_block_size = false;
auto pool_id = pool_item.first;
for (auto & kv: pool_item.second.pg_config)
for (auto & kv: pool_cfg.pg_config)
{
pg_num_t pg_num = kv.first;
auto & pg_cfg = kv.second;
@@ -772,8 +862,8 @@ void osd_t::apply_pg_config()
auto pg_it = this->pgs.find({ .pool_id = pool_id, .pg_num = pg_num });
bool currently_taken = pg_it != this->pgs.end() && pg_it->second.state != PG_OFFLINE;
// Check pool block size and bitmap granularity
if (take && this->bs_block_size != pool_item.second.data_block_size ||
this->bs_bitmap_granularity != pool_item.second.bitmap_granularity)
if (take && this->bs_block_size != pool_cfg.data_block_size ||
this->bs_bitmap_granularity != pool_cfg.bitmap_granularity)
{
if (!warned_block_size)
{
@@ -781,7 +871,7 @@ void osd_t::apply_pg_config()
"[OSD %ju] My block_size and bitmap_granularity are %u/%u"
", but pool %u has %u/%u. Refusing to start PGs of this pool\n",
this->osd_num, bs_block_size, bs_bitmap_granularity,
pool_id, pool_item.second.data_block_size, pool_item.second.bitmap_granularity
pool_id, pool_cfg.data_block_size, pool_cfg.bitmap_granularity
);
}
warned_block_size = true;
@@ -874,12 +964,12 @@ void osd_t::apply_pg_config()
}
auto & pg = this->pgs[{ .pool_id = pool_id, .pg_num = pg_num }];
pg.state = pg_cfg.cur_primary == this->osd_num ? PG_PEERING : PG_STARTING;
pg.scheme = pool_item.second.scheme;
pg.scheme = pool_cfg.scheme;
pg.pg_cursize = 0;
pg.pg_size = pool_item.second.pg_size;
pg.pg_minsize = pool_item.second.pg_minsize;
pg.pg_data_size = pool_item.second.scheme == POOL_SCHEME_REPLICATED
? 1 : pool_item.second.pg_size - pool_item.second.parity_chunks;
pg.pg_size = pool_cfg.pg_size;
pg.pg_minsize = pool_cfg.pg_minsize;
pg.pg_data_size = pool_cfg.scheme == POOL_SCHEME_REPLICATED
? 1 : pool_cfg.pg_size - pool_cfg.parity_chunks;
pg.pool_id = pool_id;
pg.pg_num = pg_num;
pg.reported_epoch = pg_cfg.epoch;
@@ -888,8 +978,8 @@ void osd_t::apply_pg_config()
pg.next_scrub = pg_cfg.next_scrub;
pg.target_set = pg_cfg.target_set;
pg.disable_pg_locks = pg_locks_localize_only &&
(pool_item.second.scheme != POOL_SCHEME_REPLICATED ||
pool_item.second.local_reads == POOL_LOCAL_READ_PRIMARY);
(pool_cfg.scheme != POOL_SCHEME_REPLICATED ||
pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY);
if (pg.scheme == POOL_SCHEME_EC)
{
use_ec(pg.pg_size, pg.pg_data_size, true);
+1 -2
View File
@@ -318,8 +318,7 @@ void osd_t::submit_recovery_op(osd_recovery_op_t *op)
// EPIPE is totally harmless (peer is gone), others like EIO/EDOM may be not
printf(
"[PG %u/%u] Recovery operation failed with object %jx:%jx: error %jd\n",
INODE_POOL(op->oid.inode),
map_to_pg(op->oid, st_cli.pool_config.at(INODE_POOL(op->oid.inode)).pg_stripe_size),
INODE_POOL(op->oid.inode), map_to_pg(op->oid),
op->oid.inode, op->oid.stripe, op->osd_op->reply.hdr.retval
);
}
+6 -6
View File
@@ -159,11 +159,10 @@ void osd_t::reset_pg(pg_t & pg)
cancel_primary_write(p.second);
}
pg.write_queue.clear();
uint64_t pg_stripe_size = st_cli.pool_config[pg.pool_id].pg_stripe_size;
for (auto it = unstable_writes.begin(); it != unstable_writes.end(); )
{
// Forget this PG's unstable writes
if (INODE_POOL(it->first.oid.inode) == pg.pool_id && map_to_pg(it->first.oid, pg_stripe_size) == pg.pg_num)
if (INODE_POOL(it->first.oid.inode) == pg.pool_id && map_to_pg(it->first.oid) == pg.pg_num)
unstable_writes.erase(it++);
else
it++;
@@ -524,6 +523,7 @@ void osd_t::relock_pg(pg_t & pg)
void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
{
auto & pool_cfg = st_cli.pool_config.at(ps->pool_id);
if (role_osd == this->osd_num)
{
// Self
@@ -533,11 +533,11 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
clock_gettime(CLOCK_REALTIME, &op->tv_begin);
op->bs_op = new blockstore_op_t();
op->bs_op->opcode = BS_OP_LIST;
op->bs_op->pg_alignment = st_cli.pool_config[ps->pool_id].pg_stripe_size;
op->bs_op->pg_alignment = pool_cfg.applied_pg_stripe_size;
op->bs_op->min_oid.inode = ((uint64_t)ps->pool_id << (64 - POOL_ID_BITS));
op->bs_op->max_oid.inode = ((uint64_t)(ps->pool_id+1) << (64 - POOL_ID_BITS)) - 1;
op->bs_op->max_oid.stripe = UINT64_MAX;
op->bs_op->pg_count = pg_counts[ps->pool_id];
op->bs_op->pg_count = pool_cfg.applied_pg_count;
op->bs_op->pg_number = ps->pg_num-1;
op->bs_op->callback = [this, ps, op, role_osd](blockstore_op_t *bs_op)
{
@@ -584,8 +584,8 @@ void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
.opcode = OSD_OP_SEC_LIST,
},
.list_pg = ps->pg_num,
.pg_count = pg_counts[ps->pool_id],
.pg_stripe_size = st_cli.pool_config[ps->pool_id].pg_stripe_size,
.pg_count = (uint32_t)pool_cfg.applied_pg_count,
.pg_stripe_size = pool_cfg.applied_pg_stripe_size,
.min_inode = ((uint64_t)(ps->pool_id) << (64 - POOL_ID_BITS)),
.max_inode = ((uint64_t)(ps->pool_id+1) << (64 - POOL_ID_BITS)) - 1,
},
+8 -1
View File
@@ -35,7 +35,14 @@ bool osd_t::prepare_primary_rw(osd_op_t *cur_op)
// oid.stripe = starting offset of the parity stripe
.stripe = (cur_op->req.rw.offset/pg_block_size)*pg_block_size,
};
pg_num_t pg_num = (oid.stripe/pool_cfg.pg_stripe_size) % pg_counts[pool_id] + 1; // like map_to_pg()
auto pg_count = pool_cfg.applied_pg_count;
if (!pg_count)
{
// Pool config is not loaded yet
finish_op(cur_op, -EPIPE);
return false;
}
pg_num_t pg_num = (oid.stripe/pool_cfg.applied_pg_stripe_size) % pg_count + 1; // like map_to_pg()
auto pg_it = pgs.find({ .pool_id = pool_id, .pg_num = pg_num });
if (pg_it == pgs.end() || pg_it->second.state == PG_OFFLINE)
{
+1 -1
View File
@@ -171,7 +171,7 @@ resume_6:
auto & w = op_data->unstable_writes[unstable_osd.start + i];
pool_pg_num_t wpg = {
.pool_id = INODE_POOL(w.oid.inode),
.pg_num = map_to_pg(w.oid, st_cli.pool_config.at(INODE_POOL(w.oid.inode)).pg_stripe_size),
.pg_num = map_to_pg(w.oid),
};
if (pgs.at(wpg).state & PG_ACTIVE)
{
+6 -5
View File
@@ -9,6 +9,7 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
{
pool_id_t pool_id = pg_id.pool_id;
pg_num_t pg_num = pg_id.pg_num;
auto & pool_cfg = st_cli.pool_config.at(pool_id);
assert(!scrub_list_op);
if (role_osd == this->osd_num)
{
@@ -19,7 +20,7 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
clock_gettime(CLOCK_REALTIME, &op->tv_begin);
op->bs_op = new blockstore_op_t();
op->bs_op->opcode = BS_OP_LIST;
op->bs_op->pg_alignment = st_cli.pool_config[pool_id].pg_stripe_size;
op->bs_op->pg_alignment = pool_cfg.applied_pg_stripe_size;
if (min_oid.inode != 0 || min_oid.stripe != 0)
op->bs_op->min_oid = min_oid;
else
@@ -30,7 +31,7 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
op->bs_op->max_oid.inode = ((uint64_t)(pool_id+1) << (64 - POOL_ID_BITS)) - 1;
op->bs_op->max_oid.stripe = UINT64_MAX;
op->bs_op->list_stable_limit = scrub_list_limit;
op->bs_op->pg_count = pg_counts[pool_id];
op->bs_op->pg_count = pool_cfg.applied_pg_count;
op->bs_op->pg_number = pg_num-1;
op->bs_op->callback = [this, op](blockstore_op_t *bs_op)
{
@@ -68,8 +69,8 @@ void osd_t::scrub_list(pool_pg_num_t pg_id, osd_num_t role_osd, object_id min_oi
.opcode = OSD_OP_SEC_LIST,
},
.list_pg = pg_num,
.pg_count = pg_counts[pool_id],
.pg_stripe_size = st_cli.pool_config[pool_id].pg_stripe_size,
.pg_count = (uint32_t)pool_cfg.applied_pg_count,
.pg_stripe_size = pool_cfg.applied_pg_stripe_size,
.min_inode = min_oid.inode ? min_oid.inode : ((uint64_t)(pool_id) << (64 - POOL_ID_BITS)),
.max_inode = ((uint64_t)(pool_id+1) << (64 - POOL_ID_BITS)) - 1,
.min_stripe = min_oid.stripe,
@@ -249,7 +250,7 @@ void osd_t::submit_scrub_op(object_id oid)
printf(
"Scrub failed with object %jx:%jx (PG %u/%u): error %jd\n",
oid.inode, oid.stripe, INODE_POOL(oid.inode),
map_to_pg(oid, st_cli.pool_config.at(INODE_POOL(oid.inode)).pg_stripe_size),
map_to_pg(oid),
osd_op->reply.hdr.retval
);
}
+23 -14
View File
@@ -79,12 +79,8 @@ void osd_t::exec_secondary(osd_op_t *op)
}
}
bool osd_t::sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid)
bool osd_t::sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid, uint32_t flags)
{
if (!enable_pg_locks)
{
return true;
}
pool_id_t pool_id = INODE_POOL(oid.inode);
auto pool_cfg_it = st_cli.pool_config.find(pool_id);
if (pool_cfg_it == st_cli.pool_config.end())
@@ -92,11 +88,19 @@ bool osd_t::sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid)
return false;
}
auto & pool_cfg = pool_cfg_it->second;
if (pool_cfg.reshard_state)
{
return false;
}
if (!enable_pg_locks || (flags & OSD_OP_IGNORE_PG_LOCK))
{
return true;
}
if (pg_locks_localize_only && (pool_cfg.scheme != POOL_SCHEME_REPLICATED || pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY))
{
return true;
}
auto ppg = (pool_pg_num_t){ .pool_id = pool_id, .pg_num = map_to_pg(oid, pool_cfg_it->second.pg_stripe_size) };
auto ppg = (pool_pg_num_t){ .pool_id = pool_id, .pg_num = map_to_pg(oid) };
auto pg_it = pgs.find(ppg);
if (pg_it != pgs.end() && pg_it->second.state != PG_OFFLINE)
{
@@ -140,8 +144,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE ||
cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE)
{
if (!(cur_op->req.sec_rw.flags & OSD_OP_IGNORE_PG_LOCK) &&
!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_rw.oid))
if (!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_rw.oid, cur_op->req.sec_rw.flags))
{
cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op);
@@ -169,8 +172,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
}
else if (cur_op->req.hdr.opcode == OSD_OP_SEC_DELETE)
{
if (!(cur_op->req.sec_del.flags & OSD_OP_IGNORE_PG_LOCK) &&
!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_del.oid))
if (!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_del.oid, cur_op->req.sec_del.flags))
{
cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op);
@@ -190,11 +192,11 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
#ifdef OSD_STUB
cur_op->bs_op->retval = 0;
#endif
if (enable_pg_locks && !(cur_op->req.sec_stab.flags & OSD_OP_IGNORE_PG_LOCK))
if (enable_pg_locks)
{
for (int i = 0; i < cur_op->bs_op->len; i++)
{
if (!sec_check_pg_lock(cl->in_osd_num, ((obj_ver_id*)cur_op->buf)[i].oid))
if (!sec_check_pg_lock(cl->in_osd_num, ((obj_ver_id*)cur_op->buf)[i].oid, cur_op->req.sec_stab.flags))
{
cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op);
@@ -213,6 +215,14 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
secondary_op_callback(cur_op);
return;
}
auto pool_id = INODE_POOL(cur_op->bs_op->min_oid.inode);
if (pool_id && !sec_check_pg_lock(0, (object_id){ .inode = cur_op->bs_op->min_oid.inode }, OSD_OP_IGNORE_PG_LOCK))
{
// Check resharding state of the pool
cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op);
return;
}
cur_op->bs_op->pg_alignment = cur_op->req.sec_list.pg_stripe_size;
cur_op->bs_op->pg_count = cur_op->req.sec_list.pg_count;
cur_op->bs_op->pg_number = cur_op->req.sec_list.list_pg - 1;
@@ -248,8 +258,7 @@ void osd_t::exec_sec_read_bmp(osd_op_t *cur_op)
void *cur_buf = reply_buf;
for (int i = 0; i < n; i++)
{
if (!sec_check_pg_lock(cl->in_osd_num, ov[i].oid) &&
!(cur_op->req.sec_read_bmp.flags & OSD_OP_IGNORE_PG_LOCK))
if (!sec_check_pg_lock(cl->in_osd_num, ov[i].oid, cur_op->req.sec_read_bmp.flags))
{
free(reply_buf);
cur_op->bs_op->retval = -EPIPE;
+3 -3
View File
@@ -199,7 +199,7 @@ void disk_mock_t::erase_buffers(uint64_t begin, uint64_t end)
{
// Cut beginning & end & stop
uint8_t *ce = (uint8_t*)malloc_or_die(be-end);
memcpy(ce, it->second.iov_base + (end-bs), be-end);
memcpy(ce, (uint8_t*)it->second.iov_base + (end-bs), be-end);
uint8_t *cs = (uint8_t*)realloc(it->second.iov_base, begin-bs);
if (!cs)
throw std::bad_alloc();
@@ -221,7 +221,7 @@ void disk_mock_t::erase_buffers(uint64_t begin, uint64_t end)
// Cut end & stop
assert(be > end);
uint8_t *ce = (uint8_t*)malloc_or_die(be-end);
memcpy(ce, it->second.iov_base + (end-bs), be-end);
memcpy(ce, (uint8_t*)it->second.iov_base + (end-bs), be-end);
buffers[be] = (iovec){ .iov_base = ce, .iov_len = be-end };
buffers.erase(it);
break;
@@ -308,7 +308,7 @@ void disk_mock_t::read_item(uint8_t *to, uint64_t offset, uint64_t len)
last = offset;
}
uint64_t cur_end = be < offset+len ? be : offset+len;
memcpy(to+last-offset, it->second.iov_base+last-bs, cur_end-last);
memcpy(to+last-offset, (uint8_t*)it->second.iov_base+last-bs, cur_end-last);
last = be;
}
if (last < offset+len)
+914 -14
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -37,6 +37,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include "crc32c.h"
#ifdef WITH_ISAL
@@ -394,6 +395,7 @@ static uint8_t zero_page[4096] = {};
uint32_t crc32c_pad(uint32_t prev_crc, const void *buf, size_t len, size_t left_pad, size_t right_pad)
{
assert(left_pad < 0x10000000 && right_pad < 0x10000000);
uint32_t r = prev_crc;
while (left_pad >= 4096)
{
+10 -2
View File
@@ -65,7 +65,7 @@ start_etcd()
--max-txn-ops=100000 --auto-compaction-retention=10 --auto-compaction-mode=revision &>./testdata/etcd$i.log &
eval ETCD${i}_PID=$!
else
node mon/mon-main.js $MON_PARAMS --antietcd_port $((ETCD_PORT+2*i-2)) --etcd_address $ETCD_URL --etcd_prefix "/vitastor" --verbose 1 >>./testdata/mon$i.log 2>&1 &
node mon/mon-main.js $MON_PARAMS --antietcd_port $((ETCD_PORT+2*i-2)) --verbose 1 >>./testdata/mon$i.log 2>&1 &
eval ETCD${i}_PID=$!
fi
}
@@ -108,12 +108,20 @@ wait_condition()
done
}
VITASTOR_CFG='"etcd_address":"'$ETCD_URL'"'
echo "{$VITASTOR_CFG}" > ./testdata/vitastor.conf
VITASTOR_CFG=./testdata/vitastor.conf
VITASTOR_CLI="build/src/cmd/vitastor-cli --config_path $VITASTOR_CFG"
# Preload build/src/client/libfio_vitastor.so so libasan detects all symbols
VITASTOR_FIO="env LD_PRELOAD=build/src/client/libfio_vitastor.so fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -conf $VITASTOR_CFG"
OSD_ARGS="$OSD_ARGS --config_path $VITASTOR_CFG"
MON_PARAMS="$MON_PARAMS --config_path $VITASTOR_CFG"
if [[ -n "$ANTIETCD" ]]; then
ETCDCTL="node mon/node_modules/.bin/anticli -e $ETCD_URL"
MON_PARAMS="--use_antietcd 1 --antietcd_data_dir ./testdata --antietcd_persist_interval 500 $MON_PARAMS"
else
ETCDCTL="${ETCD}ctl --endpoints=$ETCD_URL --dial-timeout=5s --command-timeout=10s"
MON_PARAMS="$MON_PARAMS"
start_etcd_cluster
fi
+2 -2
View File
@@ -23,7 +23,7 @@ if [[ -n "$ANTIETCD" ]]; then
start_etcd $i
done
else
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" --verbose 1 >>./testdata/mon.log 2>&1 &
node mon/mon-main.js $MON_PARAMS --verbose 1 >>./testdata/mon.log 2>&1 &
MON_PID=$!
fi
wait_etcd
@@ -40,7 +40,7 @@ start_osd_on()
{
local i=$1
local dev=$2
build/src/osd/vitastor-osd --osd_num $i --bind_address $ETCD_IP $NO_SAME $OSD_ARGS --etcd_address $ETCD_URL \
build/src/osd/vitastor-osd --osd_num $i --bind_address $ETCD_IP $NO_SAME $OSD_ARGS \
$(build/src/disk_tool/vitastor-disk simple-offsets --format options $OFFSET_ARGS $dev $OFFSET_ARGS 2>/dev/null) \
>>./testdata/osd$i.log 2>&1 &
eval OSD${i}_PID=$!
+1
View File
@@ -138,6 +138,7 @@ OLD=1 SCHEME=xor ./test_scrub.sh
OLD=1 PG_SIZE=3 ./test_scrub.sh
OLD=1 PG_SIZE=6 PG_MINSIZE=4 OSD_COUNT=6 SCHEME=ec ./test_scrub.sh
OLD=1 SCHEME=ec ./test_scrub.sh
OLD=1 ./test_partwr_csum.sh
TEST_NAME=old_csum_32k_dmj OLD=1 OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_metadata false --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh
TEST_NAME=old_csum_32k_dj OLD=1 OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh
+3 -4
View File
@@ -4,9 +4,8 @@ PG_COUNT=2048
GLOBAL_CONFIG=',"osd_out_time":1'
. `dirname $0`/run_3osds.sh
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -end_fsync=1 \
-rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -end_fsync=1 \
-rw=write -pool=1 -inode=1 -size=128M -cluster_log_level=10
start_osd 4
@@ -30,7 +29,7 @@ wait_finish_rebalance 60
sleep 1
kill -9 $OSD4_PID
sleep 1
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm-osd --force 4
$VITASTOR_CLI rm-osd --force 4
sleep 2
+1 -1
View File
@@ -2,6 +2,6 @@
. `dirname $0`/run_3osds.sh
build/src/test/test_cas --pool_id 1 --inode_id 1 --etcd_address $ETCD_URL
build/src/test/test_cas --pool_id 1 --inode_id 1 --config_path $VITASTOR_CFG
format_green OK
+3 -3
View File
@@ -1,5 +1,6 @@
#!/bin/bash -ex
GLOBAL_CONFIG=',"pg_reshard_chunk_size":100'
OSD_COUNT=${OSD_COUNT:-6}
PG_COUNT=16
@@ -7,9 +8,8 @@ PG_COUNT=16
NOBJ=$(((128*8+PG_DATA_SIZE-1)/PG_DATA_SIZE))
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-pool=1 -inode=2 -size=128M -cluster_log_level=10
try_change()
{
+3 -6
View File
@@ -6,13 +6,10 @@ GLOBAL_CONFIG=',"client_retry_interval":1000'
. `dirname $0`/run_3osds.sh
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write -pool=1 -inode=2 -size=128M
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -rw=randrw \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M -loops=100 -cluster_log_level=3 -runtime=60 &>./testdata/fio.log &
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 -rw=randrw -pool=1 -inode=2 -size=128M -loops=100 \
-cluster_log_level=3 -runtime=60 &>./testdata/fio.log &
FIO_PID=$!
try_change()
+3 -4
View File
@@ -11,9 +11,8 @@ IMG_SIZE=128
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
# Write
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 \
-mirror_file=./testdata/bin/mirror.bin -end_fsync=1 -rw=write -etcd=$ETCD_URL -image=testimg -runtime=10
$VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 \
-mirror_file=./testdata/bin/mirror.bin -end_fsync=1 -rw=write -image=testimg -runtime=10
# Intentionally corrupt OSD data and restart it
kill $OSD1_PID
@@ -29,7 +28,7 @@ wait_up 10
# Read everything back
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \
-O raw ./testdata/bin/read.bin
diff ./testdata/bin/read.bin ./testdata/bin/mirror.bin
+3 -3
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 &
MON_PID=$!
wait_etcd
@@ -28,8 +28,8 @@ $ETCDCTL put /vitastor/osd/stats/3 '{"host":"host2","size":1073741824,"time":"'$
$ETCDCTL put /vitastor/osd/stats/4 '{"host":"host2","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/5 '{"host":"host3","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/6 '{"host":"host3","size":1073741824,"time":"'$TIME'"}'
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL osd-tree
$VITASTOR_CLI osd-tree
# check that it doesn't fail
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool --ec 2+1 -n 32
$VITASTOR_CLI create-pool testpool --ec 2+1 -n 32
format_green OK
+1 -1
View File
@@ -6,7 +6,7 @@
$ETCDCTL put /vitastor/config/inode/1/120 '{"name":"testimg","size":'$((1024*1024*1024))'}'
build/src/cmd/vitastor-cli create --etcd_address $ETCD_URL -s 1G testimg2
$VITASTOR_CLI create -s 1G testimg2
t=$($ETCDCTL get --print-value-only /vitastor/config/inode/1/121 | jq -r .name)
if [[ "$t" != "testimg2" ]]; then
+5 -5
View File
@@ -4,17 +4,17 @@
# pipe in - pipe out
dd if=/dev/urandom of=./testdata/testfile bs=1M count=128
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd oimg=testimg iodepth=4 bs=1M count=128 < ./testdata/testfile
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testimg iodepth=4 bs=1M count=128 > ./testdata/testfile1
$VITASTOR_CLI dd oimg=testimg iodepth=4 bs=1M count=128 < ./testdata/testfile
$VITASTOR_CLI dd iimg=testimg iodepth=4 bs=1M count=128 > ./testdata/testfile1
diff ./testdata/testfile ./testdata/testfile1
rm ./testdata/testfile1
# snapshot
dd if=/dev/urandom of=./testdata/over bs=1M count=4
dd if=./testdata/over of=./testdata/testfile bs=1M seek=17 conv=notrunc
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testimg@snap1
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iodepth=4 if=./testdata/over oimg=testimg bs=1M seek=17
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iodepth=4 iimg=testimg of=./testdata/testfile1
$VITASTOR_CLI snap-create testimg@snap1
$VITASTOR_CLI dd iodepth=4 if=./testdata/over oimg=testimg bs=1M seek=17
$VITASTOR_CLI dd iodepth=4 iimg=testimg of=./testdata/testfile1
diff ./testdata/testfile ./testdata/testfile1
format_green OK
+2 -3
View File
@@ -15,9 +15,8 @@ for i in $(seq 1 $OSD_COUNT); do
done
wait_up 120
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -rw=randwrite -loops=1000 \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=256M -cluster_log_level=10 -runtime=5 &
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 -rw=randwrite -loops=1000 \
-pool=1 -inode=2 -size=256M -cluster_log_level=10 -runtime=5 &
FIO_PID=$!
sleep 15
+6 -8
View File
@@ -5,23 +5,21 @@ GLOBAL_CONFIG=',"client_retry_enospc":false'
. `dirname $0`/run_3osds.sh
export LD_PRELOAD="build/src/client/libfio_vitastor.so"
# Should fail with ENOSPC
if fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 \
-rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=500M -cluster_log_level=10; then
if $VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 \
-rw=write -pool=1 -inode=1 -size=500M -cluster_log_level=10; then
format_error "Should get ENOSPC, but didn't"
fi
# Should fail with ENOSPC too (the idea is to try to overwrite first objects to check their rollback)
if fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=32 \
-rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=500M -cluster_log_level=10; then
if $VITASTOR_FIO -bs=1M -direct=1 -iodepth=32 \
-rw=write -pool=1 -inode=1 -size=500M -cluster_log_level=10; then
format_error "Should get ENOSPC, but didn't"
fi
# Should complete OK
if ! fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 \
-rw=randwrite -etcd=$ETCD_URL -pool=1 -inode=1 -size=100M -cluster_log_level=10 -number_ios=4096; then
if ! $VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 \
-rw=randwrite -pool=1 -inode=1 -size=100M -cluster_log_level=10 -number_ios=4096; then
format_error "Should do random writes over ENOSPC correctly, but got an error"
fi
+4 -6
View File
@@ -5,9 +5,8 @@ ETCD_COUNT=5
. `dirname $0`/run_3osds.sh
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=randwrite \
-etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=randwrite \
-pool=1 -inode=1 -size=128M -cluster_log_level=10
kill_etcds()
{
@@ -26,8 +25,7 @@ kill_etcds()
kill_etcds &
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=1 -rw=randwrite \
-etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10 -runtime=30
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=1 -rw=randwrite \
-pool=1 -inode=1 -size=128M -cluster_log_level=10 -runtime=30
format_green OK
+7 -7
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 &
MON_PID=$!
wait_etcd
@@ -17,13 +17,13 @@ $ETCDCTL put /vitastor/osd/stats/5 '{"host":"host3","size":1073741824,"time":"'$
$ETCDCTL put /vitastor/osd/stats/6 '{"host":"host3","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/7 '{"host":"host4","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/8 '{"host":"host4","size":1073741824,"time":"'$TIME'"}'
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool --ec 3+2 -n 32 --failure_domain rack --force
$VITASTOR_CLI create-pool testpool --ec 3+2 -n 32 --failure_domain rack --force
$ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1": {"failure_domain": "rack", "name": "testpool", "parity_chunks": 2, "pg_count": 32, "pg_minsize": 4, "pg_size": 5, "scheme": "ec"}}]'
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool testpool --ec 3+3 --failure_domain host
$VITASTOR_CLI modify-pool testpool --ec 3+3 --failure_domain host
$ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1": {"failure_domain": "host", "name": "testpool", "parity_chunks": 3, "pg_count": 32, "pg_minsize": 4, "pg_size": 6, "scheme": "ec"}}]'
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm-pool testpool
$VITASTOR_CLI rm-pool testpool
$ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{}]'
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool -s 2 -n 4 --failure_domain rack --force
$VITASTOR_CLI create-pool testpool -s 2 -n 4 --failure_domain rack --force
$ETCDCTL get --print-value-only /vitastor/config/pools | jq -s -e '. == [{"1":{"name":"testpool","scheme":"replicated","pg_size":2,"pg_minsize":1,"pg_count":4,"failure_domain":"rack"}}]'
sleep 2
@@ -32,9 +32,9 @@ $ETCDCTL get --prefix /vitastor/pg/config --print-value-only | \
jq -s -e '([ .[0].items["1"] | .[].osd_set | map_values(. | tonumber) | select((.[0] <= 4) != (.[1] <= 4)) ] | length) == 4'
# test pool with size 1
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool size1pool -s 1 -n 1 --force
$VITASTOR_CLI create-pool size1pool -s 1 -n 1 --force
wait_condition 10 "$ETCDCTL get --prefix /vitastor/pg/config --print-value-only | jq -s -e '.[0].items["'"'"2"'"'"]'"
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool size1pool -s 2 --force
$VITASTOR_CLI modify-pool size1pool -s 2 --force
format_green OK
+5 -7
View File
@@ -18,9 +18,8 @@ IMG_SIZE=960
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-mirror_file=./testdata/bin/mirror.bin -etcd=$ETCD_URL -image=testimg -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-mirror_file=./testdata/bin/mirror.bin -image=testimg -cluster_log_level=10
kill_osds()
{
@@ -51,12 +50,11 @@ kill_osds()
kill_osds &
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bsrange=4k-128k -blockalign=4k -direct=1 -iodepth=32 -fsync=256 -rw=randrw \
-serialize_overlap=1 -randrepeat=0 -refill_buffers=1 -mirror_file=./testdata/bin/mirror.bin -etcd=$ETCD_URL -image=testimg -loops=10 -runtime=120
$VITASTOR_FIO -bsrange=4k-128k -blockalign=4k -direct=1 -iodepth=32 -fsync=256 -rw=randrw \
-serialize_overlap=1 -randrepeat=0 -refill_buffers=1 -mirror_file=./testdata/bin/mirror.bin -image=testimg -loops=10 -runtime=120
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \
-O raw ./testdata/bin/read.bin
if ! diff -q ./testdata/bin/read.bin ./testdata/bin/mirror.bin; then
+2 -3
View File
@@ -6,9 +6,8 @@ PG_COUNT=32
IMG_SIZE=960
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=16 -fsync=16 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=${IMG_SIZE}M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=16 -fsync=16 -rw=write \
-pool=1 -inode=2 -size=${IMG_SIZE}M -cluster_log_level=10
try_reweight 1 0
+1 -1
View File
@@ -3,6 +3,6 @@
PG_COUNT=16
. `dirname $0`/run_3osds.sh
build/src/kv/vitastor-kv-stress --etcd_address $ETCD_URL --pool_id 1 --inode_id 1 --runtime 30
build/src/kv/vitastor-kv-stress --config_path $VITASTOR_CFG --pool_id 1 --inode_id 1 --runtime 30
format_green OK
+2 -2
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 &
MON_PID=$!
wait_etcd
@@ -29,7 +29,7 @@ $ETCDCTL put /vitastor/osd/stats/13 '{"host":"host7","size":1073741824,"time":"'
$ETCDCTL put /vitastor/osd/stats/14 '{"host":"host7","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/15 '{"host":"host8","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/16 '{"host":"host8","size":1073741824,"time":"'$TIME'"}'
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool --failure_domain host --level_placement rack=112233 --ec 4+2 -n 32
$VITASTOR_CLI create-pool testpool --failure_domain host --level_placement rack=112233 --ec 4+2 -n 32
sleep 2
$ETCDCTL get --prefix /vitastor/pg/config --print-value-only | \
jq -s -e '([ .[0].items["1"] | .[].osd_set | map_values(. | tonumber) | select(
+5 -7
View File
@@ -10,7 +10,7 @@ OSD_ARGS="$OSD_ARGS"
for i in $(seq 1 $OSD_COUNT); do
dd if=/dev/zero of=./testdata/bin/test_osd$i.bin bs=1024 count=1 seek=$((OSD_SIZE*1024-1))
build/src/osd/vitastor-osd --log_level 10 --osd_num $i --bind_address 127.0.0.1 --etcd_stats_interval 5 $OSD_ARGS \
--etcd_address $ETCD_URL $(build/src/disk_tool/vitastor-disk simple-offsets --format options ./testdata/bin/test_osd$i.bin $OFFSET_ARGS 2>/dev/null) >>./testdata/osd$i.log 2>&1 &
$(build/src/disk_tool/vitastor-disk simple-offsets --format options ./testdata/bin/test_osd$i.bin $OFFSET_ARGS 2>/dev/null) >>./testdata/osd$i.log 2>&1 &
eval OSD${i}_PID=$!
done
@@ -27,9 +27,8 @@ for i in {1..30}; do
fi
done
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=32M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-pool=1 -inode=2 -size=32M -cluster_log_level=10
$ETCDCTL put /vitastor/pg/config '{"items":{"1":{"1":{"osd_set":[1,0],"primary":0}}}}'
@@ -57,9 +56,8 @@ for i in {1..30}; do
done
# Sync so all moved objects are removed from OSD 1 (they aren't removed without a sync)
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=1 -number_ios=2 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=32M -cluster_log_level=10
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=1 -number_ios=2 -rw=write \
-pool=1 -inode=2 -size=32M -cluster_log_level=10
$ETCDCTL put /vitastor/pg/config '{"items":{"1":{"1":{"osd_set":[4,5],"primary":0}}}}'
+7 -7
View File
@@ -5,9 +5,9 @@ IMMEDIATE_COMMIT=1
PG_COUNT=16
. `dirname $0`/run_3osds.sh
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 10G fsmeta
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool --used-for-app fs:fsmeta testpool
build/src/nfs/vitastor-nfs start --fs fsmeta --etcd_address $ETCD_URL --portmap 0 --port 2050 --foreground 1 --trace 1 >>./testdata/nfs.log 2>&1 &
$VITASTOR_CLI create -s 10G fsmeta
$VITASTOR_CLI modify-pool --used-for-app fs:fsmeta testpool
build/src/nfs/vitastor-nfs --config_path $VITASTOR_CFG start --fs fsmeta --portmap 0 --port 2050 --foreground 1 --trace 1 >>./testdata/nfs.log 2>&1 &
NFS_PID=$!
mkdir -p testdata/nfs
@@ -175,22 +175,22 @@ format_green "rename over existing file ok"
# check listing and removal of a bad direntry
sudo umount ./testdata/nfs/
build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta set d11/settings.jsonLGNmGn '{"ino": 123}'
build/src/kv/vitastor-kv --config_path $VITASTOR_CFG fsmeta set d11/settings.jsonLGNmGn '{"ino": 123}'
sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp
ls -l ./testdata/nfs
ls -l ./testdata/nfs/settings.jsonLGNmGn
sudo rm ./testdata/nfs/settings.jsonLGNmGn
build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)'
build/src/kv/vitastor-kv --config_path $VITASTOR_CFG fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)'
ls -l ./testdata/nfs
# repeat with ino=0
sudo umount ./testdata/nfs/
build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta set d11/settings.jsonLGNmGn '{"ino": 0}'
build/src/kv/vitastor-kv --config_path $VITASTOR_CFG fsmeta set d11/settings.jsonLGNmGn '{"ino": 0}'
sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp
ls -l ./testdata/nfs
ls -l ./testdata/nfs/settings.jsonLGNmGn
sudo rm ./testdata/nfs/settings.jsonLGNmGn
build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)'
build/src/kv/vitastor-kv --config_path $VITASTOR_CFG fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)'
ls -l ./testdata/nfs
format_green OK
+7 -7
View File
@@ -5,9 +5,9 @@ IMMEDIATE_COMMIT=1
PG_COUNT=16
. `dirname $0`/run_3osds.sh
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 10G fsmeta
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool --used-for-app fs:fsmeta testpool
build/src/nfs/vitastor-nfs start --fs fsmeta --etcd_address $ETCD_URL --portmap 0 --port 2050 --foreground 1 --trace 1 >>./testdata/nfs.log 2>&1 &
$VITASTOR_CLI create -s 10G fsmeta
$VITASTOR_CLI modify-pool --used-for-app fs:fsmeta testpool
build/src/nfs/vitastor-nfs --config_path $VITASTOR_CFG start --fs fsmeta --portmap 0 --port 2050 --foreground 1 --trace 1 >>./testdata/nfs.log 2>&1 &
NFS_PID=$!
mkdir -p testdata/nfs
@@ -16,16 +16,16 @@ MNT=$(pwd)/testdata/nfs
trap "sudo umount -f $MNT"' || true; kill -9 $(jobs -p)' EXIT
# big file
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd if=/dev/urandom of=./testdata/ref_data.bin bs=1M count=32 seek=1024B
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd if=./testdata/ref_data.bin of=$MNT/testfile oflag=direct bs=1M iodepth=4 seek=1024B skip=1024B
$VITASTOR_CLI dd if=/dev/urandom of=./testdata/ref_data.bin bs=1M count=32 seek=1024B
$VITASTOR_CLI dd if=./testdata/ref_data.bin of=$MNT/testfile oflag=direct bs=1M iodepth=4 seek=1024B skip=1024B
cp $MNT/testfile ./testdata/nfs_data.bin
if ! diff -q ./testdata/ref_data.bin $MNT/testfile; then
format_error 'Data lost during parallel unaligned writes to VitastorFS'
fi
# small shared file
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd if=/dev/urandom of=./testdata/ref_small.bin bs=10 count=500 seek=15B
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd if=./testdata/ref_small.bin of=$MNT/smallfile oflag=direct bs=10 iodepth=4 seek=15B skip=15B
$VITASTOR_CLI dd if=/dev/urandom of=./testdata/ref_small.bin bs=10 count=500 seek=15B
$VITASTOR_CLI dd if=./testdata/ref_small.bin of=$MNT/smallfile oflag=direct bs=10 iodepth=4 seek=15B skip=15B
cp $MNT/smallfile ./testdata/nfs_small.bin
if ! diff -q ./testdata/ref_small.bin $MNT/smallfile; then
format_error 'Data lost during parallel unaligned writes to a small file in VitastorFS'
+1 -1
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 &
MON_PID=$!
wait_etcd
+1 -3
View File
@@ -39,9 +39,7 @@ try_change()
fi
}
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 \
-rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -runtime=10
$VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 -rw=write -pool=1 -inode=1 -size=128M -runtime=10
PG_SIZE=7
POOLCFG='"name":"testpool","failure_domain":"osd","scheme":"ec","parity_chunks":'$((PG_SIZE-PG_DATA_SIZE))
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash -ex
OSD_ARGS="--data_csum_type crc32c"
OFFSET_ARGS=$OSD_ARGS
GLOBAL_CONFIG=',"client_eio_retry_interval":0'
. `dirname $0`/run_3osds.sh
$VITASTOR_CLI create -s 32M testimg
$VITASTOR_FIO -bs=4k -blockalign=128k -direct=1 -iodepth=16 -end_fsync=1 -rw=write -image=testimg
$VITASTOR_CLI dd iimg=testimg of=/dev/null
if grep -q 'Checksum mismatch' ./testdata/osd*.log; then
format_error Checksum mismatches detected during test
fi
format_green OK
+1 -1
View File
@@ -10,7 +10,7 @@ IMG_SIZE=256
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
NBD_DEV=$(sudo build/src/client/vitastor-nbd map --nbd_timeout 180 --etcd_address $ETCD_URL --image testimg --logfile ./testdata/nbd.log &)
NBD_DEV=$(sudo build/src/client/vitastor-nbd map --nbd_timeout 180 --config_path $VITASTOR_CFG --image testimg --logfile ./testdata/nbd.log &)
trap "sudo build/src/client/vitastor-nbd unmap $NBD_DEV"' || true; kill -9 $(jobs -p)' EXIT
+7 -9
View File
@@ -5,16 +5,14 @@ PG_COUNT=${PG_COUNT:-32}
. `dirname $0`/run_3osds.sh
check_qemu
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=4 \
-rw=write -etcd=$ETCD_URL -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=4 \
-rw=write -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=32 \
-rw=randwrite -etcd=$ETCD_URL -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10 -number_ios=1024
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=32 \
-rw=randwrite -end_fsync=1 -pool=1 -inode=1 -size=256M -runtime=10 -number_ios=1024
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=1:size=$((256*1024*1024))" \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=1:size=$((256*1024*1024))" \
-O raw ./testdata/bin/before.bin
for i in $(seq 1 $OSD_COUNT); do
@@ -72,7 +70,7 @@ done
$ETCDCTL del --prefix /vitastor/osd/state/
for i in $(seq 1 $OSD_COUNT); do
build/src/osd/vitastor-osd --osd_num $i --bind_address 127.0.0.1 $NO_SAME $OSD_ARGS --etcd_address $ETCD_URL \
build/src/osd/vitastor-osd --osd_num $i --bind_address 127.0.0.1 $NO_SAME $OSD_ARGS \
--meta_format $meta_format \
--data_device ./testdata/bin/test_osd$i.bin \
--meta_offset 0 \
@@ -82,7 +80,7 @@ for i in $(seq 1 $OSD_COUNT); do
done
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=1:size=$((256*1024*1024))" \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=1:size=$((256*1024*1024))" \
-O raw ./testdata/bin/after.bin
if ! cmp ./testdata/bin/before.bin ./testdata/bin/after.bin; then
+3 -3
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 &
MON_PID=$!
wait_etcd
@@ -11,7 +11,7 @@ $ETCDCTL put /vitastor/osd/stats/1 '{"host":"host1","size":1073741824,"time":"'$
$ETCDCTL put /vitastor/osd/stats/2 '{"host":"host1","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/3 '{"host":"host2","size":1073741824,"time":"'$TIME'"}'
$ETCDCTL put /vitastor/osd/stats/4 '{"host":"host2","size":1073741824,"time":"'$TIME'"}'
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool -s 2 -n 16 --force
$VITASTOR_CLI create-pool testpool -s 2 -n 16 --force
sleep 2
@@ -25,7 +25,7 @@ $ETCDCTL get /vitastor/pg/config --print-value-only | \
$ETCDCTL get /vitastor/pg/config --print-value-only | \
jq -s -e '([ .[0].items["1"] | .[].osd_set | map_values(. | tonumber) | select(.[0] == 4 or .[1] == 4) ] | length) == 8'
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-osd --reweight 0.5 3
$VITASTOR_CLI modify-osd --reweight 0.5 3
sleep 2
+3 -4
View File
@@ -3,12 +3,11 @@
PG_COUNT=16
. `dirname $0`/run_3osds.sh
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -pool=1 -inode=1 -size=128M -cluster_log_level=10
$ETCDCTL get --prefix '/vitastor/pg/state'
build/src/cmd/vitastor-cli rm-data --etcd_address $ETCD_URL --pool 1 --inode 1
$VITASTOR_CLI rm-data --pool 1 --inode 1
format_green OK
+9 -11
View File
@@ -5,20 +5,19 @@ PG_COUNT=16
PG_MINSIZE=2
. `dirname $0`/run_3osds.sh
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 128M testimg
$VITASTOR_CLI create -s 128M testimg
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -etcd=$ETCD_URL -image=testimg -size=128M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -image=testimg -size=128M -cluster_log_level=10
kill -9 $OSD3_PID
$ETCDCTL del /vitastor/osd/state/3
if build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm testimg --log_level 10 ; then
if $VITASTOR_CLI rm testimg --log_level 10 ; then
format_error "Delete should not be successful with inactive OSDs"
fi
if ! ( build/src/cmd/vitastor-cli --etcd_address $ETCD_URL ls | grep testimg | grep DEL ) ; then
if ! ( $VITASTOR_CLI ls | grep testimg | grep DEL ) ; then
format_error "Image should be marked as partially deleted"
fi
@@ -27,17 +26,16 @@ sleep 5
# Now do the same but without del /vitastor/osd/state
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -etcd=$ETCD_URL -image=testimg -size=128M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 \
-end_fsync=1 -fsync=1 -rw=write -image=testimg -size=128M -cluster_log_level=10
kill -9 $OSD3_PID
if build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm testimg --log_level 10 ; then
if $VITASTOR_CLI rm testimg --log_level 10 ; then
format_error "Delete should not be successful with inactive OSDs"
fi
if ! ( build/src/cmd/vitastor-cli --etcd_address $ETCD_URL ls | grep testimg | grep DEL ) ; then
if ! ( $VITASTOR_CLI ls | grep testimg | grep DEL ) ; then
format_error "Image should be marked as partially deleted"
fi
+1 -1
View File
@@ -2,7 +2,7 @@
. `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" >>./testdata/mon.log 2>&1 &
node mon/mon-main.js $MON_PARAMS >>./testdata/mon.log 2>&1 &
MON_PID=$!
wait_etcd
+8 -9
View File
@@ -20,9 +20,8 @@ check_qemu
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"testimg","size":'$((IMG_SIZE*1024*1024))'}'
# Write
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 \
-mirror_file=./testdata/bin/mirror.bin -end_fsync=1 -rw=write -etcd=$ETCD_URL -image=testimg
$VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 \
-mirror_file=./testdata/bin/mirror.bin -end_fsync=1 -rw=write -image=testimg
sleep 1
@@ -55,23 +54,23 @@ wait_condition 300 "$ETCDCTL get --prefix /vitastor/pg/history/ --print-value-on
if [[ ($SCHEME = replicated && $PG_SIZE < 3) || ($SCHEME != replicated && $((PG_SIZE-PG_DATA_SIZE)) < 2) ]]; then
# Check that objects are marked as inconsistent if 2 replicas or EC/XOR 2+1
build/src/cmd/vitastor-cli describe --etcd_address $ETCD_URL --json &>./testdata/describe.log
build/src/cmd/vitastor-cli describe --etcd_address $ETCD_URL --json | jq -e '[ .[] | select(.inconsistent) ] | length == '$((IMG_SIZE * 8 * PG_SIZE / (SCHEME = replicated ? 1 : PG_DATA_SIZE)))
$VITASTOR_CLI describe --json &>./testdata/describe.log
$VITASTOR_CLI describe --json | jq -e '[ .[] | select(.inconsistent) ] | length == '$((IMG_SIZE * 8 * PG_SIZE / (SCHEME = replicated ? 1 : PG_DATA_SIZE)))
# Fix objects using vitastor-cli fix
build/src/cmd/vitastor-cli describe --etcd_address $ETCD_URL --json | \
$VITASTOR_CLI describe --json | \
jq -s '[ .[0][] | select(.inconsistent and .osd_num == '$ZERO_OSD') ]' | \
build/src/cmd/vitastor-cli fix --etcd_address $ETCD_URL --bad_osds $ZERO_OSD
$VITASTOR_CLI fix --bad_osds $ZERO_OSD
elif [[ ($SCHEME = replicated && $PG_SIZE > 2) || ($SCHEME != replicated && $((PG_SIZE-PG_DATA_SIZE)) > 1) ]]; then
# Check that everything heals
wait_finish_rebalance 300
build/src/cmd/vitastor-cli describe --etcd_address $ETCD_URL --json | jq -e '. | length == 0'
$VITASTOR_CLI describe --json | jq -e '. | length == 0'
fi
# Read everything back
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \
-O raw ./testdata/bin/read.bin
diff ./testdata/bin/read.bin ./testdata/bin/mirror.bin
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash -ex
# Test for Issue #112: Integer division bug causes crash with block_size < 32KB
# This test verifies that small block sizes (4KB, 8KB, 16KB) work correctly
# with 4KB bitmap_granularity, both for aligned and unaligned I/O
# Arrange: Set up test environment with small block sizes
export SCHEME=replicated
export OSD_COUNT=3
export PG_COUNT=1
export PG_SIZE=2
export OSD_SIZE=256
# Test with 16KB block_size and 4KB bitmap_granularity
# This should trigger the bug: 16384 / 4096 / 8 = 4 / 8 = 0 bytes
export OFFSET_ARGS="--data_block_size 16384 --bitmap_granularity 4096"
. `dirname $0`/run_3osds.sh
# Act: Run I/O tests that exercise the bitmap code paths
echo "Test 1: 128KB aligned I/O (may work even with bug)"
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so \
-bs=128k -direct=1 -iodepth=4 -rw=randwrite \
-etcd=$ETCD_URL -pool=1 -inode=1 -size=64M -runtime=5
echo "Test 2: 4KB random I/O (will crash with bug)"
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so \
-bs=4k -direct=1 -iodepth=16 -rw=randwrite \
-etcd=$ETCD_URL -pool=1 -inode=1 -size=64M -runtime=5
echo "Test 3: Mixed read/write with 4KB I/O"
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so \
-bs=4k -direct=1 -iodepth=16 -rw=randrw -rwmixread=50 \
-etcd=$ETCD_URL -pool=1 -inode=1 -size=64M -runtime=5
echo "Test 4: Sequential 4KB writes"
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so \
-bs=4k -direct=1 -iodepth=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=1 -size=64M
# Assert: If we reach here without crash, test passed
format_green "OK: 16KB block_size with 4KB bitmap_granularity works correctly"
+12 -16
View File
@@ -7,43 +7,39 @@ check_qemu
$ETCDCTL put /vitastor/config/inode/1/2 '{"name":"testimg","size":'$((32*1024*1024))'}'
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=32M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-pool=1 -inode=2 -size=32M -cluster_log_level=10
$ETCDCTL put /vitastor/config/inode/1/2 '{"name":"testimg@0","size":'$((32*1024*1024))'}'
$ETCDCTL put /vitastor/config/inode/1/3 '{"parent_id":2,"name":"testimg","size":'$((32*1024*1024))'}'
# Preload build/src/client/libfio_vitastor.so so libasan detects all symbols
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=32 -buffer_pattern=0xdeadface \
-rw=randwrite -etcd=$ETCD_URL -image=testimg -number_ios=1024
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=32 -buffer_pattern=0xdeadface \
-rw=randwrite -image=testimg -number_ios=1024
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -rw=read -etcd=$ETCD_URL -pool=1 -inode=3 -size=32M
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -rw=read -pool=1 -inode=3 -size=32M
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=2:size=$((32*1024*1024)):skip-parents=1" \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=2:size=$((32*1024*1024)):skip-parents=1" \
-O qcow2 ./testdata/layer0.qcow2
qemu-img create -f qcow2 ./testdata/empty.qcow2 32M
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=3:size=$((32*1024*1024)):skip-parents=1" \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=3:size=$((32*1024*1024)):skip-parents=1" \
-O qcow2 -o 'cluster_size=4k,backing_fmt=qcow2' -B empty.qcow2 ./testdata/layer1.qcow2
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=3:size=$((32*1024*1024))" \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=3:size=$((32*1024*1024))" \
-O raw ./testdata/bin/merged.bin
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg@0" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg@0" \
-O raw ./testdata/bin/layer0.bin
$ETCDCTL put /vitastor/config/inode/1/3 '{"name":"testimg","size":'$((32*1024*1024))'}'
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \
-O raw ./testdata/bin/layer1.bin
node tests/merge.js ./testdata/bin/layer0.bin ./testdata/bin/layer1.bin ./testdata/bin/check.bin
@@ -54,10 +50,10 @@ cmp ./testdata/bin/merged.bin ./testdata/bin/check.bin
$ETCDCTL put /vitastor/config/inode/1/3 '{"parent_id":2,"name":"testimg","size":'$((32*1024*1024))'}'
build/src/cmd/vitastor-cli rm --etcd_address $ETCD_URL testimg@0
$VITASTOR_CLI rm testimg@0
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testimg" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testimg" \
-O raw ./testdata/bin/merged-by-tool.bin
cmp ./testdata/bin/merged.bin ./testdata/bin/merged-by-tool.bin
+11 -13
View File
@@ -5,43 +5,41 @@ check_qemu
# Test multiple snapshots
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 32M testchain
$VITASTOR_CLI create -s 32M testchain
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-image=testchain -mirror_file=./testdata/bin/mirror.bin
for i in {1..10}; do
# Create a snapshot
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@$i
$VITASTOR_CLI snap-create testchain@$i
# Check that the new snapshot is see-through
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \
-O raw ./testdata/bin/check.bin
cmp ./testdata/bin/check.bin ./testdata/bin/mirror.bin
# Write something to it
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=32 -rw=randwrite \
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=32 -rw=randwrite \
-randrepeat=$((i <= 2)) -buffer_pattern=0x$((10+i))$((10+i))$((10+i))$((10+i)) \
-etcd=$ETCD_URL -image=testchain -number_ios=1024 -mirror_file=./testdata/bin/mirror.bin
-image=testchain -number_ios=1024 -mirror_file=./testdata/bin/mirror.bin
# Check the new content
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \
-O raw ./testdata/bin/layer1.bin
cmp ./testdata/bin/layer1.bin ./testdata/bin/mirror.bin
done
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm testchain@1 testchain@9
$VITASTOR_CLI rm testchain@1 testchain@9
# Check the final image
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \
-O raw ./testdata/bin/layer1.bin
cmp ./testdata/bin/layer1.bin ./testdata/bin/mirror.bin
# Check the last remaining snapshot
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain@10" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain@10" \
-O raw ./testdata/bin/layer0.bin
cmp ./testdata/bin/layer0.bin ./testdata/bin/check.bin
+9 -11
View File
@@ -5,32 +5,30 @@ check_qemu
# Test merge to child (without "inverse rename" optimisation)
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 128M testchain
$VITASTOR_CLI create -s 128M testchain
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-image=testchain -mirror_file=./testdata/bin/mirror.bin
# Create a snapshot
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@0
$VITASTOR_CLI snap-create testchain@0
# Write something to it
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 -rw=randwrite \
-randrepeat=0 -etcd=$ETCD_URL -image=testchain -number_ios=8 -mirror_file=./testdata/bin/mirror.bin
$VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 -rw=randwrite \
-randrepeat=0 -image=testchain -number_ios=8 -mirror_file=./testdata/bin/mirror.bin
# Check the new content
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \
-O raw ./testdata/bin/layer1.bin
cmp ./testdata/bin/layer1.bin ./testdata/bin/mirror.bin
# Merge
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL rm testchain@0
$VITASTOR_CLI rm testchain@0
# Check the final image
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \
-O raw ./testdata/bin/layer1.bin
cmp ./testdata/bin/layer1.bin ./testdata/bin/mirror.bin
+14 -17
View File
@@ -5,46 +5,43 @@ check_qemu
# snapshot in another pool
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool2 -s 3 -n 4 --failure_domain osd
$VITASTOR_CLI create-pool testpool2 -s 3 -n 4 --failure_domain osd
wait_pool_up 30 2 3 4
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 128M testchain -p testpool
$VITASTOR_CLI create -s 128M testchain -p testpool
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 -fsync=1 -rw=write \
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
$VITASTOR_FIO -bs=1M -direct=1 -iodepth=4 -fsync=1 -rw=write \
-image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@snap1 -p testpool2
$VITASTOR_CLI snap-create testchain@snap1 -p testpool2
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
-image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
# Read from the first snapshot
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=128k iodepth=4 --log_level 10
$VITASTOR_CLI dd iimg=testchain of=./testdata/bin/res.bin bs=128k iodepth=4 --log_level 10
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
# Create a second snapshot - there was a bug where snapshotted reads from another pool
# were working only when the image and the snapshot were modified in the same revision
# (i.e. there was only one snapshot)
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@snap2 -p testpool2
$VITASTOR_CLI snap-create testchain@snap2 -p testpool2
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
-image=testchain -mirror_file=./testdata/bin/mirror.bin -randrepeat=0
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=128k iodepth=4 --log_level 10
$VITASTOR_CLI dd iimg=testchain of=./testdata/bin/res.bin bs=128k iodepth=4 --log_level 10
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=32k iodepth=4 conv=nosparse
$VITASTOR_CLI dd iimg=testchain of=./testdata/bin/res.bin bs=32k iodepth=4 conv=nosparse
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \
-O raw ./testdata/bin/res.bin
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
+9 -11
View File
@@ -4,34 +4,32 @@ SCHEME=${SCHEME:-ec}
. `dirname $0`/run_3osds.sh
check_qemu
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 128M testchain
$VITASTOR_CLI create -s 128M testchain
dd if=/dev/zero of=./testdata/bin/mirror.bin bs=4k seek=$(((128*1024-4)/4)) count=1
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=32k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite \
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd -number_ios=1024
$VITASTOR_FIO -bs=32k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite \
-image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd -number_ios=1024
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@snap1
$VITASTOR_CLI snap-create testchain@snap1
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
-image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd
# Now read from the snapshot
dd if=/dev/zero of=./testdata/bin/res.bin bs=4k seek=$(((128*1024-4)/4)) count=1
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=$((PG_DATA_SIZE*128))k iodepth=4 --log_level 10
$VITASTOR_CLI dd iimg=testchain of=./testdata/bin/res.bin bs=$((PG_DATA_SIZE*128))k iodepth=4 --log_level 10
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=$((PG_DATA_SIZE*128))k iodepth=4 conv=nosparse
$VITASTOR_CLI dd iimg=testchain of=./testdata/bin/res.bin bs=$((PG_DATA_SIZE*128))k iodepth=4 conv=nosparse
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
qemu-img convert -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
-f raw "vitastor:config_path=$VITASTOR_CFG:image=testchain" \
-O raw ./testdata/bin/res.bin
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
+3 -4
View File
@@ -15,14 +15,13 @@ sleep 2
# Write
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=1 \
-rw=randwrite -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -runtime=10 -number_ios=100
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=1 \
-rw=randwrite -pool=1 -inode=1 -size=128M -runtime=10 -number_ios=100
# Kill OSD 2, start OSD 1
kill $OSD2_PID
build/src/osd/vitastor-osd --osd_num 1 --bind_address 127.0.0.1 $NO_SAME $OSD_ARGS --etcd_address $ETCD_URL \
build/src/osd/vitastor-osd --osd_num 1 --bind_address 127.0.0.1 $NO_SAME $OSD_ARGS \
$(build/src/disk_tool/vitastor-disk simple-offsets --format options --device ./testdata/bin/test_osd2.bin $OFFSET_ARGS 2>/dev/null) >>./testdata/osd2.log 2>&1 &
sleep 2
+3 -3
View File
@@ -3,7 +3,7 @@
export KEEP_DATA=1
. `dirname $0`/common.sh
node mon/mon-main.js $MON_PARAMS --etcd_address $ETCD_URL --etcd_prefix "/vitastor" --verbose 1 >>./testdata/mon.log 2>&1 &
node mon/mon-main.js $MON_PARAMS --verbose 1 >>./testdata/mon.log 2>&1 &
MON_PID=$!
wait_etcd
@@ -15,7 +15,7 @@ OSD_COUNT=3
OSD_ARGS="$OSD_ARGS"
OFFSET_ARGS="$OFFSET_ARGS"
for i in $(seq 1 $OSD_COUNT); do
build/src/osd/vitastor-osd --osd_num $i --bind_address 127.0.0.1 $OSD_ARGS --etcd_address $ETCD_URL \
build/src/osd/vitastor-osd --osd_num $i --bind_address 127.0.0.1 $OSD_ARGS \
$(build/src/disk_tool/vitastor-disk simple-offsets --format options ./testdata/bin/test_osd$i.bin $OFFSET_ARGS 2>/dev/null) >>./testdata/osd$i.log 2>&1 &
eval OSD${i}_PID=$!
done
@@ -32,7 +32,7 @@ if ! cmp build/src/client/block-vitastor.so /usr/lib/x86_64-linux-gnu/qemu/block
fi
qemu-system-x86_64 -enable-kvm -m 1024 \
-drive 'file=vitastor:etcd_host=127.0.0.1\:'$ETCD_PORT'/v3:image=debian9',format=raw,if=none,id=drive-virtio-disk0,cache=none \
-drive 'file=vitastor:config_path=$VITASTOR_CFG:image=debian9',format=raw,if=none,id=drive-virtio-disk0,cache=none \
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1,write-cache=off,physical_block_size=4096,logical_block_size=512 \
-vnc 0.0.0.0:0
+2 -2
View File
@@ -9,13 +9,13 @@ $ETCDCTL put /vitastor/config/inode/1/1 '{"name":"debian9","size":'$((2048*1024*
qemu-img convert -S 4096 -p \
-f raw ~/debian9-kvm.raw \
-O raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=debian9"
-O raw "vitastor:config_path=$VITASTOR_CFG:image=debian9"
$ETCDCTL put /vitastor/config/inode/1/1 '{"name":"debian9@0","size":'$((2048*1024*1024))'}'
$ETCDCTL put /vitastor/config/inode/1/2 '{"parent_id":1,"name":"debian9","size":'$((2048*1024*1024))'}'
qemu-system-x86_64 -enable-kvm -m 1024 \
-drive 'file=vitastor:etcd_host=127.0.0.1\:'$ETCD_PORT'/v3:image=debian9',format=raw,if=none,id=drive-virtio-disk0,cache=none \
-drive 'file=vitastor:config_path=$VITASTOR_CFG:image=debian9',format=raw,if=none,id=drive-virtio-disk0,cache=none \
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1,write-cache=off,physical_block_size=4096,logical_block_size=512 \
-vnc 0.0.0.0:0
+12 -16
View File
@@ -10,43 +10,39 @@ check_qemu
echo Small sequential writes
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -numjobs=1 -iodepth=16 \
-rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -runtime=10
$VITASTOR_FIO -bs=4k -direct=1 -numjobs=1 -iodepth=16 \
-rw=write -pool=1 -inode=1 -size=128M -runtime=10
# Random writes without immediate_commit were stalling OSDs
echo 68k random writes
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=68k -direct=1 -numjobs=16 -iodepth=4 \
-rw=randwrite -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -runtime=10
$VITASTOR_FIO -bs=68k -direct=1 -numjobs=16 -iodepth=4 \
-rw=randwrite -pool=1 -inode=1 -size=128M -runtime=10
# A lot of parallel syncs was crashing the primary OSD at some point
echo T64Q1 writes with fsync
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -numjobs=64 -iodepth=1 -fsync=1 \
-rw=randwrite -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -number_ios=100
$VITASTOR_FIO -bs=4k -direct=1 -numjobs=64 -iodepth=1 -fsync=1 \
-rw=randwrite -pool=1 -inode=1 -size=128M -number_ios=100
echo Linear write
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-pool=1 -inode=1 -size=128M -cluster_log_level=10
echo T1Q1 writes with fsync=32
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=1 -fsync=32 -buffer_pattern=0xdeadface \
-rw=randwrite -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -number_ios=1024
$VITASTOR_FIO -bs=4k -direct=1 -iodepth=1 -fsync=32 -buffer_pattern=0xdeadface \
-rw=randwrite -pool=1 -inode=1 -size=128M -number_ios=1024
qemu-img convert -S 4096 -p \
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=1:size=$((128*1024*1024))" \
-f raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=1:size=$((128*1024*1024))" \
-O raw ./testdata/bin/read.bin
qemu-img convert -S 4096 -p \
-f raw ./testdata/bin/read.bin \
-O raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:pool=1:inode=1:size=$((128*1024*1024))"
-O raw "vitastor:config_path=$VITASTOR_CFG:pool=1:inode=1:size=$((128*1024*1024))"
format_green OK
+2 -3
View File
@@ -2,7 +2,7 @@
# Test the `no_same_sector_overwrites` mode
OSD_ARGS="--journal_no_same_sector_overwrites true --journal_sector_buffer_count 1024 --disable_data_fsync 1 --immediate_commit all $OSD_ARGS"
GLOBAL_CONF='{"immediate_commit":"all"}'
GLOBAL_CONFIG='{"immediate_commit":"all"}'
. `dirname $0`/run_3osds.sh
@@ -11,7 +11,6 @@ GLOBAL_CONF='{"immediate_commit":"all"}'
# Test basic write
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -rw=write -etcd=$ETCD_URL -pool=1 -inode=1 -size=128M -cluster_log_level=10
$VITASTOR_FIO -bs=4M -direct=1 -iodepth=1 -rw=write -pool=1 -inode=1 -size=128M -cluster_log_level=10
format_green OK