1 /* SPDX-License-Identifier: LGPL-2.1+ */
25 #include <linux/sched.h>
26 #include <sys/epoll.h>
27 #include <sys/mount.h>
28 #include <sys/socket.h>
29 #include <linux/limits.h>
32 #include <fuse3/fuse.h>
38 #include "lxcfs_fuse_compat.h"
40 #include "memory_utils.h"
44 /* Functions to keep track of number of threads using the library */
46 static int users_count
;
47 static pthread_mutex_t user_count_mutex
= PTHREAD_MUTEX_INITIALIZER
;
48 static void lock_mutex(pthread_mutex_t
*l
)
52 ret
= pthread_mutex_lock(l
);
54 log_exit("%s - returned: %d\n", strerror(ret
), ret
);
57 static void unlock_mutex(pthread_mutex_t
*l
)
61 ret
= pthread_mutex_unlock(l
);
63 log_exit("%s - returned: %d\n", strerror(ret
), ret
);
66 static inline void users_lock(void)
68 lock_mutex(&user_count_mutex
);
71 static inline void users_unlock(void)
73 unlock_mutex(&user_count_mutex
);
76 static pthread_t loadavg_pid
= 0;
78 /* Returns zero on success */
79 static int start_loadavg(void)
82 pthread_t (*__load_daemon
)(int);
85 __load_daemon
= (pthread_t(*)(int))dlsym(dlopen_handle
, "load_daemon");
88 return log_error(-1, "%s - Failed to start loadavg daemon", error
);
90 loadavg_pid
= __load_daemon(1);
97 /* Returns zero on success */
98 static int stop_loadavg(void)
101 int (*__stop_load_daemon
)(pthread_t
);
103 __stop_load_daemon
= (int (*)(pthread_t
))dlsym(dlopen_handle
, "stop_load_daemon");
106 return log_error(-1, "%s - Failed to stop loadavg daemon", error
);
108 if (__stop_load_daemon(loadavg_pid
))
114 static volatile sig_atomic_t need_reload
;
116 /* do_reload - reload the dynamic library. Done under
117 * lock and when we know the user_count was 0 */
118 static void do_reload(void)
121 char lxcfs_lib_path
[PATH_MAX
];
127 lxcfs_info("Closed liblxcfs.so");
128 dlclose(dlopen_handle
);
131 /* First try loading using ld.so */
133 dlopen_handle
= dlopen("liblxcfs.so", RTLD_NOW
);
135 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 sigusr1_reload(int signo
, siginfo_t
*info
, void *extra
)
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_sys_write(const char *path
, const char *buf
, size_t size
,
295 off_t offset
, struct fuse_file_info
*fi
)
298 int (*__sys_write
)(const char *path
, const char *buf
, size_t size
,
299 off_t offset
, struct fuse_file_info
*fi
);
302 __sys_write
= (int (*)(const char *, const char *, size_t, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "sys_write");
305 return log_error(-1, "%s - Failed to find sys_write()", error
);
307 return __sys_write(path
, buf
, size
, offset
, fi
);
310 static int do_cg_mkdir(const char *path
, mode_t mode
)
313 int (*__cg_mkdir
)(const char *path
, mode_t mode
);
316 __cg_mkdir
= (int (*)(const char *, mode_t
))dlsym(dlopen_handle
, "cg_mkdir");
319 return log_error(-1, "%s - Failed to find cg_mkdir()", error
);
321 return __cg_mkdir(path
, mode
);
324 static int do_cg_chown(const char *path
, uid_t uid
, gid_t gid
)
327 int (*__cg_chown
)(const char *path
, uid_t uid
, gid_t gid
);
330 __cg_chown
= (int (*)(const char *, uid_t
, gid_t
))dlsym(dlopen_handle
, "cg_chown");
333 return log_error(-1, "%s - Failed to find cg_chown()", error
);
335 return __cg_chown(path
, uid
, gid
);
338 static int do_cg_rmdir(const char *path
)
341 int (*__cg_rmdir
)(const char *path
);
344 __cg_rmdir
= (int (*)(const char *path
))dlsym(dlopen_handle
, "cg_rmdir");
347 return log_error(-1, "%s - Failed to find cg_rmdir()", error
);
349 return __cg_rmdir(path
);
352 static int do_cg_chmod(const char *path
, mode_t mode
)
355 int (*__cg_chmod
)(const char *path
, mode_t mode
);
358 __cg_chmod
= (int (*)(const char *, mode_t
))dlsym(dlopen_handle
, "cg_chmod");
361 return log_error(-1, "%s - Failed to find cg_chmod()", error
);
363 return __cg_chmod(path
, mode
);
366 static int do_cg_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
367 off_t offset
, struct fuse_file_info
*fi
)
370 int (*__cg_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
,
371 off_t offset
, struct fuse_file_info
*fi
);
374 __cg_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_readdir");
377 return log_error(-1, "%s - Failed to find cg_readdir()", error
);
379 return __cg_readdir(path
, buf
, filler
, offset
, fi
);
382 static int do_proc_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
383 off_t offset
, struct fuse_file_info
*fi
)
386 int (*__proc_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
,
387 off_t offset
, struct fuse_file_info
*fi
);
390 __proc_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "proc_readdir");
393 return log_error(-1, "%s - Failed to find proc_readdir()", error
);
395 return __proc_readdir(path
, buf
, filler
, offset
, fi
);
398 static int do_sys_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
399 off_t offset
, struct fuse_file_info
*fi
)
402 int (*__sys_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
,
403 off_t offset
, struct fuse_file_info
*fi
);
406 __sys_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*))dlsym(dlopen_handle
, "sys_readdir");
409 return log_error(-1, "%s - Failed to find sys_readdir()", error
);
411 return __sys_readdir(path
, buf
, filler
, offset
, fi
);
414 static int do_sys_readlink(const char *path
, char *buf
, size_t size
)
417 int (*__sys_readlink
)(const char *path
, char *buf
, size_t size
);
420 __sys_readlink
= (int (*)(const char *, char *, size_t))dlsym(dlopen_handle
, "sys_readlink");
423 return log_error(-1, "%s - Failed to find sys_readlink()", error
);
425 return __sys_readlink(path
, buf
, size
);
428 static int do_cg_open(const char *path
, struct fuse_file_info
*fi
)
431 int (*__cg_open
)(const char *path
, struct fuse_file_info
*fi
);
434 __cg_open
= (int (*)(const char *, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_open");
437 return log_error(-1, "%s - Failed to find cg_open()", error
);
439 return __cg_open(path
, fi
);
442 static int do_cg_access(const char *path
, int mode
)
445 int (*__cg_access
)(const char *path
, int mode
);
448 __cg_access
= (int (*)(const char *, int mode
))dlsym(dlopen_handle
, "cg_access");
451 return log_error(-1, "%s - Failed to find cg_access()", error
);
453 return __cg_access(path
, mode
);
456 static int do_proc_open(const char *path
, struct fuse_file_info
*fi
)
459 int (*__proc_open
)(const char *path
, struct fuse_file_info
*fi
);
462 __proc_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
))dlsym(dlopen_handle
, "proc_open");
465 return log_error(-1, "%s - Failed to find proc_open()", error
);
467 return __proc_open(path
, fi
);
470 static int do_proc_access(const char *path
, int mode
)
473 int (*__proc_access
)(const char *path
, int mode
);
476 __proc_access
= (int (*)(const char *, int mode
))dlsym(dlopen_handle
, "proc_access");
479 return log_error(-1, "%s - Failed to find proc_access()", error
);
481 return __proc_access(path
, mode
);
484 static int do_sys_open(const char *path
, struct fuse_file_info
*fi
)
487 int (*__sys_open
)(const char *path
, struct fuse_file_info
*fi
);
490 __sys_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
))dlsym(dlopen_handle
, "sys_open");
493 return log_error(-1, "%s - Failed to find sys_open()", error
);
495 return __sys_open(path
, fi
);
498 static int do_sys_opendir(const char *path
, struct fuse_file_info
*fi
)
501 int (*__sys_opendir
)(const char *path
, struct fuse_file_info
*fi
);
504 __sys_opendir
= (int (*)(const char *path
, struct fuse_file_info
*fi
))dlsym(dlopen_handle
, "sys_opendir");
507 return log_error(-1, "%s - Failed to find sys_opendir()", error
);
509 return __sys_opendir(path
, fi
);
512 static int do_sys_access(const char *path
, int mode
)
515 int (*__sys_access
)(const char *path
, int mode
);
518 __sys_access
= (int (*)(const char *, int mode
))dlsym(dlopen_handle
, "sys_access");
521 return log_error(-1, "%s - Failed to find sys_access()", error
);
523 return __sys_access(path
, mode
);
526 static int do_cg_release(const char *path
, struct fuse_file_info
*fi
)
529 int (*__cg_release
)(const char *path
, struct fuse_file_info
*fi
);
532 __cg_release
= (int (*)(const char *path
, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_release");
535 return log_error(-1, "%s - Failed to find cg_release()", error
);
537 return __cg_release(path
, fi
);
540 static int do_proc_release(const char *path
, struct fuse_file_info
*fi
)
543 int (*__proc_release
)(const char *path
, struct fuse_file_info
*fi
);
546 __proc_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_release");
549 return log_error(-1, "%s - Failed to find proc_release()", error
);
551 return __proc_release(path
, fi
);
554 static int do_sys_release(const char *path
, struct fuse_file_info
*fi
)
557 int (*__sys_release
)(const char *path
, struct fuse_file_info
*fi
);
560 __sys_release
= (int (*)(const char *path
, struct fuse_file_info
*))dlsym(dlopen_handle
, "sys_release");
563 return log_error(-1, "%s - Failed to find sys_release()", error
);
565 return __sys_release(path
, fi
);
568 static int do_cg_opendir(const char *path
, struct fuse_file_info
*fi
)
571 int (*__cg_opendir
)(const char *path
, struct fuse_file_info
*fi
);
574 __cg_opendir
= (int (*)(const char *path
, struct fuse_file_info
*fi
))dlsym(dlopen_handle
, "cg_opendir");
577 return log_error(-1, "%s - Failed to find cg_opendir()", error
);
579 return __cg_opendir(path
, fi
);
582 static int do_cg_releasedir(const char *path
, struct fuse_file_info
*fi
)
585 int (*__cg_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
588 __cg_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*))dlsym(dlopen_handle
, "cg_releasedir");
591 return log_error(-1, "%s - Failed to find cg_releasedir()", error
);
593 return __cg_releasedir(path
, fi
);
596 static int do_sys_releasedir(const char *path
, struct fuse_file_info
*fi
)
599 int (*__sys_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
602 __sys_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*))dlsym(dlopen_handle
, "sys_releasedir");
605 return log_error(-1, "%s - Failed to find sys_releasedir()", error
);
607 return __sys_releasedir(path
, fi
);
611 static int lxcfs_getattr(const char *path
, struct stat
*sb
, struct fuse_file_info
*fi
)
613 static int lxcfs_getattr(const char *path
, struct stat
*sb
)
619 if (strcmp(path
, "/") == 0) {
620 if (clock_gettime(CLOCK_REALTIME
, &now
) < 0)
622 sb
->st_uid
= sb
->st_gid
= 0;
623 sb
->st_atim
= sb
->st_mtim
= sb
->st_ctim
= now
;
625 sb
->st_mode
= S_IFDIR
| 00755;
630 if (strncmp(path
, "/cgroup", 7) == 0) {
632 ret
= do_cg_getattr(path
, sb
);
637 if (strncmp(path
, "/proc", 5) == 0) {
639 ret
= do_proc_getattr(path
, sb
);
644 if (strncmp(path
, "/sys", 4) == 0) {
646 ret
= do_sys_getattr(path
, sb
);
654 static int lxcfs_opendir(const char *path
, struct fuse_file_info
*fi
)
658 if (strcmp(path
, "/") == 0)
661 if (strncmp(path
, "/cgroup", 7) == 0) {
663 ret
= do_cg_opendir(path
, fi
);
668 if (strcmp(path
, "/proc") == 0)
671 if (strncmp(path
, "/sys", 4) == 0) {
673 ret
= do_sys_opendir(path
, fi
);
682 static int lxcfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
683 off_t offset
, struct fuse_file_info
*fi
, enum fuse_readdir_flags flags
)
685 static int lxcfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
686 off_t offset
, struct fuse_file_info
*fi
)
691 if (strcmp(path
, "/") == 0) {
692 if (DIR_FILLER(filler
, buf
, ".", NULL
, 0) != 0 ||
693 DIR_FILLER(filler
, buf
, "..", NULL
, 0) != 0 ||
694 DIR_FILLER(filler
, buf
, "proc", NULL
, 0) != 0 ||
695 DIR_FILLER(filler
, buf
, "sys", NULL
, 0) != 0 ||
696 DIR_FILLER(filler
, buf
, "cgroup", NULL
, 0) != 0)
702 if (strncmp(path
, "/cgroup", 7) == 0) {
704 ret
= do_cg_readdir(path
, buf
, filler
, offset
, fi
);
709 if (strcmp(path
, "/proc") == 0) {
711 ret
= do_proc_readdir(path
, buf
, filler
, offset
, fi
);
716 if (strncmp(path
, "/sys", 4) == 0) {
718 ret
= do_sys_readdir(path
, buf
, filler
, offset
, fi
);
726 static int lxcfs_access(const char *path
, int mode
)
730 if (strcmp(path
, "/") == 0 && (mode
& W_OK
) == 0)
733 if (strncmp(path
, "/cgroup", 7) == 0) {
735 ret
= do_cg_access(path
, mode
);
740 if (strncmp(path
, "/proc", 5) == 0) {
742 ret
= do_proc_access(path
, mode
);
747 if (strncmp(path
, "/sys", 4) == 0) {
749 ret
= do_sys_access(path
, mode
);
757 static int lxcfs_releasedir(const char *path
, struct fuse_file_info
*fi
)
761 if (strcmp(path
, "/") == 0)
764 if (strncmp(path
, "/cgroup", 7) == 0) {
766 ret
= do_cg_releasedir(path
, fi
);
771 if (strcmp(path
, "/proc") == 0)
774 if (strncmp(path
, "/sys", 4) == 0) {
776 ret
= do_sys_releasedir(path
, fi
);
784 static int lxcfs_open(const char *path
, struct fuse_file_info
*fi
)
788 if (strncmp(path
, "/cgroup", 7) == 0) {
790 ret
= do_cg_open(path
, fi
);
795 if (strncmp(path
, "/proc", 5) == 0) {
797 ret
= do_proc_open(path
, fi
);
802 if (strncmp(path
, "/sys", 4) == 0) {
804 ret
= do_sys_open(path
, fi
);
812 static int lxcfs_read(const char *path
, char *buf
, size_t size
, off_t offset
,
813 struct fuse_file_info
*fi
)
817 if (strncmp(path
, "/cgroup", 7) == 0) {
819 ret
= do_cg_read(path
, buf
, size
, offset
, fi
);
824 if (strncmp(path
, "/proc", 5) == 0) {
826 ret
= do_proc_read(path
, buf
, size
, offset
, fi
);
831 if (strncmp(path
, "/sys", 4) == 0) {
833 ret
= do_sys_read(path
, buf
, size
, offset
, fi
);
841 int lxcfs_write(const char *path
, const char *buf
, size_t size
, off_t offset
,
842 struct fuse_file_info
*fi
)
846 if (strncmp(path
, "/cgroup", 7) == 0) {
848 ret
= do_cg_write(path
, buf
, size
, offset
, fi
);
853 if (strncmp(path
, "/sys", 4) == 0) {
855 ret
= do_sys_write(path
, buf
, size
, offset
, fi
);
863 int lxcfs_readlink(const char *path
, char *buf
, size_t size
)
867 if (strncmp(path
, "/sys", 4) == 0) {
869 ret
= do_sys_readlink(path
, buf
, size
);
877 static int lxcfs_flush(const char *path
, struct fuse_file_info
*fi
)
882 static int lxcfs_release(const char *path
, struct fuse_file_info
*fi
)
886 if (strncmp(path
, "/cgroup", 7) == 0) {
888 ret
= do_cg_release(path
, fi
);
893 if (strncmp(path
, "/proc", 5) == 0) {
895 ret
= do_proc_release(path
, fi
);
900 if (strncmp(path
, "/sys", 4) == 0) {
902 ret
= do_sys_release(path
, fi
);
910 static int lxcfs_fsync(const char *path
, int datasync
, struct fuse_file_info
*fi
)
915 int lxcfs_mkdir(const char *path
, mode_t mode
)
919 if (strncmp(path
, "/cgroup", 7) == 0) {
921 ret
= do_cg_mkdir(path
, mode
);
930 int lxcfs_chown(const char *path
, uid_t uid
, gid_t gid
, struct fuse_file_info
*fi
)
932 int lxcfs_chown(const char *path
, uid_t uid
, gid_t gid
)
937 if (strncmp(path
, "/cgroup", 7) == 0) {
939 ret
= do_cg_chown(path
, uid
, gid
);
944 if (strncmp(path
, "/proc", 5) == 0)
947 if (strncmp(path
, "/sys", 4) == 0)
954 * cat first does a truncate before doing ops->write. This doesn't
955 * really make sense for cgroups. So just return 0 always but do
959 int lxcfs_truncate(const char *path
, off_t newsize
, struct fuse_file_info
*fi
)
961 int lxcfs_truncate(const char *path
, off_t newsize
)
964 if (strncmp(path
, "/cgroup", 7) == 0)
967 if (strncmp(path
, "/sys", 4) == 0)
973 int lxcfs_rmdir(const char *path
)
977 if (strncmp(path
, "/cgroup", 7) == 0) {
979 ret
= do_cg_rmdir(path
);
988 int lxcfs_chmod(const char *path
, mode_t mode
, struct fuse_file_info
*fi
)
990 int lxcfs_chmod(const char *path
, mode_t mode
)
995 if (strncmp(path
, "/cgroup", 7) == 0) {
997 ret
= do_cg_chmod(path
, mode
);
1002 if (strncmp(path
, "/proc", 5) == 0)
1005 if (strncmp(path
, "/sys", 4) == 0)
1012 static void *lxcfs_init(struct fuse_conn_info
*conn
, struct fuse_config
*cfg
)
1014 static void *lxcfs_init(struct fuse_conn_info
*conn
)
1018 void *(*__lxcfs_fuse_init
)(struct fuse_conn_info
* conn
, void * cfg
);
1021 __lxcfs_fuse_init
= (void *(*)(struct fuse_conn_info
* conn
, void * cfg
))dlsym(dlopen_handle
, "lxcfs_fuse_init");
1024 return log_error(NULL
, "%s - Failed to find lxcfs_fuse_init()", error
);
1026 return __lxcfs_fuse_init(conn
, NULL
);
1029 const struct fuse_operations lxcfs_ops
= {
1030 .access
= lxcfs_access
,
1031 .chmod
= lxcfs_chmod
,
1032 .chown
= lxcfs_chown
,
1033 .flush
= lxcfs_flush
,
1034 .fsync
= lxcfs_fsync
,
1035 .getattr
= lxcfs_getattr
,
1037 .mkdir
= lxcfs_mkdir
,
1039 .opendir
= lxcfs_opendir
,
1041 .readdir
= lxcfs_readdir
,
1042 .release
= lxcfs_release
,
1043 .releasedir
= lxcfs_releasedir
,
1044 .rmdir
= lxcfs_rmdir
,
1045 .truncate
= lxcfs_truncate
,
1046 .write
= lxcfs_write
,
1047 .readlink
= lxcfs_readlink
,
1064 .removexattr
= NULL
,
1074 static void usage(void)
1076 lxcfs_info("Usage: lxcfs <directory>\n");
1077 lxcfs_info("lxcfs is a FUSE-based proc, sys and cgroup virtualizing filesystem\n");
1078 lxcfs_info("Options :");
1079 lxcfs_info(" -d, --debug Run lxcfs with debugging enabled");
1080 lxcfs_info(" -f, --foreground Run lxcfs in the foreground");
1081 lxcfs_info(" -n, --help Print help");
1082 lxcfs_info(" -l, --enable-loadavg Enable loadavg virtualization");
1083 lxcfs_info(" -o Options to pass directly through fuse");
1084 lxcfs_info(" -p, --pidfile=FILE Path to use for storing lxcfs pid");
1085 lxcfs_info(" Default pidfile is %s/lxcfs.pid", RUNTIME_PATH
);
1086 lxcfs_info(" -u, --disable-swap Disable swap virtualization");
1087 lxcfs_info(" -v, --version Print lxcfs version");
1088 lxcfs_info(" --enable-cfs Enable CPU virtualization via CPU shares");
1089 lxcfs_info(" --enable-pidfd Use pidfd for process tracking");
1093 static int set_pidfile(char *pidfile
)
1095 __do_close
int fd
= -EBADF
;
1096 char buf
[INTTYPE_TO_STRLEN(long)];
1100 .l_whence
= SEEK_SET
,
1105 fd
= open(pidfile
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
| O_CLOEXEC
);
1107 return log_error(-1, "Could not open pidfile %s: %m", pidfile
);
1109 if (fcntl(fd
, F_SETLK
, &fl
) < 0) {
1110 if (errno
== EAGAIN
|| errno
== EACCES
)
1111 return log_error(-1, "PID file '%s' is already locked", pidfile
);
1112 lxcfs_error("Warning; unable to lock PID file, proceeding");
1115 if (ftruncate(fd
, 0))
1116 return log_error(-1, "Error truncating PID file '%s': %m", pidfile
);
1118 ret
= snprintf(buf
, sizeof(buf
), "%ld\n", (long)getpid());
1119 if (ret
< 0 || ret
>= sizeof(buf
))
1120 return log_error(-1, "Failed to convert pid to string %m");
1122 if (write(fd
, buf
, ret
) != ret
)
1123 return log_error(-1, "Error writing to PID file '%s': %m", pidfile
);
1128 static const struct option long_options
[] = {
1129 {"debug", no_argument
, 0, 'd' },
1130 {"disable-swap", no_argument
, 0, 'u' },
1131 {"enable-loadavg", no_argument
, 0, 'l' },
1132 {"foreground", no_argument
, 0, 'f' },
1133 {"help", no_argument
, 0, 'h' },
1134 {"version", no_argument
, 0, 'v' },
1136 {"enable-cfs", no_argument
, 0, 0 },
1137 {"enable-pidfd", no_argument
, 0, 0 },
1139 {"pidfile", required_argument
, 0, 'p' },
1143 static int append_comma_separate(char **s
, const char *append
)
1147 size_t append_len
, len
;
1152 append_len
= strlen(append
);
1158 news
= realloc(*s
, len
+ append_len
+ 2);
1161 news
= realloc(NULL
, append_len
+ 1);
1167 ret
= snprintf(news
+ len
, append_len
+ 2, ",%s", append
);
1169 ret
= snprintf(news
, append_len
+ 1, "%s", append
);
1177 int main(int argc
, char *argv
[])
1179 int pidfile_fd
= -EBADF
;
1180 int ret
= EXIT_FAILURE
;
1181 char *pidfile
= NULL
, *token
= NULL
;
1182 char pidfile_buf
[STRLITERALLEN(RUNTIME_PATH
) + STRLITERALLEN("/lxcfs.pid") + 1] = {};
1183 bool debug
= false, foreground
= false;
1185 bool nonempty
= false;
1187 bool load_use
= false;
1189 * what we pass to fuse_main is:
1190 * argv[0] -s [-f|-d] -o allow_other,directio argv[1] NULL
1193 int c
, idx
, new_argc
;
1195 const char *fuse_opts
= NULL
;
1196 char *new_fuse_opts
= NULL
;
1197 char *const *new_argv
;
1198 struct lxcfs_opts
*opts
;
1200 opts
= malloc(sizeof(struct lxcfs_opts
));
1202 lxcfs_error("Error allocating memory for options");
1206 opts
->swap_off
= false;
1207 opts
->use_pidfd
= false;
1208 opts
->use_cfs
= false;
1211 while ((c
= getopt_long(argc
, argv
, "dulfhvso:p:", long_options
, &idx
)) != -1) {
1214 if (strcmp(long_options
[idx
].name
, "enable-pidfd") == 0)
1215 opts
->use_pidfd
= true;
1216 else if (strcmp(long_options
[idx
].name
, "enable-cfs") == 0)
1217 opts
->use_cfs
= true;
1232 lxcfs_error("Specifying -o multiple times is unsupported");
1242 /* legacy argument: ignore */
1245 opts
->swap_off
= true;
1252 if (foreground
&& debug
)
1253 log_exit("Both --debug and --forgreound specified");
1255 new_argv
= &argv
[optind
];
1256 new_argc
= argc
- optind
;
1257 if (new_argc
!= 1) {
1258 lxcfs_error("Missing mountpoint");
1262 fuse_argv
[fuse_argc
++] = argv
[0];
1264 fuse_argv
[fuse_argc
++] = "-d";
1266 fuse_argv
[fuse_argc
++] = "-f";
1267 fuse_argv
[fuse_argc
++] = "-o";
1269 /* Parse additional fuse options. */
1273 dup
= strdup(fuse_opts
);
1275 lxcfs_error("Failed to copy fuse options");
1279 lxc_iterate_parts(token
, dup
, ",") {
1281 if (strcmp(token
, "allow_other") == 0)
1284 /* default for LXCFS */
1285 if (strcmp(token
, "direct_io") == 0)
1288 /* default for LXCFS */
1289 if (strncmp(token
, "entry_timeout", STRLITERALLEN("entry_timeout")) == 0)
1292 /* default for LXCFS */
1293 if (strncmp(token
, "attr_timeout", STRLITERALLEN("entry_timeout")) == 0)
1296 /* default for LXCFS */
1297 if (strncmp(token
, "allow_other", STRLITERALLEN("allow_other")) == 0)
1300 /* default with fuse3 */
1301 if (strcmp(token
, "nonempty") == 0) {
1308 if (append_comma_separate(&new_fuse_opts
, token
)) {
1309 lxcfs_error("Failed to copy fuse argument \"%s\"", token
);
1317 if (append_comma_separate(&new_fuse_opts
, "allow_other,entry_timeout=0.5,attr_timeout=0.5")) {
1318 lxcfs_error("Failed to copy fuse argument \"allow_other,entry_timeout=0.5,attr_timeout=0.5\"");
1324 if (append_comma_separate(&new_fuse_opts
, "nonempty")) {
1325 lxcfs_error("Failed to copy fuse argument \"nonempty\"");
1330 if (append_comma_separate(&new_fuse_opts
, "direct_io")) {
1331 lxcfs_error("Failed to copy fuse argument \"nonempty\"");
1337 * We can't use default_permissions since we still support systems that
1338 * don't have kernels with cgroup namespace support. On such kernels
1339 * lxcfs will provide a namespaced cgroup view and needs explicit
1340 * access helpers to make that work.
1341 * Another reason that came to me is that we can't or at least
1342 * shouldn't guarantee that we don't need more complicated access
1343 * helpers for proc and sys virtualization in the future.
1346 fuse_argv
[fuse_argc
++] = new_fuse_opts
;
1347 fuse_argv
[fuse_argc
++] = new_argv
[0];
1348 fuse_argv
[fuse_argc
] = NULL
;
1351 if (install_signal_handler(SIGUSR1
, sigusr1_reload
)) {
1352 lxcfs_error("%s - Failed to install SIGUSR1 signal handler", strerror(errno
));
1357 snprintf(pidfile_buf
, sizeof(pidfile_buf
), "%s/lxcfs.pid", RUNTIME_PATH
);
1358 pidfile
= pidfile_buf
;
1361 pidfile_fd
= set_pidfile(pidfile
);
1365 if (load_use
&& start_loadavg() != 0)
1368 if (!fuse_main(fuse_argc
, fuse_argv
, &lxcfs_ops
, opts
))
1376 dlclose(dlopen_handle
);
1379 free(new_fuse_opts
);
1381 close_prot_errno_disarm(pidfile_fd
);