Compare commits

...
Author SHA1 Message Date
Vitaliy Filippov facaa2cc6a Release 3.0.3
- Fix csum_block_size > 0 unusable with atomic writes in the new store
  (almost all atomic write requests generated invalid checksums with csum_block_size > 0)
- Fix monitor sometimes randomly failing to optimize PGs with the "problem is
  infeasible or unbounded" message due to not waiting to read full stdout of lp_solve
- Remove reshard_abort optimisation to fix chunked resharding introduced in 3.0.2 possibly
  corrupting in-memory OSD state when handling multiple rapid PG count change requests
- Fix removed inodes not disappearing from OSD statistics in the new store, leading to
  bloating of the statistics with old inodes
- Increase test coverage for the new store and fix several minor bugs:
  - Enabling/disabling of used_for_app was recalculating inode space statistics incorrectly
  - Fix object metadata validation on OSD startup rejecting some correct sequences of entries,
    possibly leading to OSD being unable to start
  - Fix PG activation with EC failing in rare cases with EBUSY when requesting to commit an
    already committed write
  - Fix a theoretically possible metadata writeback issue on ENOSPC during commit
- Fix monitor failing to optimize PGs in presence of a host with name convertible to
  js Number (like 04e278988710) :D
- Fix vitastor-cli dd sometimes (rarely) truncating the image when writing to stdout
- Fix a theoretically possible client connection object leak when io_uring is full
- Fix a leak of RDMA-CM connection objects
- Fix crashes with data_block_size < 32KB (useless setup, but anyway) (#113)
2026-02-08 01:39:57 +03:00
Vitaliy Filippov d2ac8e3827 Fix block writeback on enospc during commit 2026-02-07 16:27:26 +03:00
Vitaliy Filippov d6dacc67db Do not return EBUSY when already stable in the new store 2026-02-07 16:10:39 +03:00
Vitaliy Filippov cbe51595cb Remove reshard_abort 2026-02-07 16:05:40 +03:00
Vitaliy Filippov 6bd0830ab8 Add a test for chunked resharding 2026-02-07 16:02:17 +03:00
Vitaliy Filippov 796e82f34d Check get_compacted_count and get_compact_queue_size 2026-02-07 15:44:54 +03:00
Vitaliy Filippov db39283970 Add a test for complete_lsn_write 2026-02-07 15:36:46 +03:00
Vitaliy Filippov 9f8c686321 Add a test for redirect_intent 2026-02-07 15:09:58 +03:00
Vitaliy Filippov 2618e559d1 Add rollback tests, simplify rollback logic 2026-02-07 15:09:58 +03:00
Vitaliy Filippov 037d2bc162 Add a test for recalc_inode_stats in the new store and fix a bug in it 2026-02-07 14:00:10 +03:00
Vitaliy Filippov f0b64adb32 Fix removed inodes not disappearing from statistics in the new store 2026-02-07 02:48:49 +03:00
Vitaliy Filippov f06d64d879 Fix validate_object commit validation bug 2026-02-06 18:52:37 +03:00
Vitaliy Filippov d164499a1c Add more iterate_compaction test cases 2026-02-06 18:52:19 +03:00
Vitaliy Filippov 725e9aa8ae Remove unused read_locked_entry 2026-02-06 17:38:59 +03:00
Vitaliy Filippov 0715feffa1 Wait for finished read, not for process exit in lp_optimizer 2026-02-04 02:33:08 +03:00
Vitaliy Filippov e9f37e8dc3 Fix NaN PG optimisation error when a hostname has a name convertible to js Number... some shit like 04e278988710 2026-02-04 15:08:03 +03:00
Vitaliy Filippov 4fbe4b5654 Fix BIG_INTENT rechecks with enabled checksums 2026-02-04 02:33:50 +03:00
Vitaliy Filippov 9fb645693b Fix checksums with BIG_INTENT writes in the new store 2026-02-04 02:33:50 +03:00
Vitaliy Filippov 9e47828383 Add a test for big_intent with checksums 2026-02-04 02:33:50 +03:00
30 changed files with 990 additions and 133 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12)
project(vitastor) project(vitastor)
set(VITASTOR_VERSION "3.0.2") set(VITASTOR_VERSION "3.0.3")
include(CTest) include(CTest)
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.2 VITASTOR_VERSION ?= v3.0.3
all: build push all: build push
+1 -1
View File
@@ -49,7 +49,7 @@ spec:
capabilities: capabilities:
add: ["SYS_ADMIN"] add: ["SYS_ADMIN"]
allowPrivilegeEscalation: true allowPrivilegeEscalation: true
image: vitalif/vitastor-csi:v3.0.2 image: vitalif/vitastor-csi:v3.0.3
args: args:
- "--node=$(NODE_ID)" - "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -121,7 +121,7 @@ spec:
privileged: true privileged: true
capabilities: capabilities:
add: ["SYS_ADMIN"] add: ["SYS_ADMIN"]
image: vitalif/vitastor-csi:v3.0.2 image: vitalif/vitastor-csi:v3.0.3
args: args:
- "--node=$(NODE_ID)" - "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -5,7 +5,7 @@ package vitastor
const ( const (
vitastorCSIDriverName = "csi.vitastor.io" vitastorCSIDriverName = "csi.vitastor.io"
vitastorCSIDriverVersion = "3.0.2" vitastorCSIDriverVersion = "3.0.3"
) )
// Config struct fills the parameters of request or user input // Config struct fills the parameters of request or user input
+1 -1
View File
@@ -1,4 +1,4 @@
vitastor (3.0.2-1) unstable; urgency=medium vitastor (3.0.3-1) unstable; urgency=medium
* Bugfixes * Bugfixes
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.2 VITASTOR_VERSION ?= v3.0.3
all: build push all: build push
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# Desired Vitastor version # Desired Vitastor version
VITASTOR_VERSION=v3.0.2 VITASTOR_VERSION=v3.0.3
# Additional arguments for all containers # Additional arguments for all containers
# For example, you may want to specify a custom logging driver here # For example, you may want to specify a custom logging driver here
+2 -2
View File
@@ -26,9 +26,9 @@ at Vitastor Kubernetes operator: https://github.com/Antilles7227/vitastor-operat
The instruction is very simple. The instruction is very simple.
1. Download a Docker image of the desired version: \ 1. Download a Docker image of the desired version: \
`docker pull vitalif/vitastor:v3.0.2` `docker pull vitalif/vitastor:v3.0.3`
2. Install scripts to the host system: \ 2. Install scripts to the host system: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.2 install.sh` `docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.3 install.sh`
3. Reload udev rules: \ 3. Reload udev rules: \
`udevadm control --reload-rules` `udevadm control --reload-rules`
+2 -2
View File
@@ -25,9 +25,9 @@ Vitastor можно установить в Docker/Podman. При этом etcd,
Инструкция по установке максимально простая. Инструкция по установке максимально простая.
1. Скачайте Docker-образ желаемой версии: \ 1. Скачайте Docker-образ желаемой версии: \
`docker pull vitalif/vitastor:v3.0.2` `docker pull vitalif/vitastor:v3.0.3`
2. Установите скрипты в хост-систему командой: \ 2. Установите скрипты в хост-систему командой: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.2 install.sh` `docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.3 install.sh`
3. Перезагрузите правила udev: \ 3. Перезагрузите правила udev: \
`udevadm control --reload-rules` `udevadm control --reload-rules`
+8 -5
View File
@@ -10,16 +10,19 @@ const NO_OSD = 'Z';
async function lp_solve(text) async function lp_solve(text)
{ {
const cp = child_process.spawn('lp_solve'); const cp = child_process.spawn('lp_solve');
let stdout = '', stderr = '', finish_cb; let stdout = '', stderr = '', finish_cb, finished = 0;
cp.stdout.on('data', buf => stdout += buf.toString()); cp.stdout.on('data', buf => stdout += buf.toString());
cp.stderr.on('data', buf => stderr += buf.toString()); cp.stderr.on('data', buf => stderr += buf.toString());
cp.on('exit', () => finish_cb && finish_cb()); cp.stdout.on('end', () => finish_cb());
cp.stderr.on('end', () => finish_cb());
cp.stdin.write(text); cp.stdin.write(text);
cp.stdin.end(); cp.stdin.end();
if (cp.exitCode == null) await new Promise(ok => (finish_cb = () =>
{ {
await new Promise(ok => finish_cb = ok); finished++;
} if (finished == 2)
ok();
}));
if (!stdout.trim()) if (!stdout.trim())
{ {
return null; return null;
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "vitastor-mon", "name": "vitastor-mon",
"version": "3.0.2", "version": "3.0.3",
"description": "Vitastor SDS monitor service", "description": "Vitastor SDS monitor service",
"main": "mon-main.js", "main": "mon-main.js",
"scripts": { "scripts": {
+1 -1
View File
@@ -195,7 +195,7 @@ async function generate_pool_pgs(state, global_config, pool_id, osd_tree, levels
const folded_tree = make_hier_tree(global_config, folded.nodes.reduce((a, c) => { a[c.id] = c; return a; }, {})); const folded_tree = make_hier_tree(global_config, folded.nodes.reduce((a, c) => { a[c.id] = c; return a; }, {}));
const old_pg_count = prev_pgs.length; const old_pg_count = prev_pgs.length;
const optimize_cfg = { const optimize_cfg = {
osd_weights: folded.nodes.reduce((a, c) => { if (Number(c.id)) { a[c.id] = c.size; } return a; }, {}), osd_weights: folded.nodes.reduce((a, c) => { if (/^\d+$/.exec(c.id) && c.size != null) { a[c.id] = c.size||0; } return a; }, {}),
combinator: use_rules combinator: use_rules
// new algorithm: // new algorithm:
? new RuleCombinator(folded_tree, rules, pool_cfg.max_osd_combinations) ? new RuleCombinator(folded_tree, rules, pool_cfg.max_osd_combinations)
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "vitastor", "name": "vitastor",
"version": "3.0.2", "version": "3.0.3",
"description": "Low-level native bindings to Vitastor client library", "description": "Low-level native bindings to Vitastor client library",
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
+1 -1
View File
@@ -50,7 +50,7 @@ from cinder.volume import configuration
from cinder.volume import driver from cinder.volume import driver
from cinder.volume import volume_utils from cinder.volume import volume_utils
VITASTOR_VERSION = '3.0.2' VITASTOR_VERSION = '3.0.3'
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.2 Version: 3.0.3
Release: 1%{?dist} Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1 License: Vitastor Network Public License 1.1
URL: https://vitastor.io/ URL: https://vitastor.io/
Source0: vitastor-3.0.2.el7.tar.gz Source0: vitastor-3.0.3.el7.tar.gz
BuildRequires: gperftools-devel BuildRequires: gperftools-devel
BuildRequires: devtoolset-9-gcc-c++ BuildRequires: devtoolset-9-gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.2 Version: 3.0.3
Release: 1%{?dist} Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1 License: Vitastor Network Public License 1.1
URL: https://vitastor.io/ URL: https://vitastor.io/
Source0: vitastor-3.0.2.el8.tar.gz Source0: vitastor-3.0.3.el8.tar.gz
BuildRequires: gperftools-devel BuildRequires: gperftools-devel
BuildRequires: gcc-toolset-9-gcc-c++ BuildRequires: gcc-toolset-9-gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.2 Version: 3.0.3
Release: 1%{?dist} Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1 License: Vitastor Network Public License 1.1
URL: https://vitastor.io/ URL: https://vitastor.io/
Source0: vitastor-3.0.2.el9.tar.gz Source0: vitastor-3.0.3.el9.tar.gz
BuildRequires: gperftools-devel BuildRequires: gperftools-devel
BuildRequires: gcc-c++ BuildRequires: gcc-c++
+1 -1
View File
@@ -21,7 +21,7 @@ if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/local/?$")
endif() endif()
set(ENABLE_COVERAGE false CACHE BOOL "Enable code coverage") set(ENABLE_COVERAGE false CACHE BOOL "Enable code coverage")
add_definitions(-DVITASTOR_VERSION="3.0.2") add_definitions(-DVITASTOR_VERSION="3.0.3")
add_definitions(-D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -fno-omit-frame-pointer -fvisibility=hidden -I ${CMAKE_SOURCE_DIR}/src) add_definitions(-D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -fno-omit-frame-pointer -fvisibility=hidden -I ${CMAKE_SOURCE_DIR}/src)
add_link_options(-fno-omit-frame-pointer) add_link_options(-fno-omit-frame-pointer)
if (${WITH_ASAN}) if (${WITH_ASAN})
-1
View File
@@ -187,7 +187,6 @@ public:
// MUST be called only when nobody makes any modifications to the DB for this pool // MUST be called only when nobody makes any modifications to the DB for this pool
virtual void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit) = 0; virtual void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit) = 0;
virtual bool reshard_continue(void *reshard_state, uint64_t chunk_limit) = 0; virtual bool reshard_continue(void *reshard_state, uint64_t chunk_limit) = 0;
virtual void reshard_abort(void *reshard_state) = 0;
// Event loop // Event loop
virtual void loop() = 0; virtual void loop() = 0;
+46 -63
View File
@@ -458,19 +458,22 @@ bool blockstore_heap_t::validate_object(heap_entry_t *obj)
next_wr = wr; next_wr = wr;
if (wr->type() == BS_HEAP_ROLLBACK) if (wr->type() == BS_HEAP_ROLLBACK)
{ {
if (commit_wr && wr->version > commit_wr->version)
{
// rollback may not come before commit with a smaller version
fprintf(stderr, "Error: rollback entry %jx:%jx v%ju l%ju comes before a commit entry v%ju l%ju\n",
wr->inode, wr->stripe, wr->version, wr->lsn, commit_wr->version, commit_wr->lsn);
return false;
}
rollback_wr = wr; rollback_wr = wr;
continue; continue;
} }
if (wr->type() == BS_HEAP_COMMIT) if (wr->type() == BS_HEAP_COMMIT)
{ {
commit_wr = wr; if (commit_wr && wr->version > commit_wr->version)
{
// commit may not come before commit with a smaller version
fprintf(stderr, "Error: commit entry %jx:%jx v%ju l%ju comes before a commit entry v%ju l%ju\n",
wr->inode, wr->stripe, wr->version, wr->lsn, commit_wr->version, commit_wr->lsn);
return false;
}
if (!commit_wr)
{
commit_wr = wr;
}
continue; continue;
} }
if (wr->entry_type & BS_HEAP_STABLE) if (wr->entry_type & BS_HEAP_STABLE)
@@ -837,7 +840,6 @@ bool blockstore_heap_t::calc_checksums(heap_entry_t *wr, uint8_t *data, bool set
{ {
return true; return true;
} }
uint32_t len = 0;
if (wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE) if (wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE)
len = wr->small().len; len = wr->small().len;
else if (wr->type() == BS_HEAP_BIG_INTENT) else if (wr->type() == BS_HEAP_BIG_INTENT)
@@ -854,13 +856,14 @@ bool blockstore_heap_t::calc_checksums(heap_entry_t *wr, uint8_t *data, bool set
} }
if (wr->type() == BS_HEAP_BIG_WRITE) if (wr->type() == BS_HEAP_BIG_WRITE)
{ {
assert(offset != UINT32_MAX && len != UINT32_MAX);
return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)), return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)),
data, wr->get_int_bitmap(this), offset, offset+len, set, NULL); data, wr->get_int_bitmap(this), offset, offset+len, set, NULL);
} }
if (wr->type() == BS_HEAP_BIG_INTENT) if (wr->type() == BS_HEAP_BIG_INTENT)
{ {
auto & bi = wr->big_intent(); auto & bi = wr->big_intent();
return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)), return calc_block_checksums((uint32_t*)(wr->get_checksums(this) + bi.offset/dsk->csum_block_size * (dsk->data_csum_type & 0xFF)),
data, wr->get_int_bitmap(this), bi.offset, bi.offset+bi.len, set, NULL); data, wr->get_int_bitmap(this), bi.offset, bi.offset+bi.len, set, NULL);
} }
assert(wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE); assert(wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE);
@@ -1077,16 +1080,6 @@ bool blockstore_heap_t::reshard_check(pool_id_t pool, uint32_t pg_count, uint32_
set_it->second.pg_stripe_size == pg_stripe_size); set_it->second.pg_stripe_size == pg_stripe_size);
} }
void blockstore_heap_t::reshard_abort(void* reshard_state)
{
heap_reshard_state_t *st = (heap_reshard_state_t*)reshard_state;
for (auto sh_it = st->old_shards.begin(); sh_it != st->old_shards.end(); sh_it++)
{
block_index[sh_it->first] = std::move(sh_it->second);
}
delete st;
}
heap_entry_t *blockstore_heap_t::lock_and_read_entry(object_id oid) heap_entry_t *blockstore_heap_t::lock_and_read_entry(object_id oid)
{ {
auto obj = read_entry(oid); auto obj = read_entry(oid);
@@ -1099,27 +1092,6 @@ heap_entry_t *blockstore_heap_t::lock_and_read_entry(object_id oid)
return obj; return obj;
} }
heap_entry_t *blockstore_heap_t::read_locked_entry(object_id oid, uint64_t lsn)
{
auto obj = read_entry(oid);
assert(obj);
for (auto wr = obj; wr; wr = prev(wr))
{
if (wr->is_overwrite())
{
if (lsn == wr->lsn)
{
return obj;
}
else
{
obj = prev(wr);
}
}
}
return NULL;
}
bool blockstore_heap_t::unlock_entry(object_id oid) bool blockstore_heap_t::unlock_entry(object_id oid)
{ {
auto mvcc_it = object_mvcc.find(oid); auto mvcc_it = object_mvcc.find(oid);
@@ -1418,7 +1390,7 @@ int blockstore_heap_t::add_redirect_intent(object_id oid, heap_entry_t **obj_ptr
bitmap_set(wr->get_int_bitmap(this), offset, len, dsk->bitmap_granularity); bitmap_set(wr->get_int_bitmap(this), offset, len, dsk->bitmap_granularity);
if (dsk->data_csum_type) if (dsk->data_csum_type)
memset(wr->get_checksums(this), 0, get_csum_size(wr)); memset(wr->get_checksums(this), 0, get_csum_size(wr));
calc_checksums(wr, (uint8_t*)data, true, offset, len); calc_checksums(wr, (uint8_t*)data, true);
*obj_ptr = wr; *obj_ptr = wr;
}); });
} }
@@ -1457,11 +1429,11 @@ int blockstore_heap_t::add_big_intent(object_id oid, heap_entry_t **obj_ptr, uin
if (dsk->data_csum_type) if (dsk->data_csum_type)
{ {
if (checksums) if (checksums)
memcpy(wr->get_checksums(this), checksums, dsk->clean_entry_bitmap_size); memcpy(wr->get_checksums(this), checksums, get_csum_size(wr));
else else
{ {
memcpy(wr->get_checksums(this), obj->get_checksums(this), dsk->clean_entry_bitmap_size); memcpy(wr->get_checksums(this), obj->get_checksums(this), get_csum_size(wr));
calc_checksums(wr, (uint8_t*)data, true, offset, len); calc_checksums(wr, (uint8_t*)data, true);
} }
} }
else else
@@ -1582,7 +1554,7 @@ int blockstore_heap_t::add_commit(heap_entry_t *obj, uint64_t version, uint32_t
} }
if (!uncommitted) if (!uncommitted)
{ {
return EBUSY; return 0;
} }
return add_simple(obj, version, modified_block, BS_HEAP_COMMIT); return add_simple(obj, version, modified_block, BS_HEAP_COMMIT);
} }
@@ -1592,23 +1564,32 @@ int blockstore_heap_t::add_rollback(heap_entry_t *obj, uint64_t version, uint32_
heap_entry_t *wr = obj; heap_entry_t *wr = obj;
bool found_uncommitted = false; bool found_uncommitted = false;
uint64_t commit_version = 0; uint64_t commit_version = 0;
while (wr && !wr->is_overwrite()) uint64_t rollback_version = UINT64_MAX;
while (wr)
{ {
if (wr->type() == BS_HEAP_ROLLBACK) if (wr->type() == BS_HEAP_ROLLBACK)
{ {
auto rollback_version = wr->version; if (wr->version <= version)
wr = prev(wr);
while (wr->version > rollback_version)
{ {
assert(!(wr->entry_type & BS_HEAP_STABLE)); // All previous writes are already rolled back, stop
wr = prev(wr); break;
} }
rollback_version = wr->version;
wr = prev(wr);
continue; continue;
} }
if (wr->type() == BS_HEAP_COMMIT) if (wr->type() == BS_HEAP_COMMIT)
{ {
if (commit_version < wr->version) if (commit_version < wr->version)
{
commit_version = wr->version; commit_version = wr->version;
}
wr = prev(wr);
continue;
}
if (wr->version > rollback_version)
{
// Already rolled back, skip
wr = prev(wr); wr = prev(wr);
continue; continue;
} }
@@ -1619,14 +1600,10 @@ int blockstore_heap_t::add_rollback(heap_entry_t *obj, uint64_t version, uint32_
{ {
return EBUSY; return EBUSY;
} }
else if (wr->version == version) else
{ {
break; break;
} }
else if (wr->version < version)
{
return ENOENT;
}
} }
else if (wr->version > version) else if (wr->version > version)
{ {
@@ -1807,9 +1784,9 @@ void blockstore_heap_t::iterate_with_stable(heap_entry_t *obj, uint64_t max_lsn,
} }
else else
{ {
// 1) 1 2 3 ROLLBACK(2) COMMIT(3) -> impossible // 1) 1 2 3 ROLLBACK(2) COMMIT(3) -> 3 is unstable
// 2) 1 2 3 4 ROLLBACK(3) COMMIT(2) -> OK // 2) 1 2 3 4 ROLLBACK(3) COMMIT(2) -> OK
// 3) 1 2 3 ROLLBACK(2) 3 COMMIT(3) -> first 3 shouldn't be treated as stable // 3) 1 2 3 ROLLBACK(2) 3 COMMIT(3) -> first 3 is unstable
// 4) 1 2 3 COMMIT(3) ROLLBACK(2) -> impossible // 4) 1 2 3 COMMIT(3) ROLLBACK(2) -> impossible
// I.e. a rollback always has version >= previous commit // I.e. a rollback always has version >= previous commit
// 5) 1 2 3 4 5 ROLLBACK(4) 5 ROLLBACK(3) // 5) 1 2 3 4 5 ROLLBACK(4) 5 ROLLBACK(3)
@@ -2045,7 +2022,13 @@ void blockstore_heap_t::free_data(inode_t inode, uint64_t location)
inode = (INODE_POOL(inode) << POOL_ID_BITS); inode = (INODE_POOL(inode) << POOL_ID_BITS);
assert(data_alloc->get(location / dsk->data_block_size)); assert(data_alloc->get(location / dsk->data_block_size));
data_alloc->set(location / dsk->data_block_size, false); data_alloc->set(location / dsk->data_block_size, false);
inode_space_stats[inode] -= dsk->data_block_size; auto sp_it = inode_space_stats.find(inode);
if (sp_it != inode_space_stats.end())
{
sp_it->second -= dsk->data_block_size;
if (sp_it->second == 0)
inode_space_stats.erase(sp_it);
}
data_used_space -= dsk->data_block_size; data_used_space -= dsk->data_block_size;
} }
@@ -2328,7 +2311,7 @@ void blockstore_heap_t::set_no_inode_stats(const std::vector<uint64_t> & pool_id
{ {
// Recalculate if changed // Recalculate if changed
if (ps.second.no_inode_stats == 2 || ps.second.no_inode_stats == 1) if (ps.second.no_inode_stats == 2 || ps.second.no_inode_stats == 1)
recalc_inode_space_stats(ps.first, ps.second.no_inode_stats == 1); recalc_inode_space_stats(ps.first, ps.second.no_inode_stats == 2);
ps.second.no_inode_stats &= 1; ps.second.no_inode_stats &= 1;
} }
} }
@@ -2339,8 +2322,8 @@ void blockstore_heap_t::recalc_inode_space_stats(uint64_t pool_id, bool per_inod
auto sp_begin = inode_space_stats.lower_bound((pool_id << (64-POOL_ID_BITS))); auto sp_begin = inode_space_stats.lower_bound((pool_id << (64-POOL_ID_BITS)));
auto sp_end = inode_space_stats.lower_bound(((pool_id+1) << (64-POOL_ID_BITS))); auto sp_end = inode_space_stats.lower_bound(((pool_id+1) << (64-POOL_ID_BITS)));
inode_space_stats.erase(sp_begin, sp_end); inode_space_stats.erase(sp_begin, sp_end);
uint32_t pg_count = ps.pg_count ? ps.pg_count : 1; uint32_t pg_count = ps.pg_count;
for (uint32_t pg_num = 1; pg_num <= pg_count; pg_num++) for (uint32_t pg_num = pg_count ? 1 : 0; pg_num <= pg_count; pg_num++)
{ {
auto & pg_idx = block_index[(pool_id << (64-POOL_ID_BITS)) | pg_num]; auto & pg_idx = block_index[(pool_id << (64-POOL_ID_BITS)) | pg_num];
for (auto & ip: pg_idx) for (auto & ip: pg_idx)
+1 -4
View File
@@ -248,20 +248,17 @@ public:
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit); void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
bool reshard_continue(void* reshard_state, uint64_t chunk_limit); bool reshard_continue(void* reshard_state, uint64_t chunk_limit);
bool reshard_check(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size); bool reshard_check(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size);
void reshard_abort(void* reshard_state);
void set_no_inode_stats(const std::vector<uint64_t> & pool_ids); void set_no_inode_stats(const std::vector<uint64_t> & pool_ids);
void recalc_inode_space_stats(uint64_t pool_id, bool per_inode); void recalc_inode_space_stats(uint64_t pool_id, bool per_inode);
// read an object entry and lock it against removal // read an object entry and lock it against removal
// in the future, may become asynchronous // in the future, may become asynchronous
heap_entry_t *lock_and_read_entry(object_id oid); heap_entry_t *lock_and_read_entry(object_id oid);
// re-read a locked object entry with the given lsn (pointer may be invalidated)
heap_entry_t *read_locked_entry(object_id oid, uint64_t lsn);
// read an object entry without locking it // read an object entry without locking it
heap_entry_t *read_entry(object_id oid); heap_entry_t *read_entry(object_id oid);
// unlock an entry // unlock an entry
bool unlock_entry(object_id oid); bool unlock_entry(object_id oid);
// set or verify checksums in a write request // set or verify checksums in a write request
bool calc_checksums(heap_entry_t *wr, uint8_t *data, bool set, uint32_t offset = 0, uint32_t len = 0); bool calc_checksums(heap_entry_t *wr, uint8_t *data, bool set, uint32_t offset = UINT32_MAX, uint32_t len = UINT32_MAX);
// set or verify raw block checksums // set or verify raw block checksums
bool calc_block_checksums(uint32_t *block_csums, uint8_t *data, uint8_t *bitmap, uint32_t start, uint32_t end, bool calc_block_checksums(uint32_t *block_csums, uint8_t *data, uint8_t *bitmap, uint32_t start, uint32_t end,
bool set, std::function<void(uint32_t, uint32_t, uint32_t)> bad_block_cb); bool set, std::function<void(uint32_t, uint32_t, uint32_t)> bad_block_cb);
-5
View File
@@ -406,8 +406,3 @@ bool blockstore_impl_t::reshard_continue(void *reshard_state, uint64_t chunk_lim
{ {
return heap->reshard_continue(reshard_state, chunk_limit); return heap->reshard_continue(reshard_state, chunk_limit);
} }
void blockstore_impl_t::reshard_abort(void *reshard_state)
{
return heap->reshard_abort(reshard_state);
}
-1
View File
@@ -191,7 +191,6 @@ public:
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit); void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
bool reshard_continue(void *reshard_state, uint64_t chunk_limit); bool reshard_continue(void *reshard_state, uint64_t chunk_limit);
void reshard_abort(void *reshard_state);
// Event loop // Event loop
void loop(); void loop();
+1 -1
View File
@@ -57,9 +57,9 @@ int blockstore_impl_t::dequeue_stable(blockstore_op_t *op)
} }
assert(res == 0); assert(res == 0);
} }
resume_1:
if (priv->modified_block != UINT32_MAX && priv->modified_block2 != priv->modified_block) if (priv->modified_block != UINT32_MAX && priv->modified_block2 != priv->modified_block)
{ {
resume_1:
BS_SUBMIT_CHECK_SQES(1); BS_SUBMIT_CHECK_SQES(1);
prepare_meta_block_write(priv->modified_block); prepare_meta_block_write(priv->modified_block);
resume_2: resume_2:
-11
View File
@@ -480,17 +480,6 @@ resume_1:
return true; return true;
} }
void blockstore_impl_t::reshard_abort(void *reshard_state)
{
bs_reshard_state_t *st = (bs_reshard_state_t*)reshard_state;
for (auto sh_it = st->old_shards.begin(); sh_it != st->old_shards.end(); sh_it++)
{
auto & to = clean_db_shards[sh_it->first];
to.swap(sh_it->second);
}
delete st;
}
void blockstore_impl_t::process_list(blockstore_op_t *op) void blockstore_impl_t::process_list(blockstore_op_t *op)
{ {
uint32_t list_pg = op->pg_number+1; uint32_t list_pg = op->pg_number+1;
-1
View File
@@ -290,7 +290,6 @@ public:
// Reshard database for a pool // Reshard database for a pool
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit); void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
bool reshard_continue(void *reshard_state, uint64_t chunk_limit); bool reshard_continue(void *reshard_state, uint64_t chunk_limit);
void reshard_abort(void *reshard_state);
// Event loop // Event loop
void loop(); void loop();
+1 -1
View File
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: Vitastor Name: Vitastor
Description: Vitastor client library Description: Vitastor client library
Version: 3.0.2 Version: 3.0.3
Libs: -L${libdir} -lvitastor_client Libs: -L${libdir} -lvitastor_client
Cflags: -I${includedir} Cflags: -I${includedir}
+4 -8
View File
@@ -809,21 +809,17 @@ again:
goto again; goto again;
} }
auto & pool_cfg = pool_it->second; auto & pool_cfg = pool_it->second;
bool done = false; bool done = bs->reshard_continue(pool_cfg.reshard_state, pg_reshard_chunk_size);
if (pool_cfg.real_pg_count != pool_cfg.applied_pg_count || if (done &&
pool_cfg.pg_stripe_size != pool_cfg.applied_pg_stripe_size) (pool_cfg.real_pg_count != pool_cfg.applied_pg_count ||
pool_cfg.pg_stripe_size != pool_cfg.applied_pg_stripe_size))
{ {
// PG count changed again, reshard again // PG count changed again, reshard again
bs->reshard_abort(pool_cfg.reshard_state);
pool_cfg.applied_pg_count = pool_cfg.real_pg_count; pool_cfg.applied_pg_count = pool_cfg.real_pg_count;
pool_cfg.applied_pg_stripe_size = pool_cfg.pg_stripe_size; pool_cfg.applied_pg_stripe_size = pool_cfg.pg_stripe_size;
pool_cfg.reshard_state = bs->reshard_start(pool_id, pool_cfg.real_pg_count, pool_cfg.pg_stripe_size, pg_reshard_chunk_size); pool_cfg.reshard_state = bs->reshard_start(pool_id, pool_cfg.real_pg_count, pool_cfg.pg_stripe_size, pg_reshard_chunk_size);
done = !pool_cfg.reshard_state; done = !pool_cfg.reshard_state;
} }
else
{
done = bs->reshard_continue(pool_cfg.reshard_state, pg_reshard_chunk_size);
}
if (done) if (done)
{ {
// Pool is resharded // Pool is resharded
+906 -9
View File
File diff suppressed because it is too large Load Diff