Implement async mtime change

master
Vitaliy Filippov 2024-03-11 23:59:45 +03:00
parent 7b12342933
commit 603dc68f11
12 changed files with 98 additions and 18 deletions

View File

@ -194,7 +194,7 @@ void nfs_kv_procs(nfs_client_t *self)
void kv_fs_state_t::init(nfs_proxy_t *proxy, json11::Json cfg)
{
// Check if we're using VitastorFS
this->proxy = proxy;
fs_kv_inode = cfg["fs"].uint64_value();
if (fs_kv_inode)
{
@ -226,6 +226,9 @@ void kv_fs_state_t::init(nfs_proxy_t *proxy, json11::Json cfg)
id_alloc_batch_size = cfg["id_alloc_batch_size"].uint64_value();
if (!id_alloc_batch_size)
id_alloc_batch_size = 200;
touch_interval = cfg["touch_interval"].uint64_value();
if (touch_interval < 100) // ms
touch_interval = 100;
auto & pool_cfg = proxy->cli->st_cli.pool_config.at(proxy->default_pool_id);
pool_block_size = pool_cfg.pg_stripe_size;
pool_alignment = pool_cfg.bitmap_granularity;
@ -260,4 +263,50 @@ void kv_fs_state_t::init(nfs_proxy_t *proxy, json11::Json cfg)
}
zero_block.resize(pool_block_size < 1048576 ? 1048576 : pool_block_size);
scrap_block.resize(pool_block_size < 1048576 ? 1048576 : pool_block_size);
touch_timer_id = proxy->epmgr->tfd->set_timer(touch_interval, true, [this](int){ touch_inodes(); });
}
kv_fs_state_t::~kv_fs_state_t()
{
if (proxy && touch_timer_id >= 0)
{
proxy->epmgr->tfd->clear_timer(touch_timer_id);
touch_timer_id = -1;
}
}
static void touch_inode(nfs_proxy_t *proxy, inode_t ino, bool allow_cache)
{
kv_read_inode(proxy, ino, [proxy, ino](int res, const std::string & value, json11::Json attrs)
{
if (!res)
{
auto ientry = attrs.object_items();
ientry["mtime"] = nfstime_now_str();
// FIXME: Use "update" query
bool *found = new bool;
*found = true;
proxy->db->set(kv_inode_key(ino), json11::Json(ientry).dump(), [proxy, ino, found](int res)
{
if (!*found)
res = -ENOENT;
delete found;
if (res == -EAGAIN)
touch_inode(proxy, ino, false);
}, [value, found](int res, const std::string & old_value)
{
*found = res == 0;
return res == 0 && old_value == value;
});
}
}, allow_cache);
}
void kv_fs_state_t::touch_inodes()
{
std::set<inode_t> q = std::move(touch_queue);
for (auto ino: q)
{
touch_inode(proxy, ino, true);
}
}

View File

@ -44,6 +44,9 @@ struct kv_inode_extend_t
struct kv_fs_state_t
{
nfs_proxy_t *proxy = NULL;
int touch_timer_id = -1;
uint64_t fs_kv_inode = 0;
uint64_t fs_base_inode = 0;
uint64_t fs_inode_count = 0;
@ -51,6 +54,7 @@ struct kv_fs_state_t
uint64_t pool_block_size = 0;
uint64_t pool_alignment = 0;
uint64_t shared_inode_threshold = 0;
uint64_t touch_interval = 1000;
std::map<list_cookie_t, list_cookie_val_t> list_cookies;
uint64_t fs_next_id = 1, fs_allocated_id = 0;
@ -58,10 +62,14 @@ struct kv_fs_state_t
std::vector<shared_alloc_queue_t> allocating_shared;
uint64_t cur_shared_inode = 0, cur_shared_offset = 0;
std::map<inode_t, kv_inode_extend_t> extends;
std::set<inode_t> touch_queue;
std::vector<uint8_t> zero_block;
std::vector<uint8_t> scrap_block;
void init(nfs_proxy_t *proxy, json11::Json cfg);
void touch_inodes();
~kv_fs_state_t();
};
struct shared_file_header_t
@ -84,7 +92,7 @@ std::string kv_fh(uint64_t ino);
uint64_t kv_fh_inode(const std::string & fh);
bool kv_fh_valid(const std::string & fh);
void allocate_new_id(nfs_client_t *self, std::function<void(int res, uint64_t new_id)> cb);
void kv_read_inode(nfs_client_t *self, uint64_t ino,
void kv_read_inode(nfs_proxy_t *proxy, uint64_t ino,
std::function<void(int res, const std::string & value, json11::Json ientry)> cb,
bool allow_cache = false);
uint64_t align_shared_size(nfs_client_t *self, uint64_t size);

View File

@ -205,6 +205,10 @@ resume_5:
}
st->res = st->dup_ino ? 0 : -EEXIST;
}
if (!st->res)
{
st->self->parent->kvfs->touch_queue.insert(st->dir_ino);
}
auto cb = std::move(st->cb);
cb(st->res);
}

