]> git.proxmox.com Git - mirror_lxcfs.git/blobdiff - lxcfs.c
CPU view: handle disabling/enabling of physical CPUs at runtime
[mirror_lxcfs.git] / lxcfs.c
diff --git a/lxcfs.c b/lxcfs.c
index b36986cd97deba4f691a29132dd5af9f1ac91e2e..76b3ea26f9ca2166f61e5c4de849b007b0240ca7 100644 (file)
--- a/lxcfs.c
+++ b/lxcfs.c
@@ -8,28 +8,30 @@
 
 #define FUSE_USE_VERSION 26
 
-#include <stdio.h>
+#include <alloca.h>
 #include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <fuse.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
 #include <libgen.h>
-#include <sched.h>
 #include <pthread.h>
-#include <dlfcn.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <wait.h>
 #include <linux/sched.h>
-#include <sys/socket.h>
-#include <sys/mount.h>
 #include <sys/epoll.h>
-#include <wait.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <linux/limits.h>
 
-#include "config.h" // for VERSION
 #include "bindings.h"
+#include "config.h" // for VERSION
 
 void *dlopen_handle;
 
@@ -42,7 +44,7 @@ static void lock_mutex(pthread_mutex_t *l)
        int ret;
 
        if ((ret = pthread_mutex_lock(l)) != 0) {
-               fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret));
+               lxcfs_error("returned:%d %s\n", ret, strerror(ret));
                exit(1);
        }
 }
@@ -52,7 +54,7 @@ static void unlock_mutex(pthread_mutex_t *l)
        int ret;
 
        if ((ret = pthread_mutex_unlock(l)) != 0) {
-               fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
+               lxcfs_error("returned:%d %s\n", ret, strerror(ret));
                exit(1);
        }
 }
@@ -67,30 +69,87 @@ static void users_unlock(void)
        unlock_mutex(&user_count_mutex);
 }
 
-static int need_reload;
+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)
 {
-       if (dlopen_handle)
+       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);
+       }
 
        /* First try loading using ld.so */
        dlopen_handle = dlopen("liblxcfs.so", RTLD_LAZY);
-       if (dlopen_handle)
+       if (dlopen_handle) {
+               lxcfs_debug("%s\n", "Successfully called dlopen() on liblxcfs.so.");
                goto good;
+       }
 
-       /* Fall back to loading from /usr/lib/lxcfs/liblxcfs.so */
-       dlopen_handle = dlopen(LIBDIR "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) {
-               fprintf(stderr, "Failed to open liblxcfs\n");
+               lxcfs_error("Failed to open liblxcfs.so: %s.\n", dlerror());
                _exit(1);
        }
 
 good:
+       if (loadavg_pid > 0)
+               start_loadavg();
+
        if (need_reload)
-               fprintf(stderr, "lxcfs: reloaded\n");
+               lxcfs_error("%s\n", "lxcfs: reloaded");
        need_reload = 0;
 }
 
@@ -112,10 +171,7 @@ static void down_users(void)
 
 static void reload_handler(int sig)
 {
-       fprintf(stderr, "lxcfs: caught a SIGUSR1.  Reloading\n");
-       users_lock();
        need_reload = 1;
-       users_unlock();
 }
 
 /* Functions to run the library methods */
