Implement async mtime change
parent
7b12342933
commit
603dc68f11
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
10
src/nfs_kv.h
10
src/nfs_kv.h
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue