#include <sys/epoll.h>
#include <sys/mount.h>
#include <sys/socket.h>
+#include <linux/limits.h>
#include "bindings.h"
#include "config.h" // for VERSION
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);
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;
{
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);
return false;
}
-void swallow_arg(int *argcp, char *argv[], char *which)
+bool swallow_arg(int *argcp, char *argv[], char *which)
{
int i;
argv[i] = argv[i+1];
}
(*argcp)--;
- return;
+ return true;
}
+ return false;
}
bool swallow_option(int *argcp, char *argv[], char *opt, char **v)
{
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];
/* 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;
}
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 ((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)