@@ -127,7 +183,7 @@ static int do_cg_getattr(const char *path, struct stat *sb)
        cg_getattr = (int (*)(const char *, struct stat *)) dlsym(dlopen_handle, "cg_getattr");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_getattr: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -142,7 +198,7 @@ static int do_proc_getattr(const char *path, struct stat *sb)
        proc_getattr = (int (*)(const char *, struct stat *)) dlsym(dlopen_handle, "proc_getattr");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "proc_getattr: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -160,7 +216,7 @@ static int do_cg_read(const char *path, char *buf, size_t size, off_t offset,
        cg_read = (int (*)(const char *, char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_read");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_read: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -178,7 +234,7 @@ static int do_proc_read(const char *path, char *buf, size_t size, off_t offset,
        proc_read = (int (*)(const char *, char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_read");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "proc_read: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -195,7 +251,7 @@ static int do_cg_write(const char *path, const char *buf, size_t size, off_t off
        cg_write = (int (*)(const char *, const char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_write");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_write: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -210,7 +266,7 @@ static int do_cg_mkdir(const char *path, mode_t mode)
        cg_mkdir = (int (*)(const char *, mode_t)) dlsym(dlopen_handle, "cg_mkdir");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_mkdir: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -225,7 +281,7 @@ static int do_cg_chown(const char *path, uid_t uid, gid_t gid)
        cg_chown = (int (*)(const char *, uid_t, gid_t)) dlsym(dlopen_handle, "cg_chown");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_chown: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -240,7 +296,7 @@ static int do_cg_rmdir(const char *path)
        cg_rmdir = (int (*)(const char *path)) dlsym(dlopen_handle, "cg_rmdir");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_rmdir: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -255,7 +311,7 @@ static int do_cg_chmod(const char *path, mode_t mode)
        cg_chmod = (int (*)(const char *, mode_t)) dlsym(dlopen_handle, "cg_chmod");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_chmod: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -273,7 +329,7 @@ static int do_cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of
        cg_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_readdir");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_readdir: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -291,7 +347,7 @@ static int do_proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
        proc_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_readdir");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "proc_readdir: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -306,13 +362,28 @@ static int do_cg_open(const char *path, struct fuse_file_info *fi)
        cg_open = (int (*)(const char *, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_open");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_open: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
        return cg_open(path, fi);
 }
 
+static int do_cg_access(const char *path, int mode)
+{
+       int (*cg_access)(const char *path, int mode);
+       char *error;
+       dlerror();    /* Clear any existing error */
+       cg_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "cg_access");
+       error = dlerror();
+       if (error != NULL) {
+               lxcfs_error("%s\n", error);
+               return -1;
+       }
+
+       return cg_access(path, mode);
+}
+
 static int do_proc_open(const char *path, struct fuse_file_info *fi)
 {
        int (*proc_open)(const char *path, struct fuse_file_info *fi);
@@ -321,13 +392,28 @@ static int do_proc_open(const char *path, struct fuse_file_info *fi)
        proc_open = (int (*)(const char *path, struct fuse_file_info *fi)) dlsym(dlopen_handle, "proc_open");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "proc_open: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
        return proc_open(path, fi);
 }
 
+static int do_proc_access(const char *path, int mode)
+{
+       int (*proc_access)(const char *path, int mode);
+       char *error;
+       dlerror();    /* Clear any existing error */
+       proc_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "proc_access");
+       error = dlerror();
+       if (error != NULL) {
+               lxcfs_error("%s\n", error);
+               return -1;
+       }
+
+       return proc_access(path, mode);
+}
+
 static int do_cg_release(const char *path, struct fuse_file_info *fi)
 {
        int (*cg_release)(const char *path, struct fuse_file_info *fi);
@@ -336,7 +422,7 @@ static int do_cg_release(const char *path, struct fuse_file_info *fi)
        cg_release = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_release");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_release: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -351,7 +437,7 @@ static int do_proc_release(const char *path, struct fuse_file_info *fi)
        proc_release = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_release");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "proc_release: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -366,7 +452,7 @@ static int do_cg_opendir(const char *path, struct fuse_file_info *fi)
        cg_opendir = (int (*)(const char *path, struct fuse_file_info *fi)) dlsym(dlopen_handle, "cg_opendir");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_opendir: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -381,7 +467,7 @@ static int do_cg_releasedir(const char *path, struct fuse_file_info *fi)
        cg_releasedir = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_releasedir");
        error = dlerror();
        if (error != NULL) {
-               fprintf(stderr, "cg_releasedir: %s\n", error);
+               lxcfs_error("%s\n", error);
                return -1;
        }
 
@@ -397,11 +483,19 @@ static int do_cg_releasedir(const char *path, struct fuse_file_info *fi)
 static int lxcfs_getattr(const char *path, struct stat *sb)
 {
        int ret;
+       struct timespec now;
+
        if (strcmp(path, "/") == 0) {
+               if (clock_gettime(CLOCK_REALTIME, &now) < 0)
+                       return -EINVAL;
+               sb->st_uid = sb->st_gid = 0;
+               sb->st_atim = sb->st_mtim = sb->st_ctim = now;
+               sb->st_size = 0;
                sb->st_mode = S_IFDIR | 00755;
                sb->st_nlink = 2;
                return 0;
        }
+
        if (strncmp(path, "/cgroup", 7) == 0) {
                up_users();
                ret = do_cg_getattr(path, sb);
@@ -414,7 +508,7 @@ static int lxcfs_getattr(const char *path, struct stat *sb)
                down_users();
                return ret;
        }
-       return -EINVAL;
+       return -ENOENT;
 }
 
 static int lxcfs_opendir(const char *path, struct fuse_file_info *fi)
@@ -439,9 +533,11 @@ static int lxcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of
 {
        int ret;
        if (strcmp(path, "/") == 0) {
-               if (filler(buf, "proc", NULL, 0) != 0 ||
-                               filler(buf, "cgroup", NULL, 0) != 0)
-                       return -EINVAL;
+               if (filler(buf, ".", NULL, 0) != 0 ||
+                   filler(buf, "..", NULL, 0) != 0 ||
+                   filler(buf, "proc", NULL, 0) != 0 ||
+                   filler(buf, "cgroup", NULL, 0) != 0)
+                       return -ENOMEM;
                return 0;
        }
        if (strncmp(path, "/cgroup", 7) == 0) {
@@ -456,7 +552,30 @@ static int lxcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of
                down_users();
                return ret;
        }
-       return -EINVAL;
+       return -ENOENT;
+}
+
+static int lxcfs_access(const char *path, int mode)
+{
+       int ret;
+
+       if (strcmp(path, "/") == 0 && (mode & W_OK) == 0)
+               return 0;
+
+       if (strncmp(path, "/cgroup", 7) == 0) {
+               up_users();
+               ret = do_cg_access(path, mode);
+               down_users();
+               return ret;
+       }
+       if (strncmp(path, "/proc", 5) == 0) {
+               up_users();
+               ret = do_proc_access(path, mode);
+               down_users();
+               return ret;
+       }
+
+       return -EACCES;
 }
 
 static int lxcfs_releasedir(const char *path, struct fuse_file_info *fi)
@@ -491,7 +610,7 @@ static int lxcfs_open(const char *path, struct fuse_file_info *fi)
                return ret;
        }
 
-       return -EINVAL;
+       return -EACCES;
 }
 
 static int lxcfs_read(const char *path, char *buf, size_t size, off_t offset,
@@ -567,7 +686,7 @@ int lxcfs_mkdir(const char *path, mode_t mode)
                return ret;
        }
 
-       return -EINVAL;
+       return -EPERM;
 }
 
 int lxcfs_chown(const char *path, uid_t uid, gid_t gid)
@@ -580,7 +699,10 @@ int lxcfs_chown(const char *path, uid_t uid, gid_t gid)
                return ret;
        }
 
-       return -EINVAL;
+       if (strncmp(path, "/proc", 5) == 0)
+               return -EPERM;
+
+       return -ENOENT;
 }
 
 /*
@@ -592,7 +714,7 @@ int lxcfs_truncate(const char *path, off_t newsize)
 {
        if (strncmp(path, "/cgroup", 7) == 0)
                return 0;
-       return -EINVAL;
+       return -EPERM;
 }
 
 int lxcfs_rmdir(const char *path)
@@ -604,7 +726,7 @@ int lxcfs_rmdir(const char *path)
                down_users();
                return ret;
        }
-       return -EINVAL;
+       return -EPERM;
 }
 
 int lxcfs_chmod(const char *path, mode_t mode)
@@ -616,7 +738,11 @@ int lxcfs_chmod(const char *path, mode_t mode)
                down_users();
                return ret;
        }
-       return -EINVAL;
+
+       if (strncmp(path, "/proc", 5) == 0)
+               return -EPERM;
+
+       return -ENOENT;
 }
 
 const struct fuse_operations lxcfs_ops = {
@@ -656,19 +782,21 @@ const struct fuse_operations lxcfs_ops = {
        .fsyncdir = NULL,
        .init = NULL,
        .destroy = NULL,
-       .access = NULL,
+       .access = lxcfs_access,
        .create = NULL,
        .ftruncate = NULL,
        .fgetattr = NULL,
 };
 
-static void usage(const char *me)
+static void usage()
 {
        fprintf(stderr, "Usage:\n");
        fprintf(stderr, "\n");
-       fprintf(stderr, "%s [-p pidfile] mountpoint\n", me);
+       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, "%s -h\n", me);
+       fprintf(stderr, "lxcfs -h\n");
        exit(1);
 }
 
@@ -682,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;
 
@@ -693,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)
@@ -718,127 +847,6 @@ bool swallow_option(int *argcp, char *argv[], char *opt, char **v)
        return false;
 }
 
-static bool mkdir_p(const char *dir, mode_t mode)
-{
-       const char *tmp = dir;
-       const char *orig = dir;
-       char *makeme;
-
-       do {
-               dir = tmp + strspn(tmp, "/");
-               tmp = dir + strcspn(dir, "/");
-               makeme = strndup(orig, dir - orig);
-               if (!makeme)
-                       return false;
-               if (mkdir(makeme, mode) && errno != EEXIST) {
-                       fprintf(stderr, "failed to create directory '%s': %s",
-                               makeme, strerror(errno));
-                       free(makeme);
-                       return false;
-               }
-               free(makeme);
-       } while(tmp != dir);
-
-       return true;
-}
-
-static bool umount_if_mounted(void)
-{
-       if (umount2(basedir, MNT_DETACH) < 0 && errno != EINVAL) {
-               fprintf(stderr, "failed to umount %s: %s\n", basedir,
-                       strerror(errno));
-               return false;
-       }
-       return true;
-}
-
-static bool setup_cgfs_dir(void)
-{
-       if (!mkdir_p(basedir, 0700)) {
-               fprintf(stderr, "Failed to create lxcfs cgdir\n");
-               return false;
-       }
-       if (!umount_if_mounted()) {
-               fprintf(stderr, "Failed to clean up old lxcfs cgdir\n");
-               return false;
-       }
-       if (mount("tmpfs", basedir, "tmpfs", 0, "size=100000,mode=700") < 0) {
-               fprintf(stderr, "Failed to mount tmpfs for private controllers\n");
-               return false;
-       }
-       return true;
-}
-
-static bool do_mount_cgroup(char *controller)
-{
-       char *target;
-       size_t len;
-       int ret;
-
-       len = strlen(basedir) + strlen(controller) + 2;
-       target = alloca(len);
-       ret = snprintf(target, len, "%s/%s", basedir, controller);
-       if (ret < 0 || ret >= len)
-               return false;
-       if (mkdir(target, 0755) < 0 && errno != EEXIST)
-               return false;
-       if (mount(controller, target, "cgroup", 0, controller) < 0) {
-               fprintf(stderr, "Failed mounting cgroup %s\n", controller);
-               return false;
-       }
-       return true;
-}
-
-static bool do_mount_cgroups(void)
-{
-       bool ret;
-       FILE *f;
-       char *line = NULL;
-       size_t len = 0;
-
-       if ((f = fopen("/proc/self/cgroup", "r")) == NULL) {
-               fprintf(stderr, "Error opening /proc/self/cgroup: %s\n", strerror(errno));
-               return false;
-       }
-
-       while (getline(&line, &len, f) != -1) {
-               char *p, *p2;
-
-               p = strchr(line, ':');
-               if (!p)
-                       goto out;
-               *(p++) = '\0';
-
-               p2 = strrchr(p, ':');
-               if (!p2)
-                       goto out;
-               *p2 = '\0';
-
-               if (!do_mount_cgroup(p))
-                       goto out;
-       }
-       ret = true;
-
-out:
-       free(line);
-       fclose(f);
-       return ret;
-}
-
-static bool cgfs_setup_controllers(void)
-{
-       if (!setup_cgfs_dir()) {
-               return false;
-       }
-
-       if (!do_mount_cgroups()) {
-               fprintf(stderr, "Failed to set up cgroup mounts\n");
-               return false;
-       }
-
-       return true;
-}
-
 static int set_pidfile(char *pidfile)
 {
        int fd;
@@ -852,7 +860,7 @@ static int set_pidfile(char *pidfile)
 
        fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
        if (fd == -1) {
-               fprintf(stderr, "Could not open pidfile %s: %m", pidfile);
+               fprintf(stderr, "Could not open pidfile %s: %m\n", pidfile);
                return -1;
        }
 
@@ -883,12 +891,15 @@ static int set_pidfile(char *pidfile)
 
 int main(int argc, char *argv[])
 {
-       int ret = -1, pidfd;
-       char *pidfile = NULL, *v = NULL;
+       int ret = EXIT_FAILURE;
+       int pidfd = -1;
+       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];
@@ -896,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(1);
+               /* 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;
@@ -909,24 +932,30 @@ int main(int argc, char *argv[])
 
        if (argc == 2  && strcmp(argv[1], "--version") == 0) {
                fprintf(stderr, "%s\n", VERSION);
-               exit(0);
+               exit(EXIT_SUCCESS);
        }
        if (argc != 2 || is_help(argv[1]))
-               usage(argv[0]);
+               usage();
 
        do_reload();
-       signal(SIGUSR1, reload_handler);
+       if (signal(SIGUSR1, reload_handler) == SIG_ERR) {
+               fprintf(stderr, "Error setting USR1 signal handler: %m\n");
+               goto out;
+       }
 
        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;
 
-       if (!cgfs_setup_controllers())
-               goto out;
-
        if (!pidfile) {
                pidfile_len = strlen(RUNTIME_PATH) + strlen("/lxcfs.pid") + 1;
                pidfile = alloca(pidfile_len);
@@ -935,12 +964,20 @@ int main(int argc, char *argv[])
        if ((pidfd = set_pidfile(pidfile)) < 0)
                goto out;
 
-       ret = fuse_main(nargs, newargv, &lxcfs_ops, NULL);
+       if (load_use && start_loadavg() != 0)
+               goto out;
 
-       dlclose(dlopen_handle);
-       unlink(pidfile);
-       close(pidfd);
+       if (!fuse_main(nargs, newargv, &lxcfs_ops, NULL))
+               ret = EXIT_SUCCESS;
+       if (load_use)
+               stop_loadavg();
 
 out:
-       return ret;
+       if (dlopen_handle)
+               dlclose(dlopen_handle);
+       if (pidfile)
+               unlink(pidfile);
+       if (pidfd > 0)
+               close(pidfd);
+       exit(ret);
 }