From: Greg Farnum Date: Thu, 26 Feb 2015 23:20:11 +0000 (-0800) Subject: ceph-fuse: test dentry invalidation options and fail out if we fail X-Git-Tag: v0.93~1^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=7ed9640dfe580a6e356564a0ee1485d415d6faa3;p=ceph.git ceph-fuse: test dentry invalidation options and fail out if we fail 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 --- diff --git a/src/ceph_fuse.cc b/src/ceph_fuse.cc index 50406b92d1828..76168503d594c 100644 --- a/src/ceph_fuse.cc +++ b/src/ceph_fuse.cc @@ -13,6 +13,7 @@ */ #include +#include #include #include 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(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(reinterpret_cast(tester_rp)); + cerr << "ceph-fuse[" << getpid() << "]: fuse finished with error " << r + << " and tester_r " << tester_r <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 {