Compare commits

...

43 Commits

Author SHA1 Message Date
bbd168da43 Add qemu_file_mirror_path option to the config to allow to trick Veeam
All checks were successful
Test / test_write (push) Successful in 30s
Test / test_switch_primary (push) Successful in 34s
Test / test_write_xor (push) Successful in 34s
Test / test_write_no_same (push) Successful in 8s
Test / test_write_iothreads (push) Successful in 38s
Test / test_heal_pg_size_2 (push) Successful in 2m16s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_heal_local_read (push) Successful in 2m22s
Test / test_heal_antietcd (push) Successful in 2m18s
Test / test_heal_csum_32k_dmj (push) Successful in 2m20s
Test / test_heal_csum_32k (push) Successful in 2m19s
Test / test_heal_csum_32k_dj (push) Successful in 2m21s
Test / test_resize (push) Successful in 13s
Test / test_heal_csum_4k_dmj (push) Successful in 2m21s
Test / test_resize_auto (push) Successful in 8s
Test / test_osd_tags (push) Successful in 8s
Test / test_snapshot_pool2 (push) Successful in 14s
Test / test_enospc (push) Successful in 9s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 10s
Test / test_enospc_imm_xor (push) Successful in 15s
Test / test_scrub (push) Successful in 13s
Test / test_scrub_zero_osd_2 (push) Successful in 14s
Test / test_scrub_xor (push) Successful in 15s
Test / test_scrub_pg_size_3 (push) Successful in 15s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 15s
Test / test_nfs (push) Successful in 12s
Test / test_scrub_ec (push) Successful in 15s
Test / test_heal_csum_4k_dj (push) Successful in 2m18s
Test / test_heal_csum_4k (push) Successful in 2m19s
When qemu_file_mirror_path is set to "/dir/" in /etc/vitastor/vitastor.conf, QEMU driver
returns "/dir/image_name" as the filename in qemu-img info and in QAPI to trick software
like Veeam which expects file-based access. After that, vitastor-nfs can be mounted to that
directory to make backups work :-)
2025-08-01 01:57:03 +03:00
b529f77264 Release 2.2.3
- Support Ubuntu 24.04 Noble
- Fix clients hanging on online PG count change with in-flight operations
- Fix volume_size_info in PVE VitastorPlugin
- Implement bdrv_refresh_filename for the QEMU driver
- Fix RDMA-CM broken in 2.2.0
- Fix possible "invalid %N$ use detected" OSD crashes
- Fix vitastor-nfs build without RDMA
- Fix docker build by adding the forgotten apt/preferences
- Fix libfio_blockstore.so
- Fix "trigger event loop automatically" API version check in the QEMU driver
- Add Content-Type header for prometheus metrics
- Add a patch for libvirt 11.5
2025-07-30 10:50:02 +03:00
bf9519dcdc docker -i 2025-07-30 10:50:02 +03:00
4ba687738b Use archive for debian buster 2025-07-30 10:50:02 +03:00
8427f6fe46 Use the new build method for RPM packages too 2025-07-30 02:38:52 +03:00
efa6bc3e70 Fix docker pull commands in docs 2025-07-30 02:38:52 +03:00
da33e9b12d Add noble repository 2025-07-30 02:38:52 +03:00
Vitaliy Filippov
265127c1a7 Fix vitastor-nfs build without RDMA 2025-07-30 02:38:52 +03:00
2b30acfc1d Do not use podman and do not use build command to build packages (we are not building a docker image) 2025-07-30 02:38:52 +03:00
7fbc38ef29 Add a build file for ubuntu 24.04 2025-07-29 02:51:59 +03:00
e5070e991a Add forgotten apt/preferences 2025-07-29 01:18:55 +03:00
625552c441 Fix RDMA-CM broken in 2.2.0
All checks were successful
Test / test_write (push) Successful in 34s
Test / test_write_no_same (push) Successful in 9s
Test / test_write_xor (push) Successful in 34s
Test / test_write_iothreads (push) Successful in 36s
Test / test_heal_pg_size_2 (push) Successful in 2m17s
Test / test_heal_local_read (push) Successful in 2m19s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_heal_antietcd (push) Successful in 2m17s
Test / test_heal_csum_32k_dmj (push) Successful in 2m20s
Test / test_heal_csum_32k_dj (push) Successful in 2m22s
Test / test_heal_csum_32k (push) Successful in 2m24s
Test / test_heal_csum_4k_dmj (push) Successful in 2m19s
Test / test_resize_auto (push) Successful in 7s
Test / test_resize (push) Successful in 12s
Test / test_osd_tags (push) Successful in 7s
Test / test_snapshot_pool2 (push) Successful in 14s
Test / test_enospc (push) Successful in 10s
Test / test_enospc_xor (push) Successful in 12s
Test / test_enospc_imm (push) Successful in 10s
Test / test_enospc_imm_xor (push) Successful in 14s
Test / test_scrub (push) Successful in 15s
Test / test_scrub_zero_osd_2 (push) Successful in 15s
Test / test_scrub_xor (push) Successful in 14s
Test / test_scrub_pg_size_3 (push) Successful in 13s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 15s
Test / test_scrub_ec (push) Successful in 14s
Test / test_nfs (push) Successful in 11s
Test / test_heal_csum_4k_dj (push) Successful in 2m18s
Test / test_heal_csum_4k (push) Successful in 2m18s
Test / test_rebalance_verify (push) Successful in 2m4s
2025-07-29 00:14:05 +03:00
78c95c94f6 Use uint8_t* for BS buffers in OSD
All checks were successful
Test / test_switch_primary (push) Successful in 32s
Test / test_write (push) Successful in 30s
Test / test_write_xor (push) Successful in 34s
Test / test_write_no_same (push) Successful in 10s
Test / test_write_iothreads (push) Successful in 35s
Test / test_heal_pg_size_2 (push) Successful in 2m18s
Test / test_heal_local_read (push) Successful in 2m18s
Test / test_heal_ec (push) Successful in 2m17s
Test / test_heal_antietcd (push) Successful in 2m21s
Test / test_heal_csum_32k_dmj (push) Successful in 2m20s
Test / test_heal_csum_32k_dj (push) Successful in 2m32s
Test / test_heal_csum_32k (push) Successful in 2m30s
Test / test_heal_csum_4k_dmj (push) Successful in 2m26s
Test / test_resize (push) Successful in 13s
Test / test_resize_auto (push) Successful in 9s
Test / test_osd_tags (push) Successful in 8s
Test / test_snapshot_pool2 (push) Successful in 13s
Test / test_enospc (push) Successful in 12s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 10s
Test / test_enospc_imm_xor (push) Successful in 14s
Test / test_scrub (push) Successful in 12s
Test / test_scrub_zero_osd_2 (push) Successful in 14s
Test / test_scrub_xor (push) Successful in 14s
Test / test_scrub_pg_size_3 (push) Successful in 15s
Test / test_scrub_ec (push) Successful in 15s
Test / test_nfs (push) Successful in 10s
Test / test_heal_csum_4k_dj (push) Successful in 2m19s
Test / test_heal_csum_4k (push) Successful in 2m20s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 16s
2025-07-26 14:13:12 +03:00
488e20bf55 Remove BS_OP_SYNC_STAB_ALL from OSD
Some checks reported warnings
Test / test_rebalance_verify_ec (push) Has been cancelled
Test / test_rebalance_verify_ec_imm (push) Has been cancelled
Test / test_dd (push) Has been cancelled
Test / test_root_node (push) Has been cancelled
Test / test_switch_primary (push) Has been cancelled
Test / test_write (push) Has been cancelled
Test / test_write_xor (push) Has been cancelled
Test / test_write_iothreads (push) Has been cancelled
Test / test_write_no_same (push) Has been cancelled
Test / test_heal_pg_size_2 (push) Has been cancelled
Test / test_heal_local_read (push) Has been cancelled
Test / test_heal_ec (push) Has been cancelled
Test / test_heal_antietcd (push) Has been cancelled
Test / test_heal_csum_32k_dmj (push) Has been cancelled
Test / test_heal_csum_32k_dj (push) Has been cancelled
Test / buildenv (push) Has been cancelled
Test / test_heal_csum_32k (push) Has been cancelled
Test / test_heal_csum_4k_dmj (push) Has been cancelled
Test / test_heal_csum_4k_dj (push) Has been cancelled
Test / test_heal_csum_4k (push) Has been cancelled
Test / test_resize (push) Has been cancelled
Test / test_resize_auto (push) Has been cancelled
Test / test_snapshot_pool2 (push) Has been cancelled
Test / test_osd_tags (push) Has been cancelled
Test / test_enospc (push) Has been cancelled
Test / test_enospc_xor (push) Has been cancelled
Test / test_enospc_imm (push) Has been cancelled
Test / test_enospc_imm_xor (push) Has been cancelled
Test / test_scrub (push) Has been cancelled
Test / test_scrub_zero_osd_2 (push) Has been cancelled
2025-07-26 14:13:12 +03:00
25d6281b3e Remove BS_OP_SYNC_STAB_ALL 2025-07-26 14:13:11 +03:00
1676e50b3a Fix debug trace for fio_bs 2025-07-26 14:12:48 +03:00
8049e3c14a Use OP_WRITE_STABLE in bs_fio 2025-07-26 14:12:48 +03:00
93a30efd86 Do not use numbered printf args
Some checks reported warnings
Test / test_enospc_imm_xor (push) Blocked by required conditions
Test / test_scrub (push) Blocked by required conditions
Test / test_scrub_zero_osd_2 (push) Blocked by required conditions
Test / test_scrub_xor (push) Blocked by required conditions
Test / test_scrub_pg_size_3 (push) Blocked by required conditions
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Blocked by required conditions
Test / test_scrub_ec (push) Blocked by required conditions
Test / test_nfs (push) Blocked by required conditions
Test / buildenv (push) Successful in 9s
Test / build (push) Successful in 3m50s
Test / npm_lint (push) Successful in 10s
Test / test_cas (push) Successful in 7s
Test / make_test (push) Successful in 33s
Test / test_change_pg_count (push) Successful in 30s
Test / test_change_pg_count_ec (push) Successful in 31s
Test / test_change_pg_size (push) Successful in 8s
Test / test_create_nomaxid (push) Successful in 7s
Test / test_add_osd (push) Successful in 1m14s
Test / test_etcd_fail_antietcd (push) Successful in 38s
Test / test_etcd_fail (push) Successful in 41s
Test / test_change_pg_count_online (push) Successful in 1m8s
Test / test_interrupted_rebalance (push) Successful in 47s
Test / test_create_halfhost (push) Successful in 6s
Test / test_interrupted_rebalance_imm (push) Successful in 45s
Test / test_interrupted_rebalance_ec (push) Successful in 47s
Test / test_failure_domain (push) Successful in 9s
Test / test_minsize_1 (push) Has been cancelled
Test / test_snapshot_ec (push) Has been cancelled
Test / test_interrupted_rebalance_ec_imm (push) Has been cancelled
Test / test_snapshot (push) Has been cancelled
2025-07-26 14:11:15 +03:00
83fb121f36 Fix "Trigger event loop automatically" API version check
All checks were successful
Test / test_switch_primary (push) Successful in 31s
Test / test_write (push) Successful in 32s
Test / test_write_xor (push) Successful in 33s
Test / test_write_no_same (push) Successful in 8s
Test / test_write_iothreads (push) Successful in 37s
Test / test_heal_pg_size_2 (push) Successful in 2m16s
Test / test_heal_local_read (push) Successful in 2m19s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_heal_antietcd (push) Successful in 2m16s
Test / test_heal_csum_32k_dmj (push) Successful in 2m20s
Test / test_heal_csum_32k_dj (push) Successful in 2m19s
Test / test_heal_csum_32k (push) Successful in 2m25s
Test / test_heal_csum_4k_dmj (push) Successful in 2m17s
Test / test_resize (push) Successful in 14s
Test / test_resize_auto (push) Successful in 8s
Test / test_osd_tags (push) Successful in 9s
Test / test_snapshot_pool2 (push) Successful in 16s
Test / test_enospc (push) Successful in 11s
Test / test_enospc_xor (push) Successful in 12s
Test / test_enospc_imm (push) Successful in 10s
Test / test_enospc_imm_xor (push) Successful in 14s
Test / test_scrub (push) Successful in 13s
Test / test_scrub_zero_osd_2 (push) Successful in 14s
Test / test_scrub_xor (push) Successful in 13s
Test / test_scrub_pg_size_3 (push) Successful in 14s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 16s
Test / test_scrub_ec (push) Successful in 17s
Test / test_nfs (push) Successful in 12s
Test / test_heal_csum_4k (push) Successful in 2m19s
Test / test_heal_csum_4k_dj (push) Successful in 2m30s
2025-07-20 17:14:22 +03:00
afc97b757b Implement bdrv_refresh_filename
Some checks failed
Test / test_rebalance_verify_ec_imm (push) Successful in 1m36s
Test / test_write (push) Successful in 34s
Test / test_write_no_same (push) Successful in 7s
Test / test_write_xor (push) Successful in 35s
Test / test_write_iothreads (push) Successful in 35s
Test / test_heal_local_read (push) Failing after 2m16s
Test / test_heal_pg_size_2 (push) Successful in 2m20s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_heal_antietcd (push) Successful in 2m18s
Test / test_heal_csum_32k_dmj (push) Successful in 2m21s
Test / test_heal_csum_32k_dj (push) Successful in 2m19s
Test / test_heal_csum_32k (push) Successful in 2m29s
Test / test_heal_csum_4k_dmj (push) Successful in 2m35s
Test / test_resize (push) Successful in 13s
Test / test_resize_auto (push) Successful in 8s
Test / test_osd_tags (push) Successful in 7s
Test / test_snapshot_pool2 (push) Successful in 15s
Test / test_enospc (push) Successful in 10s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 10s
Test / test_scrub (push) Successful in 19s
Test / test_enospc_imm_xor (push) Successful in 24s
Test / test_scrub_zero_osd_2 (push) Successful in 23s
Test / test_scrub_xor (push) Successful in 21s
Test / test_scrub_pg_size_3 (push) Successful in 14s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 16s
Test / test_nfs (push) Successful in 10s
Test / test_scrub_ec (push) Successful in 15s
Test / test_heal_csum_4k (push) Successful in 2m24s
Test / test_heal_csum_4k_dj (push) Successful in 2m41s
2025-07-20 16:30:01 +03:00
68905cbf41 Fix online PG count change, add a test for it
All checks were successful
Test / test_switch_primary (push) Successful in 32s
Test / test_write (push) Successful in 32s
Test / test_write_no_same (push) Successful in 8s
Test / test_write_xor (push) Successful in 34s
Test / test_write_iothreads (push) Successful in 37s
Test / test_heal_pg_size_2 (push) Successful in 2m15s
Test / test_heal_local_read (push) Successful in 2m19s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_heal_antietcd (push) Successful in 2m16s
Test / test_heal_csum_32k_dmj (push) Successful in 2m23s
Test / test_heal_csum_32k_dj (push) Successful in 2m27s
Test / test_heal_csum_32k (push) Successful in 2m26s
Test / test_heal_csum_4k_dmj (push) Successful in 2m20s
Test / test_resize_auto (push) Successful in 8s
Test / test_resize (push) Successful in 12s
Test / test_osd_tags (push) Successful in 7s
Test / test_snapshot_pool2 (push) Successful in 13s
Test / test_enospc (push) Successful in 11s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 11s
Test / test_enospc_imm_xor (push) Successful in 15s
Test / test_scrub (push) Successful in 12s
Test / test_scrub_zero_osd_2 (push) Successful in 15s
Test / test_scrub_xor (push) Successful in 12s
Test / test_scrub_pg_size_3 (push) Successful in 14s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 18s
Test / test_scrub_ec (push) Successful in 14s
Test / test_nfs (push) Successful in 13s
Test / test_heal_csum_4k_dj (push) Successful in 2m21s
Test / test_heal_csum_4k (push) Successful in 2m21s
2025-07-15 02:33:28 +03:00
3fff667f13 Add Content-Type header for prometheus metrics
Some checks failed
Test / test_rebalance_verify_ec_imm (push) Successful in 1m40s
Test / test_write_no_same (push) Successful in 7s
Test / test_write (push) Successful in 33s
Test / test_write_xor (push) Successful in 32s
Test / test_write_iothreads (push) Successful in 35s
Test / test_heal_pg_size_2 (push) Successful in 2m20s
Test / test_heal_local_read (push) Successful in 2m26s
Test / test_heal_ec (push) Successful in 2m27s
Test / test_heal_antietcd (push) Successful in 2m41s
Test / test_heal_csum_32k_dmj (push) Successful in 2m25s
Test / test_heal_csum_32k_dj (push) Successful in 2m24s
Test / test_heal_csum_32k (push) Successful in 2m22s
Test / test_resize (push) Successful in 12s
Test / test_resize_auto (push) Failing after 5s
Test / test_heal_csum_4k_dmj (push) Successful in 2m26s
Test / test_osd_tags (push) Successful in 8s
Test / test_snapshot_pool2 (push) Successful in 15s
Test / test_enospc (push) Successful in 11s
Test / test_enospc_xor (push) Successful in 12s
Test / test_enospc_imm (push) Successful in 10s
Test / test_enospc_imm_xor (push) Successful in 12s
Test / test_scrub (push) Successful in 13s
Test / test_scrub_zero_osd_2 (push) Successful in 16s
Test / test_scrub_xor (push) Successful in 16s
Test / test_scrub_pg_size_3 (push) Successful in 14s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 17s
Test / test_scrub_ec (push) Successful in 14s
Test / test_nfs (push) Successful in 9s
Test / test_heal_csum_4k_dj (push) Successful in 2m21s
Test / test_heal_csum_4k (push) Successful in 2m19s
2025-07-14 19:51:35 +03:00
980aec1d9b Add patch for libvirt 11.5 2025-07-04 23:15:18 +03:00
f515fcce62 Fix volume_size_info in PVE VitastorPlugin 2025-06-18 12:38:09 +03:00
97bb809b54 Release 2.2.2
Some checks reported warnings
Test / test_osd_tags (push) Blocked by required conditions
Test / test_enospc (push) Blocked by required conditions
Test / test_enospc_xor (push) Blocked by required conditions
Test / test_enospc_imm (push) Blocked by required conditions
Test / test_enospc_imm_xor (push) Blocked by required conditions
Test / test_scrub (push) Blocked by required conditions
Test / test_scrub_zero_osd_2 (push) Blocked by required conditions
Test / test_scrub_xor (push) Blocked by required conditions
Test / test_scrub_pg_size_3 (push) Blocked by required conditions
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Blocked by required conditions
Test / test_scrub_ec (push) Blocked by required conditions
Test / test_nfs (push) Blocked by required conditions
Test / buildenv (push) Successful in 10s
Test / make_test (push) Has been cancelled
Test / npm_lint (push) Has been cancelled
Test / test_add_osd (push) Has been cancelled
Test / test_cas (push) Has been cancelled
Test / build (push) Has been cancelled
Test / test_change_pg_count (push) Has been cancelled
Test / test_change_pg_count_ec (push) Has been cancelled
Test / test_change_pg_size (push) Has been cancelled
Test / test_create_nomaxid (push) Has been cancelled
Test / test_etcd_fail (push) Has been cancelled
Test / test_etcd_fail_antietcd (push) Has been cancelled
Test / test_interrupted_rebalance (push) Has been cancelled
Test / test_interrupted_rebalance_imm (push) Has been cancelled
Test / test_interrupted_rebalance_ec (push) Has been cancelled
Test / test_interrupted_rebalance_ec_imm (push) Has been cancelled
Test / test_create_halfhost (push) Has been cancelled
Test / test_failure_domain (push) Has been cancelled
- Fix a bug introduced in 2.2.0 - pg_locks weren't disabled for pools without local_reads
  correctly which could lead to inactive pools during various operations
