]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ceph-fuse: test dentry invalidation options and fail out if we fail 3681/head
authorGreg Farnum <gfarnum@redhat.com>
Thu, 26 Feb 2015 23:20:11 +0000 (15:20 -0800)
committerGreg Farnum <gfarnum@redhat.com>
Thu, 26 Feb 2015 23:24:21 +0000 (15:24 -0800)
We identify the Linux kernel version and based on that either expect to
be able to invalidate dentries effectively, or expect to be able to remount
the ceph-fuse mountpoint. Test it using the Client functions and callbacks by
spinning off a thread to invoke the test that is separate from the main
FUSE loop.

Most unfortunately, there doesn't seem to be a good interface to tell
FUSE to shut down if we need to do that. See
http://fuse.996288.n3.nabble.com/libfuse-exiting-fuse-session-loop-td10686.html
I tried changing our signal invocation or attempting a simple action on
the mount point but those were ineffectual at terminating the remaining
processes; fusermount actually gets rid of them all.

Signed-off-by: Greg Farnum <gfarnum@redhat.com>
src/ceph_fuse.cc

index 50406b92d1828180f3aecbfcd6b71aba54f02754..76168503d594c71b8ec4debeae32b18d69e48fc2 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <sys/stat.h>
+#include <sys/utsname.h>
 #include <iostream>
 #include <string>
 using namespace std;
@@ -84,6 +85,8 @@ int main(int argc, const char **argv, const char *envp[]) {
   // we need to handle the forking ourselves.
   int fd[2] = {0, 0};  // parent's, child's
   pid_t childpid = 0;
+  int tester_r = 0;
+  void *tester_rp = NULL;
   bool restart_log = false;
   if (g_conf->daemonize) {
     int r = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
@@ -107,13 +110,53 @@ int main(int argc, const char **argv, const char *envp[]) {
     if (restart_log)
       g_ceph_context->_log->start();
 
+    class RemountTest : public Thread {
+    public:
+      CephFuse *cfuse;
+      Client *client;
+      RemountTest() : Thread() {}
+      void init(CephFuse *cf, Client *cl) {
+       cfuse = cf;
+       client = cl;
+      }
+      virtual ~RemountTest() {}
+      virtual void *entry() {
+       struct utsname os_info;
+       int tr = uname(&os_info);
+       assert(tr == 0);
+       assert(memcmp(os_info.sysname, "Linux", 5) == 0);
+       int major, minor;       
+       char *end_num;
+       major = strtol(os_info.release, &end_num, 10);
+       assert(major > 0);
+       ++end_num;
+       minor = strtol(end_num, NULL, 10);
+       bool can_invalidate_dentries = g_conf->client_try_dentry_invalidate &&
+         (major < 3 ||
+          (major == 3 && minor < 18));
+       tr = client->test_dentry_handling(can_invalidate_dentries);
+       if (tr != 0) {
+         cerr << "ceph-fuse[" << getpid()
+              << "]: fuse failed dentry invalidate/remount test with error "
+              << cpp_strerror(tr) << ", stopping" << std::endl;
+
+         char buf[5050];
+         string mountpoint = cfuse->get_mount_point();
+         snprintf(buf, 5049, "fusermount -u -z %s", mountpoint.c_str());
+         system(buf);
+       }
+       return reinterpret_cast<void*>(tr);
+      }
+    } tester;
+
+
     // get monmap
     Messenger *messenger = NULL;
     Client *client;
     CephFuse *cfuse;
 
-    MonClient mc(g_ceph_context);
-    int r = mc.build_initial_monmap();
+    MonClient *mc = new MonClient(g_ceph_context);
+    int r = mc->build_initial_monmap();
     if (r == -EINVAL)
       usage();
     if (r < 0)
@@ -127,7 +170,7 @@ int main(int argc, const char **argv, const char *envp[]) {
     messenger->set_policy(entity_name_t::TYPE_MDS,
                          Messenger::Policy::lossless_client(0, 0));
 
-    client = new Client(messenger, &mc);
+    client = new Client(messenger, mc);
     if (filer_flags) {
       client->set_filer_flags(filer_flags);
     }
@@ -169,17 +212,24 @@ int main(int argc, const char **argv, const char *envp[]) {
       cerr << "ceph-fuse[" << getpid() << "]: fuse failed to start" << std::endl;
       goto out_client_unmount;
     }
+
     cerr << "ceph-fuse[" << getpid() << "]: starting fuse" << std::endl;
+    tester.init(cfuse, client);
+    tester.create();
     r = cfuse->loop();
-    cerr << "ceph-fuse[" << getpid() << "]: fuse finished with error " << r << std::endl;
-
+    tester.join(&tester_rp);
+    tester_r = static_cast<int>(reinterpret_cast<uint64_t>(tester_rp));
+    cerr << "ceph-fuse[" << getpid() << "]: fuse finished with error " << r
+        << " and tester_r " << tester_r <<std::endl;
+    
+    
   out_client_unmount:
     client->unmount();
     //cout << "unmounted" << std::endl;
-
+    
     cfuse->finalize();
     delete cfuse;
-
+    
   out_shutdown:
     client->shutdown();
   out_init_failed:
@@ -189,17 +239,19 @@ int main(int argc, const char **argv, const char *envp[]) {
   out_messenger_start_failed:
     delete client;
   out_mc_start_failed:
-
+    
     if (g_conf->daemonize) {
       //cout << "child signalling parent with " << r << std::endl;
       static int foo = 0;
       foo += ::write(fd[1], &r, sizeof(r));
     }
-
+    
     delete messenger;
     g_ceph_context->put();
     free(newargv);
-
+    
+    delete mc;
+    
     //cout << "child done" << std::endl;
     return r;
   } else {