]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: use remount to trim kernel dcache 3191/head
authorYan, Zheng <zyan@redhat.com>
Wed, 17 Dec 2014 07:59:44 +0000 (15:59 +0800)
committerYan, Zheng <zyan@redhat.com>
Wed, 17 Dec 2014 07:59:44 +0000 (15:59 +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 a258a37720315cfc460da1c3ea08400fb00cf430..8377dc8095a6f6c8525a67673f3d16d6d6bc70a8 100644 (file)
@@ -156,11 +156,13 @@ Client::Client(Messenger *m, MonClient *mc)
     m_command_hook(this),
     timer(m->cct, client_lock),
     callback_handle(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),
+    remount_finisher(m->cct),
     objecter_finisher(m->cct),
     tick_event(NULL),
     monclient(mc), messenger(m), whoami(m->get_myname().num()),
@@ -451,6 +453,12 @@ void Client::shutdown()
     async_dentry_invalidator.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();
@@ -3228,18 +3236,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)
@@ -3271,14 +3283,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;
@@ -7072,6 +7077,7 @@ void Client::ll_register_callbacks(struct client_callback_args *args)
                 << " invalidate_ino_cb " << args->ino_cb
                 << " invalidate_dentry_cb " << args->dentry_cb
                 << " getgroups_cb" << args->getgroups_cb
+                << " remount_cb " << args->remount_cb
                 << dendl;
   callback_handle = args->handle;
   if (args->ino_cb) {
@@ -7082,6 +7088,10 @@ void Client::ll_register_callbacks(struct client_callback_args *args)
     dentry_invalidate_cb = args->dentry_cb;
     async_dentry_invalidator.start();
   }
+  if (args->remount_cb) {
+    remount_cb = args->remount_cb;
+    remount_finisher.start();
+  }
   getgroups_cb = args->getgroups_cb;
 }
 
index 41212779c0a70ebec5baef36f0aaf9e5d5f967a3..b46d945467ac187ea21a266e80aad3a255fe8361 100644 (file)
@@ -124,6 +124,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);
 
@@ -131,6 +132,7 @@ struct client_callback_args {
   void *handle;
   client_ino_callback_t ino_cb;
   client_dentry_callback_t dentry_cb;
+  client_remount_callback_t remount_cb;
   client_getgroups_callback_t getgroups_cb;
 };
 
@@ -221,12 +223,14 @@ class Client : public Dispatcher {
   SafeTimer timer;
 
   void *callback_handle;
+  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 remount_finisher;
   Finisher objecter_finisher;
 
   Context *tick_event;
index 891bc32fb7610f68995d9e827d34f71d6591dce4..276e608df6998f5fd460f0ed1223d892b0640e5e 100644 (file)
@@ -692,6 +692,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;
@@ -877,6 +887,7 @@ int CephFuse::Handle::start()
     handle: this,
     ino_cb: client->cct->_conf->fuse_use_invalidate_cb ? ino_invalidate_cb : NULL,
     dentry_cb: dentry_invalidate_cb,
+    remount_cb: remount_cb,
     /*
      * this is broken:
      *