.. confval:: rgw_d4n_address
.. confval:: rgw_d4n_l1_datacache_persistent_path
-.. confval:: rgw_d4n_l1_datacache_size
+.. confval:: rgw_d4n_l1_datacache_disk_reserve
.. confval:: rgw_d4n_l1_evict_cache_on_start
.. confval:: rgw_d4n_l1_fadvise
.. confval:: rgw_d4n_libaio_aio_threads
services:
- rgw
with_legacy: true
-- name: rgw_d4n_l1_datacache_size
+- name: rgw_d4n_l1_datacache_disk_reserve
type: size
level: advanced
- desc: maximum size on disk for datacache
- long_desc: The local SSD cache uses this option to configure its size in bytes. This
- option is not used by the Redis cache backend.
+ desc: amount of disk space to keep free for datacache
+ long_desc: The local SSD cache uses this option to determine how much disk space to
+ reserve. The cache can grow until disk usage reaches (total disk space - reserved space).
default: 1_G
services:
- rgw
partition_info.location = g_conf()->rgw_d4n_l1_datacache_persistent_path;
partition_info.name = "d4n";
partition_info.type = "read-cache";
- partition_info.size = g_conf()->rgw_d4n_l1_datacache_size;
+ partition_info.reserve_size = g_conf()->rgw_d4n_l1_datacache_disk_reserve;
cacheDriver = std::make_unique<rgw::cache::SSDDriver>(partition_info, admin);
}
std::string name;
std::string type;
std::string location;
- uint64_t size;
+ uint64_t reserve_size;
};
class CacheDriver {
}
}
+std::optional<fs::path> RedisDriver::resolve_valkey_data_dir(const DoutPrefixProvider* dpp) const
+{
+ try {
+ boost::system::error_code ec;
+ response<std::vector<std::string>> resp;
+ request req;
+ req.push("CONFIG", "GET", "dir");
+
+ redis_exec(conn, ec, req, resp, null_yield);
+
+ if (ec) {
+ ldpp_dout(dpp, 5) << "RedisDriver::" << __func__
+ << "(): failed to execute CONFIG GET dir: " << ec.message()
+ << dendl;
+ return std::nullopt;
+ }
+
+ const auto& entries = std::get<0>(resp);
+ std::clog << "MK| OK " << __FILE__ << " :" << __LINE__ << " | " << __func__ << "(): entries.value().size()=" << entries.value().size() << std::endl;
+ if (entries.value().size() < 2) {
+ ldpp_dout(dpp, 5) << "RedisDriver::" << __func__
+ << "(): unexpected CONFIG GET dir response size=" << entries.value().size()
+ << dendl;
+ return std::nullopt;
+ }
+
+ const fs::path dir_path(entries.value()[1]);
+ std::clog << "MK| OK " << __FILE__ << " :" << __LINE__ << " | " << __func__ << "(): dir_path=" << std::quoted(dir_path.string()) << std::endl;
+ if (dir_path.empty()) {
+ ldpp_dout(dpp, 5) << "RedisDriver::" << __func__
+ << "(): CONFIG GET dir returned empty path" << dendl;
+ return std::nullopt;
+ }
+
+ return dir_path;
+ } catch (const std::exception& e) {
+ ldpp_dout(dpp, 0) << "RedisDriver::" << __func__
+ << "(): exception while resolving data dir: " << e.what()
+ << dendl;
+ }
+
+ return std::nullopt;
+}
+
+uint64_t RedisDriver::get_free_space(const DoutPrefixProvider* dpp)
+{
+ auto data_dir = resolve_valkey_data_dir(dpp);
+ if (!data_dir) {
+ ldpp_dout(dpp, 0) << __func__ << "(): ERROR: could not resolve redis data dir" << dendl;
+ return 0;
+ }
+
+ const fs::path redis_probe_path = *data_dir;
+ ldpp_dout(dpp, 20) << __func__ << "(): redis path = " << std::quoted(redis_probe_path.string()) << dendl;
+
+ std::error_code ec;
+ fs::space_info space = fs::space(redis_probe_path, ec);
+ if (ec) {
+ ldpp_dout(dpp, 0) << __func__ << "(): ERROR: unable to stat redis path "
+ << std::quoted(redis_probe_path.string()) << " : " << ec.message() << dendl;
+ return 0;
+ }
+
+ ldpp_dout(dpp, 20) << __func__ << "(): redis partition space.available=" << space.available
+ << ", partition_info.reserve_size=" << partition_info.reserve_size << dendl;
+
+ return (space.available < partition_info.reserve_size) ? 0 : (space.available - partition_info.reserve_size);
+}
+
int RedisDriver::initialize(const DoutPrefixProvider* dpp)
{
if (partition_info.location.back() != '/') {
#pragma once
#include <aio.h>
+#include <filesystem>
+#include <optional>
+#include <system_error>
#include <boost/redis/connection.hpp>
#include "common/async/completion.h"
namespace rgw { namespace cache {
namespace net = boost::asio;
+namespace fs = std::filesystem;
using boost::redis::config;
using boost::redis::connection;
using boost::redis::request;
class RedisDriver : public CacheDriver {
public:
RedisDriver(net::io_context& io_context, Partition& _partition_info) : partition_info(_partition_info),
- free_space(_partition_info.size),
+ free_space(0),
outstanding_write_size(0)
{
conn = std::make_shared<connection>(boost::asio::make_strand(io_context));
/* Partition */
virtual Partition get_current_partition_info(const DoutPrefixProvider* dpp) override { return partition_info; }
- virtual uint64_t get_free_space(const DoutPrefixProvider* dpp) override { return free_space; }
+ virtual uint64_t get_free_space(const DoutPrefixProvider* dpp) override;
virtual int initialize(const DoutPrefixProvider* dpp) override;
virtual int put(const DoutPrefixProvider* dpp, const std::string& key, const bufferlist& bl, uint64_t len, const rgw::sal::Attrs& attrs, optional_yield y) override;
uint64_t free_space;
uint64_t outstanding_write_size;
+ std::optional<fs::path> resolve_valkey_data_dir(const DoutPrefixProvider* dpp) const;
+
struct redis_response {
request req;
boost::redis::generic_response resp;
uint64_t SSDDriver::get_free_space(const DoutPrefixProvider* dpp)
{
efs::space_info space = efs::space(partition_info.location);
- return space.available;
+ return (space.available < partition_info.reserve_size) ? 0 : (space.available - partition_info.reserve_size);
}
void SSDDriver::set_free_space(const DoutPrefixProvider* dpp, uint64_t free_space)
};
conn = std::make_shared<connection>(net::make_strand(io));
- rgw::cache::Partition partition_info{ .location = "RedisCache", .size = 1000 };
+ rgw::cache::Partition partition_info{ .location = "RedisCache", .reserve_size = 1073741824 };
cacheDriver = new rgw::cache::RedisDriver{io, partition_info};
policyDriver = new rgw::d4n::PolicyDriver(conn, cacheDriver, "lfuda", null_yield);
dir = new rgw::d4n::BlockDirectory{conn};
class SSDDriverFixture: public ::testing::Test {
protected:
virtual void SetUp() {
- rgw::cache::Partition partition_info{.name = "d4n", .type = "read-cache", .location = "rgw_d4n_datacache", .size = 5368709120};
+ rgw::cache::Partition partition_info{.name = "d4n", .type = "read-cache", .location = "rgw_d4n_datacache", .reserve_size = 1073741824};
cacheDriver = new rgw::cache::SSDDriver{partition_info, false};
ASSERT_NE(cacheDriver, nullptr);