forked from vitalif/vitastor
vitastor-disk prepare: WIP second form command of the command
parent
5a10d135f3
commit
2e0a2221eb
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]))
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue