Compare commits

...
5 Commits
Author SHA1 Message Date
Vitaliy Filippov cb639a130d Release 3.0.5
A single urgent fix for the new store: metadata was written incorrectly when
filled metadata area exceeded 4 GB due to a simple & stupid 32-bit integer overflow.
This was leading to OSDs corrupting metadata and being unable to start on the next
run.

The bug affected only the new store (meta_format=3) and OSDs with metadata area size
larger than 4 GB. You can check your OSD metadata area size by checking `data_offset`
in `vitastor-disk read-sb /dev/vitastor/osdXX-data` for single-disk OSDs or
`blockdev --getsize64 /dev/vitastor/osdXX-meta` for hybrid OSDs.

If you're affected, it's highly recommended to:
- Install updated packages without restarting OSDs
- Restart OSDs **one by one**
- If a restart of an OSD triggers "has_degraded" rebalance - wait for it to finish
  before restarting another OSD
- If an OSD fails to start with "double-claimed" errors in the log - purge and recreate it,
  and again wait for "has_degraded" rebalance to finish before proceeding to the next OSD
2026-03-07 13:54:44 +03:00
Vitaliy Filippov 892e3a8b6d Add Ubuntu 26.04 build 2026-03-07 13:54:44 +03:00
Vitaliy Filippov 0bd9c26620 Make block_sizes uint64_t to prevent other integer overflow errors in the future 2026-03-07 12:02:57 +03:00
Vitaliy Filippov ae2b1f7802 Some useless code changes for beauty 2026-03-07 00:15:16 +03:00
Vitaliy Filippov 883b2e45da Fix uint32 overflow in the new store :-X 2026-03-06 17:21:22 +03:00
28 changed files with 52 additions and 43 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.4") set(VITASTOR_VERSION "3.0.5")
include(CTest) include(CTest)
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.4 VITASTOR_VERSION ?= v3.0.5
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.4 image: vitalif/vitastor-csi:v3.0.5
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.4 image: vitalif/vitastor-csi:v3.0.5
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.4" vitastorCSIDriverVersion = "3.0.5"
) )
// Config struct fills the parameters of request or user input // Config struct fills the parameters of request or user input
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# 26.04 Resolute Raccoon
docker build --build-arg DISTRO=ubuntu --build-arg REL=resolute -t vitastor-buildenv:resolute -f vitastor-buildenv.Dockerfile .
docker run -it --rm -e REL=resolute -v `dirname $0`/../:/root/vitastor vitastor-buildenv:resolute /root/vitastor/debian/vitastor-build.sh
+1 -1
View File
@@ -1,4 +1,4 @@
vitastor (3.0.4-1) unstable; urgency=medium vitastor (3.0.5-1) unstable; urgency=medium
* Bugfixes * Bugfixes
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.4 VITASTOR_VERSION ?= v3.0.5
all: build push all: build push
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# Desired Vitastor version # Desired Vitastor version
VITASTOR_VERSION=v3.0.4 VITASTOR_VERSION=v3.0.5
# 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.4` `docker pull vitalif/vitastor:v3.0.5`
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.4 install.sh` `docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.5 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.4` `docker pull vitalif/vitastor:v3.0.5`
2. Установите скрипты в хост-систему командой: \ 2. Установите скрипты в хост-систему командой: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.4 install.sh` `docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.5 install.sh`
3. Перезагрузите правила udev: \ 3. Перезагрузите правила udev: \
`udevadm control --reload-rules` `udevadm control --reload-rules`
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "vitastor-mon", "name": "vitastor-mon",
"version": "3.0.4", "version": "3.0.5",
"description": "Vitastor SDS monitor service", "description": "Vitastor SDS monitor service",
"main": "mon-main.js", "main": "mon-main.js",
"scripts": { "scripts": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "vitastor", "name": "vitastor",
"version": "3.0.4", "version": "3.0.5",
"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.4' VITASTOR_VERSION = '3.0.5'
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.4 Version: 3.0.5
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.4.el10.tar.gz Source0: vitastor-3.0.5.el10.tar.gz
BuildRequires: gperftools-devel BuildRequires: gperftools-devel
BuildRequires: gcc-c++ BuildRequires: gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor Name: vitastor
Version: 3.0.4 Version: 3.0.5
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.4.el7.tar.gz Source0: vitastor-3.0.5.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.4 Version: 3.0.5
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.4.el8.tar.gz Source0: vitastor-3.0.5.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.4 Version: 3.0.5
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.4.el9.tar.gz Source0: vitastor-3.0.5.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.4") add_definitions(-DVITASTOR_VERSION="3.0.5")
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})
+3 -3
View File
@@ -26,14 +26,14 @@ class allocator_t;
struct blockstore_disk_t struct blockstore_disk_t
{ {
std::string data_device, meta_device, journal_device; std::string data_device, meta_device, journal_device;
uint32_t data_block_size; uint64_t data_block_size;
uint64_t cfg_journal_size, cfg_data_size; uint64_t cfg_journal_size, cfg_data_size;
// Required write alignment and journal/metadata/data areas' location alignment // Required write alignment and journal/metadata/data areas' location alignment
uint32_t disk_alignment = 4096; uint32_t disk_alignment = 4096;
// Journal block size - minimum_io_size of the journal device is the best choice // Journal block size - minimum_io_size of the journal device is the best choice
uint32_t journal_block_size = 4096; uint64_t journal_block_size = 4096;
// Metadata block size - minimum_io_size of the metadata device is the best choice // Metadata block size - minimum_io_size of the metadata device is the best choice
uint32_t meta_block_size = 4096; uint64_t meta_block_size = 4096;
// Atomic write size of the data block device // Atomic write size of the data block device
uint32_t atomic_write_size = 4096; uint32_t atomic_write_size = 4096;
// Whether we should set RWF_ATOMIC on atomic writes // Whether we should set RWF_ATOMIC on atomic writes
+3 -1
View File
@@ -301,7 +301,7 @@ int blockstore_heap_t::read_blocks(uint64_t disk_offset, uint64_t disk_size, uin
heap_entry_t *wr = (heap_entry_t*)data; heap_entry_t *wr = (heap_entry_t*)data;
if (wr->size > dsk->meta_block_size-block_offset) if (wr->size > dsk->meta_block_size-block_offset)
{ {
fprintf(stderr, "Error: entry is too large in metadata block %u at %u (%u > max %u bytes). ", fprintf(stderr, "Error: entry is too large in metadata block %u at %u (%u > max %ju bytes). ",
block_num, block_offset, wr->size, dsk->meta_block_size-block_offset); block_num, block_offset, wr->size, dsk->meta_block_size-block_offset);
corrupted_block: corrupted_block:
if (allow_corrupted) if (allow_corrupted)
@@ -2291,7 +2291,9 @@ void blockstore_heap_t::apply_inflight(heap_inflight_lsn_t & inflight)
} }
if (!next) if (!next)
{ {
// The last freed entry must be a deletion
assert(!prev); assert(!prev);
assert(wr->entry_type == BS_HEAP_DELETE|BS_HEAP_STABLE);
auto & pg_idx = block_index[get_pg_id(wr->inode, wr->stripe)]; auto & pg_idx = block_index[get_pg_id(wr->inode, wr->stripe)];
auto & inode_idx = pg_idx[wr->inode]; auto & inode_idx = pg_idx[wr->inode];
heap_inode_map_t::iterator li_it; heap_inode_map_t::iterator li_it;
+1 -1
View File
@@ -193,12 +193,12 @@ void blockstore_impl_t::loop()
heap->start_block_write(block_num); heap->start_block_write(block_num);
mb.sent = true; mb.sent = true;
} }
pending_modified_blocks.clear();
int ret = ringloop->submit(); int ret = ringloop->submit();
if (ret < 0) if (ret < 0)
{ {
throw std::runtime_error(std::string("io_uring_submit: ") + strerror(-ret)); throw std::runtime_error(std::string("io_uring_submit: ") + strerror(-ret));
} }
pending_modified_blocks.clear();
if ((initial_ring_space - ringloop->space_left()) > 0) if ((initial_ring_space - ringloop->space_left()) > 0)
{ {
live = true; live = true;
+1 -1
View File
@@ -145,7 +145,7 @@ resume_1:
printf( printf(
"Configuration stored in metadata superblock" "Configuration stored in metadata superblock"
" (meta_block_size=%u, data_block_size=%u, bitmap_granularity=%u, data_csum_type=%u, csum_block_size=%u, meta_area_size=%ju)" " (meta_block_size=%u, data_block_size=%u, bitmap_granularity=%u, data_csum_type=%u, csum_block_size=%u, meta_area_size=%ju)"
" differs from OSD configuration (%u/%u/%u, %u/%u, %ju).\n", " differs from OSD configuration (%ju/%ju/%u, %u/%u, %ju).\n",
hdr->meta_block_size, hdr->data_block_size, hdr->bitmap_granularity, hdr->meta_block_size, hdr->data_block_size, hdr->bitmap_granularity,
hdr->data_csum_type, hdr->csum_block_size, hdr->meta_area_size, hdr->data_csum_type, hdr->csum_block_size, hdr->meta_area_size,
bs->dsk.meta_block_size, bs->dsk.data_block_size, bs->dsk.bitmap_granularity, bs->dsk.meta_block_size, bs->dsk.data_block_size, bs->dsk.bitmap_granularity,
+8 -6
View File
@@ -22,21 +22,23 @@ void blockstore_impl_t::prepare_meta_block_write(uint32_t modified_block)
ring_data_t *data = ((ring_data_t*)sqe->user_data); ring_data_t *data = ((ring_data_t*)sqe->user_data);
uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.meta_block_size); uint8_t *buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, dsk.meta_block_size);
data->iov = (struct iovec){ buf, (size_t)dsk.meta_block_size }; data->iov = (struct iovec){ buf, (size_t)dsk.meta_block_size };
data->callback = [this, modified_block, buf](ring_data_t *data) data->callback = [this, modified_block](ring_data_t *data)
{ {
free(buf);
live = true; live = true;
if (data->res != data->iov.iov_len) if (data->res != data->iov.iov_len)
{ {
// FIXME: our state becomes corrupted after a write error. maybe do something better than just die // FIXME: our state becomes corrupted after a write error. maybe do something better than just die
disk_error_abort("data write", data->res, data->iov.iov_len); disk_error_abort("data write", data->res, data->iov.iov_len);
} }
modified_blocks.erase(modified_block); auto it = modified_blocks.find(modified_block);
assert(it != modified_blocks.end());
free(it->second.buf);
modified_blocks.erase(it);
heap->complete_block_write(modified_block); heap->complete_block_write(modified_block);
ringloop->wakeup(); ringloop->wakeup();
}; };
io_uring_prep_writev( io_uring_prep_writev(
sqe, dsk.meta_fd, &data->iov, 1, dsk.meta_offset + (modified_block+1)*dsk.meta_block_size sqe, dsk.meta_fd, &data->iov, 1, dsk.meta_offset + ((uint64_t)modified_block+1)*dsk.meta_block_size
); );
unsynced_meta_write_count++; unsynced_meta_write_count++;
pending_modified_blocks.push_back(modified_block); pending_modified_blocks.push_back(modified_block);
@@ -249,13 +251,12 @@ enospc:
goto enospc; goto enospc;
assert(res == 0); assert(res == 0);
PRIV(op)->lsn = obj->lsn; PRIV(op)->lsn = obj->lsn;
if (op->len)
heap->use_buffer_area(op->oid.inode, loc, op->len);
prepare_meta_block_write(PRIV(op)->modified_block); prepare_meta_block_write(PRIV(op)->modified_block);
PRIV(op)->pending_ops++; PRIV(op)->pending_ops++;
if (op->len > 0) if (op->len > 0)
{ {
// Prepare buffered data write // Prepare buffered data write
heap->use_buffer_area(op->oid.inode, loc, op->len);
if (dsk.inmemory_journal) if (dsk.inmemory_journal)
{ {
memcpy((uint8_t*)buffer_area + loc, op->buf, op->len); memcpy((uint8_t*)buffer_area + loc, op->buf, op->len);
@@ -348,6 +349,7 @@ resume_12:
} }
resume_4: resume_4:
{ {
BS_SUBMIT_CHECK_SQES(1);
auto obj = heap->read_entry(op->oid); auto obj = heap->read_entry(op->oid);
int res = 0; int res = 0;
if (PRIV(op)->write_type == _REDIRECT_INTENT) if (PRIV(op)->write_type == _REDIRECT_INTENT)
+1 -1
View File
@@ -189,7 +189,7 @@ resume_1:
printf( printf(
"Configuration stored in metadata superblock" "Configuration stored in metadata superblock"
" (meta_block_size=%u, data_block_size=%u, bitmap_granularity=%u, data_csum_type=%u, csum_block_size=%u)" " (meta_block_size=%u, data_block_size=%u, bitmap_granularity=%u, data_csum_type=%u, csum_block_size=%u)"
" differs from OSD configuration (%u/%u/%u, %u/%u).\n", " differs from OSD configuration (%ju/%ju/%u, %u/%u).\n",
hdr->meta_block_size, hdr->data_block_size, hdr->bitmap_granularity, hdr->meta_block_size, hdr->data_block_size, hdr->bitmap_granularity,
hdr->data_csum_type, hdr->csum_block_size, hdr->data_csum_type, hdr->csum_block_size,
bs->dsk.meta_block_size, bs->dsk.data_block_size, bs->dsk.bitmap_granularity, bs->dsk.meta_block_size, bs->dsk.data_block_size, bs->dsk.bitmap_granularity,
+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.4 Version: 3.0.5
Libs: -L${libdir} -lvitastor_client Libs: -L${libdir} -lvitastor_client
Cflags: -I${includedir} Cflags: -I${includedir}
+1 -1
View File
@@ -331,7 +331,7 @@ void disk_tool_t::dump_meta_header(blockstore_meta_header_v3_t *hdr)
} }
else else
{ {
printf("{\"version\":\"0.5\",\"meta_block_size\":%u,\"entries\":[\n", dsk.meta_block_size); printf("{\"version\":\"0.5\",\"meta_block_size\":%ju,\"entries\":[\n", dsk.meta_block_size);
} }
first_entry = true; first_entry = true;
} }
+4 -4
View File
@@ -212,11 +212,11 @@ void disk_tool_t::resize_init(blockstore_meta_header_v3_t *hdr)
dsk.calc_lengths(); dsk.calc_lengths();
if (((new_data_offset-dsk.data_offset) % dsk.data_block_size)) if (((new_data_offset-dsk.data_offset) % dsk.data_block_size))
{ {
fprintf(stderr, "Data alignment mismatch: old data offset is 0x%jx, new is 0x%jx, but alignment on %x should be equal\n", fprintf(stderr, "Data alignment mismatch: old data offset is 0x%jx, new is 0x%jx, but alignment on %jx should be equal\n",
dsk.data_offset, new_data_offset, dsk.data_block_size); dsk.data_offset, new_data_offset, dsk.data_block_size);
exit(1); exit(1);
} }
data_idx_diff = ((int64_t)(dsk.data_offset-new_data_offset)) / dsk.data_block_size; data_idx_diff = ((int64_t)(dsk.data_offset-new_data_offset))/((int64_t)dsk.data_block_size);
free_first = new_data_offset > dsk.data_offset ? (new_data_offset-dsk.data_offset) / dsk.data_block_size : 0; free_first = new_data_offset > dsk.data_offset ? (new_data_offset-dsk.data_offset) / dsk.data_block_size : 0;
free_last = (new_data_offset+new_data_len < dsk.data_offset+dsk.data_len) free_last = (new_data_offset+new_data_len < dsk.data_offset+dsk.data_len)
? (dsk.data_offset+dsk.data_len-new_data_offset-new_data_len) / dsk.data_block_size ? (dsk.data_offset+dsk.data_len-new_data_offset-new_data_len) / dsk.data_block_size
@@ -351,7 +351,7 @@ int disk_tool_t::resize_copy_data()
if (data->res != dsk.data_block_size) if (data->res != dsk.data_block_size)
{ {
fprintf( fprintf(
stderr, "Failed to read %u bytes at %ju from %s: %s\n", dsk.data_block_size, stderr, "Failed to read %ju bytes at %ju from %s: %s\n", dsk.data_block_size,
dsk.data_offset + moving_blocks[i].old_loc*dsk.data_block_size, dsk.data_device.c_str(), dsk.data_offset + moving_blocks[i].old_loc*dsk.data_block_size, dsk.data_device.c_str(),
data->res < 0 ? strerror(-data->res) : "short read" data->res < 0 ? strerror(-data->res) : "short read"
); );
@@ -376,7 +376,7 @@ int disk_tool_t::resize_copy_data()
if (data->res != dsk.data_block_size) if (data->res != dsk.data_block_size)
{ {
fprintf( fprintf(
stderr, "Failed to write %u bytes at %ju to %s: %s\n", dsk.data_block_size, stderr, "Failed to write %ju bytes at %ju to %s: %s\n", dsk.data_block_size,
dsk.data_offset + moving_blocks[i].new_loc*dsk.data_block_size, dsk.data_device.c_str(), dsk.data_offset + moving_blocks[i].new_loc*dsk.data_block_size, dsk.data_device.c_str(),
data->res < 0 ? strerror(-data->res) : "short write" data->res < 0 ? strerror(-data->res) : "short write"
); );