]> git.proxmox.com Git - mirror_lxcfs.git/blobdiff - lxcfs.c
Merge pull request #245 from aither64/loadavg-leak
[mirror_lxcfs.git] / lxcfs.c
diff --git a/lxcfs.c b/lxcfs.c
index d065125844baa1de19104387748018b5db816003..76b3ea26f9ca2166f61e5c4de849b007b0240ca7 100644 (file)
--- a/lxcfs.c
+++ b/lxcfs.c
@@ -28,6 +28,7 @@
 #include <sys/epoll.h>
 #include <sys/mount.h>
 #include <sys/socket.h>
+#include <linux/limits.h>
 
 #include "bindings.h"
 #include "config.h" // for VERSION
@@ -68,12 +69,57 @@ static void users_unlock(void)
        unlock_mutex(&user_count_mutex);
 }
 
+static pthread_t loadavg_pid = 0;
+
+/* Returns zero on success */
+static int start_loadavg(void) {
+       char *error;
+       pthread_t (*load_daemon)(int);
+
+       dlerror();    /* Clear any existing error */
+
+       load_daemon = (pthread_t (*)(int)) dlsym(dlopen_handle, "load_daemon");
+       error = dlerror();
+       if (error != NULL) {
+               lxcfs_error("load_daemon fails:%s\n", error);
+               return -1;
+       }
+       loadavg_pid = load_daemon(1);
+       if (loadavg_pid == 0)
+               return -1;
+
+       return 0;
+}
+
+/* Returns zero on success */
+static int stop_loadavg(void) {
+       char *error;
+       int (*stop_load_daemon)(pthread_t);
+
+       stop_load_daemon = (int (*)(pthread_t)) dlsym(dlopen_handle, "stop_load_daemon");
+       error = dlerror();
+       if (error != NULL) {
+               lxcfs_error("stop_load_daemon error: %s\n", error);
+               return -1;
+       }
+
+       if (stop_load_daemon(loadavg_pid) != 0)
+               return -1;
+
+       return 0;
+}
+
 static volatile sig_atomic_t need_reload;
 
 /* do_reload - reload the dynamic library.  Done under
  * lock and when we know the user_count was 0 */
 static void do_reload(void)
 {
+       char lxcfs_lib_path[PATH_MAX];
+
+       if (loadavg_pid > 0)
+               stop_loadavg();
+
        if (dlopen_handle) {
                lxcfs_debug("%s\n", "Closing liblxcfs.so handle.");
                dlclose(dlopen_handle);
@@ -86,13 +132,22 @@ static void do_reload(void)
                goto good;
        }
 
-       dlopen_handle = dlopen("/usr/lib/lxcfs/liblxcfs.so", RTLD_LAZY);
+#ifdef LIBDIR
+       /* LIBDIR: autoconf will setup this MACRO. Default value is $PREFIX/lib */
+        snprintf(lxcfs_lib_path, PATH_MAX, "%s/lxcfs/liblxcfs.so", LIBDIR);
+#else
+        snprintf(lxcfs_lib_path, PATH_MAX, "/usr/local/lib/lxcfs/liblxcfs.so");
+#endif
+        dlopen_handle = dlopen(lxcfs_lib_path, RTLD_LAZY);
        if (!dlopen_handle) {
                lxcfs_error("Failed to open liblxcfs.so: %s.\n", dlerror());
                _exit(1);
        }
 
 good:
+       if (loadavg_pid > 0)
+               start_loadavg();
+
        if (need_reload)
                lxcfs_error("%s\n", "lxcfs: reloaded");
        need_reload = 0;
@@ -737,7 +792,9 @@ static void usage()
 {
        fprintf(stderr, "Usage:\n");
        fprintf(stderr, "\n");
-       fprintf(stderr, "lxcfs [-p pidfile] mountpoint\n");
+       fprintf(stderr, "lxcfs [-f|-d] -l [-p pidfile] mountpoint\n");
+       fprintf(stderr, "  -f running foreground by default; -d enable debug output \n");
+       fprintf(stderr, "  -l use loadavg \n");
        fprintf(stderr, "  Default pidfile is %s/lxcfs.pid\n", RUNTIME_PATH);
        fprintf(stderr, "lxcfs -h\n");
        exit(1);
@@ -753,7 +810,7 @@ static bool is_help(char *w)
        return false;
 }
 
-void swallow_arg(int *argcp, char *argv[], char *which)
+bool swallow_arg(int *argcp, char *argv[], char *which)
 {
        int i;
 
@@ -764,8 +821,9 @@ void swallow_arg(int *argcp, char *argv[], char *which)
                        argv[i] = argv[i+1];
                }
                (*argcp)--;
-               return;
+               return true;
        }
+       return false;
 }
 
 bool swallow_option(int *argcp, char *argv[], char *opt, char **v)
@@ -835,11 +893,13 @@ int main(int argc, char *argv[])
 {
        int ret = EXIT_FAILURE;
        int pidfd = -1;
-       char *pidfile = NULL, *v = NULL;
+       char *pidfile = NULL, *saveptr = NULL, *token = NULL, *v = NULL;
        size_t pidfile_len;
+       bool debug = false, nonempty = false;
+       bool load_use = false;
        /*
         * what we pass to fuse_main is:
-        * argv[0] -s -f -o allow_other,directio argv[1] NULL
+        * argv[0] -s [-f|-d] -o allow_other,directio argv[1] NULL
         */
        int nargs = 5, cnt = 0;
        char *newargv[6];
@@ -847,10 +907,22 @@ int main(int argc, char *argv[])
        /* accomodate older init scripts */
        swallow_arg(&argc, argv, "-s");
        swallow_arg(&argc, argv, "-f");
+       debug = swallow_arg(&argc, argv, "-d");
+       if (swallow_arg(&argc, argv, "-l")) {
+               load_use = true;
+       }
        if (swallow_option(&argc, argv, "-o", &v)) {
-               if (strcmp(v, "allow_other") != 0) {
-                       fprintf(stderr, "Warning: unexpected fuse option %s\n", v);
-                       exit(EXIT_FAILURE);
+               /* Parse multiple values */
+               for (; (token = strtok_r(v, ",", &saveptr)); v = NULL) {
+                       if (strcmp(token, "allow_other") == 0) {
+                               /* Noop. this is the default. Always enabled. */
+                       } else if (strcmp(token, "nonempty") == 0) {
+                               nonempty = true;
+                       } else {
+                               free(v);
+                               fprintf(stderr, "Warning: unexpected fuse option %s\n", v);
+                               exit(EXIT_FAILURE);
+                       }
                }
                free(v);
                v = NULL;
@@ -872,9 +944,15 @@ int main(int argc, char *argv[])
        }
 
        newargv[cnt++] = argv[0];
-       newargv[cnt++] = "-f";
+       if (debug)
+               newargv[cnt++] = "-d";
+       else
+               newargv[cnt++] = "-f";
        newargv[cnt++] = "-o";
-       newargv[cnt++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5";
+       if (nonempty)
+               newargv[cnt++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5,nonempty";
+       else
+               newargv[cnt++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5";
        newargv[cnt++] = argv[1];
        newargv[cnt++] = NULL;
 
@@ -886,8 +964,13 @@ int main(int argc, char *argv[])
        if ((pidfd = set_pidfile(pidfile)) < 0)
                goto out;
 
+       if (load_use && start_loadavg() != 0)
+               goto out;
+
        if (!fuse_main(nargs, newargv, &lxcfs_ops, NULL))
                ret = EXIT_SUCCESS;
+       if (load_use)
+               stop_loadavg();
 
 out:
        if (dlopen_handle)