3 * Copyright © 2014-2016 Canonical, Inc
4 * Author: Serge Hallyn <serge.hallyn@ubuntu.com>
6 * See COPYING file for details.
13 #ifndef FUSE_USE_VERSION
14 #define FUSE_USE_VERSION 26
17 #define _FILE_OFFSET_BITS 64
35 #include <linux/sched.h>
36 #include <sys/epoll.h>
37 #include <sys/mount.h>
38 #include <sys/socket.h>
39 #include <linux/limits.h>
44 #include "memory_utils.h"
48 /* Functions to keep track of number of threads using the library */
50 static int users_count
;
51 static pthread_mutex_t user_count_mutex
= PTHREAD_MUTEX_INITIALIZER
;
52 static void lock_mutex(pthread_mutex_t
*l
)
56 ret
= pthread_mutex_lock(l
);
58 log_exit("%s - returned: %d\n", strerror(ret
), ret
);
61 static void unlock_mutex(pthread_mutex_t
*l
)
65 ret
= pthread_mutex_unlock(l
);
67 log_exit("%s - returned: %d\n", strerror(ret
), ret
);
70 static inline void users_lock(void)
72 lock_mutex(&user_count_mutex
);
75 static inline void users_unlock(void)
77 unlock_mutex(&user_count_mutex
);
80 static pthread_t loadavg_pid
= 0;
82 /* Returns zero on success */
83 static int start_loadavg(void)
86 pthread_t (*__load_daemon
)(int);
89 __load_daemon
= (pthread_t(*)(int))dlsym(dlopen_handle
, "load_daemon");
92 return log_error(-1, "%s - Failed to start loadavg daemon", error
);
94 loadavg_pid
= __load_daemon(1);
101 /* Returns zero on success */
102 static int stop_loadavg(void)
105 int (*__stop_load_daemon
)(pthread_t
);
107 __stop_load_daemon
= (int (*)(pthread_t
))dlsym(dlopen_handle
, "stop_load_daemon");
110 return log_error(-1, "%s - Failed to stop loadavg daemon", error
);
112 if (__stop_load_daemon(loadavg_pid
))
118 static volatile sig_atomic_t need_reload
;
120 /* do_reload - reload the dynamic library. Done under
121 * lock and when we know the user_count was 0 */
122 static void do_reload(void)
125 char lxcfs_lib_path
[PATH_MAX
];
131 lxcfs_info("Closed liblxcfs.so");
132 dlclose(dlopen_handle
);
135 /* First try loading using ld.so */
136 dlopen_handle
= dlopen("liblxcfs.so", RTLD_LAZY
);
138 lxcfs_debug("Opened liblxcfs.so");
143 /* LIBDIR: autoconf will setup this MACRO. Default value is $PREFIX/lib */
144 ret
= snprintf(lxcfs_lib_path
, sizeof(lxcfs_lib_path
), "%s/lxcfs/liblxcfs.so", LIBDIR
);
146 ret
= snprintf(lxcfs_lib_path
, sizeof(lxcfs_lib_path
), "/usr/local/lib/lxcfs/liblxcfs.so");
148 if (ret
< 0 || ret
>= sizeof(lxcfs_lib_path
))
149 log_exit("Failed to create path to open liblxcfs");
151 dlopen_handle
= dlopen(lxcfs_lib_path
, RTLD_LAZY
);
153 log_exit("%s - Failed to open liblxcfs.so", dlerror());
155 lxcfs_debug("Opened %s", lxcfs_lib_path
);
162 lxcfs_info("Reloaded LXCFS");
166 static void up_users(void)
169 if (users_count
== 0 && need_reload
)
175 static void down_users(void)
182 static void reload_handler(int sig
)
187 /* Functions to run the library methods */
188 static int do_cg_getattr(const char *path
, struct stat
*sb
)
191 int (*__cg_getattr
)(const char *path
, struct stat
*sb
);
194 __cg_getattr
= (int (*)(const char *, struct stat
*))dlsym(dlopen_handle
, "cg_getattr");
197 return log_error(-1, "%s - Failed to find cg_getattr()", error
);
199 return __cg_getattr(path
, sb
);
202 static int do_proc_getattr(const char *path
, struct stat
*sb
)
205 int (*__proc_getattr
)(const char *path
, struct stat
*sb
);
208 __proc_getattr
= (int (*)(const char *, struct stat
*)) dlsym(dlopen_handle
, "proc_getattr");
211 return log_error(-1, "%s - Failed to find proc_getattr()", error
);
213 return __proc_getattr(path
, sb
);
216 static int do_sys_getattr(const char *path
, struct stat
*sb
)
219 int (*__sys_getattr
)(const char *path
, struct stat
*sb
);
222 __sys_getattr
= (int (*)(const char *, struct stat
*)) dlsym(dlopen_handle
, "sys_getattr");
225 return log_error(-1, "%s - Failed to find sys_getattr()", error
);
227 return __sys_getattr(path
, sb
);
230 static int do_cg_read(const char *path
, char *buf
, size_t size
, off_t offset
,
231 struct fuse_file_info
*fi
)
234 int (*__cg_read
)(const char *path
, char *buf
, size_t size
, off_t offset
,
235 struct fuse_file_info
*fi
);
238 __cg_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_read");
241 return log_error(-1, "%s - Failed to find cg_read()", error
);
243 return __cg_read(path
, buf
, size
, offset
, fi
);
246 static int do_proc_read(const char *path
, char *buf
, size_t size
, off_t offset
,
247 struct fuse_file_info
*fi
)
250 int (*__proc_read
)(const char *path
, char *buf
, size_t size
,
251 off_t offset
, struct fuse_file_info
*fi
);
254 __proc_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "proc_read");
257 return log_error(-1, "%s - Failed to find proc_read()", error
);
259 return __proc_read(path
, buf
, size
, offset
, fi
);
262 static int do_sys_read(const char *path
, char *buf
, size_t size
, off_t offset
,
263 struct fuse_file_info
*fi
)
266 int (*__sys_read
)(const char *path
, char *buf
, size_t size
,
267 off_t offset
, struct fuse_file_info
*fi
);
270 __sys_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "sys_read");
273 return log_error(-1, "%s - Failed to find sys_read()", error
);
275 return __sys_read(path
, buf
, size
, offset
, fi
);
278 static int do_cg_write(const char *path
, const char *buf
, size_t size
,
279 off_t offset
, struct fuse_file_info
*fi
)
282 int (*__cg_write
)(const char *path
, const char *buf
, size_t size
,
283 off_t offset
, struct fuse_file_info
*fi
);
286 __cg_write
= (int (*)(const char *, const char *, size_t, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_write");
289 return log_error(-1, "%s - Failed to find cg_write()", error
);
291 return __cg_write(path
, buf
, size
, offset
, fi
);
294 static int do_cg_mkdir(const char *path
, mode_t mode
)
297 int (*__cg_mkdir
)(const char *path
, mode_t mode
);
300 __cg_mkdir
= (int (*)(const char *, mode_t
))dlsym(dlopen_handle
, "cg_mkdir");
303 return log_error(-1, "%s - Failed to find cg_mkdir()", error
);
305 return __cg_mkdir(path
, mode
);
308 static int do_cg_chown(const char *path
, uid_t uid
, gid_t gid
)
311 int (*__cg_chown
)(const char *path
, uid_t uid
, gid_t gid
);
314 __cg_chown
= (int (*)(const char *, uid_t
, gid_t
))dlsym(dlopen_handle
, "cg_chown");
317 return log_error(-1, "%s - Failed to find cg_chown()", error
);
319 return __cg_chown(path
, uid
, gid
);
322 static int do_cg_rmdir(const char *path
)
325 int (*__cg_rmdir
)(const char *path
);
328 __cg_rmdir
= (int (*)(const char *path
))dlsym(dlopen_handle
, "cg_rmdir");
331 return log_error(-1, "%s - Failed to find cg_rmdir()", error
);
333 return __cg_rmdir(path
);
336 static int do_cg_chmod(const char *path
, mode_t mode
)
339 int (*__cg_chmod
)(const char *path
, mode_t mode
);
342 __cg_chmod
= (int (*)(const char *, mode_t
))dlsym(dlopen_handle
, "cg_chmod");
345 return log_error(-1, "%s - Failed to find cg_chmod()", error
);
347 return __cg_chmod(path
, mode
);
350 static int do_cg_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
351 off_t offset
, struct fuse_file_info
*fi
)
354 int (*__cg_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
,
355 off_t offset
, struct fuse_file_info
*fi
);
358 __cg_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_readdir");
361 return log_error(-1, "%s - Failed to find cg_readdir()", error
);
363 return __cg_readdir(path
, buf
, filler
, offset
, fi
);
366 static int do_proc_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
367 off_t offset
, struct fuse_file_info
*fi
)
370 int (*__proc_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
,
371 off_t offset
, struct fuse_file_info
*fi
);
374 __proc_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "proc_readdir");
377 return log_error(-1, "%s - Failed to find proc_readdir()", error
);
379 return __proc_readdir(path
, buf
, filler
, offset
, fi
);
382 static int do_sys_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
383 off_t offset
, struct fuse_file_info
*fi
)
386 int (*__sys_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
,
387 off_t offset
, struct fuse_file_info
*fi
);
390 __sys_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "sys_readdir");
393 return log_error(-1, "%s - Failed to find sys_readdir()", error
);
395 return __sys_readdir(path
, buf
, filler
, offset
, fi
);
399 static int do_cg_open(const char *path
, struct fuse_file_info
*fi
)
402 int (*__cg_open
)(const char *path
, struct fuse_file_info
*fi
);
405 __cg_open
= (int (*)(const char *, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_open");
408 return log_error(-1, "%s - Failed to find cg_open()", error
);
410 return __cg_open(path
, fi
);
413 static int do_cg_access(const char *path
, int mode
)
416 int (*__cg_access
)(const char *path
, int mode
);
419 __cg_access
= (int (*)(const char *, int mode
))dlsym(dlopen_handle
, "cg_access");
422 return log_error(-1, "%s - Failed to find cg_access()", error
);
424 return __cg_access(path
, mode
);
427 static int do_proc_open(const char *path
, struct fuse_file_info
*fi
)
430 int (*__proc_open
)(const char *path
, struct fuse_file_info
*fi
);
433 __proc_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
))dlsym(dlopen_handle
, "proc_open");
436 return log_error(-1, "%s - Failed to find proc_open()", error
);
438 return __proc_open(path
, fi
);
441 static int do_proc_access(const char *path
, int mode
)
444 int (*__proc_access
)(const char *path
, int mode
);
447 __proc_access
= (int (*)(const char *, int mode
))dlsym(dlopen_handle
, "proc_access");
450 return log_error(-1, "%s - Failed to find proc_access()", error
);
452 return __proc_access(path
, mode
);
455 static int do_sys_open(const char *path
, struct fuse_file_info
*fi
)
458 int (*__sys_open
)(const char *path
, struct fuse_file_info
*fi
);
461 __sys_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
))dlsym(dlopen_handle
, "sys_open");
464 return log_error(-1, "%s - Failed to find sys_open()", error
);
466 return __sys_open(path
, fi
);
469 static int do_sys_access(const char *path
, int mode
)
472 int (*__sys_access
)(const char *path
, int mode
);
475 __sys_access
= (int (*)(const char *, int mode
))dlsym(dlopen_handle
, "sys_access");
478 return log_error(-1, "%s - Failed to find sys_access()", error
);
480 return __sys_access(path
, mode
);
483 static int do_cg_release(const char *path
, struct fuse_file_info
*fi
)
486 int (*__cg_release
)(const char *path
, struct fuse_file_info
*fi
);
489 __cg_release
= (int (*)(const char *path
, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_release");
492 return log_error(-1, "%s - Failed to find cg_release()", error
);
494 return __cg_release(path
, fi
);
497 static int do_proc_release(const char *path
, struct fuse_file_info
*fi
)
500 int (*__proc_release
)(const char *path
, struct fuse_file_info
*fi
);
503 __proc_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_release");
506 return log_error(-1, "%s - Failed to find proc_release()", error
);
508 return __proc_release(path
, fi
);
511 static int do_sys_release(const char *path
, struct fuse_file_info
*fi
)
514 int (*__sys_release
)(const char *path
, struct fuse_file_info
*fi
);
517 __sys_release
= (int (*)(const char *path
, struct fuse_file_info
*))dlsym(dlopen_handle
, "sys_release");
520 return log_error(-1, "%s - Failed to find sys_release()", error
);
522 return __sys_release(path
, fi
);
525 static int do_cg_opendir(const char *path
, struct fuse_file_info
*fi
)
528 int (*__cg_opendir
)(const char *path
, struct fuse_file_info
*fi
);
531 __cg_opendir
= (int (*)(const char *path
, struct fuse_file_info
*fi
))dlsym(dlopen_handle
, "cg_opendir");
534 return log_error(-1, "%s - Failed to find cg_opendir()", error
);
536 return __cg_opendir(path
, fi
);
539 static int do_cg_releasedir(const char *path
, struct fuse_file_info
*fi
)
542 int (*__cg_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
545 __cg_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_releasedir");
548 return log_error(-1, "%s - Failed to find cg_releasedir()", error
);
550 return __cg_releasedir(path
, fi
);
553 static int do_sys_releasedir(const char *path
, struct fuse_file_info
*fi
)
556 int (*__sys_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
559 __sys_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*))dlsym(dlopen_handle
, "sys_releasedir");
562 return log_error(-1, "%s - Failed to find sys_releasedir()", error
);
564 return __sys_releasedir(path
, fi
);
567 static int lxcfs_getattr(const char *path
, struct stat
*sb
)
572 if (strcmp(path
, "/") == 0) {
573 if (clock_gettime(CLOCK_REALTIME
, &now
) < 0)
575 sb
->st_uid
= sb
->st_gid
= 0;
576 sb
->st_atim
= sb
->st_mtim
= sb
->st_ctim
= now
;
578 sb
->st_mode
= S_IFDIR
| 00755;
583 if (strncmp(path
, "/cgroup", 7) == 0) {
585 ret
= do_cg_getattr(path
, sb
);
590 if (strncmp(path
, "/proc", 5) == 0) {
592 ret
= do_proc_getattr(path
, sb
);
597 if (strncmp(path
, "/sys", 4) == 0) {
599 ret
= do_sys_getattr(path
, sb
);
607 static int lxcfs_opendir(const char *path
, struct fuse_file_info
*fi
)
611 if (strcmp(path
, "/") == 0)
614 if (strncmp(path
, "/cgroup", 7) == 0) {
616 ret
= do_cg_opendir(path
, fi
);
621 if (strcmp(path
, "/proc") == 0)
624 if (strncmp(path
, "/sys", 4) == 0)
630 static int lxcfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
631 off_t offset
, struct fuse_file_info
*fi
)
635 if (strcmp(path
, "/") == 0) {
636 if (filler(buf
, ".", NULL
, 0) != 0 ||
637 filler(buf
, "..", NULL
, 0) != 0 ||
638 filler(buf
, "proc", NULL
, 0) != 0 ||
639 filler(buf
, "sys", NULL
, 0) != 0 ||
640 filler(buf
, "cgroup", NULL
, 0) != 0)
646 if (strncmp(path
, "/cgroup", 7) == 0) {
648 ret
= do_cg_readdir(path
, buf
, filler
, offset
, fi
);
653 if (strcmp(path
, "/proc") == 0) {
655 ret
= do_proc_readdir(path
, buf
, filler
, offset
, fi
);
660 if (strncmp(path
, "/sys", 4) == 0) {
662 ret
= do_sys_readdir(path
, buf
, filler
, offset
, fi
);
670 static int lxcfs_access(const char *path
, int mode
)
674 if (strcmp(path
, "/") == 0 && (mode
& W_OK
) == 0)
677 if (strncmp(path
, "/cgroup", 7) == 0) {
679 ret
= do_cg_access(path
, mode
);
684 if (strncmp(path
, "/proc", 5) == 0) {
686 ret
= do_proc_access(path
, mode
);
691 if (strncmp(path
, "/sys", 4) == 0) {
693 ret
= do_sys_access(path
, mode
);
701 static int lxcfs_releasedir(const char *path
, struct fuse_file_info
*fi
)
705 if (strcmp(path
, "/") == 0)
708 if (strncmp(path
, "/cgroup", 7) == 0) {
710 ret
= do_cg_releasedir(path
, fi
);
715 if (strcmp(path
, "/proc") == 0)
718 if (strncmp(path
, "/sys", 4) == 0) {
720 ret
= do_sys_releasedir(path
, fi
);
728 static int lxcfs_open(const char *path
, struct fuse_file_info
*fi
)
732 if (strncmp(path
, "/cgroup", 7) == 0) {
734 ret
= do_cg_open(path
, fi
);
739 if (strncmp(path
, "/proc", 5) == 0) {
741 ret
= do_proc_open(path
, fi
);
746 if (strncmp(path
, "/sys", 4) == 0) {
748 ret
= do_sys_open(path
, fi
);
756 static int lxcfs_read(const char *path
, char *buf
, size_t size
, off_t offset
,
757 struct fuse_file_info
*fi
)
761 if (strncmp(path
, "/cgroup", 7) == 0) {
763 ret
= do_cg_read(path
, buf
, size
, offset
, fi
);
768 if (strncmp(path
, "/proc", 5) == 0) {
770 ret
= do_proc_read(path
, buf
, size
, offset
, fi
);
775 if (strncmp(path
, "/sys", 4) == 0) {
777 ret
= do_sys_read(path
, buf
, size
, offset
, fi
);
785 int lxcfs_write(const char *path
, const char *buf
, size_t size
, off_t offset
,
786 struct fuse_file_info
*fi
)
790 if (strncmp(path
, "/cgroup", 7) == 0) {
792 ret
= do_cg_write(path
, buf
, size
, offset
, fi
);
800 static int lxcfs_flush(const char *path
, struct fuse_file_info
*fi
)
805 static int lxcfs_release(const char *path
, struct fuse_file_info
*fi
)
809 if (strncmp(path
, "/cgroup", 7) == 0) {
811 ret
= do_cg_release(path
, fi
);
816 if (strncmp(path
, "/proc", 5) == 0) {
818 ret
= do_proc_release(path
, fi
);
823 if (strncmp(path
, "/sys", 4) == 0) {
825 ret
= do_sys_release(path
, fi
);
833 static int lxcfs_fsync(const char *path
, int datasync
, struct fuse_file_info
*fi
)
838 int lxcfs_mkdir(const char *path
, mode_t mode
)
842 if (strncmp(path
, "/cgroup", 7) == 0) {
844 ret
= do_cg_mkdir(path
, mode
);
852 int lxcfs_chown(const char *path
, uid_t uid
, gid_t gid
)
856 if (strncmp(path
, "/cgroup", 7) == 0) {
858 ret
= do_cg_chown(path
, uid
, gid
);
863 if (strncmp(path
, "/proc", 5) == 0)
866 if (strncmp(path
, "/sys", 4) == 0)
873 * cat first does a truncate before doing ops->write. This doesn't
874 * really make sense for cgroups. So just return 0 always but do
877 int lxcfs_truncate(const char *path
, off_t newsize
)
879 if (strncmp(path
, "/cgroup", 7) == 0)
885 int lxcfs_rmdir(const char *path
)
889 if (strncmp(path
, "/cgroup", 7) == 0) {
891 ret
= do_cg_rmdir(path
);
899 int lxcfs_chmod(const char *path
, mode_t mode
)
903 if (strncmp(path
, "/cgroup", 7) == 0) {
905 ret
= do_cg_chmod(path
, mode
);
910 if (strncmp(path
, "/proc", 5) == 0)
913 if (strncmp(path
, "/sys", 4) == 0)
919 const struct fuse_operations lxcfs_ops
= {
920 .access
= lxcfs_access
,
921 .chmod
= lxcfs_chmod
,
922 .chown
= lxcfs_chown
,
923 .flush
= lxcfs_flush
,
924 .fsync
= lxcfs_fsync
,
925 .getattr
= lxcfs_getattr
,
926 .mkdir
= lxcfs_mkdir
,
928 .opendir
= lxcfs_opendir
,
930 .readdir
= lxcfs_readdir
,
931 .release
= lxcfs_release
,
932 .releasedir
= lxcfs_releasedir
,
933 .rmdir
= lxcfs_rmdir
,
934 .truncate
= lxcfs_truncate
,
935 .write
= lxcfs_write
,
960 lxcfs_info("Usage: lxcfs <directory>\n");
961 lxcfs_info("lxcfs set up fuse- and cgroup-based virtualizing filesystem\n");
962 lxcfs_info("Options :");
963 lxcfs_info("-d, --debug Run lxcfs with debugging enabled");
964 lxcfs_info("--disable-cfs Disable cpu virtualization via cpu shares");
965 lxcfs_info("-f, --foreground Run lxcfs in the foreground");
966 lxcfs_info("-n, --help Print help");
967 lxcfs_info("-l, --enable-loadavg Enable loadavg virtualization");
968 lxcfs_info("-o Options to pass directly through fuse");
969 lxcfs_info("-p, --pidfile=FILE Path to use for storing lxcfs pid");
970 lxcfs_info(" Default pidfile is %s/lxcfs.pid", RUNTIME_PATH
);
971 lxcfs_info("-u, --disable-swap Disable swap virtualization");
972 lxcfs_info("-v, --version Print lxcfs version");
973 lxcfs_info("--enable-pidfd Use pidfd for process tracking");
977 static inline bool is_help(char *w
)
979 return strcmp(w
, "-h") == 0 ||
980 strcmp(w
, "--help") == 0 ||
981 strcmp(w
, "-help") == 0 ||
982 strcmp(w
, "help") == 0;
985 static inline bool is_version(char *w
)
987 return strcmp(w
, "-v") == 0 ||
988 strcmp(w
, "--version") == 0 ||
989 strcmp(w
, "-version") == 0 ||
990 strcmp(w
, "version") == 0;
993 static bool swallow_arg(int *argcp
, char *argv
[], char *which
)
995 for (int i
= 1; argv
[i
]; i
++) {
996 if (strcmp(argv
[i
], which
) != 0)
1000 argv
[i
] = argv
[i
+ 1];
1009 static bool swallow_option(int *argcp
, char *argv
[], char *opt
, char **v
)
1011 for (int i
= 1; argv
[i
]; i
++) {
1015 if (strcmp(argv
[i
], opt
) != 0)
1019 *v
= strdup(argv
[i
+ 1]);
1022 for (; argv
[i
+ 1]; i
++)
1023 argv
[i
] = argv
[i
+ 2];
1032 static int set_pidfile(char *pidfile
)
1034 __do_close_prot_errno
int fd
= -EBADF
;
1035 char buf
[INTTYPE_TO_STRLEN(long)];
1038 fl
.l_type
= F_WRLCK
,
1039 fl
.l_whence
= SEEK_SET
,
1044 fd
= open(pidfile
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
1046 return log_error(-1, "Could not open pidfile %s: %m", pidfile
);
1048 if (fcntl(fd
, F_SETLK
, &fl
) < 0) {
1049 if (errno
== EAGAIN
|| errno
== EACCES
)
1050 return log_error(-1, "PID file '%s' is already locked", pidfile
);
1051 lxcfs_error("Warning; unable to lock PID file, proceeding");
1054 if (ftruncate(fd
, 0))
1055 return log_error(-1, "Error truncating PID file '%s': %m", pidfile
);
1057 ret
= snprintf(buf
, sizeof(buf
), "%ld\n", (long)getpid());
1058 if (ret
< 0 || ret
>= sizeof(buf
))
1059 return log_error(-1, "Failed to convert pid to string %m");
1061 if (write(fd
, buf
, ret
) != ret
)
1062 return log_error(-1, "Error writing to PID file '%s': %m", pidfile
);
1067 int main(int argc
, char *argv
[])
1069 __do_close_prot_errno
int pidfile_fd
= -EBADF
;
1070 int ret
= EXIT_FAILURE
;
1071 char *pidfile
= NULL
, *saveptr
= NULL
, *token
= NULL
, *v
= NULL
;
1072 char pidfile_buf
[STRLITERALLEN(RUNTIME_PATH
) + STRLITERALLEN("/lxcfs.pid") + 1] = {};
1073 bool debug
= false, foreground
= false, nonempty
= false;
1074 bool load_use
= false;
1076 * what we pass to fuse_main is:
1077 * argv[0] -s [-f|-d] -o allow_other,directio argv[1] NULL
1079 int nargs
= 5, cnt
= 0;
1081 struct lxcfs_opts
*opts
;
1083 opts
= malloc(sizeof(struct lxcfs_opts
));
1085 lxcfs_error("Error allocating memory for options");
1088 opts
->swap_off
= false;
1089 opts
->use_pidfd
= false;
1090 opts
->use_cfs
= true;
1092 /* accomodate older init scripts */
1093 swallow_arg(&argc
, argv
, "-s");
1095 /* -f / --foreground */
1096 foreground
= swallow_arg(&argc
, argv
, "-f");
1097 if (swallow_arg(&argc
, argv
, "--foreground"))
1101 debug
= swallow_arg(&argc
, argv
, "-d");
1102 if (swallow_arg(&argc
, argv
, "--debug"))
1105 if (foreground
&& debug
)
1106 log_exit("Both --debug and --forgreound specified");
1108 /* -l / --enable-loadavg */
1109 load_use
= swallow_arg(&argc
, argv
, "-l");
1110 if (swallow_arg(&argc
, argv
, "--enable-loadavg"))
1113 /* -u / --disable-swap */
1114 opts
->swap_off
= swallow_arg(&argc
, argv
, "-u");
1115 if (swallow_arg(&argc
, argv
, "--disable-swap"))
1116 opts
->swap_off
= true;
1118 /* --enable-pidfd */
1119 opts
->use_pidfd
= swallow_arg(&argc
, argv
, "--enable-pidfd");
1122 if (swallow_arg(&argc
, argv
, "--disable-cfs"))
1123 opts
->use_cfs
= false;
1125 if (swallow_option(&argc
, argv
, "-o", &v
)) {
1126 /* Parse multiple values */
1127 for (; (token
= strtok_r(v
, ",", &saveptr
)); v
= NULL
) {
1128 if (strcmp(token
, "allow_other") == 0) {
1129 /* Noop. this is the default. Always enabled. */
1130 } else if (strcmp(token
, "nonempty") == 0) {
1134 lxcfs_error("Warning: unexpected fuse option %s", v
);
1142 /* -p / --pidfile */
1143 if (swallow_option(&argc
, argv
, "-p", &v
))
1145 if (!pidfile
&& swallow_option(&argc
, argv
, "--pidfile", &v
))
1148 if (argc
== 2 && is_version(argv
[1])) {
1149 lxcfs_info("%s", VERSION
);
1153 if (argc
!= 2 || is_help(argv
[1]))
1157 if (signal(SIGUSR1
, reload_handler
) == SIG_ERR
) {
1158 lxcfs_error("Error setting USR1 signal handler: %m");
1162 newargv
[cnt
++] = argv
[0];
1164 newargv
[cnt
++] = "-d";
1166 newargv
[cnt
++] = "-f";
1167 newargv
[cnt
++] = "-o";
1169 newargv
[cnt
++] = "default_permissions,allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5,nonempty";
1171 newargv
[cnt
++] = "default_permissions,allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5";
1172 newargv
[cnt
++] = argv
[1];
1173 newargv
[cnt
++] = NULL
;
1176 snprintf(pidfile_buf
, sizeof(pidfile_buf
), "%s/lxcfs.pid", RUNTIME_PATH
);
1177 pidfile
= pidfile_buf
;
1180 pidfile_fd
= set_pidfile(pidfile
);
1184 if (load_use
&& start_loadavg() != 0)
1187 if (!fuse_main(nargs
, newargv
, &lxcfs_ops
, opts
))
1194 dlclose(dlopen_handle
);