vitastor-disk prepare: WIP second form command of the command

Vitaliy Filippov 2022-08-12 01:58:28 +03:00
parent 5a10d135f3
commit 2e0a2221eb
4 changed files with 129 additions and 19 deletions

View File

@ -7,6 +7,7 @@
#include "blockstore_impl.h"
#include "blockstore_disk.h"
#include "str_util.h"
static uint32_t is_power_of_two(uint64_t value)
{
@ -30,15 +31,15 @@ void blockstore_disk_t::parse_config(std::map<std::string, std::string> & config
{
disable_flock = true;
}
cfg_journal_size = strtoull(config["journal_size"].c_str(), NULL, 10);
cfg_journal_size = parse_size(config["journal_size"]);
data_device = config["data_device"];
data_offset = strtoull(config["data_offset"].c_str(), NULL, 10);
cfg_data_size = strtoull(config["data_size"].c_str(), NULL, 10);
data_offset = parse_size(config["data_offset"]);
cfg_data_size = parse_size(config["data_size"]);
meta_device = config["meta_device"];
meta_offset = strtoull(config["meta_offset"].c_str(), NULL, 10);
data_block_size = strtoull(config["block_size"].c_str(), NULL, 10);
meta_offset = parse_size(config["meta_offset"]);
data_block_size = parse_size(config["block_size"]);
journal_device = config["journal_device"];
journal_offset = strtoull(config["journal_offset"].c_str(), NULL, 10);
journal_offset = parse_size(config["journal_offset"]);
disk_alignment = strtoull(config["disk_alignment"].c_str(), NULL, 10);
journal_block_size = strtoull(config["journal_block_size"].c_str(), NULL, 10);
meta_block_size = strtoull(config["meta_block_size"].c_str(), NULL, 10);
@ -178,6 +179,7 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check)
}
}
// FIXME: Move to utils
static void check_size(int fd, uint64_t *size, uint64_t *sectsize, std::string name)
{
int sect;

View File

@ -228,7 +228,8 @@ struct disk_tool_t
json11::Json read_osd_superblock(std::string device, bool expect_exist = true);
uint32_t write_osd_superblock(std::string device, json11::Json params);
int prepare_one(std::map<std::string, std::string> options);
int prepare_one(std::map<std::string, std::string> options, int is_hdd = -1);
json11::Json::array collect_devices(const std::vector<std::string> & devices);
int prepare(std::vector<std::string> devices);
};
@ -1856,7 +1857,7 @@ static int shell_exec(const std::vector<std::string> & cmd, const std::string &
argv[i] = (char*)cmd[i].c_str();
}
argv[cmd.size()-1] = NULL;
execv(argv[0], argv);
execvp(argv[0], argv);
std::string full_cmd;
for (int i = 0; i < cmd.size(); i++)
{
@ -1865,7 +1866,7 @@ static int shell_exec(const std::vector<std::string> & cmd, const std::string &
}
full_cmd.resize(full_cmd.size() > 0 ? full_cmd.size()-1 : 0);
fprintf(stderr, "error running %s: %s", full_cmd.c_str(), strerror(errno));
exit(1);
exit(255);
}
err_fork:
close(child_stderr[1]);
@ -1877,10 +1878,10 @@ err_pipe2:
close(child_stdin[1]);
close(child_stdin[0]);
err_pipe1:
return 1;
return 255;
}
int disk_tool_t::prepare_one(std::map<std::string, std::string> options)
int disk_tool_t::prepare_one(std::map<std::string, std::string> options, int is_hdd)
{
static const char *allow_additional_params[] = {
"max_write_iodepth",
@ -1899,8 +1900,10 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options)
};
if (options.find("force") == options.end())
{
for (auto dev: std::vector<std::string>{ options["data_device"], options["meta_device"], options["journal_device"] })
std::vector<std::string> all_devs = { options["data_device"], options["meta_device"], options["journal_device"] };
for (int i = 0; i < all_devs.size(); i++)
{
const auto & dev = all_devs[i];
if (dev == "")
continue;
std::string real_dev = realpath_str(dev, false);
@ -1914,10 +1917,12 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options)
fprintf(stderr, "%s is not a partition, not creating OSD without --force\n", dev.c_str());
return 1;
}
if (i == 0 && is_hdd == -1)
is_hdd = read_file("/sys/block/"+parent_dev+"/queue/rotational") == "0";
std::string out;
if (shell_exec({ "/sbin/blkid", "-p", dev }, "", &out, NULL))
if (shell_exec({ "/sbin/blkid", "-D", "-p", dev }, "", &out, NULL) == 0)
{
fprintf(stderr, "%s contains data, not creating OSD without --force. blkid -p says:\n%s", dev.c_str(), out.c_str());
fprintf(stderr, "%s contains data, not creating OSD without --force. blkid -D -p says:\n%s", dev.c_str(), out.c_str());
return 1;
}
json11::Json sb = read_osd_superblock(dev, false);
@ -1928,12 +1933,20 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options)
}
}
}
// FIXME: Different default block_size for HDD
// FIXME: Set block_size at first call with HDD
// Calculate offsets if the same device is used for two or more of data, meta, and journal
if (options["journal_device"] == "" && options["journal_size"] == "")
if (options["journal_size"] == "")
{
options["journal_size"] = "32M";
if (options["journal_device"] == "")
options["journal_size"] = "32M";
else if (is_hdd)
options["journal_size"] = "1G";
}
if (is_hdd)
{
if (options["block_size"] == "")
options["block_size"] = "1M";
if (options["throttle_small_writes"] == "")
options["throttle_small_writes"] = "1";
}
json11::Json::object sb;
try
@ -2009,6 +2022,79 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options)
return 0;
}
json11::Json::array disk_tool_t::collect_devices(const std::vector<std::string> & devices)
{
json11::Json::array devinfo;
for (auto & dev: devices)
{
// Check if the device is a whole disk
if (dev.substr(0, 5) != "/dev/")
{
fprintf(stderr, "%s does not start with /dev/, ignoring\n", dev.c_str());
continue;
}
struct stat st;
if (stat(("/sys/block/"+dev.substr(5)).c_str(), &st) < 0)
{
if (errno == ENOENT)
{
fprintf(stderr, "%s is probably a partition (no entry in /sys/block/), ignoring\n", dev.c_str());
continue;
}
fprintf(stderr, "Error checking /sys/block/%s: %s\n", dev.c_str()+5, strerror(errno));
return {};
}
// Check if the device is an SSD
bool is_hdd = read_file("/sys/block/"+dev.substr(5)+"/queue/rotational") == "0";
// Check if it has a partition table
std::string part_dump;
int r = shell_exec({ "/sbin/sfdisk", "--dump", dev, "--json" }, "", &part_dump, NULL);
if (r != 0)
{
if (r == 255)
{
fprintf(stderr, "Error running /sbin/sfdisk --dump %s --json\n", dev.c_str());
return {};
}
// No partition table
r = shell_exec({ "/sbin/blkid", "-p", dev }, "", &part_dump, NULL);
if (r == 0)
{
fprintf(stderr, "%s contains data, skipping:\n %s\n", dev.c_str(), str_replace(trim(part_dump), "\n", "\n ").c_str());
continue;
}
part_dump = "";
}
// Decode partition table
json11::Json parts;
if (part_dump != "")
{
std::string err;
parts = json11::Json::parse(part_dump, err);
if (err != "")
{
fprintf(stderr, "sfdisk --dump %s --json returned bad JSON: %s\n", dev.c_str(), part_dump.c_str());
return {};
}
parts = parts["partitiontable"];
if (parts.is_object() && parts["label"].string_value() != "gpt")
{
fprintf(stderr, "%s contains \"%s\" partition table, only GPT is supported, skipping\n", dev.c_str(), parts["label"].string_value().c_str());
return {};
}
}
devinfo.push_back(json11::Json::object {
{ "is_hdd", is_hdd },
{ "parts", parts },
});
}
if (!devinfo.size())
{
fprintf(stderr, "No suitable devices found\n");
}
return devinfo;
}
int disk_tool_t::prepare(std::vector<std::string> devices)
{
if (options.find("data_device") != options.end() && options["data_device"] != "")
@ -2020,6 +2106,10 @@ int disk_tool_t::prepare(std::vector<std::string> devices)
}
return prepare_one(options);
}
// FIXME: Implement the second (automatic) form of the command
json11::Json::array devinfo = collect_devices(devices);
if (!devinfo.size())
{
return 1;
}
return 0;
}

View File

@ -75,6 +75,23 @@ std::string trim(const std::string & in)
return in.substr(begin, end+1-begin);
}
std::string str_replace(const std::string & in, const std::string & needle, const std::string & replacement)
{
std::string res;
int pos = 0, p2;
while ((p2 = in.find(needle, pos)) >= 0)
{
res += in.substr(pos, p2-pos);
res += replacement;
pos = p2 + replacement.size();
}
if (!pos)
{
return in;
}
return res + in.substr(pos);
}
uint64_t stoull_full(const std::string & str, int base)
{
if (isspace(str[0]))

View File

@ -10,6 +10,7 @@ std::string base64_decode(const std::string &in);
uint64_t parse_size(std::string size_str);
std::string strtolower(const std::string & in);
std::string trim(const std::string & in);
std::string str_replace(const std::string & in, const std::string & needle, const std::string & replacement);
uint64_t stoull_full(const std::string & str, int base = 0);
std::string format_size(uint64_t size, bool nobytes = false);
void print_help(const char *help_text, std::string exe_name, std::string cmd, bool all);