Support reading parameters automatically from the superblock in vitastor-disk {dump,write}-{meta,journal}
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+66
-19
@@ -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,31 @@ 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);
|
||||
dsk.data_io = dsk.meta_io = dsk.journal_io = "cached";
|
||||
dsk.open_data();
|
||||
dsk.open_meta();
|
||||
dsk.open_journal();
|
||||
dsk.calc_lengths(true);
|
||||
}
|
||||
catch (std::exception & e)
|
||||
{
|
||||
dsk.close_all();
|
||||
fprintf(stderr, "%s\n", e.what());
|
||||
return 1;
|
||||
}
|
||||
dsk.close_all();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int disk_tool_t::dump_meta()
|
||||
{
|
||||
int r = process_meta(
|
||||
|
||||
+3
-15
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
Reference in New Issue
Block a user