]> 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 fb0c05c5757e131978faea3af8b86546cbb13b44..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,8 +792,9 @@ static void usage()
 {
        fprintf(stderr, "Usage:\n");
        fprintf(stderr, "\n");
-       fprintf(stderr, "lxcfs [-f|-d] [-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);
@@ -837,9 +893,10 @@ 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;
+       bool debug = false, nonempty = false;
+       bool load_use = false;
        /*
         * what we pass to fuse_main is:
         * argv[0] -s [-f|-d] -o allow_other,directio argv[1] NULL
@@ -851,10 +908,21 @@ int main(int argc, char *argv[])
        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;
@@ -876,13 +944,15 @@ int main(int argc, char *argv[])
        }
 
        newargv[cnt++] = argv[0];
-        if (debug) {
-                newargv[cnt++] = "-d";
-        } else {
-                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;
 
@@ -894,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)