forked from vitalif/vitastor
Rewrite simple-offsets.js in C/C++
parent
d3903f039c
commit
cd21ff0b6a
|
@ -153,7 +153,8 @@ target_link_libraries(vitastor-nbd
|
||||||
|
|
||||||
# vitastor-cli
|
# vitastor-cli
|
||||||
add_executable(vitastor-cli
|
add_executable(vitastor-cli
|
||||||
cli.cpp cli_alloc_osd.cpp cli_ls.cpp cli_create.cpp cli_modify.cpp cli_flatten.cpp cli_merge.cpp cli_rm.cpp cli_snap_rm.cpp
|
cli.cpp cli_alloc_osd.cpp cli_simple_offsets.cpp
|
||||||
|
cli_ls.cpp cli_create.cpp cli_modify.cpp cli_flatten.cpp cli_merge.cpp cli_rm.cpp cli_snap_rm.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(vitastor-cli
|
target_link_libraries(vitastor-cli
|
||||||
vitastor_client
|
vitastor_client
|
||||||
|
|
16
src/cli.cpp
16
src/cli.cpp
|
@ -132,6 +132,15 @@ void cli_tool_t::help()
|
||||||
"\n"
|
"\n"
|
||||||
"%s alloc-osd\n"
|
"%s alloc-osd\n"
|
||||||
" Allocate a new OSD number and reserve it by creating empty /osd/stats/<n> key.\n"
|
" Allocate a new OSD number and reserve it by creating empty /osd/stats/<n> key.\n"
|
||||||
|
"%s simple-offsets <device>\n"
|
||||||
|
" Calculate offsets for simple&stupid (no superblock) OSD deployment. Options:\n"
|
||||||
|
" --object_size 128k Set blockstore block size\n"
|
||||||
|
" --bitmap_granularity 4k Set bitmap granularity\n"
|
||||||
|
" --journal_size 16M Set journal size\n"
|
||||||
|
" --device_block_size 4k Set device block size\n"
|
||||||
|
" --journal_offset 0 Set journal offset\n"
|
||||||
|
" --device_size 0 Set device size\n"
|
||||||
|
" --format text Result format: json, options, env, or text\n"
|
||||||
"\n"
|
"\n"
|
||||||
"GLOBAL OPTIONS:\n"
|
"GLOBAL OPTIONS:\n"
|
||||||
" --etcd_address <etcd_address>\n"
|
" --etcd_address <etcd_address>\n"
|
||||||
|
@ -142,7 +151,7 @@ void cli_tool_t::help()
|
||||||
" --no-color Disable colored output\n"
|
" --no-color Disable colored output\n"
|
||||||
" --json JSON output\n"
|
" --json JSON output\n"
|
||||||
,
|
,
|
||||||
exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name
|
exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name, exe_name
|
||||||
);
|
);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -276,6 +285,11 @@ void cli_tool_t::run(json11::Json cfg)
|
||||||
// Allocate a new OSD number
|
// Allocate a new OSD number
|
||||||
action_cb = start_alloc_osd(cfg);
|
action_cb = start_alloc_osd(cfg);
|
||||||
}
|
}
|
||||||
|
else if (cmd[0] == "simple-offsets")
|
||||||
|
{
|
||||||
|
// Calculate offsets for simple & stupid OSD deployment without superblock
|
||||||
|
action_cb = simple_offsets(cfg);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "unknown command: %s\n", cmd[0].string_value().c_str());
|
fprintf(stderr, "unknown command: %s\n", cmd[0].string_value().c_str());
|
||||||
|
|
|
@ -58,4 +58,8 @@ public:
|
||||||
std::function<bool(void)> start_flatten(json11::Json);
|
std::function<bool(void)> start_flatten(json11::Json);
|
||||||
std::function<bool(void)> start_snap_rm(json11::Json);
|
std::function<bool(void)> start_snap_rm(json11::Json);
|
||||||
std::function<bool(void)> start_alloc_osd(json11::Json cfg, uint64_t *out = NULL);
|
std::function<bool(void)> start_alloc_osd(json11::Json cfg, uint64_t *out = NULL);
|
||||||
|
std::function<bool(void)> simple_offsets(json11::Json cfg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string format_size(uint64_t size);
|
||||||
|
uint64_t parse_size(std::string size_str);
|
||||||
|
|
|
@ -94,6 +94,11 @@ struct image_creator_t
|
||||||
goto resume_2;
|
goto resume_2;
|
||||||
else if (state == 3)
|
else if (state == 3)
|
||||||
goto resume_3;
|
goto resume_3;
|
||||||
|
if (!size)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Image size is missing\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
for (auto & ic: parent->cli->st_cli.inode_config)
|
for (auto & ic: parent->cli->st_cli.inode_config)
|
||||||
{
|
{
|
||||||
if (ic.second.name == image_name)
|
if (ic.second.name == image_name)
|
||||||
|
@ -432,6 +437,31 @@ resume_3:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint64_t parse_size(std::string size_str)
|
||||||
|
{
|
||||||
|
uint64_t mul = 1;
|
||||||
|
char type_char = tolower(size_str[size_str.length()-1]);
|
||||||
|
if (type_char == 'k' || type_char == 'm' || type_char == 'g' || type_char == 't')
|
||||||
|
{
|
||||||
|
if (type_char == 'k')
|
||||||
|
mul = 1l<<10;
|
||||||
|
else if (type_char == 'm')
|
||||||
|
mul = 1l<<20;
|
||||||
|
else if (type_char == 'g')
|
||||||
|
mul = 1l<<30;
|
||||||
|
else /*if (type_char == 't')*/
|
||||||
|
mul = 1l<<40;
|
||||||
|
size_str = size_str.substr(0, size_str.length()-1);
|
||||||
|
}
|
||||||
|
uint64_t size = json11::Json(size_str).uint64_value() * mul;
|
||||||
|
if (size == 0 && size_str != "0")
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid syntax for size: %s\n", size_str.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
std::function<bool(void)> cli_tool_t::start_create(json11::Json cfg)
|
std::function<bool(void)> cli_tool_t::start_create(json11::Json cfg)
|
||||||
{
|
{
|
||||||
json11::Json::array cmd = cfg["command"].array_items();
|
json11::Json::array cmd = cfg["command"].array_items();
|
||||||
|
@ -458,33 +488,12 @@ std::function<bool(void)> cli_tool_t::start_create(json11::Json cfg)
|
||||||
image_creator->new_parent = cfg["parent"].string_value();
|
image_creator->new_parent = cfg["parent"].string_value();
|
||||||
if (cfg["size"].string_value() != "")
|
if (cfg["size"].string_value() != "")
|
||||||
{
|
{
|
||||||
std::string size_str = cfg["size"].string_value();
|
image_creator->size = parse_size(cfg["size"].string_value());
|
||||||
uint64_t mul = 1;
|
if (image_creator->size % 4096)
|
||||||
char type_char = tolower(size_str[size_str.length()-1]);
|
|
||||||
if (type_char == 'k' || type_char == 'm' || type_char == 'g' || type_char == 't')
|
|
||||||
{
|
{
|
||||||
if (type_char == 'k')
|
fprintf(stderr, "Size should be a multiple of 4096\n");
|
||||||
mul = 1l<<10;
|
|
||||||
else if (type_char == 'm')
|
|
||||||
mul = 1l<<20;
|
|
||||||
else if (type_char == 'g')
|
|
||||||
mul = 1l<<30;
|
|
||||||
else /*if (type_char == 't')*/
|
|
||||||
mul = 1l<<40;
|
|
||||||
size_str = size_str.substr(0, size_str.length()-1);
|
|
||||||
}
|
|
||||||
uint64_t size = json11::Json(size_str).uint64_value() * mul;
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Invalid syntax for size: %s\n", cfg["size"].string_value().c_str());
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (size % 4096)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Image size should be a multiple of 4096\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
image_creator->size = size;
|
|
||||||
if (image_creator->new_snap != "")
|
if (image_creator->new_snap != "")
|
||||||
{
|
{
|
||||||
fprintf(stderr, "--size can't be specified for snapshots\n");
|
fprintf(stderr, "--size can't be specified for snapshots\n");
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
// Copyright (c) Vitaliy Filippov, 2019+
|
||||||
|
// License: VNPL-1.1 (see README.md for details)
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "cli.h"
|
||||||
|
#include "cluster_client.h"
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
|
// Calculate offsets for a block device and print OSD command line parameters
|
||||||
|
std::function<bool(void)> cli_tool_t::simple_offsets(json11::Json cfg)
|
||||||
|
{
|
||||||
|
std::string device = cfg["command"][1].string_value();
|
||||||
|
uint64_t object_size = parse_size(cfg["object_size"].string_value());
|
||||||
|
uint64_t bitmap_granularity = parse_size(cfg["bitmap_granularity"].string_value());
|
||||||
|
uint64_t journal_size = parse_size(cfg["journal_size"].string_value());
|
||||||
|
uint64_t device_block_size = parse_size(cfg["device_block_size"].string_value());
|
||||||
|
uint64_t journal_offset = parse_size(cfg["journal_offset"].string_value());
|
||||||
|
uint64_t device_size = parse_size(cfg["device_size"].string_value());
|
||||||
|
std::string format = cfg["format"].string_value();
|
||||||
|
if (json_output)
|
||||||
|
format = "json";
|
||||||
|
if (!object_size)
|
||||||
|
object_size = DEFAULT_BLOCK_SIZE;
|
||||||
|
if (!bitmap_granularity)
|
||||||
|
bitmap_granularity = DEFAULT_BITMAP_GRANULARITY;
|
||||||
|
if (!journal_size)
|
||||||
|
journal_size = 16*1024*1024;
|
||||||
|
if (!device_block_size)
|
||||||
|
device_block_size = 4096;
|
||||||
|
uint64_t orig_device_size = device_size;
|
||||||
|
if (!device_size)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (stat(device.c_str(), &st) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't stat %s: %s\n", device.c_str(), strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (S_ISBLK(st.st_mode))
|
||||||
|
{
|
||||||
|
int fd = open(device.c_str(), O_DIRECT|O_RDONLY);
|
||||||
|
if (fd < 0 || ioctl(fd, BLKGETSIZE64, &device_size) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to get device size for %s: %s\n", device.c_str(), strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
if (st.st_blksize < device_block_size)
|
||||||
|
{
|
||||||
|
fprintf(
|
||||||
|
stderr, "Warning: %s reports %lu byte blocks, but we use %lu."
|
||||||
|
" Set --device_block_size=%lu if you're sure it works well with %lu byte blocks.\n",
|
||||||
|
device.c_str(), st.st_blksize, device_block_size, st.st_blksize, st.st_blksize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (S_ISREG(st.st_mode))
|
||||||
|
{
|
||||||
|
device_size = st.st_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s is neither a block device nor a regular file\n", device.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!device_size)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to get device size for %s\n", device.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (device_block_size < 512 || device_block_size > 1048576 ||
|
||||||
|
device_block_size & (device_block_size-1) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid device block size specified: %lu\n", device_block_size);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (object_size < device_block_size || object_size > MAX_BLOCK_SIZE ||
|
||||||
|
object_size & (object_size-1) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid object size specified: %lu\n", object_size);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (bitmap_granularity < device_block_size || bitmap_granularity > object_size ||
|
||||||
|
bitmap_granularity & (bitmap_granularity-1) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid bitmap granularity specified: %lu\n", bitmap_granularity);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
journal_offset = ((journal_offset+device_block_size-1)/device_block_size)*device_block_size;
|
||||||
|
uint64_t meta_offset = journal_offset + ((journal_size+device_block_size-1)/device_block_size)*device_block_size;
|
||||||
|
uint64_t entries_per_block = (device_block_size / (24 + 2*object_size/bitmap_granularity/8));
|
||||||
|
uint64_t object_count = ((device_size-meta_offset)/object_size);
|
||||||
|
uint64_t meta_size = (1 + (object_count+entries_per_block-1)/entries_per_block) * device_block_size;
|
||||||
|
uint64_t data_offset = meta_offset + meta_size;
|
||||||
|
if (format == "json")
|
||||||
|
{
|
||||||
|
// JSON
|
||||||
|
printf("%s\n", json11::Json(json11::Json::object {
|
||||||
|
{ "meta_block_size", device_block_size },
|
||||||
|
{ "journal_block_size", device_block_size },
|
||||||
|
{ "data_size", device_size-data_offset },
|
||||||
|
{ "data_device", device },
|
||||||
|
{ "journal_offset", journal_offset },
|
||||||
|
{ "meta_offset", meta_offset },
|
||||||
|
{ "data_offset", data_offset },
|
||||||
|
}).dump().c_str());
|
||||||
|
}
|
||||||
|
else if (format == "env")
|
||||||
|
{
|
||||||
|
// Env
|
||||||
|
printf(
|
||||||
|
"meta_block_size=%lu\njournal_block_size=%lu\ndata_size=%lu\n"
|
||||||
|
"data_device=%s\njournal_offset=%lu\nmeta_offset=%lu\ndata_offset=%lu\n",
|
||||||
|
device_block_size, device_block_size, device_size-data_offset,
|
||||||
|
device.c_str(), journal_offset, meta_offset, data_offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OSD command-line options
|
||||||
|
if (format != "options")
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Metadata size: %s\nOptions for the OSD:\n", format_size(meta_size).c_str());
|
||||||
|
}
|
||||||
|
if (device_block_size != 4096)
|
||||||
|
{
|
||||||
|
printf("--meta_block_size %lu\n--journal_block_size %lu\n", device_block_size, device_block_size);
|
||||||
|
}
|
||||||
|
if (orig_device_size)
|
||||||
|
{
|
||||||
|
printf("--data_size %lu\n", device_size-data_offset);
|
||||||
|
}
|
||||||
|
printf(
|
||||||
|
"--data_device %s\n--journal_offset %lu\n--meta_offset %lu\n--data_offset %lu\n",
|
||||||
|
device.c_str(), journal_offset, meta_offset, data_offset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) Vitaliy Filippov, 2019+
|
// Copyright (c) Vitaliy Filippov, 2019+
|
||||||
// License: VNPL-1.1 (see README.md for details)
|
// License: VNPL-1.1 (see README.md for details)
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
#include "cluster_client.h"
|
#include "cluster_client.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
|
Loading…
Reference in New Issue