Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
Vitaliy Filippov | 61e89c3502 | |
Vitaliy Filippov | 30e7c2ad1e | |
Vitaliy Filippov | 2e76ceabbe | |
Vitaliy Filippov | 3df088c207 | |
Vitaliy Filippov | d882a19eab | |
Vitaliy Filippov | 702be3da7a | |
Vitaliy Filippov | 99533e1c2f | |
Vitaliy Filippov | a6cceb43bf | |
Vitaliy Filippov | 745d89459a | |
Vitaliy Filippov | 48f023292d | |
Vitaliy Filippov | b58bf3ada5 | |
Vitaliy Filippov | f18a749324 | |
Vitaliy Filippov | 6e9307c522 |
|
@ -828,6 +828,24 @@ jobs:
|
|||
echo ""
|
||||
done
|
||||
|
||||
test_snapshot_pool2:
|
||||
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_snapshot_pool2.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_osd_tags:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Vitastor
|
||||
# Vitastor
|
||||
|
||||
[Read English version](README.md)
|
||||
|
||||
|
@ -22,7 +22,7 @@ TCP и RDMA и на хорошем железе может достигать з
|
|||
Vitastor поддерживает QEMU-драйвер, протоколы NBD и NFS, драйверы OpenStack, OpenNebula, Proxmox, Kubernetes.
|
||||
Другие драйверы могут также быть легко реализованы.
|
||||
|
||||
Подробности смотрите в документации по ссылкам ниже.
|
||||
Подробности смотрите в документации по ссылкам. Можете начать отсюда: [Быстрый старт](docs/intro/quickstart.ru.md).
|
||||
|
||||
## Презентации и записи докладов
|
||||
|
||||
|
@ -51,7 +51,7 @@ Vitastor поддерживает QEMU-драйвер, протоколы NBD и
|
|||
- Параметры
|
||||
- [Общие](docs/config/common.ru.md)
|
||||
- [Сетевые](docs/config/network.ru.md)
|
||||
- [Клиентский код](docs/config/client.en.md)
|
||||
- [Клиентский код](docs/config/client.ru.md)
|
||||
- [Глобальные дисковые параметры](docs/config/layout-cluster.ru.md)
|
||||
- [Дисковые параметры OSD](docs/config/layout-osd.ru.md)
|
||||
- [Прочие параметры OSD](docs/config/osd.ru.md)
|
||||
|
|
|
@ -22,7 +22,7 @@ or internal systems of public clouds.
|
|||
Vitastor supports QEMU, NBD, NFS protocols, OpenStack, OpenNebula, Proxmox, Kubernetes drivers.
|
||||
More drivers may be created easily.
|
||||
|
||||
Read more details below in the documentation.
|
||||
Read more details in the documentation. You can start from here: [Quick Start](docs/intro/quickstart.en.md).
|
||||
|
||||
## Talks and presentations
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@ SSD cache or "media-cache" - for example, a lot of Seagate EXOS drives have
|
|||
it (they have internal SSD cache even though it's not stated in datasheets).
|
||||
|
||||
Setting this parameter to "all" or "small" in OSD parameters requires enabling
|
||||
[disable_journal_fsync](layout-osd.en.yml#disable_journal_fsync) and
|
||||
[disable_meta_fsync](layout-osd.en.yml#disable_meta_fsync), setting it to
|
||||
"all" also requires enabling [disable_data_fsync](layout-osd.en.yml#disable_data_fsync).
|
||||
[disable_journal_fsync](layout-osd.en.md#disable_journal_fsync) and
|
||||
[disable_meta_fsync](layout-osd.en.md#disable_meta_fsync), setting it to
|
||||
"all" also requires enabling [disable_data_fsync](layout-osd.en.md#disable_data_fsync).
|
||||
vitastor-disk tried to do that by default, first checking/disabling drive cache.
|
||||
If it can't disable drive cache, OSD get initialized with "none".
|
||||
|
|
|
@ -112,6 +112,6 @@ HDD-дисках с внутренним SSD или "медиа" кэшем - н
|
|||
указано в спецификациях).
|
||||
|
||||
Указание "all" или "small" в настройках / командной строке OSD требует
|
||||
включения [disable_journal_fsync](layout-osd.ru.yml#disable_journal_fsync) и
|
||||
[disable_meta_fsync](layout-osd.ru.yml#disable_meta_fsync), значение "all"
|
||||
также требует включения [disable_data_fsync](layout-osd.ru.yml#disable_data_fsync).
|
||||
включения [disable_journal_fsync](layout-osd.ru.md#disable_journal_fsync) и
|
||||
[disable_meta_fsync](layout-osd.ru.md#disable_meta_fsync), значение "all"
|
||||
также требует включения [disable_data_fsync](layout-osd.ru.md#disable_data_fsync).
|
||||
|
|
|
@ -55,7 +55,7 @@ Examples:
|
|||
OSD placement tree is set in a separate etcd key `/vitastor/config/node_placement`
|
||||
in the following JSON format:
|
||||
|
||||
`
|
||||
```
|
||||
{
|
||||
"<node name or OSD number>": {
|
||||
"level": "<level>",
|
||||
|
@ -63,7 +63,7 @@ in the following JSON format:
|
|||
},
|
||||
...
|
||||
}
|
||||
`
|
||||
```
|
||||
|
||||
Here, if a node name is a number then it is assumed to refer to an OSD.
|
||||
Level of the OSD is always "osd" and cannot be overriden. You may only
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
Дерево размещения OSD задаётся в отдельном ключе etcd `/vitastor/config/node_placement`
|
||||
в следующем JSON-формате:
|
||||
|
||||
`
|
||||
```
|
||||
{
|
||||
"<имя узла или номер OSD>": {
|
||||
"level": "<уровень>",
|
||||
|
@ -62,7 +62,7 @@
|
|||
},
|
||||
...
|
||||
}
|
||||
`
|
||||
```
|
||||
|
||||
Здесь, если название узла - число, считается, что это OSD. Уровень OSD
|
||||
всегда равен "osd" и не может быть переопределён. Для OSD вы можете только
|
||||
|
|
|
@ -97,9 +97,9 @@
|
|||
it (they have internal SSD cache even though it's not stated in datasheets).
|
||||
|
||||
Setting this parameter to "all" or "small" in OSD parameters requires enabling
|
||||
[disable_journal_fsync](layout-osd.en.yml#disable_journal_fsync) and
|
||||
[disable_meta_fsync](layout-osd.en.yml#disable_meta_fsync), setting it to
|
||||
"all" also requires enabling [disable_data_fsync](layout-osd.en.yml#disable_data_fsync).
|
||||
[disable_journal_fsync](layout-osd.en.md#disable_journal_fsync) and
|
||||
[disable_meta_fsync](layout-osd.en.md#disable_meta_fsync), setting it to
|
||||
"all" also requires enabling [disable_data_fsync](layout-osd.en.md#disable_data_fsync).
|
||||
vitastor-disk tried to do that by default, first checking/disabling drive cache.
|
||||
If it can't disable drive cache, OSD get initialized with "none".
|
||||
info_ru: |
|
||||
|
@ -156,6 +156,6 @@
|
|||
указано в спецификациях).
|
||||
|
||||
Указание "all" или "small" в настройках / командной строке OSD требует
|
||||
включения [disable_journal_fsync](layout-osd.ru.yml#disable_journal_fsync) и
|
||||
[disable_meta_fsync](layout-osd.ru.yml#disable_meta_fsync), значение "all"
|
||||
также требует включения [disable_data_fsync](layout-osd.ru.yml#disable_data_fsync).
|
||||
включения [disable_journal_fsync](layout-osd.ru.md#disable_journal_fsync) и
|
||||
[disable_meta_fsync](layout-osd.ru.md#disable_meta_fsync), значение "all"
|
||||
также требует включения [disable_data_fsync](layout-osd.ru.md#disable_data_fsync).
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
[Читать на русском](opennebula.ru.md)
|
||||
|
||||
# OpenNebula
|
||||
|
||||
## Automatic Installation
|
||||
|
||||
OpenNebula plugin is packaged as `vitastor-opennebula` Debian and RPM package since Vitastor 1.9.0. So:
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
[Read in English](opennebula.en.md)
|
||||
|
||||
# OpenNebula
|
||||
|
||||
## Автоматическая установка
|
||||
|
||||
Плагин OpenNebula Vitastor распространяется как Debian и RPM пакет `vitastor-opennebula`, начиная с версии Vitastor 1.9.0. Так что:
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
set -e
|
||||
|
||||
reapply_patch() {
|
||||
if ! patch -f --dry-run -F 0 -R $1 < $2 >/dev/null; then
|
||||
if ! [[ -e $1 ]]; then
|
||||
echo "$1 does not exist, OpenNebula is not installed"
|
||||
elif ! patch -f --dry-run -F 0 -R $1 < $2 >/dev/null; then
|
||||
already_applied=0
|
||||
if ! patch --no-backup-if-mismatch -r - -F 0 -f $1 < $2; then
|
||||
applied_ok=0
|
||||
|
@ -15,8 +17,13 @@ echo "Reapplying Vitastor patches to OpenNebula's oned.conf, vmm_execrc and down
|
|||
already_applied=1
|
||||
applied_ok=1
|
||||
reapply_patch /var/lib/one/remotes/datastore/downloader.sh /var/lib/one/remotes/datastore/vitastor/downloader-vitastor.sh.diff
|
||||
reapply_patch /etc/one/oned.conf /var/lib/one/remotes/datastore/vitastor/oned.conf.diff
|
||||
reapply_patch /etc/one/vmm_exec/vmm_execrc /var/lib/one/remotes/datastore/vitastor/vmm_execrc.diff
|
||||
if [[ -e /etc/one/oned.conf ]]; then
|
||||
if ! /var/lib/one/remotes/datastore/vitastor/patch-oned-conf.py /etc/one/oned.conf; then
|
||||
applied_ok=0
|
||||
already_applied=0
|
||||
fi
|
||||
fi
|
||||
if [[ "$already_applied" = 1 ]]; then
|
||||
echo "OK: Vitastor OpenNebula patches are already applied"
|
||||
elif [[ "$applied_ok" = 1 ]]; then
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/env python3
|
||||
# Patch /etc/one/oned.conf for Vitastor support
|
||||
# -s = also enable save.vitastor/restore.vitastor overrides
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
|
||||
class Fixer:
|
||||
save_restore = 0
|
||||
|
||||
def require_sub_cb(self, m, cb):
|
||||
self.found = 1
|
||||
return cb(m)
|
||||
|
||||
def require_sub(self, regexp, cb, text, error):
|
||||
self.found = 0
|
||||
new_text = re.sub(regexp, lambda m: self.require_sub_cb(m, cb), text)
|
||||
if not self.found and error:
|
||||
self.errors.append(error)
|
||||
return new_text
|
||||
|
||||
def fix(self, oned_conf):
|
||||
self.errors = []
|
||||
self.kvm_found = 0
|
||||
oned_conf = self.require_sub(r'((?:^|\n)[ \t]*VM_MAD\s*=\s*\[)([^\]]+)\]', lambda m: m.group(1)+self.fix_vm_mad(m.group(2))+']', oned_conf, 'VM_MAD not found')
|
||||
if not self.kvm_found:
|
||||
self.errors.append("VM_MAD[NAME=kvm].ARGUMENTS not found")
|
||||
oned_conf = self.require_sub(r'((?:^|\n)[ \t]*TM_MAD\s*=\s*\[)([^\]]+)\]', lambda m: m.group(1)+self.fix_tm_mad(m.group(2))+']', oned_conf, 'TM_MAD not found')
|
||||
oned_conf = self.require_sub(r'((?:^|\n)[ \t]*DATASTORE_MAD\s*=\s*\[)([^\]]+)\]', lambda m: m.group(1)+self.fix_datastore_mad(m.group(2))+']', oned_conf, 'DATASTORE_MAD not found')
|
||||
if oned_conf[-1:] != '\n':
|
||||
oned_conf += '\n'
|
||||
if not re.compile(r'(^|\n)[ \t]*INHERIT_DATASTORE_ATTR\s*=\s*"VITASTOR_CONF"').search(oned_conf):
|
||||
oned_conf += '\nINHERIT_DATASTORE_ATTR="VITASTOR_CONF"\n'
|
||||
if not re.compile(r'(^|\n)[ \t]*INHERIT_DATASTORE_ATTR\s*=\s*"IMAGE_PREFIX"').search(oned_conf):
|
||||
oned_conf += '\nINHERIT_DATASTORE_ATTR="IMAGE_PREFIX"\n'
|
||||
if not re.compile(r'(^|\n)[ \t]*TM_MAD_CONF\s*=\s*\[[^\]]*NAME\s*=\s*"vitastor"').search(oned_conf):
|
||||
oned_conf += ('\nTM_MAD_CONF = [\n'+
|
||||
' NAME = "vitastor", LN_TARGET = "NONE", CLONE_TARGET = "SELF", SHARED = "YES",\n'+
|
||||
' DS_MIGRATE = "NO", DRIVER = "raw", ALLOW_ORPHANS="format",\n'+
|
||||
' TM_MAD_SYSTEM = "ssh,shared", LN_TARGET_SSH = "SYSTEM", CLONE_TARGET_SSH = "SYSTEM",\n'+
|
||||
' DISK_TYPE_SSH = "FILE", LN_TARGET_SHARED = "NONE",\n'+
|
||||
' CLONE_TARGET_SHARED = "SELF", DISK_TYPE_SHARED = "FILE"\n'+
|
||||
']\n')
|
||||
if not re.compile(r'(^|\n)[ \t]*DS_MAD_CONF\s*=\s*\[[^\]]*NAME\s*=\s*"vitastor"').search(oned_conf):
|
||||
oned_conf += ('\nDS_MAD_CONF = [\n'+
|
||||
' NAME = "vitastor",\n'+
|
||||
' REQUIRED_ATTRS = "DISK_TYPE,BRIDGE_LIST",\n'+
|
||||
' PERSISTENT_ONLY = "NO",\n'+
|
||||
' MARKETPLACE_ACTIONS = "export"\n'+
|
||||
']\n')
|
||||
return oned_conf
|
||||
|
||||
def fix_vm_mad(self, vm_mad_params):
|
||||
if re.compile(r'\bNAME\s*=\s*"kvm"').search(vm_mad_params):
|
||||
vm_mad_params = re.sub(r'\b(ARGUMENTS\s*=\s*")([^"]+)"', lambda m: m.group(1)+self.fix_vm_mad_args(m.group(2))+'"', vm_mad_params)
|
||||
self.kvm_found = 1
|
||||
return vm_mad_params
|
||||
|
||||
def fix_vm_mad_args(self, args):
|
||||
args = self.fix_vm_mad_override(args, 'deploy')
|
||||
if self.save_restore:
|
||||
args = self.fix_vm_mad_override(args, 'save')
|
||||
args = self.fix_vm_mad_override(args, 'restore')
|
||||
return args
|
||||
|
||||
def fix_vm_mad_override(self, args, override):
|
||||
m = re.compile(r'-l (\S+)').search(args)
|
||||
if m and re.compile(override+'='+override+'.vitastor').search(m.group(1)):
|
||||
return args
|
||||
elif m and re.compile(override+'=').search(m.group(1)):
|
||||
self.errors.append(override+"= is already overridden in -l option in VM_MAD[NAME=kvm].ARGUMENTS")
|
||||
return args
|
||||
elif m:
|
||||
return self.require_sub(r'-l (\S+)', lambda m: '-l '+m.group(1)+','+override+'='+override+'.vitastor', args, '-l option not found in VM_MAD[NAME=kvm].ARGUMENTS')
|
||||
else:
|
||||
return args+' -l '+override+'='+override+'.vitastor'
|
||||
|
||||
def fix_tm_mad(self, params):
|
||||
return self.require_sub(r'\b(ARGUMENTS\s*=\s*")([^"]+)"', lambda m: m.group(1)+self.fix_tm_mad_args('d', m.group(2), "TM_MAD")+'"', params, "TM_MAD.ARGUMENTS not found")
|
||||
|
||||
def fix_tm_mad_args(self, opt, args, v):
|
||||
return self.require_sub('(-'+opt+r') (\S+)', lambda m: self.fix_tm_mad_arg(m), args, "-"+opt+" option not found in "+v+".ARGUMENTS")
|
||||
|
||||
def fix_tm_mad_arg(self, m):
|
||||
a = m.group(2).split(',')
|
||||
if 'vitastor' not in a:
|
||||
a += [ 'vitastor' ]
|
||||
return m.group(1)+' '+(','.join(a))
|
||||
|
||||
def fix_datastore_mad(self, params):
|
||||
params = self.require_sub(r'\b(ARGUMENTS\s*=\s*")([^"]+)"', lambda m: m.group(1)+self.fix_tm_mad_args('d', m.group(2), "DATASTORE_MAD")+'"', params, "DATASTORE_MAD.ARGUMENTS not found")
|
||||
return self.require_sub(r'\b(ARGUMENTS\s*=\s*")([^"]+)"', lambda m: m.group(1)+self.fix_tm_mad_args('s', m.group(2), "DATASTORE_MAD")+'"', params, "")
|
||||
|
||||
fixer = Fixer()
|
||||
oned_conf_file = ''
|
||||
for arg in sys.argv[1:]:
|
||||
if arg == '-s':
|
||||
fixer.save_restore = 1
|
||||
else:
|
||||
oned_conf_file = arg
|
||||
break
|
||||
if not oned_conf_file:
|
||||
sys.stderr.write("USAGE: ./patch-oned-conf.py [-s] /etc/one/oned.conf\n-s means also enable save.vitastor/restore.vitastor overrides\n")
|
||||
sys.exit(1)
|
||||
with open(oned_conf_file, 'r') as fd:
|
||||
oned_conf = fd.read()
|
||||
new_conf = fixer.fix(oned_conf)
|
||||
if new_conf != oned_conf:
|
||||
os.rename(oned_conf_file, oned_conf_file+'.bak')
|
||||
with open(oned_conf_file, 'w') as fd:
|
||||
fd.write(new_conf)
|
||||
if len(fixer.errors) > 0:
|
||||
sys.stderr.write("ERROR: Failed to patch "+oned_conf_file+", patch it manually. Errors:\n- "+('\n- '.join(fixer.errors))+'\n')
|
||||
sys.exit(1)
|
|
@ -993,7 +993,8 @@ int blockstore_impl_t::read_bitmap(object_id oid, uint64_t target_version, void
|
|||
{
|
||||
while (dirty_it->first.oid == oid)
|
||||
{
|
||||
if (target_version >= dirty_it->first.version)
|
||||
// Condition has to be the same as in dequeue_read()
|
||||
if (!IS_IN_FLIGHT(dirty_it->second.state) && target_version >= dirty_it->first.version)
|
||||
{
|
||||
if (result_version)
|
||||
*result_version = dirty_it->first.version;
|
||||
|
|
|
@ -10,7 +10,7 @@ endif (IBVERBS_LIBRARIES)
|
|||
add_library(vitastor_common STATIC
|
||||
../util/epoll_manager.cpp etcd_state_client.cpp messenger.cpp ../util/addr_util.cpp
|
||||
msgr_stop.cpp msgr_op.cpp msgr_send.cpp msgr_receive.cpp ../util/ringloop.cpp ../../json11/json11.cpp
|
||||
http_client.cpp osd_ops.cpp pg_states.cpp ../util/timerfd_manager.cpp ../util/str_util.cpp ${MSGR_RDMA}
|
||||
http_client.cpp osd_ops.cpp pg_states.cpp ../util/timerfd_manager.cpp ../util/str_util.cpp ../util/json_util.cpp ${MSGR_RDMA}
|
||||
)
|
||||
target_link_libraries(vitastor_common pthread)
|
||||
target_compile_options(vitastor_common PUBLIC -fPIC)
|
||||
|
|
|
@ -955,7 +955,7 @@ void cluster_client_t::slice_rw(cluster_op_t *op)
|
|||
? (stripe + pg_block_size) : (op->offset + op->len);
|
||||
op->parts[i].iov.reset();
|
||||
op->parts[i].flags = 0;
|
||||
if (op->cur_inode != op->inode || op->opcode == OSD_OP_READ && dirty_copied)
|
||||
if (op->opcode != OSD_OP_READ_CHAIN_BITMAP && op->cur_inode != op->inode || op->opcode == OSD_OP_READ && dirty_copied)
|
||||
{
|
||||
// Read remaining parts from upper layers
|
||||
uint64_t prev = begin, cur = begin;
|
||||
|
|
|
@ -369,6 +369,7 @@ struct cli_dd_t
|
|||
{
|
||||
cli_tool_t *parent;
|
||||
|
||||
std::vector<std::string> conv, iflag, oflag;
|
||||
dd_in_info_t iinfo;
|
||||
dd_out_info_t oinfo;
|
||||
|
||||
|
@ -766,6 +767,49 @@ struct cli_dd_t
|
|||
goto resume_3;
|
||||
else if (state == 4)
|
||||
goto resume_4;
|
||||
for (int i = 0; i < conv.size(); i++)
|
||||
{
|
||||
if (conv[i] == "nofsync")
|
||||
oinfo.end_fsync = false;
|
||||
else if (conv[i] == "trunc")
|
||||
oinfo.out_trunc = true;
|
||||
else if (conv[i] == "nocreat")
|
||||
oinfo.out_create = false;
|
||||
else if (conv[i] == "noerror")
|
||||
ignore_errors = true;
|
||||
else if (conv[i] == "nosparse")
|
||||
write_zero = true;
|
||||
else
|
||||
{
|
||||
result = (cli_result_t){ .err = EINVAL, .text = "Unknown option conv="+conv[i] };
|
||||
state = 100;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < iflag.size(); i++)
|
||||
{
|
||||
if (iflag[i] == "direct")
|
||||
iinfo.in_direct = true;
|
||||
else
|
||||
{
|
||||
result = (cli_result_t){ .err = EINVAL, .text = "Unknown option iflag="+iflag[i] };
|
||||
state = 100;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < oflag.size(); i++)
|
||||
{
|
||||
if (oflag[i] == "direct")
|
||||
oinfo.out_direct = true;
|
||||
else if (oflag[i] == "append")
|
||||
oinfo.out_append = true;
|
||||
else
|
||||
{
|
||||
result = (cli_result_t){ .err = EINVAL, .text = "Unknown option oflag="+oflag[i] };
|
||||
state = 100;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((oinfo.oimg != "" && oinfo.ofile != "") || (iinfo.iimg != "" && iinfo.ifile != ""))
|
||||
{
|
||||
result = (cli_result_t){ .err = EINVAL, .text = "Image and file can't be specified at the same time" };
|
||||
|
@ -908,6 +952,18 @@ static uint64_t parse_blocks(json11::Json v, uint64_t bs, uint64_t def)
|
|||
return res;
|
||||
}
|
||||
|
||||
static std::vector<std::string> explode_json(const std::string & sep, json11::Json opt)
|
||||
{
|
||||
if (opt.is_array())
|
||||
{
|
||||
std::vector<std::string> arr;
|
||||
for (auto & item: opt.array_items())
|
||||
arr.push_back(item.as_string());
|
||||
return arr;
|
||||
}
|
||||
return explode(sep, opt.as_string(), true);
|
||||
}
|
||||
|
||||
std::function<bool(cli_result_t &)> cli_tool_t::start_dd(json11::Json cfg)
|
||||
{
|
||||
auto dd = new cli_dd_t();
|
||||
|
@ -923,7 +979,7 @@ std::function<bool(cli_result_t &)> cli_tool_t::start_dd(json11::Json cfg)
|
|||
dd->oseek = parse_blocks(cfg["oseek"], dd->blocksize, 0);
|
||||
if (!dd->oseek)
|
||||
dd->oseek = parse_blocks(cfg["seek"], dd->blocksize, 0);
|
||||
dd->iseek = parse_blocks(cfg["oseek"], dd->blocksize, 0);
|
||||
dd->iseek = parse_blocks(cfg["iseek"], dd->blocksize, 0);
|
||||
if (!dd->iseek)
|
||||
dd->iseek = parse_blocks(cfg["skip"], dd->blocksize, 0);
|
||||
dd->iodepth = cfg["iodepth"].uint64_value();
|
||||
|
@ -935,25 +991,9 @@ std::function<bool(cli_result_t &)> cli_tool_t::start_dd(json11::Json cfg)
|
|||
progress = true;
|
||||
dd->iinfo.detect_size = cfg["size"].is_null();
|
||||
dd->oinfo.out_size = parse_size(cfg["size"].as_string());
|
||||
std::vector<std::string> conv = explode(",", cfg["conv"].string_value(), true);
|
||||
if (std::find(conv.begin(), conv.end(), "nofsync") != conv.end())
|
||||
dd->oinfo.end_fsync = false;
|
||||
if (std::find(conv.begin(), conv.end(), "trunc") != conv.end())
|
||||
dd->oinfo.out_trunc = true;
|
||||
if (std::find(conv.begin(), conv.end(), "nocreat") != conv.end())
|
||||
dd->oinfo.out_create = false;
|
||||
if (std::find(conv.begin(), conv.end(), "noerror") != conv.end())
|
||||
dd->ignore_errors = true;
|
||||
if (std::find(conv.begin(), conv.end(), "nosparse") != conv.end())
|
||||
dd->write_zero = true;
|
||||
conv = explode(",", cfg["iflag"].string_value(), true);
|
||||
if (std::find(conv.begin(), conv.end(), "direct") != conv.end())
|
||||
dd->iinfo.in_direct = true;
|
||||
conv = explode(",", cfg["oflag"].string_value(), true);
|
||||
if (std::find(conv.begin(), conv.end(), "direct") != conv.end())
|
||||
dd->oinfo.out_direct = true;
|
||||
if (std::find(conv.begin(), conv.end(), "append") != conv.end())
|
||||
dd->oinfo.out_append = true;
|
||||
dd->conv = explode_json(",", cfg["conv"]);
|
||||
dd->iflag = explode_json(",", cfg["iflag"]);
|
||||
dd->oflag = explode_json(",", cfg["oflag"]);
|
||||
return [dd](cli_result_t & result)
|
||||
{
|
||||
dd->loop();
|
||||
|
|
|
@ -6,7 +6,7 @@ project(vitastor)
|
|||
add_executable(vitastor-disk
|
||||
disk_tool.cpp disk_simple_offsets.cpp
|
||||
disk_tool_journal.cpp disk_tool_meta.cpp disk_tool_prepare.cpp disk_tool_resize.cpp disk_tool_udev.cpp disk_tool_utils.cpp disk_tool_upgrade.cpp
|
||||
../util/crc32c.c ../util/str_util.cpp ../../json11/json11.cpp ../util/rw_blocking.cpp ../util/allocator.cpp ../util/ringloop.cpp ../blockstore/blockstore_disk.cpp
|
||||
../util/crc32c.c ../util/str_util.cpp ../util/json_util.cpp ../../json11/json11.cpp ../util/rw_blocking.cpp ../util/allocator.cpp ../util/ringloop.cpp ../blockstore/blockstore_disk.cpp
|
||||
)
|
||||
target_link_libraries(vitastor-disk
|
||||
tcmalloc_minimal
|
||||
|
|
|
@ -143,8 +143,10 @@ static const char *help_text =
|
|||
" For now, this only checks that device cache is in write-through mode if fsync is disabled.\n"
|
||||
" Intended for use from startup scripts (i.e. from systemd units).\n"
|
||||
"\n"
|
||||
"vitastor-disk dump-journal [OPTIONS] <osd_device>\n"
|
||||
"vitastor-disk dump-journal [OPTIONS] <journal_file> <journal_block_size> <offset> <size>\n"
|
||||
" Dump journal in human-readable or JSON (if --json is specified) format.\n"
|
||||
" Dump journal in text or JSON (if --json is specified) format.\n"
|
||||
" You can specify any OSD device (data, metadata or journal), or the layout manually.\n"
|
||||
" Options:\n"
|
||||
" --all Scan the whole journal area for entries and dump them, even outdated ones\n"
|
||||
" --json Dump journal in JSON format\n"
|
||||
|
@ -152,16 +154,21 @@ static const char *help_text =
|
|||
" --format data Same as \"entries\", but also include small write data\n"
|
||||
" --format blocks Dump as an array of journal blocks each containing array of entries\n"
|
||||
"\n"
|
||||
"vitastor-disk write-journal <osd_device>\n"
|
||||
"vitastor-disk write-journal <journal_file> <journal_block_size> <bitmap_size> <offset> <size>\n"
|
||||
" Write journal from JSON taken from standard input in the same format as produced by\n"
|
||||
" `dump-journal --json --format data`.\n"
|
||||
" You can specify any OSD device (data, metadata or journal), or the layout manually.\n"
|
||||
"\n"
|
||||
"vitastor-disk dump-meta <osd_device>\n"
|
||||
"vitastor-disk dump-meta <meta_file> <meta_block_size> <offset> <size>\n"
|
||||
" Dump metadata in JSON format.\n"
|
||||
" You can specify any OSD device (data, metadata or journal), or the layout manually.\n"
|
||||
"\n"
|
||||
"vitastor-disk write-meta <osd_device>\n"
|
||||
"vitastor-disk write-meta <meta_file> <offset> <size>\n"
|
||||
" Write metadata from JSON taken from standard input in the same format as produced by\n"
|
||||
" `dump-meta`. Intended for debugging.\n"
|
||||
" Write metadata from JSON taken from standard input in the same format as produced by `dump-meta`.\n"
|
||||
" You can specify any OSD device (data, metadata or journal), or the layout manually.\n"
|
||||
"\n"
|
||||
"vitastor-disk simple-offsets <device>\n"
|
||||
" Calculate offsets for old simple&stupid (no superblock) OSD deployment. Options:\n"
|
||||
|
@ -249,29 +256,49 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
if (!strcmp(cmd[0], "dump-journal"))
|
||||
{
|
||||
if (cmd.size() < 5)
|
||||
if (cmd.size() != 2 && cmd.size() < 5)
|
||||
{
|
||||
print_help(help_text, aliased ? "vitastor-dump-journal" : "vitastor-disk", cmd[0], false);
|
||||
return 1;
|
||||
}
|
||||
self.dsk.journal_device = cmd[1];
|
||||
self.dsk.journal_block_size = strtoul(cmd[2], NULL, 10);
|
||||
self.dsk.journal_offset = strtoull(cmd[3], NULL, 10);
|
||||
self.dsk.journal_len = strtoull(cmd[4], NULL, 10);
|
||||
if (cmd.size() > 2)
|
||||
{
|
||||
self.dsk.journal_block_size = strtoul(cmd[2], NULL, 10);
|
||||
self.dsk.journal_offset = strtoull(cmd[3], NULL, 10);
|
||||
self.dsk.journal_len = strtoull(cmd[4], NULL, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// First argument is an OSD device - take metadata layout parameters from it
|
||||
if (self.dump_load_check_superblock(self.dsk.journal_device))
|
||||
return 1;
|
||||
}
|
||||
return self.dump_journal();
|
||||
}
|
||||
else if (!strcmp(cmd[0], "write-journal"))
|
||||
{
|
||||
if (cmd.size() < 6)
|
||||
if (cmd.size() != 2 && cmd.size() < 6)
|
||||
{
|
||||
print_help(help_text, "vitastor-disk", cmd[0], false);
|
||||
return 1;
|
||||
}
|
||||
self.new_journal_device = cmd[1];
|
||||
self.dsk.journal_block_size = strtoul(cmd[2], NULL, 10);
|
||||
self.dsk.clean_entry_bitmap_size = strtoul(cmd[3], NULL, 10);
|
||||
self.new_journal_offset = strtoull(cmd[4], NULL, 10);
|
||||
self.new_journal_len = strtoull(cmd[5], NULL, 10);
|
||||
if (cmd.size() > 2)
|
||||
{
|
||||
self.dsk.journal_block_size = strtoul(cmd[2], NULL, 10);
|
||||
self.dsk.clean_entry_bitmap_size = strtoul(cmd[3], NULL, 10);
|
||||
self.new_journal_offset = strtoull(cmd[4], NULL, 10);
|
||||
self.new_journal_len = strtoull(cmd[5], NULL, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// First argument is an OSD device - take metadata layout parameters from it
|
||||
if (self.dump_load_check_superblock(self.new_journal_device))
|
||||
return 1;
|
||||
self.new_journal_offset = self.dsk.journal_offset;
|
||||
self.new_journal_len = self.dsk.journal_len;
|
||||
}
|
||||
std::string json_err;
|
||||
json11::Json entries = json11::Json::parse(read_all_fd(0), json_err);
|
||||
if (json_err != "")
|
||||
|
@ -296,27 +323,47 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
else if (!strcmp(cmd[0], "dump-meta"))
|
||||
{
|
||||
if (cmd.size() < 5)
|
||||
if (cmd.size() != 2 && cmd.size() < 5)
|
||||
{
|
||||
print_help(help_text, "vitastor-disk", cmd[0], false);
|
||||
return 1;
|
||||
}
|
||||
self.dsk.meta_device = cmd[1];
|
||||
self.dsk.meta_block_size = strtoul(cmd[2], NULL, 10);
|
||||
self.dsk.meta_offset = strtoull(cmd[3], NULL, 10);
|
||||
self.dsk.meta_len = strtoull(cmd[4], NULL, 10);
|
||||
if (cmd.size() > 2)
|
||||
{
|
||||
self.dsk.meta_block_size = strtoul(cmd[2], NULL, 10);
|
||||
self.dsk.meta_offset = strtoull(cmd[3], NULL, 10);
|
||||
self.dsk.meta_len = strtoull(cmd[4], NULL, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// First argument is an OSD device - take metadata layout parameters from it
|
||||
if (self.dump_load_check_superblock(self.dsk.meta_device))
|
||||
return 1;
|
||||
}
|
||||
return self.dump_meta();
|
||||
}
|
||||
else if (!strcmp(cmd[0], "write-meta"))
|
||||
{
|
||||
if (cmd.size() < 4)
|
||||
if (cmd.size() != 2 && cmd.size() < 4)
|
||||
{
|
||||
print_help(help_text, "vitastor-disk", cmd[0], false);
|
||||
return 1;
|
||||
}
|
||||
self.new_meta_device = cmd[1];
|
||||
self.new_meta_offset = strtoull(cmd[2], NULL, 10);
|
||||
self.new_meta_len = strtoull(cmd[3], NULL, 10);
|
||||
if (cmd.size() > 2)
|
||||
{
|
||||
self.new_meta_offset = strtoull(cmd[2], NULL, 10);
|
||||
self.new_meta_len = strtoull(cmd[3], NULL, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// First argument is an OSD device - take metadata layout parameters from it
|
||||
if (self.dump_load_check_superblock(self.new_meta_device))
|
||||
return 1;
|
||||
self.new_meta_offset = self.dsk.meta_offset;
|
||||
self.new_meta_len = self.dsk.meta_len;
|
||||
}
|
||||
std::string json_err;
|
||||
json11::Json meta = json11::Json::parse(read_all_fd(0), json_err);
|
||||
if (json_err != "")
|
||||
|
|
|
@ -93,6 +93,8 @@ struct disk_tool_t
|
|||
void dump_meta_header(blockstore_meta_header_v2_t *hdr);
|
||||
void dump_meta_entry(uint64_t block_num, clean_disk_entry *entry, uint8_t *bitmap);
|
||||
|
||||
int dump_load_check_superblock(const std::string & device);
|
||||
|
||||
int write_json_journal(json11::Json entries);
|
||||
int write_json_meta(json11::Json meta);
|
||||
|
||||
|
|
|
@ -517,6 +517,12 @@ int disk_tool_t::write_json_journal(json11::Json entries)
|
|||
uint32_t data_csum_size = !dsk.data_csum_type ? 0 : ne->small_write.len/dsk.csum_block_size*(dsk.data_csum_type & 0xFF);
|
||||
fromhexstr(rec["bitmap"].string_value(), dsk.clean_entry_bitmap_size, ((uint8_t*)ne) + sizeof(journal_entry_small_write) + data_csum_size);
|
||||
fromhexstr(rec["data"].string_value(), ne->small_write.len, new_journal_data);
|
||||
if (ne->small_write.len > 0 && !rec["data"].is_string())
|
||||
{
|
||||
fprintf(stderr, "Error: entry data is missing, please generate the dump with --json --format data\n");
|
||||
free(new_journal_buf);
|
||||
return 1;
|
||||
}
|
||||
if (dsk.data_csum_type)
|
||||
fromhexstr(rec["block_csums"].string_value(), data_csum_size, ((uint8_t*)ne) + sizeof(journal_entry_small_write));
|
||||
if (rec["data"].is_string())
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "disk_tool.h"
|
||||
#include "rw_blocking.h"
|
||||
#include "osd_id.h"
|
||||
#include "json_util.h"
|
||||
|
||||
int disk_tool_t::process_meta(std::function<void(blockstore_meta_header_v2_t *)> hdr_fn,
|
||||
std::function<void(uint64_t, clean_disk_entry*, uint8_t*)> record_fn)
|
||||
|
@ -149,6 +150,24 @@ int disk_tool_t::process_meta(std::function<void(blockstore_meta_header_v2_t *)>
|
|||
return 0;
|
||||
}
|
||||
|
||||
int disk_tool_t::dump_load_check_superblock(const std::string & device)
|
||||
{
|
||||
json11::Json sb = read_osd_superblock(device, true, false);
|
||||
if (sb.is_null())
|
||||
return 1;
|
||||
try
|
||||
{
|
||||
auto cfg = json_to_string_map(sb["params"].object_items());
|
||||
dsk.parse_config(cfg);
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
fprintf(stderr, "%s\n", e.what());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int disk_tool_t::dump_meta()
|
||||
{
|
||||
int r = process_meta(
|
||||
|
@ -176,7 +195,7 @@ void disk_tool_t::dump_meta_header(blockstore_meta_header_v2_t *hdr)
|
|||
{
|
||||
printf(
|
||||
"{\"version\":\"0.9\",\"meta_block_size\":%u,\"data_block_size\":%u,\"bitmap_granularity\":%u,"
|
||||
"\"data_csum_type\":%s,\"csum_block_size\":%u,\"entries\":[\n",
|
||||
"\"data_csum_type\":\"%s\",\"csum_block_size\":%u,\"entries\":[\n",
|
||||
hdr->meta_block_size, hdr->data_block_size, hdr->bitmap_granularity,
|
||||
csum_type_str(hdr->data_csum_type).c_str(), hdr->csum_block_size
|
||||
);
|
||||
|
@ -243,12 +262,16 @@ int disk_tool_t::write_json_meta(json11::Json meta)
|
|||
? meta["data_block_size"].uint64_value() : 131072;
|
||||
new_hdr->bitmap_granularity = meta["bitmap_granularity"].uint64_value()
|
||||
? meta["bitmap_granularity"].uint64_value() : 4096;
|
||||
new_hdr->data_csum_type = meta["data_csum_type"].is_number()
|
||||
? meta["data_csum_type"].uint64_value()
|
||||
: (meta["data_csum_type"].string_value() == "crc32c"
|
||||
? BLOCKSTORE_CSUM_CRC32C
|
||||
: BLOCKSTORE_CSUM_NONE);
|
||||
new_hdr->csum_block_size = meta["csum_block_size"].uint64_value();
|
||||
if (new_hdr->version >= BLOCKSTORE_META_FORMAT_V2)
|
||||
{
|
||||
new_hdr->data_csum_type = meta["data_csum_type"].is_number()
|
||||
? meta["data_csum_type"].uint64_value()
|
||||
: (meta["data_csum_type"].string_value() == "crc32c"
|
||||
? BLOCKSTORE_CSUM_CRC32C
|
||||
: BLOCKSTORE_CSUM_NONE);
|
||||
new_hdr->csum_block_size = meta["csum_block_size"].uint64_value();
|
||||
new_hdr->header_csum = crc32c(0, new_hdr, sizeof(*new_hdr));
|
||||
}
|
||||
uint32_t new_clean_entry_header_size = (new_hdr->version == BLOCKSTORE_META_FORMAT_V1
|
||||
? sizeof(clean_disk_entry) : sizeof(clean_disk_entry) + 4 /*entry_csum*/);
|
||||
new_clean_entry_bitmap_size = (new_hdr->data_block_size / new_hdr->bitmap_granularity + 7) / 8;
|
||||
|
|
|
@ -14,19 +14,7 @@
|
|||
#include "osd.h"
|
||||
#include "http_client.h"
|
||||
#include "str_util.h"
|
||||
|
||||
static blockstore_config_t json_to_bs(const json11::Json::object & config)
|
||||
{
|
||||
blockstore_config_t bs;
|
||||
for (auto kv: config)
|
||||
{
|
||||
if (kv.second.is_string())
|
||||
bs[kv.first] = kv.second.string_value();
|
||||
else if (!kv.second.is_null())
|
||||
bs[kv.first] = kv.second.dump();
|
||||
}
|
||||
return bs;
|
||||
}
|
||||
#include "json_util.h"
|
||||
|
||||
osd_t::osd_t(const json11::Json & config, ring_loop_t *ringloop)
|
||||
{
|
||||
|
@ -46,7 +34,7 @@ osd_t::osd_t(const json11::Json & config, ring_loop_t *ringloop)
|
|||
|
||||
if (!json_is_true(this->config["disable_blockstore"]))
|
||||
{
|
||||
auto bs_cfg = json_to_bs(this->config);
|
||||
auto bs_cfg = json_to_string_map(this->config);
|
||||
this->bs = new blockstore_t(bs_cfg, ringloop, tfd);
|
||||
// Wait for blockstore initialisation before actually starting OSD logic
|
||||
// to prevent peering timeouts during restart with filled databases
|
||||
|
@ -151,7 +139,7 @@ void osd_t::parse_config(bool init)
|
|||
}
|
||||
if (bs)
|
||||
{
|
||||
auto bs_cfg = json_to_bs(config);
|
||||
auto bs_cfg = json_to_string_map(config);
|
||||
bs->parse_config(bs_cfg);
|
||||
}
|
||||
st_cli.parse_config(config);
|
||||
|
|
|
@ -337,7 +337,7 @@ std::vector<osd_chain_read_t> osd_t::collect_chained_read_requests(osd_op_t *cur
|
|||
{
|
||||
uint8_t *part_bitmap = ((uint8_t*)op_data->snapshot_bitmaps) + chain_pos*stripe_count*clean_entry_bitmap_size;
|
||||
int start = !cur_op->req.rw.len ? 0 : (cur_op->req.rw.offset - op_data->oid.stripe)/bs_bitmap_granularity;
|
||||
int end = !cur_op->req.rw.len ? op_data->pg_data_size*clean_entry_bitmap_size : start + cur_op->req.rw.len/bs_bitmap_granularity;
|
||||
int end = !cur_op->req.rw.len ? op_data->pg_data_size*clean_entry_bitmap_size*8 : start + cur_op->req.rw.len/bs_bitmap_granularity;
|
||||
// Skip unneeded part in the beginning
|
||||
while (start < end && (
|
||||
((global_bitmap[start>>3] >> (start&7)) & 1) ||
|
||||
|
@ -369,12 +369,15 @@ std::vector<osd_chain_read_t> osd_t::collect_chained_read_requests(osd_op_t *cur
|
|||
global_bitmap[cur>>3] = global_bitmap[cur>>3] | (part_bitmap[cur>>3] & (1 << (cur&7)));
|
||||
}
|
||||
// Add request
|
||||
chain_reads.push_back((osd_chain_read_t){
|
||||
.chain_pos = chain_pos,
|
||||
.inode = op_data->read_chain[chain_pos],
|
||||
.offset = start*bs_bitmap_granularity,
|
||||
.len = (end-start)*bs_bitmap_granularity,
|
||||
});
|
||||
if (cur_op->req.rw.len)
|
||||
{
|
||||
chain_reads.push_back((osd_chain_read_t){
|
||||
.chain_pos = chain_pos,
|
||||
.inode = op_data->read_chain[chain_pos],
|
||||
.offset = start*bs_bitmap_granularity,
|
||||
.len = (end-start)*bs_bitmap_granularity,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return chain_reads;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Vitaliy Filippov, 2019+
|
||||
// License: VNPL-1.1 or GNU GPL-2.0+ (see README.md for details)
|
||||
|
||||
#include "json_util.h"
|
||||
|
||||
std::map<std::string, std::string> json_to_string_map(const json11::Json::object & config)
|
||||
{
|
||||
std::map<std::string, std::string> bs;
|
||||
for (auto kv: config)
|
||||
{
|
||||
if (kv.second.is_string())
|
||||
bs[kv.first] = kv.second.string_value();
|
||||
else if (!kv.second.is_null())
|
||||
bs[kv.first] = kv.second.dump();
|
||||
}
|
||||
return bs;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) Vitaliy Filippov, 2019+
|
||||
// License: VNPL-1.1 or GNU GPL-2.0+ (see README.md for details)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "json11/json11.hpp"
|
||||
|
||||
std::map<std::string, std::string> json_to_string_map(const json11::Json::object & config);
|
|
@ -489,7 +489,7 @@ std::string format_datetime(uint64_t unixtime)
|
|||
bool is_zero(void *buf, size_t size)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i <= size-8)
|
||||
while (i+8 <= size)
|
||||
{
|
||||
if (*(uint64_t*)((uint8_t*)buf + i))
|
||||
return false;
|
||||
|
|
|
@ -83,16 +83,19 @@ fi
|
|||
POOLCFG='"name":"testpool","failure_domain":"osd",'$POOLCFG
|
||||
$ETCDCTL put /vitastor/config/pools '{"1":{'$POOLCFG',"pg_size":'$PG_SIZE',"pg_minsize":'$PG_MINSIZE',"pg_count":'$PG_COUNT'}}'
|
||||
|
||||
wait_up()
|
||||
wait_pool_up()
|
||||
{
|
||||
local sec=$1
|
||||
local pool=$2
|
||||
local pgsize=$3
|
||||
local pgcount=$4
|
||||
local i=0
|
||||
local configured=0
|
||||
while [[ $i -lt $sec ]]; do
|
||||
if $ETCDCTL get /vitastor/pg/config --print-value-only | jq -s -e '(. | length) != 0 and ([ .[0].items["1"][] |
|
||||
select(((.osd_set | select(. != 0) | sort | unique) | length) == '$PG_SIZE') ] | length) == '$PG_COUNT; then
|
||||
if $ETCDCTL get /vitastor/pg/config --print-value-only | jq -s -e '(. | length) != 0 and ([ .[0].items["'$pool'"][] |
|
||||
select(((.osd_set | select(. != 0) | sort | unique) | length) == '$pgsize') ] | length) == '$pgcount; then
|
||||
configured=1
|
||||
if $ETCDCTL get /vitastor/pg/state/1/ --prefix --print-value-only | jq -s -e '[ .[] | select(.state == ["active"]) ] | length == '$PG_COUNT; then
|
||||
if $ETCDCTL get /vitastor/pg/state/$pool/ --prefix --print-value-only | jq -s -e '[ .[] | select(.state == ["active"]) ] | length == '$pgcount; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
@ -107,6 +110,11 @@ wait_up()
|
|||
done
|
||||
}
|
||||
|
||||
wait_up()
|
||||
{
|
||||
wait_pool_up "$1" 1 $PG_SIZE $PG_COUNT
|
||||
}
|
||||
|
||||
if [[ $OSD_COUNT -gt 0 ]]; then
|
||||
wait_up 120
|
||||
fi
|
||||
|
|
|
@ -68,6 +68,8 @@ TEST_NAME=csum_4k_dmj OSD_ARGS="--data_csum_type crc32c --inmemory_metadata fal
|
|||
TEST_NAME=csum_4k_dj OSD_ARGS="--data_csum_type crc32c --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh
|
||||
TEST_NAME=csum_4k OSD_ARGS="--data_csum_type crc32c" OFFSET_ARGS=$OSD_ARGS ./test_heal.sh
|
||||
|
||||
./test_snapshot_pool2.sh
|
||||
|
||||
./test_osd_tags.sh
|
||||
|
||||
./test_enospc.sh
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
. `dirname $0`/run_3osds.sh
|
||||
check_qemu
|
||||
|
||||
# snapshot in another pool
|
||||
|
||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create-pool testpool2 -s 3 -n 4 --failure_domain osd
|
||||
|
||||
wait_pool_up 30 2 3 4
|
||||
|
||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 128M testchain -p testpool
|
||||
|
||||
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
||||
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=1M -direct=1 -iodepth=4 -fsync=1 -rw=write \
|
||||
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd
|
||||
|
||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL snap-create testchain@snap1 -p testpool2
|
||||
|
||||
LD_PRELOAD="build/src/client/libfio_vitastor.so" \
|
||||
fio -thread -name=test -ioengine=build/src/client/libfio_vitastor.so -bs=4k -direct=1 -iodepth=4 -end_fsync=1 -rw=randwrite -number_ios=32 \
|
||||
-etcd=$ETCD_URL -image=testchain -mirror_file=./testdata/bin/mirror.bin -buffer_pattern=0xabcd
|
||||
|
||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=128k iodepth=4
|
||||
|
||||
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
|
||||
|
||||
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL dd iimg=testchain of=./testdata/bin/res.bin bs=32k iodepth=4 conv=nosparse
|
||||
|
||||
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
|
||||
|
||||
qemu-img convert -p \
|
||||
-f raw "vitastor:etcd_host=127.0.0.1\:$ETCD_PORT/v3:image=testchain" \
|
||||
-O raw ./testdata/bin/res.bin
|
||||
|
||||
cmp ./testdata/bin/res.bin ./testdata/bin/mirror.bin
|
||||
|
||||
format_green OK
|
Loading…
Reference in New Issue