timer(m->cct, client_lock),
callback_handle(NULL),
switch_interrupt_cb(NULL),
+ remount_cb(NULL),
ino_invalidate_cb(NULL),
dentry_invalidate_cb(NULL),
getgroups_cb(NULL),
async_ino_invalidator(m->cct),
async_dentry_invalidator(m->cct),
interrupt_finisher(m->cct),
+ remount_finisher(m->cct),
objecter_finisher(m->cct),
tick_event(NULL),
monclient(mc), messenger(m), whoami(m->get_myname().num()),
interrupt_finisher.stop();
}
+ if (remount_cb) {
+ ldout(cct, 10) << "shutdown stopping remount finisher" << dendl;
+ remount_finisher.wait_for_empty();
+ remount_finisher.stop();
+ }
+
objectcacher->stop(); // outside of client_lock! this does a join.
client_lock.Lock();
sync_cond.Signal();
}
+class C_Client_Remount : public Context {
+private:
+ Client *client;
+public:
+ C_Client_Remount(Client *c) : client(c) {}
+ void finish(int r) {
+ client->remount_cb(client->callback_handle);
+ }
+};
+
void Client::_invalidate_kernel_dcache()
{
- // notify kernel to invalidate top level directory entries. As a side effect,
- // unused inodes underneath these entries get pruned.
- if (dentry_invalidate_cb && root->dir) {
- for (ceph::unordered_map<string, Dentry*>::iterator p = root->dir->dentries.begin();
- p != root->dir->dentries.end();
- ++p) {
- if (p->second->inode)
- _schedule_invalidate_dentry_callback(p->second, false);
- }
- }
+ // Hacky:
+ // when remounting a file system, linux kernel trims all unused dentries in the file system
+ if (remount_cb)
+ remount_finisher.queue(new C_Client_Remount(this));
}
void Client::trim_caps(MetaSession *s, int max)
while (q != in->dn_set.end()) {
Dentry *dn = *q++;
if (dn->lru_is_expireable()) {
- if (dn->dir->parent_inode->ino == MDS_INO_ROOT) {
- // Only issue one of these per DN for inodes in root: handle
- // others more efficiently by calling for root-child DNs at
- // the end of this function.
- _schedule_invalidate_dentry_callback(dn, true);
- }
trim_dentry(dn);
-
} else {
ldout(cct, 20) << " not expirable: " << dn->name << dendl;
all = false;
<< " invalidate_dentry_cb " << args->dentry_cb
<< " getgroups_cb" << args->getgroups_cb
<< " switch_interrupt_cb " << args->switch_intr_cb
+ << " remount_cb " << args->remount_cb
<< dendl;
callback_handle = args->handle;
if (args->ino_cb) {
switch_interrupt_cb = args->switch_intr_cb;
interrupt_finisher.start();
}
+ if (args->remount_cb) {
+ remount_cb = args->remount_cb;
+ remount_finisher.start();
+ }
getgroups_cb = args->getgroups_cb;
}
typedef void (*client_dentry_callback_t)(void *handle, vinodeno_t dirino,
vinodeno_t ino, string& name);
+typedef void (*client_remount_callback_t)(void *handle);
typedef int (*client_getgroups_callback_t)(void *handle, uid_t uid, gid_t **sgids);
typedef void(*client_switch_interrupt_callback_t)(void *req, void *data);
client_ino_callback_t ino_cb;
client_dentry_callback_t dentry_cb;
client_switch_interrupt_callback_t switch_intr_cb;
+ client_remount_callback_t remount_cb;
client_getgroups_callback_t getgroups_cb;
};
void *callback_handle;
client_switch_interrupt_callback_t switch_interrupt_cb;
+ client_remount_callback_t remount_cb;
client_ino_callback_t ino_invalidate_cb;
client_dentry_callback_t dentry_invalidate_cb;
client_getgroups_callback_t getgroups_cb;
Finisher async_ino_invalidator;
Finisher async_dentry_invalidator;
Finisher interrupt_finisher;
+ Finisher remount_finisher;
Finisher objecter_finisher;
Context *tick_event;
#endif
}
+static void remount_cb(void *handle)
+{
+ // used for trimming kernel dcache. when remounting a file system, linux kernel
+ // trims all unused dentries in the file system
+ char cmd[1024];
+ CephFuse::Handle *cfuse = (CephFuse::Handle *)handle;
+ snprintf(cmd, sizeof(cmd), "mount -i -o remount %s", cfuse->mountpoint);
+ system(cmd);
+}
+
static void do_init(void *data, fuse_conn_info *bar)
{
CephFuse::Handle *cfuse = (CephFuse::Handle *)data;
ino_cb: client->cct->_conf->fuse_use_invalidate_cb ? ino_invalidate_cb : NULL,
dentry_cb: dentry_invalidate_cb,
switch_intr_cb: switch_interrupt_cb,
+ remount_cb: remount_cb,
/*
* this is broken:
*