]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: use remount to trim kernel dcache 3121/head
authorYan, Zheng <zyan@redhat.com>
Tue, 9 Dec 2014 06:12:08 +0000 (14:12 +0800)
committerYan, Zheng <zyan@redhat.com>
Tue, 9 Dec 2014 08:06:41 +0000 (16:06 +0800)
when remounting a file system, linux kernel trims all unused dentry
in the file system.

Fixes: #10277
Signed-off-by: Yan, Zheng <zyan@redhat.com>
src/client/Client.cc
src/client/Client.h
src/client/fuse_ll.cc

index d67172ae643c90348bfdb095aeec957727638336..a85b63580eed74965001b05370f7aae5ed5af7f4 100644 (file)
@@ -158,12 +158,14 @@ Client::Client(Messenger *m, MonClient *mc)
     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()),
@@ -461,6 +463,12 @@ void Client::shutdown()
     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();
@@ -3275,18 +3283,22 @@ void Client::remove_session_caps(MetaSession *s)
   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)
@@ -3318,14 +3330,7 @@ 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;
@@ -7601,6 +7606,7 @@ void Client::ll_register_callbacks(struct client_callback_args *args)
                 << " 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) {
@@ -7615,6 +7621,10 @@ void Client::ll_register_callbacks(struct client_callback_args *args)
     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;
 }
 
index 8d00037324f237438e96495538319b1abf47fa91..d8b355c5c5c1988b2024356583831a99f400096f 100644 (file)
@@ -136,6 +136,7 @@ typedef void (*client_ino_callback_t)(void *handle, vinodeno_t ino, int64_t off,
 
 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);
@@ -145,6 +146,7 @@ struct client_callback_args {
   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;
 };
 
@@ -236,6 +238,7 @@ class Client : public Dispatcher {
 
   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;
@@ -243,6 +246,7 @@ class Client : public Dispatcher {
   Finisher async_ino_invalidator;
   Finisher async_dentry_invalidator;
   Finisher interrupt_finisher;
+  Finisher remount_finisher;
   Finisher objecter_finisher;
 
   Context *tick_event;
index 1f43530572080c71ed5600b0d442aaa35bbf666d..6503e951033678ba7151fe80166df34c098d5554 100644 (file)
@@ -755,6 +755,16 @@ static void dentry_invalidate_cb(void *handle, vinodeno_t dirino,
 #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;
@@ -944,6 +954,7 @@ int CephFuse::Handle::start()
     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:
      *