View File

@ -9,12 +9,12 @@
#include "nfs_kv.h"
// Attributes are always stored in the inode
void kv_read_inode(nfs_client_t *self, uint64_t ino,
void kv_read_inode(nfs_proxy_t *proxy, uint64_t ino,
std::function<void(int res, const std::string & value, json11::Json ientry)> cb,
bool allow_cache)
{
auto key = kv_inode_key(ino);
self->parent->db->get(key, [=](int res, const std::string & value)
proxy->db->get(key, [=](int res, const std::string & value)
{
if (ino == KV_ROOT_INODE && res == -ENOENT)
{
@ -55,7 +55,7 @@ int kv_nfs3_getattr_proc(void *opaque, rpc_op_t *rop)
rpc_queue_reply(rop);
return 0;
}
kv_read_inode(self, ino, [=](int res, const std::string & value, json11::Json attrs)
kv_read_inode(self->parent, ino, [=](int res, const std::string & value, json11::Json attrs)
{
if (self->parent->trace)
fprintf(stderr, "[%d] GETATTR %ju -> %s\n", self->nfs_fd, ino, value.c_str());

View File

@ -47,7 +47,7 @@ resume_0:
// Check that the source inode exists and is not a directory
st->wait = st->retrying ? 1 : 2;
st->res2 = 0;
kv_read_inode(st->self, st->ino, [st](int res, const std::string & value, json11::Json attrs)
kv_read_inode(st->self->parent, st->ino, [st](int res, const std::string & value, json11::Json attrs)
{
st->res = res == 0 ? (attrs["type"].string_value() == "dir" ? -EISDIR : 0) : res;
st->ientry_text = value;
@ -58,7 +58,7 @@ resume_0:
if (!st->retrying)
{
// Check that the new directory exists
kv_read_inode(st->self, st->dir_ino, [st](int res, const std::string & value, json11::Json attrs)
kv_read_inode(st->self->parent, st->dir_ino, [st](int res, const std::string & value, json11::Json attrs)
{
st->res2 = res == 0 ? (attrs["type"].string_value() == "dir" ? 0 : -ENOTDIR) : res;
if (!--st->wait)
@ -138,6 +138,10 @@ resume_4:
st->dir_ino, st->filename.c_str(), strerror(-st->res2), st->res2);
}
}
if (!st->res)
{
st->self->parent->kvfs->touch_queue.insert(st->dir_ino);
}
auto cb = std::move(st->cb);
cb(st->res);
}

View File

@ -41,7 +41,7 @@ int kv_nfs3_lookup_proc(void *opaque, rpc_op_t *rop)
return;
}
uint64_t ino = direntry["ino"].uint64_value();
kv_read_inode(self, ino, [=](int res, const std::string & value, json11::Json ientry)
kv_read_inode(self->parent, ino, [=](int res, const std::string & value, json11::Json ientry)
{
if (res < 0)
{
@ -79,7 +79,7 @@ int kv_nfs3_readlink_proc(void *opaque, rpc_op_t *rop)
rpc_queue_reply(rop);
return 0;
}
kv_read_inode(self, kv_fh_inode(args->symlink), [=](int res, const std::string & value, json11::Json attrs)
kv_read_inode(self->parent, kv_fh_inode(args->symlink), [=](int res, const std::string & value, json11::Json attrs)
{
if (res < 0)
{

View File

@ -43,7 +43,7 @@ static void nfs_kv_continue_read(nfs_kv_read_state *st, int state)
resume_0:
if (st->offset + sizeof(shared_file_header_t) < st->self->parent->kvfs->shared_inode_threshold)
{
kv_read_inode(st->self, st->ino, [st](int res, const std::string & value, json11::Json attrs)
kv_read_inode(st->self->parent, st->ino, [st](int res, const std::string & value, json11::Json attrs)
{
st->res = res;
st->ientry = attrs;

View File

@ -50,7 +50,7 @@ static void kv_getattr_next(nfs_kv_readdir_state *st)
{
auto idx = st->getattr_cur++;
st->getattr_running++;
kv_read_inode(st->self, st->entries[idx].fileid, [st, idx](int res, const std::string & value, json11::Json ientry)
kv_read_inode(st->self->parent, st->entries[idx].fileid, [st, idx](int res, const std::string & value, json11::Json ientry)
{
if (res == 0)
{
@ -96,7 +96,7 @@ static void nfs_kv_continue_readdir(nfs_kv_readdir_state *st, int state)
// Add . and ..
if (st->cookie <= 1)
{
kv_read_inode(st->self, st->dir_ino, [st](int res, const std::string & value, json11::Json ientry)
kv_read_inode(st->self->parent, st->dir_ino, [st](int res, const std::string & value, json11::Json ientry)
{
st->res = res;
st->ientry_text = value;
@ -138,7 +138,7 @@ resume_1:
st->parent_ino = st->ientry["parent_ino"].uint64_value();
if (st->parent_ino)
{
kv_read_inode(st->self, st->ientry["parent_ino"].uint64_value(), [st](int res, const std::string & value, json11::Json ientry)
kv_read_inode(st->self->parent, st->ientry["parent_ino"].uint64_value(), [st](int res, const std::string & value, json11::Json ientry)
{
st->res = res;
st->parent_ientry_text = value;

View File

@ -207,6 +207,7 @@ resume_5:
}
else
{
st->self->parent->kvfs->touch_queue.erase(st->ino);
st->self->parent->db->del(kv_inode_key(st->ino), [st](int res)
{
st->res = res;
@ -249,6 +250,10 @@ resume_7:
cb(st->res);
return;
}
if (!st->res)
{
st->self->parent->kvfs->touch_queue.insert(st->dir_ino);
}
auto cb = std::move(st->cb);
cb(0);
}

View File

@ -157,7 +157,7 @@ resume_3:
else
{
// Check that the new directory is actually a directory
kv_read_inode(st->self, st->new_dir_ino, [st](int res, const std::string & value, json11::Json attrs)
kv_read_inode(st->self->parent, st->new_dir_ino, [st](int res, const std::string & value, json11::Json attrs)
{
st->res = res == 0 ? (attrs["type"].string_value() == "dir" ? 0 : -ENOTDIR) : res;
nfs_kv_continue_rename(st, 4);
@ -222,7 +222,7 @@ resume_7again:
if (st->new_exists && st->new_direntry["type"].string_value() != "dir")
{
// (Maybe) delete old destination file data
kv_read_inode(st->self, st->new_direntry["ino"].uint64_value(), [st](int res, const std::string & value, json11::Json attrs)
kv_read_inode(st->self->parent, st->new_direntry["ino"].uint64_value(), [st](int res, const std::string & value, json11::Json attrs)
{
st->res = res;
st->new_ientry_text = value;
@ -306,7 +306,7 @@ resume_9:
// Change parent_ino in old ientry
st->allow_cache = true;
resume_10:
kv_read_inode(st->self, st->old_direntry["ino"].uint64_value(), [st](int res, const std::string & value, json11::Json ientry)
kv_read_inode(st->self->parent, st->old_direntry["ino"].uint64_value(), [st](int res, const std::string & value, json11::Json ientry)
{
st->res = res;
st->old_ientry_text = value;
@ -348,6 +348,11 @@ resume_12:
return;
}
}
if (!st->res)
{
st->self->parent->kvfs->touch_queue.insert(st->old_dir_ino);
st->self->parent->kvfs->touch_queue.insert(st->new_dir_ino);
}
auto cb = std::move(st->cb);
cb(st->res);
}

View File

@ -35,8 +35,9 @@ static void nfs_kv_continue_setattr(nfs_kv_setattr_state *st, int state)
fprintf(stderr, "BUG: invalid state in nfs_kv_continue_setattr()");
abort();
}
st->self->parent->kvfs->touch_queue.erase(st->ino);
resume_0:
kv_read_inode(st->self, st->ino, [st](int res, const std::string & value, json11::Json attrs)
kv_read_inode(st->self->parent, st->ino, [st](int res, const std::string & value, json11::Json attrs)
{
st->res = res;
st->ientry_text = value;

View File

@ -745,7 +745,7 @@ resume_0:
cb(0);
return;
}
kv_read_inode(st->self, st->ino, [st](int res, const std::string & value, json11::Json attrs)
kv_read_inode(st->self->parent, st->ino, [st](int res, const std::string & value, json11::Json attrs)
{
st->res = res;
st->ientry_text = value;
@ -961,6 +961,10 @@ resume_16:
st->self->parent->kvfs->extends.erase(st->ino);
}
}
else
{
st->self->parent->kvfs->touch_queue.insert(st->ino);
}
if (st->res == -EAGAIN)
{
// Restart