Auto-guess atomic_write_size from /sys
This commit is contained in:
@@ -52,6 +52,8 @@ void blockstore_disk_t::parse_config(std::map<std::string, std::string> & config
|
|||||||
meta_format = stoull_full(config["meta_format"]);
|
meta_format = stoull_full(config["meta_format"]);
|
||||||
atomic_write_size = (config.find("atomic_write_size") != config.end()
|
atomic_write_size = (config.find("atomic_write_size") != config.end()
|
||||||
? parse_size(config["atomic_write_size"]) : 4096);
|
? parse_size(config["atomic_write_size"]) : 4096);
|
||||||
|
use_atomic_flag = config.find("use_atomic_flag") != config.end() &&
|
||||||
|
(config["use_atomic_flag"] == "true" || config["use_atomic_flag"] == "1" || config["use_atomic_flag"] == "yes");
|
||||||
if (config.find("data_io") == config.end() &&
|
if (config.find("data_io") == config.end() &&
|
||||||
config.find("meta_io") == config.end() &&
|
config.find("meta_io") == config.end() &&
|
||||||
config.find("journal_io") == config.end())
|
config.find("journal_io") == config.end())
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ struct blockstore_disk_t
|
|||||||
uint32_t meta_block_size = 4096;
|
uint32_t meta_block_size = 4096;
|
||||||
// Atomic write size of the data block device
|
// Atomic write size of the data block device
|
||||||
uint32_t atomic_write_size = 4096;
|
uint32_t atomic_write_size = 4096;
|
||||||
|
// Whether we should set RWF_ATOMIC on atomic writes
|
||||||
|
bool use_atomic_flag = false;
|
||||||
// Sparse write tracking granularity. 4 KB is a good choice. Must be a multiple of disk_alignment
|
// Sparse write tracking granularity. 4 KB is a good choice. Must be a multiple of disk_alignment
|
||||||
uint32_t bitmap_granularity = 4096;
|
uint32_t bitmap_granularity = 4096;
|
||||||
// Data checksum type, BLOCKSTORE_CSUM_NONE or BLOCKSTORE_CSUM_CRC32C
|
// Data checksum type, BLOCKSTORE_CSUM_NONE or BLOCKSTORE_CSUM_CRC32C
|
||||||
|
|||||||
@@ -48,3 +48,7 @@
|
|||||||
#define COPY_BUF_COALESCED 0x10
|
#define COPY_BUF_COALESCED 0x10
|
||||||
#define COPY_BUF_PADDED 0x20
|
#define COPY_BUF_PADDED 0x20
|
||||||
#define COPY_BUF_SKIP_CSUM 0x40
|
#define COPY_BUF_SKIP_CSUM 0x40
|
||||||
|
|
||||||
|
#ifndef RWF_ATOMIC
|
||||||
|
#define RWF_ATOMIC 0x40
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -444,6 +444,8 @@ resume_10:
|
|||||||
data->iov = (struct iovec){ op->buf, op->len };
|
data->iov = (struct iovec){ op->buf, op->len };
|
||||||
data->callback = [this, op](ring_data_t *data) { handle_write_event(data, op); };
|
data->callback = [this, op](ring_data_t *data) { handle_write_event(data, op); };
|
||||||
io_uring_prep_writev(sqe, dsk.data_fd, &data->iov, 1, dsk.data_offset + PRIV(op)->location + op->offset);
|
io_uring_prep_writev(sqe, dsk.data_fd, &data->iov, 1, dsk.data_offset + PRIV(op)->location + op->offset);
|
||||||
|
if (dsk.use_atomic_flag)
|
||||||
|
sqe->rw_flags = RWF_ATOMIC;
|
||||||
PRIV(op)->pending_ops++;
|
PRIV(op)->pending_ops++;
|
||||||
PRIV(op)->op_state = 7;
|
PRIV(op)->op_state = 7;
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -169,7 +169,8 @@ void disk_tool_simple_offsets(json11::Json cfg, bool json_output);
|
|||||||
|
|
||||||
uint64_t sscanf_json(const char *fmt, const json11::Json & str);
|
uint64_t sscanf_json(const char *fmt, const json11::Json & str);
|
||||||
void fromhexstr(const std::string & from, int bytes, uint8_t *to);
|
void fromhexstr(const std::string & from, int bytes, uint8_t *to);
|
||||||
int disable_cache(std::string dev);
|
int disable_cache(const std::string & dev);
|
||||||
|
uint64_t get_atomic_write_size(const std::string & dev);
|
||||||
uint64_t get_device_size(const std::string & dev, bool should_exist = false);
|
uint64_t get_device_size(const std::string & dev, bool should_exist = false);
|
||||||
std::string get_parent_device(std::string dev);
|
std::string get_parent_device(std::string dev);
|
||||||
int shell_exec(const std::vector<std::string> & cmd, const std::string & in, std::string *out, std::string *err);
|
int shell_exec(const std::vector<std::string> & cmd, const std::string & in, std::string *out, std::string *err);
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options, int is_
|
|||||||
"discard_on_start",
|
"discard_on_start",
|
||||||
"min_discard_size",
|
"min_discard_size",
|
||||||
"discard_granularity",
|
"discard_granularity",
|
||||||
|
"atomic_write_size",
|
||||||
|
"use_atomic_flag",
|
||||||
};
|
};
|
||||||
if (options.find("force") == options.end())
|
if (options.find("force") == options.end())
|
||||||
{
|
{
|
||||||
@@ -58,6 +60,18 @@ int disk_tool_t::prepare_one(std::map<std::string, std::string> options, int is_
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (options.find("atomic_write_size") == options.end())
|
||||||
|
{
|
||||||
|
auto data_dev = realpath_str(options["data_device"], false);
|
||||||
|
uint64_t atomic_write_size = get_atomic_write_size(data_dev);
|
||||||
|
if (atomic_write_size > 4096)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Data device %s supports atomic writes up to %ju bytes, enabling. Enjoy faster writes!\n",
|
||||||
|
data_dev.c_str(), atomic_write_size);
|
||||||
|
options["atomic_write_size"] = std::to_string(atomic_write_size);
|
||||||
|
options["use_atomic_flag"] = "1";
|
||||||
|
}
|
||||||
|
}
|
||||||
for (auto dev: std::vector<std::string>{"data", "meta", "journal"})
|
for (auto dev: std::vector<std::string>{"data", "meta", "journal"})
|
||||||
{
|
{
|
||||||
if (options[dev+"_device"] != "" && options["disable_"+dev+"_fsync"] == "auto")
|
if (options[dev+"_device"] != "" && options["disable_"+dev+"_fsync"] == "auto")
|
||||||
|
|||||||
@@ -367,6 +367,19 @@ int disk_tool_t::pre_exec_osd(std::string device)
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (sb["params"]["atomic_write_size"].uint64_value() > 4096 &&
|
||||||
|
sb["params"]["use_atomic_flag"].bool_value())
|
||||||
|
{
|
||||||
|
uint64_t atomic_write_size = get_atomic_write_size(sb["real_data_device"].string_value());
|
||||||
|
if (atomic_write_size < sb["params"]["atomic_write_size"].uint64_value())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Atomic write size is set to %ju in the OSD superblock but data device %s only supports %ju."
|
||||||
|
" Did you enable IOMMU? Linux has a hardcoded max_hw_sectors_kb value for NVMe drives.\n",
|
||||||
|
sb["params"]["atomic_write_size"].uint64_value(),
|
||||||
|
sb["real_data_device"].string_value().c_str(), atomic_write_size);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (json_is_true(sb["params"]["disable_meta_fsync"]) &&
|
if (json_is_true(sb["params"]["disable_meta_fsync"]) &&
|
||||||
sb["real_meta_device"].string_value() != "" && sb["real_meta_device"] != sb["real_data_device"] &&
|
sb["real_meta_device"].string_value() != "" && sb["real_meta_device"] != sb["real_data_device"] &&
|
||||||
check_disabled_cache(sb["real_meta_device"].string_value()) != 0)
|
check_disabled_cache(sb["real_meta_device"].string_value()) != 0)
|
||||||
|
|||||||
@@ -56,8 +56,16 @@ static int check_queue_cache(std::string dev, std::string parent_dev)
|
|||||||
return trim(r) == "write through" ? 0 : -1;
|
return trim(r) == "write through" ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t get_atomic_write_size(const std::string & dev)
|
||||||
|
{
|
||||||
|
auto parent_dev = get_parent_device(dev);
|
||||||
|
if (parent_dev == "")
|
||||||
|
return 0;
|
||||||
|
return stoull_full(trim(read_file("/sys/block/"+parent_dev.substr(5)+"/queue/atomic_write_max_bytes")));
|
||||||
|
}
|
||||||
|
|
||||||
// returns 1 = warning, -1 = error, 0 = success
|
// returns 1 = warning, -1 = error, 0 = success
|
||||||
int disable_cache(std::string dev)
|
int disable_cache(const std::string & dev)
|
||||||
{
|
{
|
||||||
auto parent_dev = get_parent_device(dev);
|
auto parent_dev = get_parent_device(dev);
|
||||||
if (parent_dev == "")
|
if (parent_dev == "")
|
||||||
|
|||||||
Reference in New Issue
Block a user