- Fix an old bug where OSDs could send sub-operations to incorrect peer OSDs when their
  connections were stopped and reestablished quickly, in 2.2.0 it was usually leading
  to "sequencing broken" messages in OSD logs
- Fix debug use_sync_send_recv mode
2025-06-07 12:56:48 +03:00
6022a61329 Decouple break_pg_locks from outbound OSD disconnections
All checks were successful
Test / test_switch_primary (push) Successful in 34s
Test / test_write (push) Successful in 33s
Test / test_write_xor (push) Successful in 36s
Test / test_write_no_same (push) Successful in 7s
Test / test_write_iothreads (push) Successful in 41s
Test / test_heal_pg_size_2 (push) Successful in 2m17s
Test / test_heal_local_read (push) Successful in 2m20s
Test / test_heal_ec (push) Successful in 2m20s
Test / test_heal_antietcd (push) Successful in 2m17s
Test / test_heal_csum_32k_dmj (push) Successful in 2m21s
Test / test_heal_csum_32k_dj (push) Successful in 2m21s
Test / test_heal_csum_32k (push) Successful in 2m27s
Test / test_heal_csum_4k_dmj (push) Successful in 2m18s
Test / test_resize (push) Successful in 13s
Test / test_resize_auto (push) Successful in 8s
Test / test_osd_tags (push) Successful in 7s
Test / test_snapshot_pool2 (push) Successful in 14s
Test / test_enospc (push) Successful in 11s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 11s
Test / test_enospc_imm_xor (push) Successful in 15s
Test / test_scrub (push) Successful in 14s
Test / test_scrub_zero_osd_2 (push) Successful in 13s
Test / test_scrub_xor (push) Successful in 14s
Test / test_scrub_pg_size_3 (push) Successful in 17s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 16s
Test / test_scrub_ec (push) Successful in 16s
Test / test_nfs (push) Successful in 13s
Test / test_heal_csum_4k_dj (push) Successful in 2m20s
Test / test_heal_csum_4k (push) Successful in 2m21s
2025-06-05 02:48:54 +03:00
a3c1996101 Do not accidentally clear incorrect osd_peer_fds entries
Some checks failed
Test / test_switch_primary (push) Successful in 33s
Test / test_write (push) Successful in 32s
Test / test_write_xor (push) Successful in 34s
Test / test_write_no_same (push) Successful in 8s
Test / test_write_iothreads (push) Successful in 39s
Test / test_heal_pg_size_2 (push) Successful in 2m18s
Test / test_heal_ec (push) Successful in 2m20s
Test / test_heal_antietcd (push) Successful in 2m18s
Test / test_heal_csum_32k_dmj (push) Successful in 2m21s
Test / test_heal_csum_32k_dj (push) Successful in 2m18s
Test / test_heal_csum_32k (push) Successful in 2m21s
Test / test_heal_csum_4k_dmj (push) Successful in 2m25s
Test / test_heal_csum_4k_dj (push) Successful in 2m22s
Test / test_resize_auto (push) Successful in 9s
Test / test_resize (push) Successful in 13s
Test / test_heal_csum_4k (push) Successful in 2m18s
Test / test_osd_tags (push) Successful in 8s
Test / test_snapshot_pool2 (push) Successful in 16s
Test / test_enospc (push) Successful in 12s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 10s
Test / test_enospc_imm_xor (push) Successful in 13s
Test / test_scrub (push) Successful in 13s
Test / test_scrub_zero_osd_2 (push) Successful in 14s
Test / test_scrub_xor (push) Successful in 15s
Test / test_scrub_pg_size_3 (push) Successful in 15s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 18s
Test / test_nfs (push) Successful in 11s
Test / test_scrub_ec (push) Successful in 16s
Test / test_heal_local_read (push) Failing after 10m10s
2025-06-05 02:22:13 +03:00
8d2a1f0297 Fix PG lock auto-enabling/auto-disabling in the default configuration 2025-06-05 02:22:01 +03:00
91cbc313c2 Change "on osd -123" logging to "on peer 123" for unknown connections 2025-06-05 02:22:01 +03:00
f0a025428e Postpone read/write handlers using timerfd in the debug use_sync_send_recv mode 2025-06-05 02:22:01 +03:00
67071158bd Cancel outbound operations only in the osd_client_t destructor
This is required to prevent disconnected peers from sometimes receiving messages
suited for other peers - stop_client was freeing the operations even though they
were still references in the io_uring requests in progress. This was leading to
OSDs sometimes receiving garbage and "broken sequencing" errors in logs as the
memory was usually already reallocated for other operations
2025-06-05 02:09:41 +03:00
cd028612c8 Use a separate osd_client_t::in_osd_num for inbound OSD connections 2025-06-05 02:09:41 +03:00
f390e73dae Log broken sequence numbers in "sequencing" errors 2025-06-05 02:09:41 +03:00
de2539c491 Correct Proxmox version 2025-06-03 01:56:09 +03:00
957a4fce7e Release 2.2.1
All checks were successful
Test / test_rebalance_verify_ec_imm (push) Successful in 1m47s
Test / test_write_no_same (push) Successful in 9s
Test / test_write_xor (push) Successful in 36s
Test / test_write_iothreads (push) Successful in 36s
Test / test_heal_pg_size_2 (push) Successful in 2m15s
Test / test_heal_local_read (push) Successful in 2m21s
Test / test_heal_ec (push) Successful in 2m16s
Test / test_heal_antietcd (push) Successful in 2m18s
Test / test_heal_csum_32k_dmj (push) Successful in 2m29s
Test / test_heal_csum_32k_dj (push) Successful in 2m24s
Test / test_heal_csum_32k (push) Successful in 2m29s
Test / test_heal_csum_4k_dmj (push) Successful in 2m27s
Test / test_resize_auto (push) Successful in 11s
Test / test_resize (push) Successful in 18s
Test / test_osd_tags (push) Successful in 10s
Test / test_snapshot_pool2 (push) Successful in 18s
Test / test_enospc (push) Successful in 12s
Test / test_enospc_xor (push) Successful in 14s
Test / test_enospc_imm (push) Successful in 11s
Test / test_enospc_imm_xor (push) Successful in 15s
Test / test_scrub (push) Successful in 12s
Test / test_scrub_zero_osd_2 (push) Successful in 14s
Test / test_scrub_xor (push) Successful in 16s
Test / test_scrub_pg_size_3 (push) Successful in 13s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 16s
Test / test_scrub_ec (push) Successful in 17s
Test / test_nfs (push) Successful in 11s
Test / test_heal_csum_4k_dj (push) Successful in 2m24s
Test / test_heal_csum_4k (push) Successful in 2m27s
Test / test_rebalance_verify (push) Successful in 1m51s
- Fix vitastor-disk purge broken after adding the "OSD is still running" check
- Fix iothreads hanging after adding zero-copy send support
- Fix enabling localized reads online (without restarting OSDs) in the default PG lock mode
2025-05-25 01:04:48 +03:00
f201ecdd51 Fix missing mutex unlock with zero-copy and iothreads O_o
All checks were successful
Test / test_switch_primary (push) Successful in 32s
Test / test_write (push) Successful in 33s
Test / test_write_xor (push) Successful in 36s
Test / test_write_no_same (push) Successful in 8s
Test / test_write_iothreads (push) Successful in 37s
Test / test_heal_pg_size_2 (push) Successful in 2m17s
Test / test_heal_local_read (push) Successful in 2m18s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_heal_antietcd (push) Successful in 2m17s
Test / test_heal_csum_32k_dmj (push) Successful in 2m21s
Test / test_heal_csum_32k_dj (push) Successful in 2m26s
Test / test_heal_csum_32k (push) Successful in 2m30s
Test / test_heal_csum_4k_dmj (push) Successful in 2m18s
Test / test_resize_auto (push) Successful in 9s
Test / test_resize (push) Successful in 13s
Test / test_osd_tags (push) Successful in 8s
Test / test_snapshot_pool2 (push) Successful in 14s
Test / test_enospc (push) Successful in 12s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 11s
Test / test_enospc_imm_xor (push) Successful in 13s
Test / test_scrub (push) Successful in 14s
Test / test_scrub_zero_osd_2 (push) Successful in 15s
Test / test_scrub_xor (push) Successful in 16s
Test / test_scrub_pg_size_3 (push) Successful in 14s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 16s
Test / test_scrub_ec (push) Successful in 15s
Test / test_nfs (push) Successful in 11s
Test / test_heal_csum_4k_dj (push) Successful in 2m19s
Test / test_heal_csum_4k (push) Successful in 2m19s
2025-05-24 00:56:31 +03:00
4afb617f59 Also zero-init sqe
Some checks failed
Test / test_rebalance_verify_ec_imm (push) Successful in 1m43s
Test / test_write_no_same (push) Successful in 8s
Test / test_write_xor (push) Successful in 36s
Test / test_heal_pg_size_2 (push) Successful in 2m17s
Test / test_heal_local_read (push) Successful in 2m17s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_heal_antietcd (push) Successful in 2m17s
Test / test_heal_csum_32k_dmj (push) Successful in 2m25s
Test / test_heal_csum_32k_dj (push) Successful in 2m19s
Test / test_heal_csum_32k (push) Successful in 2m28s
Test / test_resize (push) Successful in 14s
Test / test_resize_auto (push) Successful in 8s
Test / test_snapshot_pool2 (push) Successful in 14s
Test / test_osd_tags (push) Successful in 7s
Test / test_enospc (push) Successful in 10s
Test / test_enospc_xor (push) Successful in 13s
Test / test_enospc_imm (push) Successful in 11s
Test / test_heal_csum_4k_dmj (push) Successful in 2m20s
Test / test_enospc_imm_xor (push) Successful in 13s
Test / test_heal_csum_4k_dj (push) Successful in 2m20s
Test / test_scrub (push) Successful in 13s
Test / test_scrub_zero_osd_2 (push) Successful in 15s
Test / test_heal_csum_4k (push) Successful in 2m19s
Test / test_scrub_xor (push) Successful in 15s
Test / test_scrub_pg_size_3 (push) Successful in 14s
Test / test_nfs (push) Successful in 14s
Test / test_scrub_ec (push) Successful in 16s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 19s
Test / test_rebalance_verify (push) Successful in 1m55s
Test / test_write_iothreads (push) Failing after 3m5s
2025-05-23 21:18:37 +03:00
d3fde0569f Add a test with enabled iothreads
Some checks failed
Test / test_switch_primary (push) Successful in 34s
Test / test_write (push) Successful in 32s
Test / test_write_no_same (push) Successful in 8s
Test / test_write_xor (push) Successful in 34s
Test / test_heal_pg_size_2 (push) Successful in 2m16s
Test / test_heal_local_read (push) Successful in 2m18s
Test / test_heal_ec (push) Successful in 2m18s
Test / test_write_iothreads (push) Failing after 3m5s
Test / test_heal_csum_4k_dmj (push) Has been cancelled
Test / test_heal_csum_4k_dj (push) Has been cancelled
Test / test_heal_csum_4k (push) Has been cancelled
Test / test_resize (push) Has been cancelled
Test / test_resize_auto (push) Has been cancelled
Test / test_snapshot_pool2 (push) Has been cancelled
Test / test_osd_tags (push) Has been cancelled
Test / test_enospc (push) Has been cancelled
Test / test_enospc_xor (push) Has been cancelled
Test / test_enospc_imm (push) Has been cancelled
Test / test_enospc_imm_xor (push) Has been cancelled
Test / test_scrub (push) Has been cancelled
Test / test_scrub_zero_osd_2 (push) Has been cancelled
Test / test_scrub_xor (push) Has been cancelled
Test / test_scrub_pg_size_3 (push) Has been cancelled
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Has been cancelled
Test / test_scrub_ec (push) Has been cancelled
Test / test_nfs (push) Has been cancelled
Test / test_heal_csum_32k (push) Has been cancelled
Test / test_heal_csum_32k_dmj (push) Has been cancelled
Test / test_heal_antietcd (push) Has been cancelled
Test / test_heal_csum_32k_dj (push) Has been cancelled
2025-05-23 21:05:18 +03:00
438b64f6c3 Allow to enable PG locks online when changing local_reads in pool configuration
Some checks reported warnings
Test / test_switch_primary (push) Has been cancelled
Test / test_write (push) Has been cancelled
Test / test_write_xor (push) Has been cancelled
Test / test_write_no_same (push) Has been cancelled
Test / test_heal_pg_size_2 (push) Has been cancelled
Test / test_heal_local_read (push) Has been cancelled
Test / test_heal_ec (push) Has been cancelled
Test / test_heal_antietcd (push) Has been cancelled
Test / test_heal_csum_32k_dmj (push) Has been cancelled
Test / test_heal_csum_32k_dj (push) Has been cancelled
Test / test_heal_csum_32k (push) Has been cancelled
Test / test_heal_csum_4k_dmj (push) Has been cancelled
Test / test_heal_csum_4k_dj (push) Has been cancelled
Test / test_heal_csum_4k (push) Has been cancelled
Test / test_resize (push) Has been cancelled
Test / test_resize_auto (push) Has been cancelled
Test / test_snapshot_pool2 (push) Has been cancelled
Test / test_osd_tags (push) Has been cancelled
Test / test_enospc (push) Has been cancelled
Test / test_enospc_xor (push) Has been cancelled
Test / test_enospc_imm (push) Has been cancelled
Test / test_enospc_imm_xor (push) Has been cancelled
Test / test_scrub (push) Has been cancelled
Test / test_scrub_zero_osd_2 (push) Has been cancelled
Test / test_scrub_xor (push) Has been cancelled
Test / test_scrub_pg_size_3 (push) Has been cancelled
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Has been cancelled
Test / test_scrub_ec (push) Has been cancelled
Test / test_nfs (push) Has been cancelled
Test / make_test (push) Has been cancelled
2025-05-23 20:54:47 +03:00
2b0a802ea1 Fix iothreads sometimes hanging after adding zerocopy support
Some checks reported warnings
Test / test_rebalance_verify_imm (push) Successful in 1m39s
Test / test_dd (push) Successful in 11s
Test / test_rebalance_verify_ec (push) Successful in 1m44s
Test / test_root_node (push) Successful in 7s
Test / test_rebalance_verify_ec_imm (push) Successful in 1m44s
Test / test_write_no_same (push) Successful in 8s
Test / test_switch_primary (push) Successful in 32s
Test / test_write (push) Successful in 31s
Test / test_write_xor (push) Successful in 35s
Test / test_heal_csum_32k_dmj (push) Has been cancelled
Test / test_heal_csum_32k_dj (push) Has been cancelled
Test / test_heal_csum_32k (push) Has been cancelled
Test / test_heal_csum_4k_dmj (push) Has been cancelled
Test / test_heal_csum_4k_dj (push) Has been cancelled
Test / test_heal_ec (push) Has been cancelled
Test / test_heal_csum_4k (push) Has been cancelled
Test / test_resize (push) Has been cancelled
Test / test_heal_pg_size_2 (push) Has been cancelled
Test / test_resize_auto (push) Has been cancelled
Test / test_heal_local_read (push) Has been cancelled
Test / test_snapshot_pool2 (push) Has been cancelled
Test / test_heal_antietcd (push) Has been cancelled
Test / test_osd_tags (push) Has been cancelled
Test / test_enospc (push) Has been cancelled
Test / test_enospc_xor (push) Has been cancelled
Test / test_enospc_imm (push) Has been cancelled
Test / test_enospc_imm_xor (push) Has been cancelled
Test / test_scrub (push) Has been cancelled
Test / test_scrub_zero_osd_2 (push) Has been cancelled
Test / test_scrub_xor (push) Has been cancelled
2025-05-23 20:54:03 +03:00
0dd49c1d67 Followup to "allow to purge running OSDs again"
All checks were successful
Test / test_write_no_same (push) Successful in 7s
Test / test_rebalance_verify_ec_imm (push) Successful in 1m44s
Test / test_write (push) Successful in 34s
Test / test_write_xor (push) Successful in 35s
Test / test_heal_pg_size_2 (push) Successful in 2m16s
Test / test_heal_local_read (push) Successful in 2m19s
Test / test_heal_ec (push) Successful in 2m17s
Test / test_heal_antietcd (push) Successful in 2m19s
Test / test_heal_csum_32k_dmj (push) Successful in 2m16s
Test / test_heal_csum_32k_dj (push) Successful in 2m18s
Test / test_heal_csum_32k (push) Successful in 2m19s
Test / test_heal_csum_4k_dmj (push) Successful in 2m17s
Test / test_resize_auto (push) Successful in 8s
Test / test_resize (push) Successful in 13s
Test / test_osd_tags (push) Successful in 9s
Test / test_snapshot_pool2 (push) Successful in 13s
Test / test_enospc (push) Successful in 10s
Test / test_enospc_xor (push) Successful in 12s
Test / test_enospc_imm (push) Successful in 9s
Test / test_enospc_imm_xor (push) Successful in 14s
Test / test_scrub (push) Successful in 14s
Test / test_scrub_zero_osd_2 (push) Successful in 15s
Test / test_scrub_xor (push) Successful in 14s
Test / test_scrub_pg_size_3 (push) Successful in 14s
Test / test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec (push) Successful in 15s
Test / test_scrub_ec (push) Successful in 14s
Test / test_nfs (push) Successful in 11s
Test / test_heal_csum_4k_dj (push) Successful in 2m17s
Test / test_heal_csum_4k (push) Successful in 2m18s
Test / test_rebalance_verify (push) Successful in 1m37s
2025-05-22 01:10:05 +03:00
410170db96 Add notes about VNPL in English 2025-05-20 02:12:49 +03:00
7d8523e0e5 Add more notes about VNPL in Russian 2025-05-19 02:41:34 +03:00
74 changed files with 1436 additions and 430 deletions

View File

@@ -144,6 +144,24 @@ jobs:
echo ""
done
test_change_pg_count_online:
runs-on: ubuntu-latest
needs: build
container: ${{env.TEST_IMAGE}}:${{github.sha}}
steps:
- name: Run test
id: test
timeout-minutes: 3
run: /root/vitastor/tests/test_change_pg_count_online.sh
- name: Print logs
if: always() && steps.test.outcome == 'failure'
run: |
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
echo "-------- $i --------"
cat $i
echo ""
done
test_change_pg_size:
runs-on: ubuntu-latest
needs: build
@@ -684,6 +702,24 @@ jobs:
echo ""
done
test_write_iothreads:
runs-on: ubuntu-latest
needs: build
container: ${{env.TEST_IMAGE}}:${{github.sha}}
steps:
- name: Run test
id: test
timeout-minutes: 3
run: TEST_NAME=iothreads GLOBAL_CONFIG=',"client_iothread_count":4' /root/vitastor/tests/test_write.sh
- name: Print logs
if: always() && steps.test.outcome == 'failure'
run: |
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
echo "-------- $i --------"
cat $i
echo ""
done
test_write_no_same:
runs-on: ubuntu-latest
needs: build

View File

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

View File

@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v2.2.0
VITASTOR_VERSION ?= v2.2.3
all: build push

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,4 @@
#!/bin/bash
cat < vitastor.Dockerfile > ../Dockerfile
cd ..
mkdir -p packages
sudo podman build --build-arg DISTRO=debian --build-arg REL=bookworm -v `pwd`/packages:/root/packages -f Dockerfile .
rm Dockerfile
docker build --build-arg DISTRO=debian --build-arg REL=bookworm -t vitastor-buildenv:bookworm -f vitastor-buildenv.Dockerfile .
docker run -i --rm -e REL=bookworm -v `dirname $0`/../:/root/vitastor vitastor-buildenv:bookworm /root/vitastor/debian/vitastor-build.sh

View File

@@ -1,7 +1,4 @@
#!/bin/bash
cat < vitastor.Dockerfile > ../Dockerfile
cd ..
mkdir -p packages
sudo podman build --build-arg DISTRO=debian --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f Dockerfile .
rm Dockerfile
docker build --build-arg DISTRO=debian --build-arg REL=bullseye -t vitastor-buildenv:bullseye -f vitastor-buildenv.Dockerfile .
docker run -i --rm -e REL=bullseye -v `dirname $0`/../:/root/vitastor vitastor-buildenv:bullseye /root/vitastor/debian/vitastor-build.sh

View File

@@ -1,7 +1,4 @@
#!/bin/bash
cat < vitastor.Dockerfile > ../Dockerfile
cd ..
mkdir -p packages
sudo podman build --build-arg DISTRO=debian --build-arg REL=buster -v `pwd`/packages:/root/packages -f Dockerfile .
rm Dockerfile
docker build --build-arg DISTRO=debian --build-arg REL=buster -t vitastor-buildenv:buster -f vitastor-buildenv.Dockerfile .
docker run -i --rm -e REL=buster -v `dirname $0`/../:/root/vitastor vitastor-buildenv:buster /root/vitastor/debian/vitastor-build.sh

View File

@@ -1,7 +1,5 @@
#!/bin/bash
# Ubuntu 22.04 Jammy Jellyfish
cat < vitastor.Dockerfile > ../Dockerfile
cd ..
mkdir -p packages
sudo podman build --build-arg DISTRO=ubuntu --build-arg REL=jammy -v `pwd`/packages:/root/packages -f Dockerfile .
rm Dockerfile
docker build --build-arg DISTRO=ubuntu --build-arg REL=jammy -t vitastor-buildenv:jammy -f vitastor-buildenv.Dockerfile .
docker run -i --rm -e REL=jammy -v `dirname $0`/../:/root/vitastor vitastor-buildenv:jammy /root/vitastor/debian/vitastor-build.sh

5
debian/build-vitastor-ubuntu-noble.sh vendored Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
# 24.04 Noble Numbat
docker build --build-arg DISTRO=ubuntu --build-arg REL=noble -t vitastor-buildenv:noble -f vitastor-buildenv.Dockerfile .
docker run -i --rm -e REL=noble -v `dirname $0`/../:/root/vitastor vitastor-buildenv:noble /root/vitastor/debian/vitastor-build.sh

2
debian/changelog vendored
View File

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

59
debian/vitastor-build.sh vendored Executable file
View File

@@ -0,0 +1,59 @@
#!/bin/bash
# To be ran inside buildenv docker
set -e -x
[ -e /usr/lib/x86_64-linux-gnu/pkgconfig/libisal.pc ] || cp /root/vitastor/debian/libisal.pc /usr/lib/x86_64-linux-gnu/pkgconfig
mkdir -p /root/fio-build/
cd /root/fio-build/
rm -rf /root/fio-build/*
dpkg-source -x /root/fio*.dsc
FULLVER=`head -n1 /root/vitastor/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'`
VER=${FULLVER%%-*}
rm -rf /root/vitastor-$VER
mkdir /root/vitastor-$VER
cd /root/vitastor
cp -a $(ls | grep -v packages) /root/vitastor-$VER
rm -rf /root/vitastor/packages/vitastor-$REL
mkdir -p /root/vitastor/packages/vitastor-$REL
mv /root/vitastor-$VER /root/vitastor/packages/vitastor-$REL/
cd /root/vitastor/packages/vitastor-$REL/vitastor-$VER
rm -rf fio
ln -s /root/fio-build/fio-*/ ./fio
FIO=`head -n1 fio/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'`
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h
sh copy-fio-includes.sh
rm fio
mkdir -p a b debian/patches
mv fio-copy b/fio
diff -NaurpbB a b > debian/patches/fio-headers.patch || true
echo fio-headers.patch >> debian/patches/series
rm -rf a b
echo "dep:fio=$FIO" > debian/fio_version
cd /root/vitastor/packages/vitastor-$REL/vitastor-$VER
mkdir mon/node_modules
cd mon/node_modules
curl -s https://git.yourcmc.ru/vitalif/antietcd/archive/master.tar.gz | tar -zx
curl -s https://git.yourcmc.ru/vitalif/tinyraft/archive/master.tar.gz | tar -zx
cd /root/vitastor/packages/vitastor-$REL
tar --sort=name --mtime='2020-01-01' --owner=0 --group=0 --exclude=debian -cJf vitastor_$VER.orig.tar.xz vitastor-$VER
cd vitastor-$VER
DEBEMAIL="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v "$FULLVER""$REL" "Rebuild for $REL"
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa
rm -rf /root/vitastor/packages/vitastor-$REL/vitastor-*/
# Why does ubuntu rename debug packages to *.ddeb?
if ls *.ddeb >/dev/null; then
perl -i -pe 's/\.ddeb/.deb/' *.buildinfo *.changes
for i in *.ddeb; do
mv $i ${i%%.ddeb}.deb
done
fi

31
debian/vitastor-buildenv.Dockerfile vendored Normal file
View File

@@ -0,0 +1,31 @@
# Build environment for building Vitastor packages for Debian inside a container
# cd ..
# docker build --build-arg DISTRO=debian --build-arg REL=bullseye -f debian/vitastor.Dockerfile -t vitastor-buildenv:bullseye .
# docker run --rm -e REL=bullseye -v ./:/root/vitastor /root/vitastor/debian/vitastor-build.sh
ARG DISTRO=debian
ARG REL=
FROM $DISTRO:$REL
ARG DISTRO=debian
ARG REL=
WORKDIR /root
RUN set -e -x; \
if [ "$REL" = "buster" ]; then \
perl -i -pe 's/deb.debian.org/archive.debian.org/' /etc/apt/sources.list; \
apt-get update; \
apt-get -y install wget; \
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg; \
echo "deb https://vitastor.io/debian $REL main" >> /etc/apt/sources.list; \
fi; \
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/*.sources || true; \
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
RUN apt-get update && \
apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts libjerasure-dev cmake \
libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl nodejs npm node-nan node-bindings && \
apt-get -y build-dep fio && \
apt-get --download-only source fio

View File

@@ -1,65 +0,0 @@
# Build Vitastor packages for Debian inside a container
# cd ..; podman build --build-arg DISTRO=debian --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/vitastor.Dockerfile .
ARG DISTRO=debian
ARG REL=
FROM $DISTRO:$REL
ARG DISTRO=debian
ARG REL=
WORKDIR /root
RUN set -e -x; \
if [ "$REL" = "buster" ]; then \
apt-get update; \
apt-get -y install wget; \
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg; \
echo "deb https://vitastor.io/debian $REL main" >> /etc/apt/sources.list; \
fi; \
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/debian.sources || true; \
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
RUN apt-get update && \
apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts libjerasure-dev cmake \
libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl nodejs npm node-nan node-bindings && \
apt-get -y build-dep fio && \
apt-get --download-only source fio
ADD . /root/vitastor
RUN set -e -x; \
[ -e /usr/lib/x86_64-linux-gnu/pkgconfig/libisal.pc ] || cp /root/vitastor/debian/libisal.pc /usr/lib/x86_64-linux-gnu/pkgconfig; \
mkdir -p /root/fio-build/; \
cd /root/fio-build/; \
rm -rf /root/fio-build/*; \
dpkg-source -x /root/fio*.dsc; \
mkdir -p /root/packages/vitastor-$REL; \
rm -rf /root/packages/vitastor-$REL/*; \
cd /root/packages/vitastor-$REL; \
FULLVER=$(head -n1 /root/vitastor/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
VER=${FULLVER%%-*}; \
cp -r /root/vitastor vitastor-$VER; \
cd vitastor-$VER; \
ln -s /root/fio-build/fio-*/ ./fio; \
FIO=$(head -n1 fio/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
sh copy-fio-includes.sh; \
rm fio; \
mkdir -p a b debian/patches; \
mv fio-copy b/fio; \
diff -NaurpbB a b > debian/patches/fio-headers.patch || true; \
echo fio-headers.patch >> debian/patches/series; \
rm -rf a b; \
echo "dep:fio=$FIO" > debian/fio_version; \
cd /root/packages/vitastor-$REL/vitastor-$VER; \
mkdir mon/node_modules; \
cd mon/node_modules; \
curl -s https://git.yourcmc.ru/vitalif/antietcd/archive/master.tar.gz | tar -zx; \
curl -s https://git.yourcmc.ru/vitalif/tinyraft/archive/master.tar.gz | tar -zx; \
cd /root/packages/vitastor-$REL; \
tar --sort=name --mtime='2020-01-01' --owner=0 --group=0 --exclude=debian -cJf vitastor_$VER.orig.tar.xz vitastor-$VER; \
cd vitastor-$VER; \
DEBFULLNAME="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v "$FULLVER""$REL" "Rebuild for $REL"; \
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \
rm -rf /root/packages/vitastor-$REL/vitastor-*/

View File

@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v2.2.0
VITASTOR_VERSION ?= v2.2.3
all: build push

View File

@@ -0,0 +1,3 @@
Package: *
Pin: release n=bookworm-backports
Pin-Priority: 500

View File

@@ -4,7 +4,7 @@
#
# Desired Vitastor version
VITASTOR_VERSION=v2.2.0
VITASTOR_VERSION=v2.2.3
# Additional arguments for all containers
# For example, you may want to specify a custom logging driver here

View File

@@ -74,7 +74,7 @@ Consider `use_rdmacm` for such networks.
## use_rdmacm
- Type: boolean
- Default: true
- Default: false
Use an alternative implementation of RDMA through RDMA-CM (Connection
Manager). Works with all RDMA networks: Infiniband, iWARP and

View File

@@ -74,7 +74,7 @@ RDMA-устройства, но они не имеют соединения с
## use_rdmacm
- Тип: булево (да/нет)
- Значение по умолчанию: true
- Значение по умолчанию: false
Использовать альтернативную реализацию RDMA на основе RDMA-CM (Connection
Manager). Работает со всеми типами RDMA-сетей: Infiniband, iWARP и

View File

@@ -51,7 +51,7 @@
Рассмотрите включение `use_rdmacm` для таких сетей.
- name: use_rdmacm
type: bool
default: true
default: false
info: |
Use an alternative implementation of RDMA through RDMA-CM (Connection
Manager). Works with all RDMA networks: Infiniband, iWARP and

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 vitastor:v2.2.0`
`docker pull vitalif/vitastor:v2.2.3`
2. Install scripts to the host system: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitastor:v2.2.0 install.sh`
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v2.2.3 install.sh`
3. Reload udev rules: \
`udevadm control --reload-rules`

View File

@@ -25,9 +25,9 @@ Vitastor можно установить в Docker/Podman. При этом etcd,
Инструкция по установке максимально простая.
1. Скачайте Docker-образ желаемой версии: \
`docker pull vitastor:v2.2.0`
`docker pull vitalif/vitastor:v2.2.3`
2. Установите скрипты в хост-систему командой: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitastor:v2.2.0 install.sh`
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v2.2.3 install.sh`
3. Перезагрузите правила udev: \
`udevadm control --reload-rules`

View File

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

View File

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

View File

@@ -6,10 +6,10 @@
# Proxmox VE
To enable Vitastor support in Proxmox Virtual Environment (6.4-8.1 are supported):
To enable Vitastor support in Proxmox Virtual Environment (6.4-8.x are supported):
- Add the corresponding Vitastor Debian repository into sources.list on Proxmox hosts:
bookworm for 8.1, pve8.0 for 8.0, bullseye for 7.4, pve7.3 for 7.3, pve7.2 for 7.2, pve7.1 for 7.1, buster for 6.4
bookworm for 8.1+, pve8.0 for 8.0, bullseye for 7.4, pve7.3 for 7.3, pve7.2 for 7.2, pve7.1 for 7.1, buster for 6.4
- Install vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* or see note) packages from Vitastor repository
- Define storage in `/etc/pve/storage.cfg` (see below)
- Block network access from VMs to Vitastor network (to OSDs and etcd),

View File

@@ -6,10 +6,10 @@
# Proxmox VE
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-8.1):
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-8.x):
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
bookworm для 8.1, pve8.0 для 8.0, bullseye для 7.4, pve7.3 для 7.3, pve7.2 для 7.2, pve7.1 для 7.1, buster для 6.4
bookworm для 8.1+, pve8.0 для 8.0, bullseye для 7.4, pve7.3 для 7.3, pve7.2 для 7.2, pve7.1 для 7.1, buster для 6.4
- Установите пакеты vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* или см. сноску) из репозитория Vitastor
- Определите тип хранилища в `/etc/pve/storage.cfg` (см. ниже)
- Обязательно заблокируйте доступ от виртуальных машин к сети Vitastor (OSD и etcd), т.к. Vitastor (пока) не поддерживает аутентификацию

View File

@@ -10,8 +10,17 @@ Copyright (c) Vitaliy Filippov (vitalif [at] yourcmc.ru), 2019+
Join Vitastor Telegram Chat: https://t.me/vitastor
All server-side code (OSD, Monitor and so on) is licensed under the terms of
Vitastor Network Public License 1.1 (VNPL 1.1), a copyleft license based on
License: VNPL 1.1 for server-side code and dual VNPL 1.1 + GPL 2.0+ for client tools.
Server-side code is licensed only under the terms of VNPL.
Client libraries (cluster_client and so on) are dual-licensed under the same
VNPL 1.1 and also GNU GPL 2.0 or later to allow for compatibility with GPLed
software like QEMU and fio.
## VNPL
Vitastor Network Public License 1.1 (VNPL 1.1) is a copyleft license based on
GNU GPLv3.0 with the additional "Network Interaction" clause which requires
opensourcing all programs directly or indirectly interacting with Vitastor
through a computer network and expressly designed to be used in conjunction
@@ -20,18 +29,83 @@ the terms of the same license, but also under the terms of any GPL-Compatible
Free Software License, as listed by the Free Software Foundation.
This is a stricter copyleft license than the Affero GPL.
Please note that VNPL doesn't require you to open the code of proprietary
software running inside a VM if it's not specially designed to be used with
Vitastor.
The idea of VNPL is, in addition to modules linked to Vitastor code in a single
binary file, to extend copyleft action to micro-service modules only interacting
with it over the network.
Basically, you can't use the software in a proprietary environment to provide
its functionality to users without opensourcing all intermediary components
standing between the user and Vitastor or purchasing a commercial license
from the author 😀.
Client libraries (cluster_client and so on) are dual-licensed under the same
VNPL 1.1 and also GNU GPL 2.0 or later to allow for compatibility with GPLed
software like QEMU and fio.
At the same time, VNPL doesn't impose any restrictions on software *not specially designed*
to be used with Vitastor, for example, on Windows running inside a VM with a Vitastor disk.
You can find the full text of VNPL-1.1 in the file [VNPL-1.1.txt](../../VNPL-1.1.txt).
GPL 2.0 is also included in this repository as [GPL-2.0.txt](../../GPL-2.0.txt).
## Explanation
Network copyleft is governed by the clause **13. Remote Network Interaction** of VNPL.
A program is considered to be a "Proxy Program" if it meets both conditions:
- It is specially designed to be used with Vitastor. Basically, it means that the program
has any functionality specific to Vitastor and thus "knows" that it works with Vitastor,
not with something random.
- It interacts with Vitastor directly or indirectly through any programming interface,
including API, CLI, network or any wrapper (also considered a Proxy Program itself).
If, in addition to that:
- You give any user an apportunity to interact with Vitastor directly or indirectly through
any computer interface including the network or any number of wrappers (Proxy Programs).
Then VNPL requires you to publish the code of all above Proxy Programs to all above users
under the terms of any GPL-compatible license - that is, GPL, LGPL, MIT/BSD or Apache 2,
because "GPL compatibility" is treated as an ability to legally include licensed code in
a GPL application.
So, if you have a "Proxy Program", but it's not open to the user who directly or indirectly
interacts with Vitastor - you are forbidden to use Vitastor under the terms of VNPL and you
need a commercial license which doesn't contain open-source requirements.
## Examples
- Vitastor Kubernetes CSI driver which creates PersistentVolumes by calling `vitastor-cli create`.
- Yes, it interacts with Vitastor through vitastor-cli.
- Yes, it is designed specially for use with Vitastor (it has no sense otherwise).
- So, CSI driver **definitely IS** a Proxy Program and must be published under the terms of
a free software license.
- Windows, installed in a VM with the system disk on Vitastor storage.
- Yes, it interacts with Vitastor indirectly - it reads and writes data through the block
device interface, emulated by QEMU.
- No, it definitely isn't designed specially for use with Vitastor - Windows was created long
ago before Vitastor and doesn't know anything about it.
- So, Windows **definitely IS NOT** a Proxy Program and VNPL doesn't require to open it.
- Cloud control panel which makes requests to Vitastor Kubernetes CSI driver.
- Yes, it interacts with Vitastor indirectly through the CSI driver, which is a Proxy Program.
- May or may not be designed specially for use with Vitastor. How to determine exactly?
Imagine that Vitastor is replaced with any other storage (for example, with a proprietary).
Do control panel functions change in any way? If they do (for example, if snapshots stop working),
then the panel contains specific functionality and thus is designed specially for use with Vitastor.
Otherwise, the panel is universal and isn't designed specially for Vitastor.
- So, whether you are required to open-source the panel also **depends** on whether it
contains specific functionality or not.
## Why?
Because I believe into the spirit of copyleft (Linux wouldn't become so popular without GPL!)
and, at the same time, I want to have a way to monetize the product.
Existing licenses including AGPL are useless for it with an SDS - SDS is a very deeply
internal software which is almost definitely invisible to the user and thus AGPL doesn't
require anyone to open the code even if they make a proprietary fork.
And, in fact, the current situation in the world where GPL is though to only restrict direct
linking of programs into a single executable file, isn't much correct. Nowadays, programs
are more often linked with network API calls, not with /usr/bin/ld, and a software product
may consist of dozens of microservices interacting with each other over the network.
That's why we need VNPL to keep the license sufficiently copyleft.
## License Texts
- VNPL 1.1 in English: [VNPL-1.1.txt](../../VNPL-1.1.txt)
- VNPL 1.1 in Russian: [VNPL-1.1-RU.txt](../../VNPL-1.1-RU.txt)
- GPL 2.0: [GPL-2.0.txt](../../GPL-2.0.txt)

View File

@@ -12,6 +12,14 @@
Лицензия: VNPL 1.1 на серверный код и двойная VNPL 1.1 + GPL 2.0+ на клиентский.
Серверные компоненты распространяются только на условиях VNPL.
Клиентские библиотеки распространяются на условиях двойной лицензии VNPL 1.0
и также на условиях GNU GPL 2.0 или более поздней версии. Так сделано в целях
совместимости с таким ПО, как QEMU и fio.
## VNPL
VNPL - "сетевой копилефт", собственная свободная копилефт-лицензия
Vitastor Network Public License 1.1, основанная на GNU GPL 3.0 с дополнительным
условием "Сетевого взаимодействия", требующим распространять все программы,
@@ -29,9 +37,70 @@ Vitastor Network Public License 1.1, основанная на GNU GPL 3.0 с д
На Windows и любое другое ПО, не разработанное *специально* для использования
вместе с Vitastor, никакие ограничения не накладываются.
Клиентские библиотеки распространяются на условиях двойной лицензии VNPL 1.0
и также на условиях GNU GPL 2.0 или более поздней версии. Так сделано в целях
совместимости с таким ПО, как QEMU и fio.
## Пояснение
Вы можете найти полный текст VNPL 1.1 на английском языке в файле [VNPL-1.1.txt](../../VNPL-1.1.txt),
VNPL 1.1 на русском языке в файле [VNPL-1.1-RU.txt](../../VNPL-1.1-RU.txt), а GPL 2.0 в файле [GPL-2.0.txt](../../GPL-2.0.txt).
Сетевой копилефт регулируется пунктом лицензии **13. Удалённое сетевое взаимодействие**.
Программа считается "прокси-программой", если верны оба условия:
- Она создана специально для работы вместе с Vitastor. По сути это означает, что программа
должна иметь специфичный для Vitastor функционал, то есть, "знать", что она взаимодействует
именно с Vitastor.
- Она прямо или косвенно взаимодействует с Vitastor через абсолютно любой программный
интерфейс, включая любые способы вызова: API, CLI, сеть или через какую-то обёртку (в
свою очередь тоже являющуюся прокси-программой).
Если в дополнение к этому также:
- Вы предоставляете любому пользователю возможность взаимодействовать с Vitastor по сети,
опять-таки, через любой интерфейс или любую серию "обёрток" (прокси-программ)
То, согласно VNPL, вы должны открыть код "прокси-программ" **таким пользователям** на условиях
любой GPL-совместимой лицензии - то есть, GPL, LGPL, MIT/BSD или Apache 2 - "совместимость с GPL"
понимается как возможность включать лицензируемый код в GPL-приложение.
Соответственно, если у вас есть "прокси-программа", но её код не открыт пользователю,
который прямо или косвенно взаимодействует с Vitastor - вам запрещено использовать Vitastor
на условиях VNPL и вам нужна коммерческая лицензия, не содержащая требований об открытии кода.
## Примеры
- Kubernetes CSI-драйвер Vitastor, создающий PersistentVolume с помощью вызова `vitastor-cli create`.
- Да, взаимодействует с Vitastor через vitastor-cli.
- Да, создавался специально для работы с Vitastor (иначе в чём же ещё его смысл).
- Значит, CSI-драйвер **точно считается** "прокси-программой" и должен быть открыт под свободной
лицензией.
- Windows, установленный в виртуальную машину на диске Vitastor.
- Да, взаимодействует с Vitastor "прямо или косвенно" - пишет и читает данные через интерфейс
блочного устройства, эмулируемый QEMU.
- Нет, точно не создан *специально для работы с Vitastor* - когда его создавали, никакого
Vitastor ещё и в помине не было.
- Значит, Windows **точно не считается** "прокси-программой" и на него требования VNPL не распространяются.
- Панель управления облака, делающая запросы к Kubernetes CSI-драйверу Vitastor.
- Да, взаимодействует с Vitastor косвенно через CSI-драйвер, являющийся "прокси-программой".
- Сходу не известно, создавалась ли конкретно для работы с Vitastor. Как понять, да или нет?
Представьте, что Vitastor заменён на любую другую систему хранения (например, на проприетарную).
Работа панели управления изменится? Если да (например, перестанут работать снапшоты) - значит,
панель содержит специфичный функционал и "создана специально для работы с Vitastor".
Если нет - значит, специфичного функционала панель не содержит и в принципе она универсальна.
- Нужно ли открывать панель - **зависит** от того, содержит она специфичный функционал или нет.
## Почему так?
Потому что я одновременно верю в дух копилефт-лицензий (Linux не стал бы так популярен,
если бы не GPL!) и хочу иметь возможность монетизации продукта.
При этом использовать даже AGPL для программной СХД бессмысленно - это глубоко внутреннее
ПО, которое пользователь почти наверняка не увидит вообще, поэтому и открывать код никому
никогда не придётся, даже при создании производного продукта.
Да и в целом сложившаяся в мире ситуация, при которой действие GPL ограничивается только
прямым связыванием в один исполняемый файл, не очень корректна. В настоящее время программы
гораздо чаще интегрируют сетевыми вызовами, а не с помощью /usr/bin/ld, и общий программный
продукт может состоять из нескольких десятков микросервисов, взаимодействующих по сети.
Поэтому для сохранения достаточной "копилефтности" и придумана VNPL.
## Тексты лицензий
- VNPL 1.1 на английском языке: [VNPL-1.1.txt](../../VNPL-1.1.txt)
- VNPL 1.1 на русском языке: [VNPL-1.1-RU.txt](../../VNPL-1.1-RU.txt)
- GPL 2.0: [GPL-2.0.txt](../../GPL-2.0.txt)

View File

@@ -96,6 +96,7 @@ class Mon
}
else
{
res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');
res.write(export_prometheus_metrics(this.state));
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "vitastor-mon",
"version": "2.2.0",
"version": "2.2.3",
"description": "Vitastor SDS monitor service",
"main": "mon-main.js",
"scripts": {

View File

@@ -1,6 +1,6 @@
{
"name": "vitastor",
"version": "2.2.0",
"version": "2.2.3",
"description": "Low-level native bindings to Vitastor client library",
"main": "index.js",
"keywords": [

View File

@@ -410,8 +410,8 @@ sub volume_size_info
my $prefix = defined $scfg->{vitastor_prefix} ? $scfg->{vitastor_prefix} : 'pve/';
my ($vtype, $name, $vmid) = $class->parse_volname($volname);
my $info = _process_list($scfg, $storeid, run_cli($scfg, [ 'ls', $prefix.$name ]))->[0];
#return wantarray ? ($size, $format, $used, $parent, $st->ctime) : $size;
return $info->{size};
# (size, format, used, parent, ctime)
return wantarray ? ($info->{size}, $info->{format}, $info->{size}, $info->{parent}, 0) : $info->{size};
}
sub volume_resize

View File

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

View File

@@ -0,0 +1,637 @@
diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h
index aaad4a3da1..5f5daa8341 100644
--- a/include/libvirt/libvirt-storage.h
+++ b/include/libvirt/libvirt-storage.h
@@ -326,6 +326,7 @@ typedef enum {
VIR_CONNECT_LIST_STORAGE_POOLS_ZFS = 1 << 17, /* (Since: 1.2.8) */
VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE = 1 << 18, /* (Since: 3.1.0) */
VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI_DIRECT = 1 << 19, /* (Since: 5.6.0) */
+ VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR = 1 << 20, /* (Since: 5.0.0) */
} virConnectListAllStoragePoolsFlags;
int virConnectListAllStoragePools(virConnectPtr conn,
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 1e24e41a48..ce359a4cf8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -7435,7 +7435,8 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node,
src->configFile = virXPathString("string(./config/@file)", ctxt);
if (src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
- src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS)
+ src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS ||
+ src->protocol == VIR_STORAGE_NET_PROTOCOL_VITASTOR)
src->query = virXMLPropString(node, "query");
if (virDomainStorageNetworkParseHosts(node, ctxt, &src->hosts, &src->nhosts) < 0)
@@ -31871,6 +31872,7 @@ virDomainStorageSourceTranslateSourcePool(virStorageSource *src,
case VIR_STORAGE_POOL_MPATH:
case VIR_STORAGE_POOL_RBD:
+ case VIR_STORAGE_POOL_VITASTOR:
case VIR_STORAGE_POOL_SHEEPDOG:
case VIR_STORAGE_POOL_GLUSTER:
case VIR_STORAGE_POOL_LAST:
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index b28af7fa56..d1aae6e43e 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -504,6 +504,7 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
case VIR_STORAGE_NET_PROTOCOL_RBD:
break;
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
case VIR_STORAGE_NET_PROTOCOL_NBD:
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
@@ -576,7 +577,7 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
}
}
- /* internal snapshots and config files are currently supported only with rbd: */
+ /* internal snapshots are currently supported only with rbd: */
if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK &&
src->protocol != VIR_STORAGE_NET_PROTOCOL_RBD) {
if (src->snapshot) {
@@ -584,10 +585,14 @@ virDomainDiskDefValidateSourceChainOne(const virStorageSource *src)
_("<snapshot> element is currently supported only with 'rbd' disks"));
return -1;
}
-
+ }
+ /* config files are currently supported only with rbd and vitastor: */
+ if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK &&
+ src->protocol != VIR_STORAGE_NET_PROTOCOL_RBD &&
+ src->protocol != VIR_STORAGE_NET_PROTOCOL_VITASTOR) {
if (src->configFile) {
virReportError(VIR_ERR_XML_ERROR, "%s",
- _("<config> element is currently supported only with 'rbd' disks"));
+ _("<config> element is currently supported only with 'rbd' and 'vitastor' disks"));
return -1;
}
}
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 183dd5db5e..dcc0d1a778 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -2066,6 +2066,35 @@
</element>
</define>
+ <define name="diskSourceNetworkProtocolVitastor">
+ <element name="source">
+ <interleave>
+ <attribute name="protocol">
+ <value>vitastor</value>
+ </attribute>
+ <ref name="diskSourceCommon"/>
+ <optional>
+ <attribute name="name"/>
+ </optional>
+ <optional>
+ <attribute name="query"/>
+ </optional>
+ <zeroOrMore>
+ <ref name="diskSourceNetworkHost"/>
+ </zeroOrMore>
+ <optional>
+ <element name="config">
+ <attribute name="file">
+ <ref name="absFilePath"/>
+ </attribute>
+ <empty/>
+ </element>
+ </optional>
+ <empty/>
+ </interleave>
+ </element>
+ </define>
+
<define name="diskSourceNetworkProtocolISCSI">
<element name="source">
<attribute name="protocol">
@@ -2416,6 +2445,7 @@
<ref name="diskSourceNetworkProtocolSimple"/>
<ref name="diskSourceNetworkProtocolVxHS"/>
<ref name="diskSourceNetworkProtocolNFS"/>
+ <ref name="diskSourceNetworkProtocolVitastor"/>
</choice>
</define>
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 1dc9365bf2..a8a736be81 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -56,7 +56,7 @@ VIR_ENUM_IMPL(virStoragePool,
"logical", "disk", "iscsi",
"iscsi-direct", "scsi", "mpath",
"rbd", "sheepdog", "gluster",
- "zfs", "vstorage",
+ "zfs", "vstorage", "vitastor",
);
VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
@@ -242,6 +242,18 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
.formatToString = virStorageFileFormatTypeToString,
}
},
+ {.poolType = VIR_STORAGE_POOL_VITASTOR,
+ .poolOptions = {
+ .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
+ VIR_STORAGE_POOL_SOURCE_NETWORK |
+ VIR_STORAGE_POOL_SOURCE_NAME),
+ },
+ .volOptions = {
+ .defaultFormat = VIR_STORAGE_FILE_RAW,
+ .formatFromString = virStorageVolumeFormatFromString,
+ .formatToString = virStorageFileFormatTypeToString,
+ }
+ },
{.poolType = VIR_STORAGE_POOL_SHEEPDOG,
.poolOptions = {
.flags = (VIR_STORAGE_POOL_SOURCE_HOST |
@@ -538,6 +550,11 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
_("element 'name' is mandatory for RBD pool"));
return -1;
}
+ if (pool_type == VIR_STORAGE_POOL_VITASTOR && source->name == NULL) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("element 'name' is mandatory for Vitastor pool"));
+ return -1;
+ }
if (options->formatFromString) {
g_autofree char *format = NULL;
@@ -1127,6 +1144,7 @@ virStoragePoolDefFormatBuf(virBuffer *buf,
/* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
* files, so they don't have a target */
if (def->type != VIR_STORAGE_POOL_RBD &&
+ def->type != VIR_STORAGE_POOL_VITASTOR &&
def->type != VIR_STORAGE_POOL_SHEEPDOG &&
def->type != VIR_STORAGE_POOL_GLUSTER &&
def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index fc67957cfe..720c07ef74 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -103,6 +103,7 @@ typedef enum {
VIR_STORAGE_POOL_GLUSTER, /* Gluster device */
VIR_STORAGE_POOL_ZFS, /* ZFS */
VIR_STORAGE_POOL_VSTORAGE, /* Virtuozzo Storage */
+ VIR_STORAGE_POOL_VITASTOR, /* Vitastor */
VIR_STORAGE_POOL_LAST,
} virStoragePoolType;
@@ -454,6 +455,7 @@ VIR_ENUM_DECL(virStoragePartedFs);
VIR_CONNECT_LIST_STORAGE_POOLS_SCSI | \
VIR_CONNECT_LIST_STORAGE_POOLS_MPATH | \
VIR_CONNECT_LIST_STORAGE_POOLS_RBD | \
+ VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR | \
VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG | \
VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER | \
VIR_CONNECT_LIST_STORAGE_POOLS_ZFS | \
diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
index 8a063be244..dd9c7f11a2 100644
--- a/src/conf/storage_source_conf.c
+++ b/src/conf/storage_source_conf.c
@@ -89,6 +89,7 @@ VIR_ENUM_IMPL(virStorageNetProtocol,
"ssh",
"vxhs",
"nfs",
+ "vitastor",
);
@@ -1314,6 +1315,7 @@ virStorageSourceNetworkDefaultPort(virStorageNetProtocol protocol)
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
return 24007;
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
case VIR_STORAGE_NET_PROTOCOL_RBD:
/* we don't provide a default for RBD */
return 0;
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index ebddf28cd6..873a2be65c 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -130,6 +130,7 @@ typedef enum {
VIR_STORAGE_NET_PROTOCOL_SSH,
VIR_STORAGE_NET_PROTOCOL_VXHS,
VIR_STORAGE_NET_PROTOCOL_NFS,
+ VIR_STORAGE_NET_PROTOCOL_VITASTOR,
VIR_STORAGE_NET_PROTOCOL_LAST
} virStorageNetProtocol;
diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c
index 59fa5da372..4739167f5f 100644
--- a/src/conf/virstorageobj.c
+++ b/src/conf/virstorageobj.c
@@ -1438,6 +1438,7 @@ virStoragePoolObjSourceFindDuplicateCb(const void *payload,
return 1;
break;
+ case VIR_STORAGE_POOL_VITASTOR:
case VIR_STORAGE_POOL_ISCSI_DIRECT:
case VIR_STORAGE_POOL_RBD:
case VIR_STORAGE_POOL_LAST:
@@ -1921,6 +1922,8 @@ virStoragePoolObjMatch(virStoragePoolObj *obj,
(obj->def->type == VIR_STORAGE_POOL_MPATH)) ||
(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_RBD) &&
(obj->def->type == VIR_STORAGE_POOL_RBD)) ||
+ (MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR) &&
+ (obj->def->type == VIR_STORAGE_POOL_VITASTOR)) ||
(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG) &&
(obj->def->type == VIR_STORAGE_POOL_SHEEPDOG)) ||
(MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER) &&
diff --git a/src/libvirt-storage.c b/src/libvirt-storage.c
index db7660aac4..561df34709 100644
--- a/src/libvirt-storage.c
+++ b/src/libvirt-storage.c
@@ -94,6 +94,7 @@ virStoragePoolGetConnect(virStoragePoolPtr pool)
* VIR_CONNECT_LIST_STORAGE_POOLS_SCSI
* VIR_CONNECT_LIST_STORAGE_POOLS_MPATH
* VIR_CONNECT_LIST_STORAGE_POOLS_RBD
+ * VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR
* VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG
* VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER
* VIR_CONNECT_LIST_STORAGE_POOLS_ZFS
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index bdd30dd65a..5353e00b4a 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -1081,6 +1081,7 @@ libxlMakeNetworkDiskSrcStr(virStorageSource *src,
case VIR_STORAGE_NET_PROTOCOL_SSH:
case VIR_STORAGE_NET_PROTOCOL_VXHS:
case VIR_STORAGE_NET_PROTOCOL_NFS:
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
case VIR_STORAGE_NET_PROTOCOL_LAST:
case VIR_STORAGE_NET_PROTOCOL_NONE:
virReportError(VIR_ERR_NO_SUPPORT,
diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c
index ec8de30c01..61eab9606d 100644
--- a/src/libxl/xen_xl.c
+++ b/src/libxl/xen_xl.c
@@ -1461,6 +1461,7 @@ xenFormatXLDiskSrcNet(virStorageSource *src)
case VIR_STORAGE_NET_PROTOCOL_SSH:
case VIR_STORAGE_NET_PROTOCOL_VXHS:
case VIR_STORAGE_NET_PROTOCOL_NFS:
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
case VIR_STORAGE_NET_PROTOCOL_LAST:
case VIR_STORAGE_NET_PROTOCOL_NONE:
virReportError(VIR_ERR_NO_SUPPORT,
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 32568d4ae6..e625fa0720 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -731,6 +731,38 @@ qemuBlockStorageSourceGetRBDProps(virStorageSource *src,
}
+static virJSONValue *
+qemuBlockStorageSourceGetVitastorProps(virStorageSource *src)
+{
+ virJSONValue *ret = NULL;
+ virStorageNetHostDef *host;
+ size_t i;
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+ g_autofree char *etcd = NULL;
+
+ for (i = 0; i < src->nhosts; i++) {
+ host = src->hosts + i;
+ if ((virStorageNetHostTransport)host->transport != VIR_STORAGE_NET_HOST_TRANS_TCP) {
+ return NULL;
+ }
+ virBufferAsprintf(&buf, i > 0 ? ",%s:%u" : "%s:%u", host->name, host->port);
+ }
+ if (src->nhosts > 0) {
+ etcd = virBufferContentAndReset(&buf);
+ }
+
+ if (virJSONValueObjectAdd(&ret,
+ "S:etcd-host", etcd,
+ "S:etcd-prefix", src->query,
+ "S:config-path", src->configFile,
+ "s:image", src->path,
+ NULL) < 0)
+ return NULL;
+
+ return ret;
+}
+
+
static virJSONValue *
qemuBlockStorageSourceGetSshProps(virStorageSource *src)
{
@@ -1082,6 +1114,12 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource *src,
return NULL;
break;
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
+ driver = "vitastor";
+ if (!(fileprops = qemuBlockStorageSourceGetVitastorProps(src)))
+ return NULL;
+ break;
+
case VIR_STORAGE_NET_PROTOCOL_SSH:
driver = "ssh";
if (!(fileprops = qemuBlockStorageSourceGetSshProps(src)))
@@ -1985,6 +2023,7 @@ qemuBlockGetBackingStoreString(virStorageSource *src,
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
case VIR_STORAGE_NET_PROTOCOL_RBD:
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
case VIR_STORAGE_NET_PROTOCOL_VXHS:
case VIR_STORAGE_NET_PROTOCOL_NFS:
case VIR_STORAGE_NET_PROTOCOL_SSH:
@@ -2365,6 +2404,12 @@ qemuBlockStorageSourceCreateGetStorageProps(virStorageSource *src,
return -1;
break;
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
+ driver = "vitastor";
+ if (!(location = qemuBlockStorageSourceGetVitastorProps(src)))
+ return -1;
+ break;
+
case VIR_STORAGE_NET_PROTOCOL_SSH:
if (srcPriv->nbdkitProcess) {
/* disk creation not yet supported with nbdkit, and even if it
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 0d2548d8d4..91121d6e1f 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -4526,7 +4526,8 @@ qemuDomainValidateStorageSource(virStorageSource *src,
if (src->query &&
(actualType != VIR_STORAGE_TYPE_NETWORK ||
(src->protocol != VIR_STORAGE_NET_PROTOCOL_HTTPS &&
- src->protocol != VIR_STORAGE_NET_PROTOCOL_HTTP))) {
+ src->protocol != VIR_STORAGE_NET_PROTOCOL_HTTP &&
+ src->protocol != VIR_STORAGE_NET_PROTOCOL_VITASTOR))) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("query is supported only with HTTP(S) protocols"));
return -1;
@@ -8954,6 +8955,7 @@ qemuDomainPrepareStorageSourceTLS(virStorageSource *src,
break;
case VIR_STORAGE_NET_PROTOCOL_RBD:
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 8128154749..afb339b9b0 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -662,6 +662,7 @@ qemuSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDef *snapdisk,
case VIR_STORAGE_NET_PROTOCOL_NONE:
case VIR_STORAGE_NET_PROTOCOL_NBD:
case VIR_STORAGE_NET_PROTOCOL_RBD:
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
@@ -887,6 +888,7 @@ qemuSnapshotPrepareDiskInternal(virDomainDiskDef *disk,
case VIR_STORAGE_NET_PROTOCOL_NONE:
case VIR_STORAGE_NET_PROTOCOL_NBD:
case VIR_STORAGE_NET_PROTOCOL_RBD:
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index e19e032427..59f91f4710 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -1626,6 +1626,7 @@ storageVolLookupByPathCallback(virStoragePoolObj *obj,
case VIR_STORAGE_POOL_GLUSTER:
case VIR_STORAGE_POOL_RBD:
+ case VIR_STORAGE_POOL_VITASTOR:
case VIR_STORAGE_POOL_SHEEPDOG:
case VIR_STORAGE_POOL_ZFS:
case VIR_STORAGE_POOL_LAST:
diff --git a/src/storage_file/storage_source_backingstore.c b/src/storage_file/storage_source_backingstore.c
index 80681924ea..8a3ade9ec0 100644
--- a/src/storage_file/storage_source_backingstore.c
+++ b/src/storage_file/storage_source_backingstore.c
@@ -287,6 +287,75 @@ virStorageSourceParseRBDColonString(const char *rbdstr,
}
+static int
+virStorageSourceParseVitastorColonString(const char *colonstr,
+ virStorageSource *src)
+{
+ char *p, *e, *next;
+ g_autofree char *options = NULL;
+
+ /* optionally skip the "vitastor:" prefix if provided */
+ if (STRPREFIX(colonstr, "vitastor:"))
+ colonstr += strlen("vitastor:");
+
+ options = g_strdup(colonstr);
+
+ p = options;
+ while (*p) {
+ /* find : delimiter or end of string */
+ for (e = p; *e && *e != ':'; ++e) {
+ if (*e == '\\') {
+ e++;
+ if (*e == '\0')
+ break;
+ }
+ }
+ if (*e == '\0') {
+ next = e; /* last kv pair */
+ } else {
+ next = e + 1;
+ *e = '\0';
+ }
+
+ if (STRPREFIX(p, "image=")) {
+ src->path = g_strdup(p + strlen("image="));
+ } else if (STRPREFIX(p, "etcd-prefix=")) {
+ src->query = g_strdup(p + strlen("etcd-prefix="));
+ } else if (STRPREFIX(p, "config-path=")) {
+ src->configFile = g_strdup(p + strlen("config-path="));
+ } else if (STRPREFIX(p, "etcd-host=")) {
+ char *h, *sep;
+
+ h = p + strlen("etcd-host=");
+ while (h < e) {
+ for (sep = h; sep < e; ++sep) {
+ if (*sep == '\\' && (sep[1] == ',' ||
+ sep[1] == ';' ||
+ sep[1] == ' ')) {
+ *sep = '\0';
+ sep += 2;
+ break;
+ }
+ }
+
+ if (virStorageSourceRBDAddHost(src, h) < 0)
+ return -1;
+
+ h = sep;
+ }
+ }
+
+ p = next;
+ }
+
+ if (!src->path) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
virStorageSourceParseNBDColonString(const char *nbdstr,
virStorageSource *src)
@@ -399,6 +468,11 @@ virStorageSourceParseBackingColon(virStorageSource *src,
return -1;
break;
+ case VIR_STORAGE_NET_PROTOCOL_VITASTOR:
+ if (virStorageSourceParseVitastorColonString(path, src) < 0)
+ return -1;
+ break;
+
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
case VIR_STORAGE_NET_PROTOCOL_LAST:
case VIR_STORAGE_NET_PROTOCOL_NONE:
@@ -975,6 +1049,54 @@ virStorageSourceParseBackingJSONRBD(virStorageSource *src,
return 0;
}
+static int
+virStorageSourceParseBackingJSONVitastor(virStorageSource *src,
+ virJSONValue *json,
+ const char *jsonstr G_GNUC_UNUSED,
+ int opaque G_GNUC_UNUSED)
+{
+ const char *filename;
+ const char *image = virJSONValueObjectGetString(json, "image");
+ const char *conf = virJSONValueObjectGetString(json, "config-path");
+ const char *etcd_prefix = virJSONValueObjectGetString(json, "etcd-prefix");
+ virJSONValue *servers = virJSONValueObjectGetArray(json, "server");
+ size_t nservers;
+ size_t i;
+
+ src->type = VIR_STORAGE_TYPE_NETWORK;
+ src->protocol = VIR_STORAGE_NET_PROTOCOL_VITASTOR;
+
+ /* legacy syntax passed via 'filename' option */
+ if ((filename = virJSONValueObjectGetString(json, "filename")))
+ return virStorageSourceParseVitastorColonString(filename, src);
+
+ if (!image) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("missing image name in Vitastor backing volume "
+ "JSON specification"));
+ return -1;
+ }
+
+ src->path = g_strdup(image);
+ src->configFile = g_strdup(conf);
+ src->query = g_strdup(etcd_prefix);
+
+ if (servers) {
+ nservers = virJSONValueArraySize(servers);
+
+ src->hosts = g_new0(virStorageNetHostDef, nservers);
+ src->nhosts = nservers;
+
+ for (i = 0; i < nservers; i++) {
+ if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts + i,
+ virJSONValueArrayGet(servers, i)) < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static int
virStorageSourceParseBackingJSONRaw(virStorageSource *src,
virJSONValue *json,
@@ -1152,6 +1274,7 @@ static const struct virStorageSourceJSONDriverParser jsonParsers[] = {
{"sheepdog", false, virStorageSourceParseBackingJSONSheepdog, 0},
{"ssh", false, virStorageSourceParseBackingJSONSSH, 0},
{"rbd", false, virStorageSourceParseBackingJSONRBD, 0},
+ {"vitastor", false, virStorageSourceParseBackingJSONVitastor, 0},
{"raw", true, virStorageSourceParseBackingJSONRaw, 0},
{"nfs", false, virStorageSourceParseBackingJSONNFS, 0},
{"vxhs", false, virStorageSourceParseBackingJSONVxHS, 0},
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 25335d9002..cf54069fbe 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -7340,6 +7340,7 @@ testStorageVolumeTypeForPool(int pooltype)
case VIR_STORAGE_POOL_ISCSI_DIRECT:
case VIR_STORAGE_POOL_GLUSTER:
case VIR_STORAGE_POOL_RBD:
+ case VIR_STORAGE_POOL_VITASTOR:
return VIR_STORAGE_VOL_NETWORK;
case VIR_STORAGE_POOL_LOGICAL:
case VIR_STORAGE_POOL_DISK:
diff --git a/tests/storagepoolcapsschemadata/poolcaps-fs.xml b/tests/storagepoolcapsschemadata/poolcaps-fs.xml
index eee75af746..8bd0a57bdd 100644
--- a/tests/storagepoolcapsschemadata/poolcaps-fs.xml
+++ b/tests/storagepoolcapsschemadata/poolcaps-fs.xml
@@ -204,4 +204,11 @@
</enum>
</volOptions>
</pool>
+ <pool type='vitastor' supported='no'>
+ <volOptions>
+ <defaultFormat type='raw'/>
+ <enum name='targetFormatType'>
+ </enum>
+ </volOptions>
+ </pool>
</storagepoolCapabilities>
diff --git a/tests/storagepoolcapsschemadata/poolcaps-full.xml b/tests/storagepoolcapsschemadata/poolcaps-full.xml
index 805950a937..852df0de16 100644
--- a/tests/storagepoolcapsschemadata/poolcaps-full.xml
+++ b/tests/storagepoolcapsschemadata/poolcaps-full.xml
@@ -204,4 +204,11 @@
</enum>
</volOptions>
</pool>
+ <pool type='vitastor' supported='yes'>
+ <volOptions>
+ <defaultFormat type='raw'/>
+ <enum name='targetFormatType'>
+ </enum>
+ </volOptions>
+ </pool>
</storagepoolCapabilities>
diff --git a/tests/storagepoolxml2argvtest.c b/tests/storagepoolxml2argvtest.c
index d5c2531ab8..b19308ac38 100644
--- a/tests/storagepoolxml2argvtest.c
+++ b/tests/storagepoolxml2argvtest.c
@@ -57,6 +57,7 @@ testCompareXMLToArgvFiles(bool shouldFail,
case VIR_STORAGE_POOL_GLUSTER:
case VIR_STORAGE_POOL_ZFS:
case VIR_STORAGE_POOL_VSTORAGE:
+ case VIR_STORAGE_POOL_VITASTOR:
case VIR_STORAGE_POOL_LAST:
default:
VIR_TEST_DEBUG("pool type '%s' has no xml2argv test", defTypeStr);
diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c
index 2010ef1356..072e2ff9e8 100644
--- a/tools/virsh-pool.c
+++ b/tools/virsh-pool.c
@@ -1187,6 +1187,9 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
case VIR_STORAGE_POOL_VSTORAGE:
flags |= VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE;
break;
+ case VIR_STORAGE_POOL_VITASTOR:
+ flags |= VIR_CONNECT_LIST_STORAGE_POOLS_VITASTOR;
+ break;
case VIR_STORAGE_POOL_LAST:
break;
}

View File

@@ -7,22 +7,24 @@ set -e
VITASTOR=$(dirname $0)
VITASTOR=$(realpath "$VITASTOR/..")
EL=$(rpm --eval '%dist')
if [ "$EL" = ".el8" ]; then
REL=$(rpm --eval '%dist')
REL=${REL##.}
if [ "$REL" = "el8" ]; then
# CentOS 8
. /opt/rh/gcc-toolset-9/enable
elif [ "$EL" = ".el7" ]; then
elif [ "$REL" = "el7" ]; then
# CentOS 7
. /opt/rh/devtoolset-9/enable
fi
cd ~/rpmbuild/SPECS
rpmbuild -bp fio.spec
cd $VITASTOR
VER=$(grep ^Version: rpm/vitastor-el7.spec | awk '{print $2}')
VER=$(grep ^Version: rpm/vitastor-$REL.spec | awk '{print $2}')
rm -rf fio
ln -s ~/rpmbuild/BUILD/fio*/ fio
sh copy-fio-includes.sh
rm fio
mv fio-copy fio
FIO=`rpm -qi fio | perl -e 'while(<>) { /^Epoch[\s:]+(\S+)/ && print "$1:"; /^Version[\s:]+(\S+)/ && print $1; /^Release[\s:]+(\S+)/ && print "-$1"; }'`
perl -i -pe 's/(Requires:\s*fio)([^\n]+)?/$1 = '$FIO'/' $VITASTOR/rpm/vitastor-el$EL.spec
tar --transform "s#^#vitastor-$VER/#" --exclude 'rpm/*.rpm' -czf $VITASTOR/../vitastor-$VER$(rpm --eval '%dist').tar.gz *
perl -i -pe 's/(Requires:\s*fio)([^\n]+)?/$1 = '$FIO'/' $VITASTOR/rpm/vitastor-$REL.spec
tar --transform "s#^#vitastor-$VER/#" --exclude 'rpm/*.rpm' -czf $VITASTOR/../vitastor-$VER.$REL.tar.gz $(ls | grep -v packages)

16
rpm/vitastor-build.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -e -x
REL=$(rpm --eval '%dist')
REL=${REL##.}
cd /root/vitastor/rpm
./build-tarball.sh
VER=$(grep ^Version: vitastor-$REL.spec | awk '{print $2}')
cp /root/vitastor-$VER.$REL.tar.gz ~/rpmbuild/SOURCES
cp vitastor-$REL.spec ~/rpmbuild/SPECS/vitastor.spec
cd ~/rpmbuild/SPECS/
rpmbuild -ba vitastor.spec
mkdir -p /root/vitastor/packages/vitastor-$REL
rm -rf /root/vitastor/packages/vitastor-$REL/*
cp ~/rpmbuild/RPMS/*/*vitastor* /root/vitastor/packages/vitastor-$REL/
cp ~/rpmbuild/SRPMS/vitastor* /root/vitastor/packages/vitastor-$REL/

View File

@@ -1,5 +1,8 @@
# Build packages for CentOS 7 inside a container
# cd ..; podman build -t vitastor-el7 -v `pwd`/packages:/root/packages -f rpm/vitastor-el7.Dockerfile .
# cd ..
# docker build -t vitastor-buildenv:el7 -f rpm/vitastor-el7.Dockerfile .
# docker run -i --rm -v ./:/root/vitastor vitastor-buildenv:el7 /root/vitastor/rpm/vitastor-build.sh
# localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
FROM centos:7
@@ -7,7 +10,9 @@ FROM centos:7
WORKDIR /root
RUN rm -f /etc/yum.repos.d/CentOS-Media.repo
RUN sed -i 's/^mirrorlist=/#mirrorlist=/; s!#baseurl=http://mirror.centos.org/centos/\$releasever!baseurl=http://vault.centos.org/7.9.2009!' /etc/yum.repos.d/*.repo
RUN yum -y --enablerepo=extras install centos-release-scl epel-release yum-utils rpm-build
RUN perl -i -pe 's!mirrorlist=!#mirrorlist=!s; s!#\s*baseurl=http://mirror.centos.org!baseurl=http://vault.centos.org!' /etc/yum.repos.d/CentOS-SCLo-scl*.repo
RUN yum -y install https://vitastor.io/rpms/centos/7/vitastor-release-1.0-1.el7.noarch.rpm
RUN yum -y install devtoolset-9-gcc-c++ devtoolset-9-libatomic-devel gcc make cmake gperftools-devel \
fio rh-nodejs12 jerasure-devel libisa-l-devel gf-complete-devel rdma-core-devel libnl3-devel
@@ -30,18 +35,3 @@ RUN set -e; \
cp ~/rpmbuild/SRPMS/liburing* /root/packages/liburing-el7/
RUN rpm -i `ls /root/packages/liburing-el7/liburing-*.x86_64.rpm | grep -v debug`
ADD . /root/vitastor
RUN set -e; \
cd /root/vitastor/rpm; \
sh build-tarball.sh; \
VER=$(grep ^Version: vitastor-el7.spec | awk '{print $2}'); \
cp /root/vitastor-$VER.el7.tar.gz ~/rpmbuild/SOURCES; \
cp vitastor-el7.spec ~/rpmbuild/SPECS/vitastor.spec; \
cd ~/rpmbuild/SPECS/; \
rpmbuild -ba vitastor.spec; \
mkdir -p /root/packages/vitastor-el7; \
rm -rf /root/packages/vitastor-el7/*; \
cp ~/rpmbuild/RPMS/*/*vitastor* /root/packages/vitastor-el7/; \
cp ~/rpmbuild/SRPMS/vitastor* /root/packages/vitastor-el7/

View File

@@ -1,11 +1,11 @@
Name: vitastor
Version: 2.2.0
Version: 2.2.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-2.2.0.el7.tar.gz
Source0: vitastor-2.2.3.el7.tar.gz
BuildRequires: liburing-devel >= 0.6
BuildRequires: gperftools-devel
@@ -82,7 +82,7 @@ Vitastor library headers for development.
Summary: Vitastor - fio drivers
Group: Development/Libraries
Requires: vitastor-client = %{version}-%{release}
Requires: fio = 3.7-1.el7
Requires: fio = 3.7-2.el7
%description -n vitastor-fio

View File

@@ -1,5 +1,7 @@
# Build packages for CentOS 8 inside a container
# cd ..; podman build -t vitastor-el8 -v `pwd`/packages:/root/packages -f rpm/vitastor-el8.Dockerfile .
# cd ..
# docker build -t vitastor-buildenv:el8 -f rpm/vitastor-el8.Dockerfile .
# docker run -i --rm -v ./:/root/vitastor vitastor-buildenv:el8 /root/vitastor/rpm/vitastor-build.sh
FROM centos:8
@@ -29,18 +31,3 @@ RUN set -e; \
cp ~/rpmbuild/SRPMS/liburing* /root/packages/liburing-el8/
RUN rpm -i `ls /root/packages/liburing-el8/liburing-*.x86_64.rpm | grep -v debug`
ADD . /root/vitastor
RUN set -e; \
cd /root/vitastor/rpm; \
sh build-tarball.sh; \
VER=$(grep ^Version: vitastor-el8.spec | awk '{print $2}'); \
cp /root/vitastor-$VER.el8.tar.gz ~/rpmbuild/SOURCES; \
cp vitastor-el8.spec ~/rpmbuild/SPECS/vitastor.spec; \
cd ~/rpmbuild/SPECS/; \
rpmbuild -ba vitastor.spec; \
mkdir -p /root/packages/vitastor-el8; \
rm -rf /root/packages/vitastor-el8/*; \
cp ~/rpmbuild/RPMS/*/*vitastor* /root/packages/vitastor-el8/; \
cp ~/rpmbuild/SRPMS/vitastor* /root/packages/vitastor-el8/

View File

@@ -1,11 +1,11 @@
Name: vitastor
Version: 2.2.0
Version: 2.2.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-2.2.0.el8.tar.gz
Source0: vitastor-2.2.3.el8.tar.gz
BuildRequires: liburing-devel >= 0.6
BuildRequires: gperftools-devel
@@ -80,7 +80,7 @@ Vitastor library headers for development.
Summary: Vitastor - fio drivers
Group: Development/Libraries
Requires: vitastor-client = %{version}-%{release}
Requires: fio = 3.7-3.el8
Requires: fio = 3.19-3.el8
%description -n vitastor-fio

View File

@@ -1,5 +1,7 @@
# Build packages for AlmaLinux 9 inside a container
# cd ..; podman build -t vitastor-el9 -v `pwd`/packages:/root/packages -f rpm/vitastor-el9.Dockerfile .
# cd ..
# docker build -t vitastor-buildenv:el9 -f rpm/vitastor-el9.Dockerfile .
# docker run -i --rm -v ./:/root/vitastor vitastor-buildenv:el9 /root/vitastor/rpm/vitastor-build.sh
FROM almalinux:9
@@ -12,18 +14,3 @@ RUN dnf -y install gcc-c++ gperftools-devel fio nodejs rpm-build jerasure-devel
RUN dnf download --source fio
RUN rpm --nomd5 -i fio*.src.rpm
RUN cd ~/rpmbuild/SPECS && dnf builddep -y --spec fio.spec
ADD . /root/vitastor
RUN set -e; \
cd /root/vitastor/rpm; \
sh build-tarball.sh; \
VER=$(grep ^Version: vitastor-el9.spec | awk '{print $2}'); \
cp /root/vitastor-$VER.el9.tar.gz ~/rpmbuild/SOURCES; \
cp vitastor-el9.spec ~/rpmbuild/SPECS/vitastor.spec; \
cd ~/rpmbuild/SPECS/; \
rpmbuild -ba vitastor.spec; \
mkdir -p /root/packages/vitastor-el9; \
rm -rf /root/packages/vitastor-el9/*; \
cp ~/rpmbuild/RPMS/*/*vitastor* /root/packages/vitastor-el9/; \
cp ~/rpmbuild/SRPMS/vitastor* /root/packages/vitastor-el9/

View File

@@ -1,11 +1,11 @@
Name: vitastor
Version: 2.2.0
Version: 2.2.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-2.2.0.el9.tar.gz
Source0: vitastor-2.2.3.el9.tar.gz
BuildRequires: liburing-devel >= 0.6
BuildRequires: gperftools-devel

View File

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

View File

@@ -42,8 +42,7 @@
#define BS_OP_DELETE 6
#define BS_OP_LIST 7
#define BS_OP_ROLLBACK 8
#define BS_OP_SYNC_STAB_ALL 9
#define BS_OP_MAX 9
#define BS_OP_MAX 8
#define BS_OP_PRIVATE_DATA_SIZE 256
@@ -113,14 +112,6 @@ Input:
Output:
- retval = 0 or negative error number (-ENOENT if no such version for stabilize)
## BS_OP_SYNC_STAB_ALL
ONLY FOR TESTS! Sync and mark all unstable object versions as stable, at once.
Input: Nothing except opcode
Output:
- retval = 0 or negative error number (-EINVAL)
## BS_OP_LIST
Get a list of all objects in this Blockstore.
@@ -147,7 +138,7 @@ Output:
struct blockstore_op_t
{
// operation
uint64_t opcode;
uint64_t opcode = 0;
// finish callback
std::function<void (blockstore_op_t*)> callback;
union __attribute__((__packed__))
@@ -171,9 +162,9 @@ struct blockstore_op_t
uint32_t list_stable_limit;
};
};
void *buf;
void *bitmap;
int retval;
void *buf = NULL;
void *bitmap = NULL;
int retval = 0;
uint8_t private_data[BS_OP_PRIVATE_DATA_SIZE];
};

View File

@@ -343,44 +343,6 @@ void blockstore_impl_t::enqueue_op(blockstore_op_t *op)
ringloop->set_immediate([op]() { std::function<void (blockstore_op_t*)>(op->callback)(op); });
return;
}
if (op->opcode == BS_OP_SYNC_STAB_ALL)
{
std::function<void(blockstore_op_t*)> *old_callback = new std::function<void(blockstore_op_t*)>(op->callback);
op->opcode = BS_OP_SYNC;
op->callback = [this, old_callback](blockstore_op_t *op)
{
if (op->retval >= 0 && unstable_writes.size() > 0)
{
op->opcode = BS_OP_STABLE;
op->len = unstable_writes.size();
obj_ver_id *vers = new obj_ver_id[op->len];
op->buf = vers;
int i = 0;
for (auto it = unstable_writes.begin(); it != unstable_writes.end(); it++, i++)
{
vers[i] = {
.oid = it->first,
.version = it->second,
};
}
unstable_writes.clear();
op->callback = [old_callback](blockstore_op_t *op)
{
obj_ver_id *vers = (obj_ver_id*)op->buf;
delete[] vers;
op->buf = NULL;
(*old_callback)(op);
delete old_callback;
};
this->enqueue_op(op);
}
else
{
(*old_callback)(op);
delete old_callback;
}
};
}
if ((op->opcode == BS_OP_WRITE || op->opcode == BS_OP_WRITE_STABLE || op->opcode == BS_OP_DELETE) && !enqueue_write(op))
{
ringloop->set_immediate([op]() { std::function<void (blockstore_op_t*)>(op->callback)(op); });

View File

@@ -5,14 +5,14 @@
//
// Initialize storage for tests:
//
// dd if=/dev/zero of=test_data.bin bs=1024 count=1048576
// dd if=/dev/zero of=test_meta.bin bs=1024 count=256
// dd if=/dev/zero of=test_journal.bin bs=1024 count=4096
// dd if=/dev/zero of=test_data.bin bs=1M count=1024
//
// Random write:
//
// fio -thread -ioengine=./libfio_blockstore.so -name=test -bs=4k -direct=1 -fsync=16 -iodepth=16 -rw=randwrite \
// -bs_config='{"data_device":"./test_data.bin"}' -size=1000M
// [LD_PRELOAD=libasan.so.8] \
// fio -name=test -thread -ioengine=../build/src/blockstore/libfio_vitastor_blk.so \
// -bs=4k -direct=1 -rw=randwrite -iodepth=16 -size=900M -loops=10 \
// -bs_config='{"data_device":"./test_data.bin","meta_offset":0,"journal_offset":16777216,"data_offset":33554432,"disable_data_fsync":true,"immediate_commit":"all","journal_no_same_sector_overwrites":true}'
//
// Linear write:
//
@@ -38,12 +38,14 @@ struct bs_data
std::vector<io_u*> completed;
int op_n = 0, inflight = 0;
bool last_sync = false;
bool trace = false;
};
struct bs_options
{
int __pad;
char *json_config = NULL;
int trace = 0;
};
static struct fio_option options[] = {
@@ -56,6 +58,16 @@ static struct fio_option options[] = {
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_FILENAME,
},
{
.name = "bs_trace",
.lname = "trace",
.type = FIO_OPT_BOOL,
.off1 = offsetof(struct bs_options, trace),
.help = "Trace operations",
.def = "0",
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_FILENAME,
},
{
.name = NULL,
},
@@ -63,6 +75,7 @@ static struct fio_option options[] = {
static int bs_setup(struct thread_data *td)
{
bs_options *o = (bs_options*)td->eo;
bs_data *bsd;
//fio_file *f;
//int r;
@@ -83,6 +96,8 @@ static int bs_setup(struct thread_data *td)
td->o.open_files++;
}
bsd->trace = o->trace ? true : false;
//f = td->files[0];
//f->real_file_size = size;
return 0;
@@ -176,20 +191,19 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io)
op->version = UINT64_MAX; // last unstable
op->offset = io->offset % bsd->bs->get_block_size();
op->len = io->xfer_buflen;
op->callback = [io](blockstore_op_t *op)
op->callback = [io, n = bsd->op_n](blockstore_op_t *op)
{
io->error = op->retval < 0 ? -op->retval : 0;
bs_data *bsd = (bs_data*)io->engine_data;
bsd->inflight--;
bsd->completed.push_back(io);
#ifdef BLOCKSTORE_DEBUG
printf("--- OP_READ %llx n=%d retval=%d\n", io, n, op->retval);
#endif
if (bsd->trace)
printf("--- OP_READ %zx n=%d retval=%d\n", (size_t)op, n, op->retval);
delete op;
};
break;
case DDIR_WRITE:
op->opcode = BS_OP_WRITE;
op->opcode = BS_OP_WRITE_STABLE;
op->buf = io->xfer_buf;
op->oid = {
.inode = 1,
@@ -198,30 +212,28 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io)
op->version = 0; // assign automatically
op->offset = io->offset % bsd->bs->get_block_size();
op->len = io->xfer_buflen;
op->callback = [io](blockstore_op_t *op)
op->callback = [io, n = bsd->op_n](blockstore_op_t *op)
{
io->error = op->retval < 0 ? -op->retval : 0;
bs_data *bsd = (bs_data*)io->engine_data;
bsd->inflight--;
bsd->completed.push_back(io);
#ifdef BLOCKSTORE_DEBUG
printf("--- OP_WRITE %llx n=%d retval=%d\n", io, n, op->retval);
#endif
if (bsd->trace)
printf("--- OP_WRITE %zx n=%d retval=%d\n", (size_t)op, n, op->retval);
delete op;
};
bsd->last_sync = false;
break;
case DDIR_SYNC:
op->opcode = BS_OP_SYNC_STAB_ALL;
op->callback = [io](blockstore_op_t *op)
op->opcode = BS_OP_SYNC;
op->callback = [io, n = bsd->op_n](blockstore_op_t *op)
{
bs_data *bsd = (bs_data*)io->engine_data;
io->error = op->retval < 0 ? -op->retval : 0;
bsd->completed.push_back(io);
bsd->inflight--;
#ifdef BLOCKSTORE_DEBUG
printf("--- OP_SYNC %llx n=%d retval=%d\n", io, n, op->retval);
#endif
if (bsd->trace)
printf("--- OP_SYNC %zx n=%d retval=%d\n", (size_t)op, n, op->retval);
delete op;
};
bsd->last_sync = true;
@@ -232,9 +244,8 @@ static enum fio_q_status bs_queue(struct thread_data *td, struct io_u *io)
return FIO_Q_COMPLETED;
}
#ifdef BLOCKSTORE_DEBUG
printf("+++ %s %llx n=%d\n", op->opcode == OP_READ ? "OP_READ" : (op->opcode == OP_WRITE ? "OP_WRITE" : "OP_SYNC"), io, n);
#endif
if (bsd->trace)
printf("+++ %s %zx n=%d\n", op->opcode == BS_OP_READ ? "OP_READ" : (op->opcode == BS_OP_WRITE_STABLE ? "OP_WRITE" : "OP_SYNC"), (size_t)op, bsd->op_n);
io->error = 0;
bsd->inflight++;
bsd->bs->enqueue_op(op);

View File

@@ -57,6 +57,7 @@ cluster_client_t::cluster_client_t(ring_loop_t *ringloop, timerfd_manager_t *tfd
st_cli.on_load_config_hook = [this](json11::Json::object & cfg) { on_load_config_hook(cfg); };
st_cli.on_change_osd_state_hook = [this](uint64_t peer_osd) { on_change_osd_state_hook(peer_osd); };
st_cli.on_change_pool_config_hook = [this]() { on_change_pool_config_hook(); };
st_cli.on_change_pg_config_hook = [this]() { on_change_pool_config_hook(); };
st_cli.on_change_pg_state_hook = [this](pool_id_t pool_id, pg_num_t pg_num, osd_num_t prev_primary) { on_change_pg_state_hook(pool_id, pg_num, prev_primary); };
st_cli.on_change_node_placement_hook = [this]() { on_change_node_placement_hook(); };
st_cli.on_load_pgs_hook = [this](bool success) { on_load_pgs_hook(success); };
@@ -563,7 +564,7 @@ osd_num_t cluster_client_t::select_nearest_osd(const std::vector<osd_num_t> & os
void cluster_client_t::on_load_pgs_hook(bool success)
{
for (auto pool_item: st_cli.pool_config)
for (auto & pool_item: st_cli.pool_config)
{
pg_counts[pool_item.first] = pool_item.second.real_pg_count;
}
@@ -583,10 +584,15 @@ void cluster_client_t::on_load_pgs_hook(bool success)
void cluster_client_t::on_change_pool_config_hook()
{
for (auto pool_item: st_cli.pool_config)
for (auto & pool_item: st_cli.pool_config)
{
if (pg_counts[pool_item.first] != pool_item.second.real_pg_count)
{
if (log_level > 2 && pg_counts[pool_item.first])
{
printf("Pool %u (%s) PG count changed from %lu to %lu\n", pool_item.first, pool_item.second.name.c_str(),
pg_counts[pool_item.first], pool_item.second.real_pg_count);
}
// At this point, all pool operations should have been suspended
// And now they have to be resliced!
for (auto op = op_queue_head; op; op = op->next)

View File

@@ -1056,6 +1056,10 @@ void etcd_state_client_t::parse_state(const etcd_kv_t & kv)
}
pool_item.second.real_pg_count = n;
}
if (on_change_pg_config_hook)
{
on_change_pg_config_hook();
}
}
else if (key.substr(0, etcd_prefix.length()+12) == etcd_prefix+"/pg/history/")
{
@@ -1182,9 +1186,7 @@ void etcd_state_client_t::parse_state(const etcd_kv_t & kv)
osd_num_t peer_osd = std::stoull(key.substr(etcd_prefix.length()+11));
if (peer_osd > 0)
{
if (value.is_object() && value["state"] == "up" &&
value["addresses"].is_array() &&
value["port"].int64_value() > 0 && value["port"].int64_value() < 65536)
if (value.is_object() && value["state"] == "up")
{
this->peer_states[peer_osd] = value;
this->seen_peers.insert(peer_osd);

View File

@@ -142,6 +142,7 @@ public:
std::function<json11::Json()> load_pgs_checks_hook;
std::function<void(bool)> on_load_pgs_hook;
std::function<void()> on_change_pool_config_hook;
std::function<void()> on_change_pg_config_hook;
std::function<void(pool_id_t)> on_change_backfillfull_hook;
std::function<void(pool_id_t, pg_num_t, osd_num_t)> on_change_pg_state_hook;
std::function<void(pool_id_t, pg_num_t)> on_change_pg_history_hook;

View File

@@ -188,7 +188,7 @@ void osd_messenger_t::init()
auto cl = cl_it->second;
cl_it++;
auto peer_fd = cl->peer_fd;
if (!cl->osd_num || cl->peer_state != PEER_CONNECTED && cl->peer_state != PEER_RDMA)
if (!cl->osd_num && !cl->in_osd_num || cl->peer_state != PEER_CONNECTED && cl->peer_state != PEER_RDMA)
{
// Do not run keepalive on regular clients
continue;
@@ -199,7 +199,7 @@ void osd_messenger_t::init()
if (!cl->ping_time_remaining)
{
// Ping timed out, stop the client
fprintf(stderr, "Ping timed out for OSD %ju (client %d), disconnecting peer\n", cl->osd_num, cl->peer_fd);
fprintf(stderr, "Ping timed out for OSD %ju (client %d), disconnecting peer\n", cl->in_osd_num ? cl->in_osd_num : cl->osd_num, cl->peer_fd);
stop_client(peer_fd, true);
// Restart iterator because it may be invalidated
cl_it = clients.upper_bound(peer_fd);
@@ -230,7 +230,7 @@ void osd_messenger_t::init()
return;
}
int fail_fd = (op->reply.hdr.retval != 0 ? op->peer_fd : -1);
auto fail_osd_num = cl->osd_num;
auto fail_osd_num = cl->in_osd_num ? cl->in_osd_num : cl->osd_num;
cl->ping_time_remaining = 0;
delete op;
if (fail_fd >= 0)

View File

@@ -60,6 +60,7 @@ struct osd_client_t
int ping_time_remaining = 0;
int idle_time_remaining = 0;
osd_num_t osd_num = 0;
osd_num_t in_osd_num = 0;
bool is_incoming = false;
void *in_buf = NULL;
@@ -98,6 +99,7 @@ struct osd_client_t
std::vector<osd_op_t*> zc_free_list;
~osd_client_t();
void cancel_ops();
};
struct osd_wanted_peer_t
@@ -235,6 +237,7 @@ public:
void outbox_push(osd_op_t *cur_op);
std::function<void(osd_op_t*)> exec_op;
std::function<void(osd_num_t)> repeer_pgs;
std::function<void(osd_num_t)> break_pg_locks;
std::function<bool(osd_client_t*, json11::Json)> check_config_hook;
void read_requests();
void send_replies();

View File

@@ -173,6 +173,7 @@ struct osd_op_t
osd_op_buf_list_t iov;
~osd_op_t();
void cancel();
bool is_recovery_related();
};

View File

@@ -510,7 +510,6 @@ void osd_messenger_t::rdmacm_established(rdma_cm_event *ev)
rc->qp = conn->cmid->qp;
// And an osd_client_t
auto cl = new osd_client_t();
cl->is_incoming = true;
cl->peer_addr = conn->parsed_addr;
cl->peer_port = conn->rdmacm_port;
cl->peer_fd = conn->peer_fd;

View File

@@ -8,11 +8,12 @@ void osd_messenger_t::read_requests()
for (int i = 0; i < read_ready_clients.size(); i++)
{
int peer_fd = read_ready_clients[i];
osd_client_t *cl = clients[peer_fd];
if (cl->read_msg.msg_iovlen)
auto cl_it = clients.find(peer_fd);
if (cl_it == clients.end() || !cl_it->second || cl_it->second->read_msg.msg_iovlen)
{
continue;
}
auto cl = cl_it->second;
if (cl->read_remaining < receive_buffer_size)
{
cl->read_iov.iov_base = cl->in_buf;
@@ -33,8 +34,12 @@ void osd_messenger_t::read_requests()
auto iothread = iothreads.size() ? iothreads[peer_fd % iothreads.size()] : NULL;
io_uring_sqe sqe_local;
ring_data_t data_local;
sqe_local.user_data = (uint64_t)&data_local;
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
if (iothread)
{
sqe_local = { .user_data = (uint64_t)&data_local };
data_local = {};
}
if (!sqe)
{
cl->read_msg.msg_iovlen = 0;
@@ -56,7 +61,8 @@ void osd_messenger_t::read_requests()
{
result = -errno;
}
handle_read(result, cl);
// like set_immediate
tfd->set_timer_us(0, false, [this, result, cl](int){ handle_read(result, cl); });
}
}
read_ready_clients.clear();
@@ -228,7 +234,7 @@ bool osd_messenger_t::handle_finished_read(osd_client_t *cl)
{
if (cl->read_op->req.hdr.id != cl->read_op_id)
{
fprintf(stderr, "Warning: operation sequencing is broken on client %d, stopping client\n", cl->peer_fd);
fprintf(stderr, "Warning: operation sequencing is broken on client %d: expected num %ju, got %ju, stopping client\n", cl->peer_fd, cl->read_op_id, cl->read_op->req.hdr.id);
stop_client(cl->peer_fd);
return false;
}

View File

@@ -194,12 +194,14 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
auto iothread = iothreads.size() ? iothreads[peer_fd % iothreads.size()] : NULL;
io_uring_sqe sqe_local;
ring_data_t data_local;
sqe_local.user_data = (uint64_t)&data_local;
io_uring_sqe* sqe = (iothread ? &sqe_local : ringloop->get_sqe());
if (!sqe)
if (iothread)
{
return false;
sqe_local = { .user_data = (uint64_t)&data_local };
data_local = {};
}
if (!sqe)
return false;
cl->write_msg.msg_iov = cl->send_list.data();
cl->write_msg.msg_iovlen = cl->send_list.size() < IOV_MAX ? cl->send_list.size() : IOV_MAX;
cl->refs++;
@@ -237,7 +239,8 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
{
result = -errno;
}
handle_send(result, false, false, cl);
// like set_immediate
tfd->set_timer_us(0, false, [this, result, cl](int){ handle_send(result, false, false, cl); });
}
return true;
}

View File

@@ -9,38 +9,37 @@
#include "msgr_rdma.h"
#endif
void osd_messenger_t::cancel_osd_ops(osd_client_t *cl)
void osd_client_t::cancel_ops()
{
std::vector<osd_op_t*> cancel_ops;
cancel_ops.resize(cl->sent_ops.size());
cancel_ops.resize(sent_ops.size());
int i = 0;
for (auto p: cl->sent_ops)
for (auto p: sent_ops)
{
cancel_ops[i++] = p.second;
}
cl->sent_ops.clear();
cl->outbox.clear();
sent_ops.clear();
for (auto op: cancel_ops)
{
cancel_op(op);
op->cancel();
}
}
void osd_messenger_t::cancel_op(osd_op_t *op)
void osd_op_t::cancel()
{
if (op->op_type == OSD_OP_OUT)
if (op_type == OSD_OP_OUT && callback)
{
op->reply.hdr.magic = SECONDARY_OSD_REPLY_MAGIC;
op->reply.hdr.id = op->req.hdr.id;
op->reply.hdr.opcode = op->req.hdr.opcode;
op->reply.hdr.retval = -EPIPE;
// Copy lambda to be unaffected by `delete op`
std::function<void(osd_op_t*)>(op->callback)(op);
reply.hdr.magic = SECONDARY_OSD_REPLY_MAGIC;
reply.hdr.id = req.hdr.id;
reply.hdr.opcode = req.hdr.opcode;
reply.hdr.retval = -EPIPE;
// Copy lambda to be unaffected by `delete this`
(std::function<void(osd_op_t*)>(callback))(this);
}
else
{
// This function is only called in stop_client(), so it's fine to destroy the operation
delete op;
delete this;
}
}
@@ -63,6 +62,10 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
{
fprintf(stderr, "[OSD %ju] Stopping client %d (OSD peer %ju)\n", osd_num, peer_fd, cl->osd_num);
}
else if (cl->in_osd_num)
{
fprintf(stderr, "[OSD %ju] Stopping client %d (incoming OSD peer %ju)\n", osd_num, peer_fd, cl->in_osd_num);
}
else
{
fprintf(stderr, "[OSD %ju] Stopping client %d (regular client)\n", osd_num, peer_fd);
@@ -73,8 +76,12 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
cl->peer_state = PEER_STOPPED;
if (cl->osd_num)
{
// ...and forget OSD peer
osd_peer_fds.erase(cl->osd_num);
auto osd_it = osd_peer_fds.find(cl->osd_num);
if (osd_it != osd_peer_fds.end() && osd_it->second == cl->peer_fd)
{
// ...and forget OSD peer
osd_peer_fds.erase(osd_it);
}
}
#ifndef __MOCK__
// Then remove FD from the eventloop so we don't accidentally read something
@@ -101,30 +108,17 @@ void osd_messenger_t::stop_client(int peer_fd, bool force, bool force_delete)
}
}
#endif
if (cl->in_osd_num && break_pg_locks)
{
// Break PG locks
break_pg_locks(cl->in_osd_num);
}
if (cl->osd_num)
{
// Then repeer PGs because cancel_op() callbacks can try to perform
// some actions and we need correct PG states to not do something silly
repeer_pgs(cl->osd_num);
}
// Then cancel all operations
if (cl->read_op)
{
if (!cl->read_op->callback)
{
delete cl->read_op;
}
else
{
cancel_op(cl->read_op);
}
cl->read_op = NULL;
}
if (cl->osd_num)
{
// Cancel outbound operations
cancel_osd_ops(cl);
}
// Find the item again because it can be invalidated at this point
it = clients.find(peer_fd);
if (it != clients.end())
@@ -149,6 +143,17 @@ osd_client_t::~osd_client_t()
close(peer_fd);
peer_fd = -1;
}
// Then cancel all operations
// Operations have to be canceled only after clearing all references to osd_client_t
// because otherwise their buffers may be still present in io_uring asynchronous requests
if (read_op)
{
// read_op may be an incoming op or a continued response for an outbound op
read_op->cancel();
read_op = NULL;
}
// Cancel outbound ops
cancel_ops();
#ifndef __MOCK__
#ifdef WITH_RDMA
if (rdma_conn)

View File

@@ -14,6 +14,7 @@
#endif
#include "block/block_int.h"
#include "qapi/error.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h"
@@ -58,12 +59,14 @@ typedef struct VitastorClient
{
void *proxy;
int uring_eventfd;
int auto_loop;
void *watch;
char *config_path;
char *etcd_host;
char *etcd_prefix;
char *image;
char *file_mirror_path;
int skip_parents;
uint64_t inode;
uint64_t pool;
@@ -155,16 +158,19 @@ static void qemu_vitastor_unescape(char *src)
// vitastor[:key=value]*
// vitastor[:etcd_host=127.0.0.1]:inode=1:pool=1[:rdma_gid_index=3]
// vitastor:config_path=/etc/vitastor/vitastor.conf:image=testimg
// vitastor://?config_path=/etc/vitastor/vitastor.conf&image=testimg
static void vitastor_parse_filename(const char *filename, QDict *options, Error **errp)
{
const char *start;
char *p, *buf;
if (!strstart(filename, "vitastor:", &start))
int url_style = strstart(filename, "vitastor://?", &start);
if (!url_style && !strstart(filename, "vitastor:", &start))
{
error_setg(errp, "File name must start with 'vitastor:'");
return;
}
char delim = url_style ? '&' : ':';
buf = g_strdup(start);
p = buf;
@@ -184,7 +190,7 @@ static void vitastor_parse_filename(const char *filename, QDict *options, Error
if (name[i] == '_')
name[i] = '-';
qemu_vitastor_unescape(name);
value = qemu_vitastor_next_tok(p, ':', &p);
value = qemu_vitastor_next_tok(p, delim, &p);
qemu_vitastor_unescape(value);
if (!strcmp(name, "inode") ||
!strcmp(name, "pool") ||
@@ -294,9 +300,8 @@ static void coroutine_fn vitastor_co_get_metadata(VitastorRPC *task)
qemu_mutex_lock(&client->mutex);
vitastor_c_watch_inode(client->proxy, client->image, vitastor_co_generic_cb, task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client);
#endif
if (!client->auto_loop)
vitastor_schedule_uring_handler(client);
qemu_mutex_unlock(&client->mutex);
while (!task->complete)
@@ -429,6 +434,70 @@ static void strarray_free(str_array *a)
}
#endif
static void check_config(VitastorClient *client)
{
size_t bufsize = 64*1024, maxsize = 1024*1024, done = 0;
ssize_t r = 0;
char *data = NULL;
QObject *obj = NULL;
QDict *qd = NULL;
int fd = open(client->config_path, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "vitastor: failed to read %s: %s\n", client->config_path, strerror(errno));
return;
}
data = (char*)malloc(bufsize);
if (!data)
{
fprintf(stderr, "vitastor: memory allocation failed\n");
goto end_free;
}
while (1)
{
if (bufsize <= done)
{
if (bufsize >= maxsize)
{
fprintf(stderr, "vitastor: config file exceeds %zu bytes\n", maxsize);
goto end_free;
}
bufsize *= 2;
data = (char*)realloc(data, bufsize);
if (!data)
{
fprintf(stderr, "vitastor: memory allocation failed\n");
goto end_free;
}
}
r = read(fd, data+done, bufsize-done);
if (r < 0)
{
if (errno == EAGAIN || errno == EINTR)
continue;
fprintf(stderr, "vitastor: failed to read %s: %s\n", client->config_path, strerror(errno));
break;
}
done += r;
}
obj = qobject_from_json(data
#if QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 9 || QEMU_VERSION_MAJOR >= 3
, NULL
#endif
);
qd = qobject_to(QDict, obj);
if (qd)
{
client->file_mirror_path = g_strdup(qdict_get_try_str(qd, "qemu_file_mirror_path"));
}
end_free:
if (obj)
qobject_unref(obj);
if (data)
free(data);
close(fd);
}
static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, Error **errp)
{
VitastorRPC task;
@@ -447,8 +516,15 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
client->rdma_gid_index = qdict_get_try_int(options, "rdma-gid-index", 0);
client->rdma_mtu = qdict_get_try_int(options, "rdma-mtu", 0);
client->ctx = bdrv_get_aio_context(bs);
if (client->config_path && strlen(client->config_path))
{
check_config(client);
}
#if defined VITASTOR_C_API_VERSION && VITASTOR_C_API_VERSION >= 2
str_array opt = {};
char version_buffer[32];
memset(version_buffer, ' ', sizeof(version_buffer));
version_buffer[sizeof(version_buffer)-1] = '\0';
strarray_push_kv(&opt, "config_path", qdict_get_try_str(options, "config-path"));
strarray_push_kv(&opt, "etcd_address", qdict_get_try_str(options, "etcd-host"));
strarray_push_kv(&opt, "etcd_prefix", qdict_get_try_str(options, "etcd-prefix"));
@@ -458,7 +534,9 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
strarray_push_kv(&opt, "rdma_gid_index", qdict_get_try_str(options, "rdma-gid-index"));
strarray_push_kv(&opt, "rdma_mtu", qdict_get_try_str(options, "rdma-mtu"));
strarray_push_kv(&opt, "client_writeback_allowed", (flags & BDRV_O_NOCACHE) ? "0" : "1");
strarray_push_kv(&opt, "__version_check_buffer", version_buffer);
client->proxy = vitastor_c_create_uring_json(opt.items, opt.len);
client->auto_loop = 0;
strarray_free(&opt);
if (client->proxy)
{
@@ -471,6 +549,12 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
return -1;
}
universal_aio_set_fd_handler(client->ctx, client->uring_eventfd, vitastor_uring_handler, NULL, client);
int vitastor_version[3] = { 0 };
if (sscanf(version_buffer, "%d.%d.%d", &vitastor_version[0], &vitastor_version[1], &vitastor_version[2]) == 3 &&
vitastor_version[0] >= 2)
{
client->auto_loop = 1;
}
}
else
{
@@ -604,6 +688,34 @@ static void vitastor_close(BlockDriverState *bs)
client->last_bitmap = NULL;
}
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 2
static void vitastor_refresh_filename(BlockDriverState *bs)
{
VitastorClient *client = bs->opaque;
size_t len = 0;
int n = 0;
if (client->image && client->file_mirror_path)
{
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s%s", client->file_mirror_path, client->image);
return;
}
len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), "vitastor://");
if (len < sizeof(bs->exact_filename))
{
if (client->image)
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cimage=%s", (n++ ? '&' : '?'), client->image);
else
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cpool=%ju&inode=%ju&size=%ju", (n++ ? '&' : '?'), client->pool, client->inode, client->size);
}
if (client->config_path && len < sizeof(bs->exact_filename))
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cconfig_path=%s", (n++ ? '&' : '?'), client->config_path);
if (client->etcd_host && len < sizeof(bs->exact_filename))
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cetcd_host=%s", (n++ ? '&' : '?'), client->etcd_host);
if (client->etcd_prefix && len < sizeof(bs->exact_filename))
len += snprintf(bs->exact_filename+len, sizeof(bs->exact_filename)-len, "%cetcd_prefix=%s", (n++ ? '&' : '?'), client->etcd_prefix);
}
#endif
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
static int vitastor_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
{
@@ -767,9 +879,8 @@ static int coroutine_fn vitastor_co_preadv(BlockDriverState *bs,
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
qemu_mutex_lock(&client->mutex);
vitastor_c_read(client->proxy, inode, offset, bytes, iov->iov, iov->niov, vitastor_co_read_cb, &task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client);
#endif
if (!client->auto_loop)
vitastor_schedule_uring_handler(client);
qemu_mutex_unlock(&client->mutex);
while (!task.complete)
@@ -803,9 +914,8 @@ static int coroutine_fn vitastor_co_pwritev(BlockDriverState *bs,
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
qemu_mutex_lock(&client->mutex);
vitastor_c_write(client->proxy, inode, offset, bytes, 0, iov->iov, iov->niov, vitastor_co_generic_cb, &task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client);
#endif
if (!client->auto_loop)
vitastor_schedule_uring_handler(client);
qemu_mutex_unlock(&client->mutex);
while (!task.complete)
@@ -885,9 +995,8 @@ static int coroutine_fn vitastor_co_block_status(
task.bitmap = client->last_bitmap = NULL;
qemu_mutex_lock(&client->mutex);
vitastor_c_read_bitmap(client->proxy, task.inode, task.offset, task.len, !client->skip_parents, vitastor_co_read_bitmap_cb, &task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client);
#endif
if (!client->auto_loop)
vitastor_schedule_uring_handler(client);
qemu_mutex_unlock(&client->mutex);
while (!task.complete)
{
@@ -974,9 +1083,8 @@ static int coroutine_fn vitastor_co_flush(BlockDriverState *bs)
qemu_mutex_lock(&client->mutex);
vitastor_c_sync(client->proxy, vitastor_co_generic_cb, &task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client);
#endif
if (!client->auto_loop)
vitastor_schedule_uring_handler(client);
qemu_mutex_unlock(&client->mutex);
while (!task.complete)
@@ -1038,6 +1146,9 @@ static BlockDriver bdrv_vitastor = {
.bdrv_get_info = vitastor_get_info,
.bdrv_getlength = vitastor_getlength,
#endif
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR >= 2
.bdrv_refresh_filename = vitastor_refresh_filename,
#endif
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
.bdrv_probe_blocksizes = vitastor_probe_blocksizes,
#endif

View File

@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: Vitastor
Description: Vitastor client library
Version: 2.2.0
Version: 2.2.3
Libs: -L${libdir} -lvitastor_client
Cflags: -I${includedir}

View File

@@ -178,7 +178,14 @@ vitastor_c *vitastor_c_create_uring_json(const char **options, int options_len)
json11::Json::object cfg;
for (int i = 0; i < options_len-1; i += 2)
{
cfg[options[i]] = std::string(options[i+1]);
if (!strcmp(options[i], "__version_check_buffer"))
{
int buf_size = strlen(options[i+1])+1;
if (buf_size > strlen(VITASTOR_VERSION))
strncpy((char*)options[i+1], VITASTOR_VERSION, buf_size);
}
else
cfg[options[i]] = std::string(options[i+1]);
}
json11::Json cfg_json(cfg);
vitastor_c *self = new vitastor_c;

View File

@@ -7,7 +7,7 @@
#define VITASTOR_QEMU_PROXY_H
// C API wrapper version
#define VITASTOR_C_API_VERSION 5
#define VITASTOR_C_API_VERSION 4
#ifndef POOL_ID_BITS
#define POOL_ID_BITS 16

View File

@@ -70,7 +70,7 @@ struct rm_osd_t
{
if (parent->cli->st_cli.peer_states.find(osd_id) != parent->cli->st_cli.peer_states.end())
{
is_warning = true;
is_warning = !allow_up;
still_up.push_back(osd_id);
}
}

View File

@@ -72,12 +72,14 @@ static const char* help_text =
" --port <PORT> use port <PORT> for NFS services (default is 2049)\n"
" specify \"auto\" to auto-select and print port\n"
" --portmap 0 do not listen on port 111 (portmap/rpcbind, requires root)\n"
#ifdef WITH_RDMACM
" --nfs_rdma <PORT> enable NFS-RDMA at RDMA-CM port <PORT> (you can try 20049)\n"
" if RDMA is enabled and --port is set to 0, TCP will be disabled\n"
" --nfs_rdma_credit 16 maximum operation credit for RDMA clients (max iodepth)\n"
" --nfs_rdma_send 1024 maximum RDMA send operation count (should be larger than iodepth)\n"
" --nfs_rdma_alloc 1M RDMA memory allocation rounding\n"
" --nfs_rdma_gc 64M maximum unused RDMA buffers\n"
#endif
"\n"
"vitastor-nfs --fs <NAME> upgrade\n"
" Upgrade FS metadata. Can be run online, but server(s) should be restarted\n"
@@ -205,12 +207,15 @@ void nfs_proxy_t::run(json11::Json cfg)
default_pool = cfg["pool"].as_string();
portmap_enabled = !json_is_false(cfg["portmap"]);
nfs_port = cfg["port"].uint64_value() & 0xffff;
#ifdef WITH_RDMACM
nfs_rdma_port = cfg["nfs_rdma"].uint64_value() & 0xffff;
#endif
// Allow RDMA-only mode if port is explicitly set to 0
// Allow port auto-selection in server mode if explicitly set to --port auto
nfs_port_auto = cfg["port"] == "auto";
if (!nfs_port)
nfs_port = nfs_port_auto ? 0 : (!cfg["port"].is_null() && nfs_rdma_port ? -1 : 2049);
#ifdef WITH_RDMACM
nfs_rdma_credit = cfg["nfs_rdma_credit"].uint64_value();
if (!nfs_rdma_credit)
nfs_rdma_credit = 16;
@@ -223,6 +228,7 @@ void nfs_proxy_t::run(json11::Json cfg)
nfs_rdma_gc = cfg["nfs_rdma_gc"].uint64_value();
if (!nfs_rdma_gc)
nfs_rdma_gc = 64*1048576;
#endif
export_root = cfg["nfspath"].string_value();
if (!export_root.size())
export_root = "/";
@@ -391,10 +397,12 @@ void nfs_proxy_t::run_server(json11::Json cfg)
}
});
}
#ifdef WITH_RDMACM
if (nfs_rdma_port)
{
rdma_context = create_rdma(bind_address, nfs_rdma_port, nfs_rdma_credit, nfs_rdma_max_send, nfs_rdma_alloc, nfs_rdma_gc);
}
#endif
if (mountpoint != "")
{
mount_fs();

View File

@@ -85,6 +85,7 @@ osd_t::osd_t(const json11::Json & config, ring_loop_t *ringloop)
msgr.ringloop = this->ringloop;
msgr.exec_op = [this](osd_op_t *op) { exec_op(op); };
msgr.repeer_pgs = [this](osd_num_t peer_osd) { repeer_pgs(peer_osd); };
msgr.break_pg_locks = [this](osd_num_t peer_osd) { break_pg_locks(peer_osd); };
msgr.check_config_hook = [this](osd_client_t *cl, json11::Json conf) { return check_peer_config(cl, conf); };
msgr.init();
@@ -195,7 +196,6 @@ void osd_t::parse_config(bool init)
etcd_stats_interval = 30;
readonly = json_is_true(config["readonly"]);
run_primary = !json_is_false(config["run_primary"]);
allow_test_ops = json_is_true(config["allow_test_ops"]);
}
log_level = config["log_level"].uint64_value();
auto old_no_rebalance = no_rebalance;
@@ -469,11 +469,7 @@ void osd_t::exec_op(osd_op_t *cur_op)
finish_op(cur_op, -EROFS);
return;
}
if (cur_op->req.hdr.opcode == OSD_OP_TEST_SYNC_STAB_ALL)
{
exec_sync_stab_all(cur_op);
}
else if (cur_op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)
if (cur_op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)
{
exec_show_config(cur_op);
}

View File

@@ -119,7 +119,6 @@ class osd_t
bool disable_tcp = false;
// FIXME: Implement client queue depth limit
int client_queue_depth = 128;
bool allow_test_ops = false;
int print_stats_interval = 3;
int slow_log_interval = 10;
int immediate_commit = IMMEDIATE_NONE;
@@ -278,6 +277,8 @@ class osd_t
void handle_peers();
bool check_peer_config(osd_client_t *cl, json11::Json conf);
void repeer_pgs(osd_num_t osd_num);
void repeer_pg(pg_t & pg);
void break_pg_locks(osd_num_t osd_num);
void start_pg_peering(pg_t & pg);
void drop_dirty_pg_connections(pool_pg_num_t pg);
void record_pg_lock(pg_t & pg, osd_num_t peer_osd, uint64_t pg_state);
@@ -317,7 +318,6 @@ class osd_t
// secondary ops
bool sec_check_pg_lock(osd_num_t primary_osd, const object_id &oid);
void exec_sync_stab_all(osd_op_t *cur_op);
void exec_show_config(osd_op_t *cur_op);
void exec_secondary(osd_op_t *cur_op);
void exec_secondary_real(osd_op_t *cur_op);

View File

@@ -432,9 +432,16 @@ void osd_t::apply_pg_locks_localize_only()
}
auto & pool_cfg = pool_it->second;
auto & pg = pp.second;
auto old_disable_pg_locks = pg.disable_pg_locks;
pg.disable_pg_locks = pg_locks_localize_only &&
pool_cfg.scheme == POOL_SCHEME_REPLICATED &&
pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY;
(pool_cfg.scheme != POOL_SCHEME_REPLICATED ||
pool_cfg.local_reads == POOL_LOCAL_READ_PRIMARY);
if (!pg.disable_pg_locks && old_disable_pg_locks)
{
// Relock PG
printf("[PG %u/%u] Repeer to enable PG locks\n", pg.pool_id, pg.pg_num);
repeer_pg(pg);
}
}
}
@@ -877,8 +884,8 @@ void osd_t::apply_pg_config()
pg.next_scrub = pg_cfg.next_scrub;
pg.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_item.second.scheme != POOL_SCHEME_REPLICATED ||
pool_item.second.local_reads == POOL_LOCAL_READ_PRIMARY);
if (pg.scheme == POOL_SCHEME_EC)
{
use_ec(pg.pg_size, pg.pg_data_size, true);

View File

@@ -189,7 +189,7 @@ bool osd_t::submit_flush_op(pool_id_t pool_id, pg_num_t pg_num, pg_flush_batch_t
{
.len = (uint32_t)count,
},
.buf = op->buf,
.buf = (uint8_t*)op->buf,
});
bs->enqueue_op(op->bs_op);
}

View File

@@ -73,18 +73,25 @@ void osd_t::handle_peers()
}
}
void osd_t::break_pg_locks(osd_num_t peer_osd)
{
for (auto lock_it = pg_locks.begin(); lock_it != pg_locks.end(); )
{
if (lock_it->second.primary_osd == peer_osd)
{
if (log_level > 3)
{
printf("Break PG %u/%u lock on disconnection of OSD %ju\n", lock_it->first.pool_id, lock_it->first.pg_num, peer_osd);
}
pg_locks.erase(lock_it++);
}
else
lock_it++;
}
}
void osd_t::repeer_pgs(osd_num_t peer_osd)
{
if (msgr.osd_peer_fds.find(peer_osd) == msgr.osd_peer_fds.end())
{
for (auto lock_it = pg_locks.begin(); lock_it != pg_locks.end(); )
{
if (lock_it->second.primary_osd == peer_osd)
pg_locks.erase(lock_it++);
else
lock_it++;
}
}
// Re-peer affected PGs
for (auto & p: pgs)
{
@@ -104,21 +111,26 @@ void osd_t::repeer_pgs(osd_num_t peer_osd)
{
// Repeer this pg
printf("[PG %u/%u] Repeer because of OSD %ju\n", pg.pool_id, pg.pg_num, peer_osd);
if (!(pg.state & (PG_ACTIVE | PG_REPEERING)) || pg.can_repeer())
{
start_pg_peering(pg);
}
else
{
// Stop accepting new operations, wait for current ones to finish or fail
pg.state = pg.state & ~PG_ACTIVE | PG_REPEERING;
report_pg_state(pg);
}
repeer_pg(pg);
}
}
}
}
void osd_t::repeer_pg(pg_t & pg)
{
if (!(pg.state & (PG_ACTIVE | PG_REPEERING)) || pg.can_repeer())
{
start_pg_peering(pg);
}
else
{
// Stop accepting new operations, wait for current ones to finish or fail
pg.state = pg.state & ~PG_ACTIVE | PG_REPEERING;
report_pg_state(pg);
}
}
// Reset PG state (when peering or stopping)
void osd_t::reset_pg(pg_t & pg)
{
@@ -466,6 +478,7 @@ void osd_t::relock_pg(pg_t & pg)
auto pg_it = pgs.find(pg_id);
if (pg_it == pgs.end())
{
printf("Warning: PG %u/%u is gone during lock attempt\n", pg_id.pool_id, pg_id.pg_num);
return;
}
auto & pg = pg_it->second;
@@ -475,15 +488,14 @@ void osd_t::relock_pg(pg_t & pg)
}
else if (op->reply.hdr.retval != -EPIPE)
{
printf(
(op->reply.hdr.retval == -ENOENT
? "Failed to %1$s PG %2$u/%3$u on OSD %4$ju - peer didn't load PG info yet\n"
: (op->reply.sec_lock.cur_primary
? "Failed to %1$s PG %2$u/%3$u on OSD %4$ju - taken by OSD %6$ju (retval=%5$jd)\n"
: "Failed to %1$s PG %2$u/%3$u on OSD %4$ju - retval=%5$jd\n")),
op->req.sec_lock.flags == OSD_SEC_UNLOCK_PG ? "unlock" : "lock",
pg_id.pool_id, pg_id.pg_num, peer_osd, op->reply.hdr.retval, op->reply.sec_lock.cur_primary
);
printf("Failed to %s PG %u/%u on OSD %ju - ", op->req.sec_lock.flags == OSD_SEC_UNLOCK_PG ? "unlock" : "lock",
pg_id.pool_id, pg_id.pg_num, peer_osd);
if (op->reply.hdr.retval == -ENOENT)
printf("peer didn't load PG info yet\n");
else if (op->reply.sec_lock.cur_primary)
printf("taken by OSD %ju (retval=%jd)\n", op->reply.sec_lock.cur_primary, op->reply.hdr.retval);
else
printf("retval=%jd\n", op->reply.hdr.retval);
// Retry relocking/unlocking PG after a short time
pg.lock_waiting = true;
tfd->set_timer(pg_lock_retry_interval_ms, false, [this, pg_id](int)

View File

@@ -209,8 +209,8 @@ void osd_t::submit_primary_subop(osd_op_t *cur_op, osd_op_t *subop,
.offset = wr ? si->write_start : si->read_start,
.len = subop_len,
} },
.buf = wr ? si->write_buf : si->read_buf,
.bitmap = si->bmp_buf,
.buf = (uint8_t*)(wr ? si->write_buf : si->read_buf),
.bitmap = (uint8_t*)si->bmp_buf,
});
#ifdef OSD_DEBUG
printf(
@@ -290,7 +290,6 @@ static uint64_t bs_op_to_osd_op[] = {
OSD_OP_SEC_DELETE, // BS_OP_DELETE = 6
OSD_OP_SEC_LIST, // BS_OP_LIST = 7
OSD_OP_SEC_ROLLBACK, // BS_OP_ROLLBACK = 8
OSD_OP_TEST_SYNC_STAB_ALL, // BS_OP_SYNC_STAB_ALL = 9
};
void osd_t::handle_primary_bs_subop(osd_op_t *subop)
@@ -417,16 +416,17 @@ void osd_t::handle_primary_subop(osd_op_t *subop, osd_op_t *cur_op)
if (retval != expected)
{
int64_t peer_osd = (msgr.clients.find(subop->peer_fd) != msgr.clients.end()
? msgr.clients[subop->peer_fd]->osd_num : -subop->peer_fd);
? msgr.clients[subop->peer_fd]->osd_num : 0);
if (opcode == OSD_OP_SEC_READ || opcode == OSD_OP_SEC_WRITE || opcode == OSD_OP_SEC_WRITE_STABLE)
{
printf(
subop->peer_fd >= 0
? "%1$s subop to %2$jx:%3$jx v%4$ju failed on osd %7$jd: retval = %5$d (expected %6$d)\n"
: "%1$s subop to %2$jx:%3$jx v%4$ju failed locally: retval = %5$d (expected %6$d)\n",
osd_op_names[opcode], subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, subop->req.sec_rw.version,
retval, expected, peer_osd
);
printf("%s subop to %jx:%jx v%ju failed ", osd_op_names[opcode],
subop->req.sec_rw.oid.inode, subop->req.sec_rw.oid.stripe, subop->req.sec_rw.version);
if (subop->peer_fd >= 0 && peer_osd > 0)
printf("on osd %ju: retval = %d (expected %d)\n", peer_osd, retval, expected);
else if (peer_osd > 0)
printf("on peer %d: retval = %d (expected %d)\n", subop->peer_fd, retval, expected);
else
printf("locally: retval = %d (expected %d)\n", retval, expected);
}
else if (opcode == OSD_OP_SEC_DELETE)
{
@@ -702,7 +702,7 @@ void osd_t::submit_primary_stab_subops(osd_op_t *cur_op)
{
.len = (uint32_t)stab_osd.len,
},
.buf = (void*)(op_data->unstable_writes + stab_osd.start),
.buf = (uint8_t*)(op_data->unstable_writes + stab_osd.start),
});
bs->enqueue_op(subops[i].bs_op);
}
@@ -789,7 +789,7 @@ void osd_t::submit_primary_rollback_subops(osd_op_t *cur_op, const uint64_t* osd
{
.len = 1,
},
.buf = (void*)(op_data->unstable_writes + i),
.buf = (uint8_t*)(op_data->unstable_writes + i),
});
#ifdef OSD_DEBUG
printf(

View File

@@ -91,16 +91,17 @@ 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 (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 pg_it = pgs.find(ppg);
if (pg_it != pgs.end() && pg_it->second.state != PG_OFFLINE)
{
return false;
}
if (pg_it->second.disable_pg_locks)
{
return true;
}
auto lock_it = pg_locks.find(ppg);
return lock_it != pg_locks.end() && lock_it->second.primary_osd == primary_osd;
}
@@ -140,7 +141,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
cur_op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE)
{
if (!(cur_op->req.sec_rw.flags & OSD_OP_IGNORE_PG_LOCK) &&
!sec_check_pg_lock(cl->osd_num, cur_op->req.sec_rw.oid))
!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_rw.oid))
{
cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op);
@@ -160,8 +161,8 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
cur_op->bs_op->version = cur_op->req.sec_rw.version;
cur_op->bs_op->offset = cur_op->req.sec_rw.offset;
cur_op->bs_op->len = cur_op->req.sec_rw.len;
cur_op->bs_op->buf = cur_op->buf;
cur_op->bs_op->bitmap = cur_op->bitmap;
cur_op->bs_op->buf = (uint8_t*)cur_op->buf;
cur_op->bs_op->bitmap = (uint8_t*)cur_op->bitmap;
#ifdef OSD_STUB
cur_op->bs_op->retval = cur_op->bs_op->len;
#endif
@@ -169,7 +170,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
else if (cur_op->req.hdr.opcode == OSD_OP_SEC_DELETE)
{
if (!(cur_op->req.sec_del.flags & OSD_OP_IGNORE_PG_LOCK) &&
!sec_check_pg_lock(cl->osd_num, cur_op->req.sec_del.oid))
!sec_check_pg_lock(cl->in_osd_num, cur_op->req.sec_del.oid))
{
cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op);
@@ -185,7 +186,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
cur_op->req.hdr.opcode == OSD_OP_SEC_ROLLBACK)
{
cur_op->bs_op->len = cur_op->req.sec_stab.len/sizeof(obj_ver_id);
cur_op->bs_op->buf = cur_op->buf;
cur_op->bs_op->buf = (uint8_t*)cur_op->buf;
#ifdef OSD_STUB
cur_op->bs_op->retval = 0;
#endif
@@ -193,7 +194,7 @@ void osd_t::exec_secondary_real(osd_op_t *cur_op)
{
for (int i = 0; i < cur_op->bs_op->len; i++)
{
if (!sec_check_pg_lock(cl->osd_num, ((obj_ver_id*)cur_op->buf)[i].oid))
if (!sec_check_pg_lock(cl->in_osd_num, ((obj_ver_id*)cur_op->buf)[i].oid))
{
cur_op->bs_op->retval = -EPIPE;
secondary_op_callback(cur_op);
@@ -247,7 +248,7 @@ void osd_t::exec_sec_read_bmp(osd_op_t *cur_op)
void *cur_buf = reply_buf;
for (int i = 0; i < n; i++)
{
if (!sec_check_pg_lock(cl->osd_num, ov[i].oid) &&
if (!sec_check_pg_lock(cl->in_osd_num, ov[i].oid) &&
!(cur_op->req.sec_read_bmp.flags & OSD_OP_IGNORE_PG_LOCK))
{
free(reply_buf);
@@ -269,7 +270,7 @@ void osd_t::exec_sec_lock(osd_op_t *cur_op)
{
cur_op->reply.sec_lock.cur_primary = 0;
auto cl = msgr.clients.at(cur_op->peer_fd);
if (!cl->osd_num ||
if (!cl->in_osd_num ||
cur_op->req.sec_lock.flags != OSD_SEC_LOCK_PG &&
cur_op->req.sec_lock.flags != OSD_SEC_UNLOCK_PG ||
cur_op->req.sec_lock.pool_id > ((uint64_t)1<<POOL_ID_BITS) ||
@@ -290,7 +291,7 @@ void osd_t::exec_sec_lock(osd_op_t *cur_op)
auto lock_it = pg_locks.find(ppg);
if (cur_op->req.sec_lock.flags == OSD_SEC_LOCK_PG)
{
if (lock_it != pg_locks.end() && lock_it->second.primary_osd != cl->osd_num)
if (lock_it != pg_locks.end() && lock_it->second.primary_osd != cl->in_osd_num)
{
cur_op->reply.sec_lock.cur_primary = lock_it->second.primary_osd;
finish_op(cur_op, -EBUSY);
@@ -303,13 +304,21 @@ void osd_t::exec_sec_lock(osd_op_t *cur_op)
finish_op(cur_op, -EBUSY);
return;
}
if (log_level > 3)
{
printf("Lock PG %u/%u for OSD %ju\n", ppg.pool_id, ppg.pg_num, cl->in_osd_num);
}
pg_locks[ppg] = (osd_pg_lock_t){
.primary_osd = cl->osd_num,
.primary_osd = cl->in_osd_num,
.state = cur_op->req.sec_lock.pg_state,
};
}
else if (lock_it != pg_locks.end() && lock_it->second.primary_osd == cl->osd_num)
else if (lock_it != pg_locks.end() && lock_it->second.primary_osd == cl->in_osd_num)
{
if (log_level > 3)
{
printf("Unlock PG %u/%u by OSD %ju\n", ppg.pool_id, ppg.pg_num, cl->in_osd_num);
}
pg_locks.erase(lock_it);
}
finish_op(cur_op, 0);
@@ -323,7 +332,7 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
: json11::Json();
auto peer_osd_num = req_json["osd_num"].uint64_value();
auto cl = msgr.clients.at(cur_op->peer_fd);
cl->osd_num = peer_osd_num;
cl->in_osd_num = peer_osd_num;
if (req_json["features"]["check_sequencing"].bool_value())
{
cl->check_sequencing = true;
@@ -369,27 +378,3 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
cur_op->iov.push_back(cur_op->buf, cfg_str.size()+1);
finish_op(cur_op, cfg_str.size()+1);
}
void osd_t::exec_sync_stab_all(osd_op_t *cur_op)
{
// Sync and stabilize all objects
// This command is only valid for tests
cur_op->bs_op = new blockstore_op_t();
if (!allow_test_ops)
{
cur_op->bs_op->retval = -EINVAL;
secondary_op_callback(cur_op);
return;
}
cur_op->bs_op->opcode = BS_OP_SYNC_STAB_ALL;
cur_op->bs_op->callback = [this, cur_op](blockstore_op_t *bs_op)
{
secondary_op_callback(cur_op);
};
#ifdef OSD_STUB
cur_op->bs_op->retval = 0;
secondary_op_callback(cur_op);
#else
bs->enqueue_op(cur_op->bs_op);
#endif
}

View File

@@ -121,6 +121,7 @@ void pretend_connected(cluster_client_t *cli, osd_num_t osd_num)
cli->msgr.osd_peer_fds[osd_num] = peer_fd;
cli->msgr.clients[peer_fd] = new osd_client_t();
cli->msgr.clients[peer_fd]->osd_num = osd_num;
cli->msgr.clients[peer_fd]->peer_fd = peer_fd;
cli->msgr.clients[peer_fd]->peer_state = PEER_CONNECTED;
cli->msgr.wanted_peers.erase(osd_num);
cli->msgr.repeer_pgs(osd_num);

View File

@@ -125,6 +125,8 @@ void ring_loop_t::loop()
if (cqe->flags & IORING_CQE_F_MORE)
{
// There will be a second notification
if (mt)
mu.unlock();
d->res = cqe->res;
d->more = true;
if (d->callback)

View File

@@ -10,6 +10,8 @@ cd $(dirname $0)
./test_change_pg_count.sh
SCHEME=ec ./test_change_pg_count.sh
./test_change_pg_count_online.sh
./test_change_pg_size.sh
./test_create_nomaxid.sh
@@ -59,6 +61,7 @@ SCHEME=ec IMMEDIATE_COMMIT=1 ./test_rebalance_verify.sh
./test_write.sh
SCHEME=xor ./test_write.sh
TEST_NAME=iothreads GLOBAL_CONFIG=',"client_iothread_count":4' ./test_write.sh
./test_write_no_same.sh

View File

@@ -0,0 +1,61 @@
#!/bin/bash -ex
OSD_COUNT=${OSD_COUNT:-6}
PG_COUNT=16
GLOBAL_CONFIG=',"client_retry_interval":1000'
. `dirname $0`/run_3osds.sh
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4M -direct=1 -iodepth=1 -fsync=1 -rw=write \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -rw=randrw \
-etcd=$ETCD_URL -pool=1 -inode=2 -size=128M -loops=100 -cluster_log_level=3 -runtime=60 &>./testdata/fio.log &
FIO_PID=$!
try_change()
{
n=$1
for i in {1..6}; do
echo --- Change PG count to $n --- >>testdata/osd$i.log
done
echo --- Change PG count to $n --- >>testdata/mon.log
$ETCDCTL put /vitastor/config/pools '{"1":{'$POOLCFG',"pg_size":'$PG_SIZE',"pg_minsize":'$PG_MINSIZE',"pg_count":'$n'}}'
echo "Pool 1 (testpool) PG count changed from $PG_COUNT to $n" >> testdata/pgr.log
PG_COUNT=$n
sleep 10
}
sleep 5
# 16 -> 32
try_change 32
# 32 -> 16
try_change 16
# 16 -> 25
try_change 25
# 25 -> 17
try_change 17
# 17 -> 16
try_change 16
wait $FIO_PID
grep -P 'Pool 1 \(testpool\) PG count changed from \d+ to \d+' testdata/fio.log > testdata/pgc.log
diff testdata/pgr.log testdata/pgc.log
format_green OK