diff --git a/0001-Fix-test_reload-for-lxcfs-chroot.patch b/0001-Fix-test_reload-for-lxcfs-chroot.patch new file mode 100644 index 0000000..6b1d803 --- /dev/null +++ b/0001-Fix-test_reload-for-lxcfs-chroot.patch @@ -0,0 +1,72 @@ +From ec2b5e7c6297a82914f59d7b49714beb5f8afeef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?St=C3=A9phane=20Graber?= +Date: Tue, 16 Aug 2016 12:36:01 -0400 +Subject: [PATCH 01/24] Fix test_reload for lxcfs chroot +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Stéphane Graber +--- + bindings.c | 10 +--------- + tests/test_reload.sh | 8 ++++---- + 2 files changed, 5 insertions(+), 13 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 04f0b08..2fb4acf 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -3610,17 +3610,9 @@ out: + #if RELOADTEST + void iwashere(void) + { +- char *name, *cwd = get_current_dir_name(); +- size_t len; + int fd; + +- if (!cwd) +- exit(1); +- len = strlen(cwd) + strlen("/iwashere") + 1; +- name = alloca(len); +- snprintf(name, len, "%s/iwashere", cwd); +- free(cwd); +- fd = creat(name, 0755); ++ fd = creat("/tmp/lxcfs-iwashere", 0644); + if (fd >= 0) + close(fd); + } +diff --git a/tests/test_reload.sh b/tests/test_reload.sh +index 5474cbb..5e37ace 100755 +--- a/tests/test_reload.sh ++++ b/tests/test_reload.sh +@@ -26,7 +26,7 @@ cleanup() { + umount -l ${testdir} + fi + rm -rf ${testdir} ${installdir} +- rm -f iwashere ++ rm -f /tmp/lxcfs-iwashere + rm -f ${pidfile} + if [ ${FAILED} -eq 1 ]; then + echo "liblxcfs.so reload test FAILED" +@@ -50,9 +50,9 @@ while [ ! -d ${testdir}/proc ]; do + count=$((count+1)) + done + +-rm -f iwashere ++rm -f /tmp/lxcfs-iwashere + cat ${testdir}/proc/uptime +-[ ! -f iwashere ] ++[ ! -f /tmp/lxcfs-iwashere ] + ( + cd ${topdir}; + make liblxcfstest.la +@@ -65,5 +65,5 @@ cp ${libdir}/liblxcfstest.so ${libdir}/liblxcfs.so + kill -USR1 ${lxcfspid} + + cat ${testdir}/proc/uptime +-[ -f iwashere ] ++[ -f /tmp/lxcfs-iwashere ] + FAILED=0 +-- +2.9.3 + diff --git a/0001-skip-empty-entries-under-proc-self-cgroup.patch b/0001-skip-empty-entries-under-proc-self-cgroup.patch deleted file mode 100644 index 4026dbb..0000000 --- a/0001-skip-empty-entries-under-proc-self-cgroup.patch +++ /dev/null @@ -1,60 +0,0 @@ -From a67719f64d07d7fee96b1e145a03659fe4db0c6e Mon Sep 17 00:00:00 2001 -From: Christian Brauner -Date: Sat, 9 Jul 2016 13:19:06 +0200 -Subject: [PATCH] skip empty entries under /proc/self/cgroup - -If cgroupv2 is enabled either alone or together with legacy hierarchies -/proc/self/cgroup can contain entries of the form: - - 0::/ - -This will cause lxcfs to fail the cgroup mounts because it parses out the empty -string "" and later on passes it to mount(). Let's skip such entries. - -Signed-off-by: Christian Brauner ---- - bindings.c | 8 ++++++++ - lxcfs.c | 8 ++++++++ - 2 files changed, 16 insertions(+) - -diff --git a/bindings.c b/bindings.c -index cb98e12..8186ca9 100644 ---- a/bindings.c -+++ b/bindings.c -@@ -3951,6 +3951,14 @@ static void __attribute__((constructor)) collect_subsystems(void) - goto out; - *p2 = '\0'; - -+ /* With cgroupv2 /proc/self/cgroup can contain entries of the -+ * form: 0::/ This will cause lxcfs to fail the cgroup mounts -+ * because it parses out the empty string "" and later on passes -+ * it to mount(). Let's skip such entries. -+ */ -+ if (!strcmp(p, "")) -+ continue; -+ - if (!store_hierarchy(line, p)) - goto out; - } -diff --git a/lxcfs.c b/lxcfs.c -index 7455267..1d19a10 100644 ---- a/lxcfs.c -+++ b/lxcfs.c -@@ -859,6 +859,14 @@ static bool do_mount_cgroups(void) - goto out; - *p2 = '\0'; - -+ /* With cgroupv2 /proc/self/cgroup can contain entries of the -+ * form: 0::/ This will cause lxcfs to fail the cgroup mounts -+ * because it parses out the empty string "" and later on passes -+ * it to mount(). Let's skip such entries. -+ */ -+ if (!strcmp(p, "")) -+ continue; -+ - if (!do_mount_cgroup(p)) - goto out; - } --- -2.8.4 - diff --git a/0002-Virtualize-more-of-the-meminfo-fields.patch b/0002-Virtualize-more-of-the-meminfo-fields.patch new file mode 100644 index 0000000..807fc5e --- /dev/null +++ b/0002-Virtualize-more-of-the-meminfo-fields.patch @@ -0,0 +1,118 @@ +From c6095b08bb3731f2b25fa2312e31da2d21b2b3eb Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Thu, 18 Aug 2016 00:03:51 -0500 +Subject: [PATCH 02/24] Virtualize more of the meminfo fields + +The worst remaining offending line appears to be VmallocTotal. +Suggestions for how to calculate that would be appreciated. + +Closes #119 + +Signed-off-by: Serge Hallyn +--- + bindings.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 56 insertions(+), 8 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 2fb4acf..1fa1027 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -2943,16 +2943,32 @@ static bool startswith(const char *line, const char *pref) + return false; + } + +-static void get_mem_cached(char *memstat, unsigned long *v) ++static void parse_memstat(char *memstat, unsigned long *cached, ++ unsigned long *active_anon, unsigned long *inactive_anon, ++ unsigned long *active_file, unsigned long *inactive_file, ++ unsigned long *unevictable) + { + char *eol; + +- *v = 0; + while (*memstat) { +- if (startswith(memstat, "total_cache")) { +- sscanf(memstat + 11, "%lu", v); +- *v /= 1024; +- return; ++ if (startswith(memstat, "cache")) { ++ sscanf(memstat + 11, "%lu", cached); ++ *cached /= 1024; ++ } else if (startswith(memstat, "active_anon")) { ++ sscanf(memstat + 11, "%lu", active_anon); ++ *active_anon /= 1024; ++ } else if (startswith(memstat, "inactive_anon")) { ++ sscanf(memstat + 11, "%lu", inactive_anon); ++ *inactive_anon /= 1024; ++ } else if (startswith(memstat, "active_file")) { ++ sscanf(memstat + 11, "%lu", active_file); ++ *active_file /= 1024; ++ } else if (startswith(memstat, "inactive_file")) { ++ sscanf(memstat + 11, "%lu", inactive_file); ++ *inactive_file /= 1024; ++ } else if (startswith(memstat, "unevictable")) { ++ sscanf(memstat + 11, "%lu", unevictable); ++ *unevictable /= 1024; + } + eol = strchr(memstat, '\n'); + if (!eol) +@@ -3069,7 +3085,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + *memswlimit_str = NULL, *memswusage_str = NULL, + *memswlimit_default_str = NULL, *memswusage_default_str = NULL; + unsigned long memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0, +- cached = 0, hosttotal = 0; ++ cached = 0, hosttotal = 0, active_anon = 0, inactive_anon = 0, ++ active_file = 0, inactive_file = 0, unevictable = 0; + char *line = NULL; + size_t linelen = 0, total_len = 0, rv = 0; + char *cache = d->buf; +@@ -3128,7 +3145,9 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + memlimit /= 1024; + memusage /= 1024; + +- get_mem_cached(memstat_str, &cached); ++ parse_memstat(memstat_str, &cached, &active_anon, ++ &inactive_anon, &active_file, &inactive_file, ++ &unevictable); + + f = fopen("/proc/meminfo", "r"); + if (!f) +@@ -3170,6 +3189,35 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + } else if (startswith(line, "SwapCached:")) { + snprintf(lbuf, 100, "SwapCached: %8lu kB\n", 0UL); + printme = lbuf; ++ } else if (startswith(line, "Active")) { ++ snprintf(lbuf, 100, "Active: %8lu kB\n", ++ active_anon + active_file); ++ printme = lbuf; ++ } else if (startswith(line, "Inactive")) { ++ snprintf(lbuf, 100, "Inactive: %8lu kB\n", ++ inactive_anon + inactive_file); ++ printme = lbuf; ++ } else if (startswith(line, "Active(anon)")) { ++ snprintf(lbuf, 100, "Active(anon): %8lu kB\n", active_anon); ++ printme = lbuf; ++ } else if (startswith(line, "Inactive(anon)")) { ++ snprintf(lbuf, 100, "Inactive(anon): %8lu kB\n", inactive_anon); ++ printme = lbuf; ++ } else if (startswith(line, "Active(file)")) { ++ snprintf(lbuf, 100, "Active(file): %8lu kB\n", active_file); ++ printme = lbuf; ++ } else if (startswith(line, "Inactive(file)")) { ++ snprintf(lbuf, 100, "Inactive(file): %8lu kB\n", inactive_file); ++ printme = lbuf; ++ } else if (startswith(line, "Unevictable")) { ++ snprintf(lbuf, 100, "Unevictable: %8lu kB\n", unevictable); ++ printme = lbuf; ++ } else if (startswith(line, "SReclaimable")) { ++ snprintf(lbuf, 100, "SReclaimable: %8lu kB\n", 0UL); ++ printme = lbuf; ++ } else if (startswith(line, "SUnreclaim")) { ++ snprintf(lbuf, 100, "SUnreclaim: %8lu kB\n", 0UL); ++ printme = lbuf; + } else + printme = line; + +-- +2.9.3 + diff --git a/0003-pam-fix-race-in-cgroup-creation.patch b/0003-pam-fix-race-in-cgroup-creation.patch new file mode 100644 index 0000000..9a80b33 --- /dev/null +++ b/0003-pam-fix-race-in-cgroup-creation.patch @@ -0,0 +1,57 @@ +From 56ee748c3fd89752a6262471eb49d3b670bb3c09 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sun, 21 Aug 2016 13:26:42 -0500 +Subject: [PATCH 03/24] pam: fix race in cgroup creation + +If we find that a cgroup already exists, we should + +1. remove all the cgroups which we've created so far +2. set existed to true +3. return failure + +The caller should then detect that existed == true, +and re-try with the next index. + +Signed-off-by: Serge Hallyn +--- + pam/pam_cgfs.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/pam/pam_cgfs.c b/pam/pam_cgfs.c +index 08f0694..24510e1 100644 +--- a/pam/pam_cgfs.c ++++ b/pam/pam_cgfs.c +@@ -585,7 +585,7 @@ static bool cgfs_create_forone(struct controller *c, uid_t uid, gid_t gid, const + #if DEBUG + fprintf(stderr, "%s existed\n", path); + #endif +- return true; ++ return false; + } + + bool pass = mkdir_p(c->mount_path, path); +@@ -794,16 +794,16 @@ static int handle_login(const char *user) + return PAM_SESSION_ERR; + } + ++ existed = false; + if (!cgfs_create(cg, uid, gid, &existed)) { ++ if (existed) { ++ idx++; ++ continue; ++ } + mysyslog(LOG_ERR, "Failed to create a cgroup for user %s\n", user); + return PAM_SESSION_ERR; + } + +- if (existed == 1) { +- idx++; +- continue; +- } +- + if (!cgfs_enter(cg, false)) { + mysyslog(LOG_ERR, "Failed to enter user cgroup %s for user %s\n", cg, user); + return PAM_SESSION_ERR; +-- +2.9.3 + diff --git a/0004-meminfo-don-t-show-negative-swapfree.patch b/0004-meminfo-don-t-show-negative-swapfree.patch new file mode 100644 index 0000000..5f069fe --- /dev/null +++ b/0004-meminfo-don-t-show-negative-swapfree.patch @@ -0,0 +1,41 @@ +From b4665ce0c3b5bd6d2ceca843b52bd70ae5fb639a Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sun, 21 Aug 2016 15:05:31 -0500 +Subject: [PATCH 04/24] meminfo: don't show negative swapfree + +Also commonize some of the mem{,sw} free/used calculations. + +Closes #115 +--- + bindings.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 2fb4acf..9bac10a 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -3155,8 +3155,10 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + snprintf(lbuf, 100, "SwapTotal: %8lu kB\n", memswlimit - memlimit); + printme = lbuf; + } else if (startswith(line, "SwapFree:") && memswlimit > 0 && memswusage > 0) { +- snprintf(lbuf, 100, "SwapFree: %8lu kB\n", +- (memswlimit - memlimit) - (memswusage - memusage)); ++ unsigned long swaptotal = memswlimit - memlimit, ++ swapusage = memswusage - memusage, ++ swapfree = swapusage < swaptotal ? swaptotal - swapusage : 0; ++ snprintf(lbuf, 100, "SwapFree: %8lu kB\n", swapfree); + printme = lbuf; + } else if (startswith(line, "Slab:")) { + snprintf(lbuf, 100, "Slab: %8lu kB\n", 0UL); +@@ -3472,6 +3474,8 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, + char cpu_char[10]; /* That's a lot of cores */ + char *c; + ++ if (strlen(line) == 0) ++ continue; + if (sscanf(line, "cpu%9[^ ]", cpu_char) != 1) { + /* not a ^cpuN line containing a number N, just print it */ + l = snprintf(cache, cache_size, "%s", line); +-- +2.9.3 + diff --git a/0005-bindings-improve-debugging.patch b/0005-bindings-improve-debugging.patch new file mode 100644 index 0000000..a4996de --- /dev/null +++ b/0005-bindings-improve-debugging.patch @@ -0,0 +1,147 @@ +From 7dd6560a9b506c83c1a577e620ca0e81f0c6a9dd Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Wed, 24 Aug 2016 15:43:49 +0200 +Subject: [PATCH 05/24] bindings: improve debugging + +- replace multiple DEBUG ifdefines with a single ifdefine at the top +- ifdefine lxcfs_debug() macro function that expands to nothing when -DDEBUG is + not given + +Signed-off-by: Christian Brauner +--- + bindings.c | 62 ++++++++++++++++++++++++++++++-------------------------------- + 1 file changed, 30 insertions(+), 32 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 916b43d..e3975cc 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -48,6 +48,16 @@ return -1; + extern int pivot_root(const char * new_root, const char * put_old); + #endif + ++#ifdef DEBUG ++#define lxcfs_debug(format, ...) \ ++ do { \ ++ fprintf(stderr, "%s: %d: %s: " format, __FILE__, __LINE__, \ ++ __func__, __VA_ARGS__); \ ++ } while (false) ++#else ++#define lxcfs_debug(format, ...) ++#endif /* DEBUG */ ++ + enum { + LXC_TYPE_CGDIR, + LXC_TYPE_CGFILE, +@@ -160,10 +170,10 @@ static bool initpid_still_valid(struct pidns_init_store *e, struct stat *nsfdsb) + snprintf(fnam, 100, "/proc/%d", e->initpid); + if (stat(fnam, &initsb) < 0) + return false; +-#if DEBUG +- fprintf(stderr, "comparing ctime %ld %ld for pid %d\n", +- e->ctime, initsb.st_ctime, e->initpid); +-#endif ++ ++ lxcfs_debug("Comparing ctime %ld == %ld for pid %d.\n", e->ctime, ++ initsb.st_ctime, e->initpid); ++ + if (e->ctime != initsb.st_ctime) + return false; + return true; +@@ -175,9 +185,8 @@ static void remove_initpid(struct pidns_init_store *e) + struct pidns_init_store *tmp; + int h; + +-#if DEBUG +- fprintf(stderr, "remove_initpid: removing entry for %d\n", e->initpid); +-#endif ++ lxcfs_debug("Remove_initpid: removing entry for %d.\n", e->initpid); ++ + h = HASH(e->ino); + if (pidns_hash_table[h] == e) { + pidns_hash_table[h] = e->next; +@@ -212,18 +221,18 @@ static void prune_initpid_store(void) + now = time(NULL); + if (now < last_prune + PURGE_SECS) + return; +-#if DEBUG +- fprintf(stderr, "pruning\n"); +-#endif ++ ++ lxcfs_debug("%s\n", "Pruning."); ++ + last_prune = now; + threshold = now - 2 * PURGE_SECS; + + for (i = 0; i < PIDNS_HASH_SIZE; i++) { + for (prev = NULL, e = pidns_hash_table[i]; e; ) { + if (e->lastcheck < threshold) { +-#if DEBUG +- fprintf(stderr, "Removing cached entry for %d\n", e->initpid); +-#endif ++ ++ lxcfs_debug("Removing cached entry for %d.\n", e->initpid); ++ + delme = e; + if (prev) + prev->next = e->next; +@@ -247,9 +256,8 @@ static void save_initpid(struct stat *sb, pid_t pid) + struct stat procsb; + int h; + +-#if DEBUG +- fprintf(stderr, "save_initpid: adding entry for %d\n", pid); +-#endif ++ lxcfs_debug("Save_initpid: adding entry for %d.\n", pid); ++ + snprintf(fpath, 100, "/proc/%d", pid); + if (stat(fpath, &procsb) < 0) + return; +@@ -577,9 +585,7 @@ static bool recursive_rmdir(const char *dirname, int fd) + + dir = fdopendir(dupfd); + if (!dir) { +-#if DEBUG +- fprintf(stderr, "%s: failed to open %s: %s\n", __func__, dirname, strerror(errno)); +-#endif ++ lxcfs_debug("Failed to open %s: %s.\n", dirname, strerror(errno)); + return false; + } + +@@ -602,18 +608,12 @@ static bool recursive_rmdir(const char *dirname, int fd) + + ret = fstatat(fd, pathname, &mystat, AT_SYMLINK_NOFOLLOW); + if (ret) { +-#if DEBUG +- fprintf(stderr, "%s: failed to stat %s: %s\n", __func__, pathname, strerror(errno)); +-#endif ++ lxcfs_debug("Failed to stat %s: %s.\n", pathname, strerror(errno)); + continue; + } +- if (S_ISDIR(mystat.st_mode)) { +- if (!recursive_rmdir(pathname, fd)) { +-#if DEBUG +- fprintf(stderr, "Error removing %s\n", pathname); +-#endif +- } +- } ++ if (S_ISDIR(mystat.st_mode)) ++ if (!recursive_rmdir(pathname, fd)) ++ lxcfs_debug("Error removing %s.\n", pathname); + } + + ret = true; +@@ -623,9 +623,7 @@ static bool recursive_rmdir(const char *dirname, int fd) + } + + if (unlinkat(fd, dirname, AT_REMOVEDIR) < 0) { +-#if DEBUG +- fprintf(stderr, "%s: failed to delete %s: %s\n", __func__, dirname, strerror(errno)); +-#endif ++ lxcfs_debug("Failed to delete %s: %s.\n", dirname, strerror(errno)); + ret = false; + } + close(fd); +-- +2.9.3 + diff --git a/0006-bindings-use-openat-fd-for-fstatat-unlinkat.patch b/0006-bindings-use-openat-fd-for-fstatat-unlinkat.patch new file mode 100644 index 0000000..c612e68 --- /dev/null +++ b/0006-bindings-use-openat-fd-for-fstatat-unlinkat.patch @@ -0,0 +1,71 @@ +From 2e81a5e3d8f70f395b83941e3a0277f995c27e08 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 22 Aug 2016 02:47:27 +0200 +Subject: [PATCH 06/24] bindings: use openat fd for fstatat(), unlinkat() + +Signed-off-by: Christian Brauner +--- + bindings.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/bindings.c b/bindings.c +index e3975cc..f0e7b80 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -571,7 +571,7 @@ int cgfs_create(const char *controller, const char *cg, uid_t uid, gid_t gid) + return 0; + } + +-static bool recursive_rmdir(const char *dirname, int fd) ++static bool recursive_rmdir(const char *dirname, int fd, int cfd) + { + struct dirent *direntp; + DIR *dir; +@@ -593,9 +593,6 @@ static bool recursive_rmdir(const char *dirname, int fd) + struct stat mystat; + int rc; + +- if (!direntp) +- break; +- + if (!strcmp(direntp->d_name, ".") || + !strcmp(direntp->d_name, "..")) + continue; +@@ -606,13 +603,13 @@ static bool recursive_rmdir(const char *dirname, int fd) + continue; + } + +- ret = fstatat(fd, pathname, &mystat, AT_SYMLINK_NOFOLLOW); +- if (ret) { ++ rc = fstatat(cfd, pathname, &mystat, AT_SYMLINK_NOFOLLOW); ++ if (rc) { + lxcfs_debug("Failed to stat %s: %s.\n", pathname, strerror(errno)); + continue; + } + if (S_ISDIR(mystat.st_mode)) +- if (!recursive_rmdir(pathname, fd)) ++ if (!recursive_rmdir(pathname, fd, cfd)) + lxcfs_debug("Error removing %s.\n", pathname); + } + +@@ -622,7 +619,7 @@ static bool recursive_rmdir(const char *dirname, int fd) + ret = false; + } + +- if (unlinkat(fd, dirname, AT_REMOVEDIR) < 0) { ++ if (unlinkat(cfd, dirname, AT_REMOVEDIR) < 0) { + lxcfs_debug("Failed to delete %s: %s.\n", dirname, strerror(errno)); + ret = false; + } +@@ -652,7 +649,7 @@ bool cgfs_remove(const char *controller, const char *cg) + if (fd < 0) + return false; + +- return recursive_rmdir(dirnam, fd); ++ return recursive_rmdir(dirnam, fd, cfd); + } + + bool cgfs_chmod_file(const char *controller, const char *file, mode_t mode) +-- +2.9.3 + diff --git a/0007-bindings-close-open-fds-on-error.patch b/0007-bindings-close-open-fds-on-error.patch new file mode 100644 index 0000000..2d612e1 --- /dev/null +++ b/0007-bindings-close-open-fds-on-error.patch @@ -0,0 +1,63 @@ +From 7213ec5c20b91ff62d38c7b39f82c5e713aff08c Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 22 Aug 2016 17:48:12 +0200 +Subject: [PATCH 07/24] bindings: close open fds on error + +Signed-off-by: Christian Brauner +--- + bindings.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/bindings.c b/bindings.c +index f0e7b80..0cc926b 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -571,7 +571,7 @@ int cgfs_create(const char *controller, const char *cg, uid_t uid, gid_t gid) + return 0; + } + +-static bool recursive_rmdir(const char *dirname, int fd, int cfd) ++static bool recursive_rmdir(const char *dirname, int fd, const int cfd) + { + struct dirent *direntp; + DIR *dir; +@@ -586,6 +586,7 @@ static bool recursive_rmdir(const char *dirname, int fd, int cfd) + dir = fdopendir(dupfd); + if (!dir) { + lxcfs_debug("Failed to open %s: %s.\n", dirname, strerror(errno)); ++ close(dupfd); + return false; + } + +@@ -623,7 +624,8 @@ static bool recursive_rmdir(const char *dirname, int fd, int cfd) + lxcfs_debug("Failed to delete %s: %s.\n", dirname, strerror(errno)); + ret = false; + } +- close(fd); ++ ++ close(dupfd); + + return ret; + } +@@ -633,6 +635,7 @@ bool cgfs_remove(const char *controller, const char *cg) + int fd, cfd; + size_t len; + char *dirnam, *tmpc; ++ bool bret; + + tmpc = find_mounted_controller(controller, &cfd); + if (!tmpc) +@@ -649,7 +652,9 @@ bool cgfs_remove(const char *controller, const char *cg) + if (fd < 0) + return false; + +- return recursive_rmdir(dirnam, fd, cfd); ++ bret = recursive_rmdir(dirnam, fd, cfd); ++ close(fd); ++ return bret; + } + + bool cgfs_chmod_file(const char *controller, const char *file, mode_t mode) +-- +2.9.3 + diff --git a/0008-bindings-grant-access-to-var-lib-lxcfs.patch b/0008-bindings-grant-access-to-var-lib-lxcfs.patch new file mode 100644 index 0000000..2bed8ac --- /dev/null +++ b/0008-bindings-grant-access-to-var-lib-lxcfs.patch @@ -0,0 +1,48 @@ +From 17e6e1e29fa875fbcae6e70c9580911f937d1cde Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Sun, 21 Aug 2016 00:22:38 +0200 +Subject: [PATCH 08/24] bindings: grant access to /var/lib/lxcfs + +Signed-off-by: Christian Brauner +--- + lxcfs.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/lxcfs.c b/lxcfs.c +index 47afe13..98b5d91 100644 +--- a/lxcfs.c ++++ b/lxcfs.c +@@ -424,11 +424,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); +@@ -489,6 +497,10 @@ static int lxcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of + static int lxcfs_access(const char *path, int mode) + { + int ret; ++ ++ if (strcmp(path, "/") == 0 && access(path, R_OK) == 0) ++ return 0; ++ + if (strncmp(path, "/cgroup", 7) == 0) { + up_users(); + ret = do_cg_access(path, mode); +-- +2.9.3 + diff --git a/0009-bindings-enable-access-to-var-lib-lxcfs-cgroup.patch b/0009-bindings-enable-access-to-var-lib-lxcfs-cgroup.patch new file mode 100644 index 0000000..7b5c1bd --- /dev/null +++ b/0009-bindings-enable-access-to-var-lib-lxcfs-cgroup.patch @@ -0,0 +1,38 @@ +From 6f0f6b832b5312e510add2fc4c571376184b59b8 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Sun, 21 Aug 2016 00:02:32 +0200 +Subject: [PATCH 09/24] bindings: enable access to /var/lib/lxcfs/cgroup + +Signed-off-by: Christian Brauner +--- + bindings.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 0cc926b..6ae0c06 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -1909,11 +1909,18 @@ out: + + int cg_access(const char *path, int mode) + { ++ int ret; + const char *cgroup; +- char *last = NULL, *path1, *path2, * cgdir = NULL, *controller; ++ char *path1, *path2, *controller; ++ char *last = NULL, *cgdir = NULL; + struct cgfs_files *k = NULL; + struct fuse_context *fc = fuse_get_context(); +- int ret; ++ ++ if (strcmp(path, "/cgroup") == 0) { ++ if ((mode & W_OK) == 0) ++ return -EACCES; ++ return 0; ++ } + + if (!fc) + return -EIO; +-- +2.9.3 + diff --git a/0010-bindings-allow-access-to-var-lib-lxcfs-proc.patch b/0010-bindings-allow-access-to-var-lib-lxcfs-proc.patch new file mode 100644 index 0000000..b9a5d40 --- /dev/null +++ b/0010-bindings-allow-access-to-var-lib-lxcfs-proc.patch @@ -0,0 +1,27 @@ +From e7849aa3f722c6ac7a16fd87147a295b708a2855 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Sun, 21 Aug 2016 00:11:13 +0200 +Subject: [PATCH 10/24] bindings: allow access to /var/lib/lxcfs/proc + +Signed-off-by: Christian Brauner +--- + bindings.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/bindings.c b/bindings.c +index 6ae0c06..04b2a5f 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -4075,6 +4075,9 @@ int proc_open(const char *path, struct fuse_file_info *fi) + + int proc_access(const char *path, int mask) + { ++ if (strcmp(path, "/proc") == 0 && access(path, R_OK) == 0) ++ return 0; ++ + /* these are all read-only */ + if ((mask & ~R_OK) != 0) + return -EACCES; +-- +2.9.3 + diff --git a/0011-lxcfs-bindings-show-.-and-.-dir-entries.patch b/0011-lxcfs-bindings-show-.-and-.-dir-entries.patch new file mode 100644 index 0000000..9ed9095 --- /dev/null +++ b/0011-lxcfs-bindings-show-.-and-.-dir-entries.patch @@ -0,0 +1,66 @@ +From d639f86341f7f07f0ade0c937fd576586bfb949e Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Sun, 21 Aug 2016 13:53:27 +0200 +Subject: [PATCH 11/24] lxcfs, bindings: show "." and ".." dir entries + +Signed-off-by: Christian Brauner +--- + bindings.c | 17 +++++++++++------ + lxcfs.c | 6 ++++-- + 2 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 04b2a5f..997db7b 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -1742,6 +1742,9 @@ int cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset + struct fuse_context *fc = fuse_get_context(); + char **clist = NULL; + ++ if (filler(buf, ".", NULL, 0) != 0 || filler(buf, "..", NULL, 0) != 0) ++ return -EIO; ++ + if (d->type != LXC_TYPE_CGDIR) { + fprintf(stderr, "Internal error: file cache info used in readdir\n"); + return -EIO; +@@ -4024,12 +4027,14 @@ int proc_getattr(const char *path, struct stat *sb) + int proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, + struct fuse_file_info *fi) + { +- if (filler(buf, "cpuinfo", NULL, 0) != 0 || +- filler(buf, "meminfo", NULL, 0) != 0 || +- filler(buf, "stat", NULL, 0) != 0 || +- filler(buf, "uptime", NULL, 0) != 0 || +- filler(buf, "diskstats", NULL, 0) != 0 || +- filler(buf, "swaps", NULL, 0) != 0) ++ if (filler(buf, ".", NULL, 0) != 0 || ++ filler(buf, "..", NULL, 0) != 0 || ++ filler(buf, "cpuinfo", NULL, 0) != 0 || ++ filler(buf, "meminfo", NULL, 0) != 0 || ++ filler(buf, "stat", NULL, 0) != 0 || ++ filler(buf, "uptime", NULL, 0) != 0 || ++ filler(buf, "diskstats", NULL, 0) != 0 || ++ filler(buf, "swaps", NULL, 0) != 0) + return -EINVAL; + return 0; + } +diff --git a/lxcfs.c b/lxcfs.c +index 98b5d91..0c695b7 100644 +--- a/lxcfs.c ++++ b/lxcfs.c +@@ -474,8 +474,10 @@ 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) ++ if (filler(buf, ".", NULL, 0) != 0 || ++ filler(buf, "..", NULL, 0) != 0 || ++ filler(buf, "proc", NULL, 0) != 0 || ++ filler(buf, "cgroup", NULL, 0) != 0) + return -EINVAL; + return 0; + } +-- +2.9.3 + diff --git a/0012-lxcfs-better-fs-behavior-on-var-lib-lxcfs.patch b/0012-lxcfs-better-fs-behavior-on-var-lib-lxcfs.patch new file mode 100644 index 0000000..b480b58 --- /dev/null +++ b/0012-lxcfs-better-fs-behavior-on-var-lib-lxcfs.patch @@ -0,0 +1,125 @@ +From f9b24a3e01e49dfa2b98c138f3d4f6f687c8d0b6 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 22 Aug 2016 11:36:02 +0200 +Subject: [PATCH 12/24] lxcfs: better fs behavior on /var/lib/lxcfs + +return -EPERM for mkdir(), rmdir(), chown(), chmod() on top directory +/var/lib/lxcfs. + +Signed-off-by: Christian Brauner +--- + lxcfs.c | 29 ++++++++++++++++++----------- + 1 file changed, 18 insertions(+), 11 deletions(-) + +diff --git a/lxcfs.c b/lxcfs.c +index 0c695b7..a013033 100644 +--- a/lxcfs.c ++++ b/lxcfs.c +@@ -449,7 +449,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) +@@ -478,7 +478,7 @@ static int lxcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of + filler(buf, "..", NULL, 0) != 0 || + filler(buf, "proc", NULL, 0) != 0 || + filler(buf, "cgroup", NULL, 0) != 0) +- return -EINVAL; ++ return -ENOMEM; + return 0; + } + if (strncmp(path, "/cgroup", 7) == 0) { +@@ -493,14 +493,14 @@ 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 && access(path, R_OK) == 0) ++ if (strcmp(path, "/") == 0 && (mode & W_OK) == 0) + return 0; + + if (strncmp(path, "/cgroup", 7) == 0) { +@@ -516,7 +516,7 @@ static int lxcfs_access(const char *path, int mode) + return ret; + } + +- return -EINVAL; ++ return -EACCES; + } + + static int lxcfs_releasedir(const char *path, struct fuse_file_info *fi) +@@ -551,7 +551,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, +@@ -627,7 +627,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) +@@ -640,7 +640,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; + } + + /* +@@ -652,7 +655,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) +@@ -664,7 +667,7 @@ int lxcfs_rmdir(const char *path) + down_users(); + return ret; + } +- return -EINVAL; ++ return -EPERM; + } + + int lxcfs_chmod(const char *path, mode_t mode) +@@ -676,7 +679,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 = { +-- +2.9.3 + diff --git a/0013-bindings-non-functional-changes.patch b/0013-bindings-non-functional-changes.patch new file mode 100644 index 0000000..9e653b5 --- /dev/null +++ b/0013-bindings-non-functional-changes.patch @@ -0,0 +1,40 @@ +From 3adc421c2619aa43631493562d0adc60940346af Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 22 Aug 2016 11:56:46 +0200 +Subject: [PATCH 13/24] bindings: non functional changes + +- whitespace fixes for pick_controller_from_path() + +Signed-off-by: Christian Brauner +--- + bindings.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 997db7b..cf56208 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -1508,9 +1508,9 @@ static char *pick_controller_from_path(struct fuse_context *fc, const char *path + + if (strlen(path) < 9) + return NULL; +- if (*(path+7) != '/') ++ if (*(path + 7) != '/') + return NULL; +- p1 = path+8; ++ p1 = path + 8; + contr = strdupa(p1); + if (!contr) + return NULL; +@@ -1519,7 +1519,7 @@ static char *pick_controller_from_path(struct fuse_context *fc, const char *path + *slash = '\0'; + + int i; +- for (i = 0; i < num_hierarchies; i++) { ++ for (i = 0; i < num_hierarchies; i++) { + if (hierarchies[i] && strcmp(hierarchies[i], contr) == 0) + return hierarchies[i]; + } +-- +2.9.3 + diff --git a/0014-bindings-set-errno-in-pick_controller_from_path.patch b/0014-bindings-set-errno-in-pick_controller_from_path.patch new file mode 100644 index 0000000..3a24cde --- /dev/null +++ b/0014-bindings-set-errno-in-pick_controller_from_path.patch @@ -0,0 +1,51 @@ +From 99142521d202c1b626dd308e25c42eb95f613c21 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 22 Aug 2016 12:00:25 +0200 +Subject: [PATCH 14/24] bindings: set errno in pick_controller_from_path() + +This will allow us to provide better standard fs behavior. + +Signed-off-by: Christian Brauner +--- + bindings.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/bindings.c b/bindings.c +index cf56208..f3cd85d 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -1506,14 +1506,20 @@ static char *pick_controller_from_path(struct fuse_context *fc, const char *path + const char *p1; + char *contr, *slash; + +- if (strlen(path) < 9) ++ if (strlen(path) < 9) { ++ errno = EINVAL; + return NULL; +- if (*(path + 7) != '/') ++ } ++ if (*(path + 7) != '/') { ++ errno = EINVAL; + return NULL; ++ } + p1 = path + 8; + contr = strdupa(p1); +- if (!contr) ++ if (!contr) { ++ errno = ENOMEM; + return NULL; ++ } + slash = strstr(contr, "/"); + if (slash) + *slash = '\0'; +@@ -1523,6 +1529,7 @@ static char *pick_controller_from_path(struct fuse_context *fc, const char *path + if (hierarchies[i] && strcmp(hierarchies[i], contr) == 0) + return hierarchies[i]; + } ++ errno = ENOENT; + return NULL; + } + +-- +2.9.3 + diff --git a/0015-bindings-more-consistent-fs-behavior.patch b/0015-bindings-more-consistent-fs-behavior.patch new file mode 100644 index 0000000..7c80380 --- /dev/null +++ b/0015-bindings-more-consistent-fs-behavior.patch @@ -0,0 +1,100 @@ +From 2f7036d08de5c60c72985b37f8ff5c01d248109a Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 22 Aug 2016 12:20:10 +0200 +Subject: [PATCH 15/24] bindings: more consistent fs behavior + +- e.g. let cg_mkdir() return EPERM + +Signed-off-by: Christian Brauner +--- + bindings.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/bindings.c b/bindings.c +index f3cd85d..281aad2 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -1605,7 +1605,7 @@ int cg_getattr(const char *path, struct stat *sb) + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -EIO; ++ return -errno; + cgroup = find_cgroup_in_path(path); + if (!cgroup) { + /* this is just /cgroup/controller, return it as a dir */ +@@ -1705,7 +1705,7 @@ int cg_opendir(const char *path, struct fuse_file_info *fi) + // return list of keys for the controller, and list of child cgroups + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -EIO; ++ return -errno; + + cgroup = find_cgroup_in_path(path); + if (!cgroup) { +@@ -1863,7 +1863,7 @@ int cg_open(const char *path, struct fuse_file_info *fi) + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -EIO; ++ return -errno; + cgroup = find_cgroup_in_path(path); + if (!cgroup) + return -EINVAL; +@@ -1937,7 +1937,7 @@ int cg_access(const char *path, int mode) + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -EIO; ++ return -errno; + cgroup = find_cgroup_in_path(path); + if (!cgroup) { + // access("/sys/fs/cgroup/systemd", mode) - rx allowed, w not +@@ -2724,7 +2724,7 @@ int cg_chown(const char *path, uid_t uid, gid_t gid) + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -EINVAL; ++ return -errno; + cgroup = find_cgroup_in_path(path); + if (!cgroup) + /* this is just /cgroup/controller */ +@@ -2789,7 +2789,7 @@ int cg_chmod(const char *path, mode_t mode) + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -EINVAL; ++ return -errno; + cgroup = find_cgroup_in_path(path); + if (!cgroup) + /* this is just /cgroup/controller */ +@@ -2854,7 +2854,7 @@ int cg_mkdir(const char *path, mode_t mode) + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -EINVAL; ++ return errno == ENOENT ? -EPERM : -errno; + + cgroup = find_cgroup_in_path(path); + if (!cgroup) +@@ -2875,7 +2875,7 @@ int cg_mkdir(const char *path, mode_t mode) + else if (last && strcmp(next, last) == 0) + ret = -EEXIST; + else +- ret = -ENOENT; ++ ret = -EPERM; + goto out; + } + +@@ -2908,7 +2908,7 @@ int cg_rmdir(const char *path) + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -EINVAL; ++ return -errno; + + cgroup = find_cgroup_in_path(path); + if (!cgroup) +-- +2.9.3 + diff --git a/0016-add-pld-linux-support.patch b/0016-add-pld-linux-support.patch new file mode 100644 index 0000000..baafc7b --- /dev/null +++ b/0016-add-pld-linux-support.patch @@ -0,0 +1,47 @@ +From 00d7fdd826af7afd37f18d99e371bd0aeb1afb79 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= +Date: Fri, 26 Aug 2016 00:18:46 +0300 +Subject: [PATCH 16/24] add pld linux support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Elan Ruusamäe +--- + configure.ac | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index dae4218..6c5c8be 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -66,6 +66,7 @@ if test "z$with_distro" = "z"; then + AC_CHECK_FILE(/etc/mandrakelinux-release, with_distro="openmandriva") + AC_CHECK_FILE(/etc/mandriva-release,with_distro="openmandriva") + AC_CHECK_FILE(/etc/pardus-release,with_distro="pardus") ++ AC_CHECK_FILE(/etc/pld-release,with_distro="pld") + fi + with_distro=`echo ${with_distro} | tr '[[:upper:]]' '[[:lower:]]'` + +@@ -76,7 +77,7 @@ case $with_distro in + ubuntu) + distroconf=default.conf.ubuntu + ;; +- redhat|centos|fedora|oracle|oracleserver) ++ redhat|centos|fedora|oracle|oracleserver|pld) + distroconf=default.conf.libvirt + ;; + *) +@@ -108,6 +109,9 @@ case "$with_init_script" in + ubuntu) + init_script=upstart,systemd,sysvinit + ;; ++ pld) ++ init_script=systemd,sysvinit ++ ;; + slackware) + echo -n "Warning: bsd init job not yet implemented" + init_script= +-- +2.9.3 + diff --git a/0017-don-t-use-argv-0-in-usage-output.patch b/0017-don-t-use-argv-0-in-usage-output.patch new file mode 100644 index 0000000..6c9771a --- /dev/null +++ b/0017-don-t-use-argv-0-in-usage-output.patch @@ -0,0 +1,50 @@ +From c3fb7d7fbdc2d9cb2e9e818ac8fce52442583921 Mon Sep 17 00:00:00 2001 +From: Evgeni Golov +Date: Fri, 26 Aug 2016 09:33:09 +0200 +Subject: [PATCH 17/24] don't use argv[0] in usage output + +otherwise this generates "funny" manpages like + /home/remote/egolov/Devel/lxcfs/.libs/lt-lxcfs [-p pidfile] mountpoint + /home/remote/egolov/Devel/lxcfs/.libs/lt-lxcfs -h +or + /build/lxcfs-8lNGve/lxcfs-2.0/.1/.libs/lt-lxcfs [-p pidfile] mountpoint + /build/lxcfs-8lNGve/lxcfs-2.0/.1/.libs/lt-lxcfs -h + +Signed-off-by: Evgeni Golov +--- + lxcfs.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/lxcfs.c b/lxcfs.c +index 47afe13..e745ce5 100644 +--- a/lxcfs.c ++++ b/lxcfs.c +@@ -708,13 +708,13 @@ const struct fuse_operations lxcfs_ops = { + .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 [-p pidfile] mountpoint\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); + } + +@@ -838,7 +838,7 @@ int main(int argc, char *argv[]) + exit(EXIT_SUCCESS); + } + if (argc != 2 || is_help(argv[1])) +- usage(argv[0]); ++ usage(); + + do_reload(); + if (signal(SIGUSR1, reload_handler) == SIG_ERR) { +-- +2.9.3 + diff --git a/0018-bindings-revert-cgroup-check.patch b/0018-bindings-revert-cgroup-check.patch new file mode 100644 index 0000000..b2a4e41 --- /dev/null +++ b/0018-bindings-revert-cgroup-check.patch @@ -0,0 +1,50 @@ +From 9873c5e858f9628435afa7ff6b6cc50afbb91e06 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Thu, 25 Aug 2016 22:33:07 +0200 +Subject: [PATCH 18/24] bindings: revert cgroup check + +We do not need to check whether mode & W_OK is passed in. Even if the cgroup +root mount is writeable operations like cg_mkdir() et al. will fail with e.g. +EPERM. Basically all operations will fail on the cgroup root mount point because +the first operation they perform is pick_controller_from_path(). That is to say +they try to e.g. pick "blkio" from /var/lib/lxcfs/cgroup/blkio/some/cgroups an +similiar for all other controllers. If pick_controller_from_path() fails they +all return an appropriate errno. For example, cg_mkdir() does: + + controller = pick_controller_from_path(fc, path); + if (!controller) + return errno == ENOENT ? -EPERM : -errno; + +This means, we do not need to return an errno already in cg_access when +mode & W_OK is passed in. This has the advantage that users are still able to +descend into /var/lib/lxcfs/cgroup via: + + cd /var/lib/lxcfs/cgroup + +but are still blocked from doing any write operations. + +Signed-off-by: Christian Brauner +--- + bindings.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 281aad2..8a5909a 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -1926,11 +1926,8 @@ int cg_access(const char *path, int mode) + struct cgfs_files *k = NULL; + struct fuse_context *fc = fuse_get_context(); + +- if (strcmp(path, "/cgroup") == 0) { +- if ((mode & W_OK) == 0) +- return -EACCES; ++ if (strcmp(path, "/cgroup") == 0) + return 0; +- } + + if (!fc) + return -EIO; +-- +2.9.3 + diff --git a/0019-bindings-improve-returned-errnos.patch b/0019-bindings-improve-returned-errnos.patch new file mode 100644 index 0000000..21381fa --- /dev/null +++ b/0019-bindings-improve-returned-errnos.patch @@ -0,0 +1,113 @@ +From bc70ba9b492f1af79ce692471f3e300eaf4afe29 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Fri, 26 Aug 2016 10:32:32 +0200 +Subject: [PATCH 19/24] bindings: improve returned errnos + +Signed-off-by: Christian Brauner +--- + bindings.c | 34 ++++++++++++++++++++-------------- + 1 file changed, 20 insertions(+), 14 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 8a5909a..aaba840 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -1541,12 +1541,17 @@ static const char *find_cgroup_in_path(const char *path) + { + const char *p1; + +- if (strlen(path) < 9) ++ if (strlen(path) < 9) { ++ errno = EINVAL; + return NULL; +- p1 = strstr(path+8, "/"); +- if (!p1) ++ } ++ p1 = strstr(path + 8, "/"); ++ if (!p1) { ++ errno = EINVAL; + return NULL; +- return p1+1; ++ } ++ errno = 0; ++ return p1 + 1; + } + + /* +@@ -1866,7 +1871,7 @@ int cg_open(const char *path, struct fuse_file_info *fi) + return -errno; + cgroup = find_cgroup_in_path(path); + if (!cgroup) +- return -EINVAL; ++ return -errno; + + get_cgdir_and_path(cgroup, &cgdir, &last); + if (!last) { +@@ -2717,15 +2722,16 @@ int cg_chown(const char *path, uid_t uid, gid_t gid) + return -EIO; + + if (strcmp(path, "/cgroup") == 0) +- return -EINVAL; ++ return -EPERM; + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -errno; ++ return errno == ENOENT ? -EPERM : -errno; ++ + cgroup = find_cgroup_in_path(path); + if (!cgroup) + /* this is just /cgroup/controller */ +- return -EINVAL; ++ return -EPERM; + + get_cgdir_and_path(cgroup, &cgdir, &last); + +@@ -2782,15 +2788,16 @@ int cg_chmod(const char *path, mode_t mode) + return -EIO; + + if (strcmp(path, "/cgroup") == 0) +- return -EINVAL; ++ return -EPERM; + + controller = pick_controller_from_path(fc, path); + if (!controller) +- return -errno; ++ return errno == ENOENT ? -EPERM : -errno; ++ + cgroup = find_cgroup_in_path(path); + if (!cgroup) + /* this is just /cgroup/controller */ +- return -EINVAL; ++ return -EPERM; + + get_cgdir_and_path(cgroup, &cgdir, &last); + +@@ -2848,14 +2855,13 @@ int cg_mkdir(const char *path, mode_t mode) + if (!fc) + return -EIO; + +- + controller = pick_controller_from_path(fc, path); + if (!controller) + return errno == ENOENT ? -EPERM : -errno; + + cgroup = find_cgroup_in_path(path); + if (!cgroup) +- return -EINVAL; ++ return -errno; + + get_cgdir_and_path(cgroup, &cgdir, &last); + if (!last) +@@ -2909,7 +2915,7 @@ int cg_rmdir(const char *path) + + cgroup = find_cgroup_in_path(path); + if (!cgroup) +- return -EINVAL; ++ return -errno; + + get_cgdir_and_path(cgroup, &cgdir, &last); + if (!last) { +-- +2.9.3 + diff --git a/0020-bindings-make-rmdir-behave-more-consistently.patch b/0020-bindings-make-rmdir-behave-more-consistently.patch new file mode 100644 index 0000000..8c965b1 --- /dev/null +++ b/0020-bindings-make-rmdir-behave-more-consistently.patch @@ -0,0 +1,78 @@ +From e254948fb93869c1a771cf5778161e703a422918 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Fri, 26 Aug 2016 16:26:27 +0200 +Subject: [PATCH 20/24] bindings: make rmdir behave more consistently + +We should be able to safely return -EPERM for: + + if (!pick_controller_from_path()) + /* Someone's trying to delete "/cgroup". */ + + if (!find_cgroup_in_path()) + /* Someone's trying to delete a controller e.g. "/blkio". */ + + if (!get_cgdir_and_path()) { + /* Someone's trying to delete a cgroup on the same level as the + * "/lxc" cgroup e.g. rmdir "/cgroup/blkio/lxc" or + * rmdir "/cgroup/blkio/init.slice". + */ + } + +All other interesting cases are caught further down. + +Signed-off-by: Christian Brauner +--- + bindings.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/bindings.c b/bindings.c +index aaba840..4413a7d 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -1507,7 +1507,7 @@ static char *pick_controller_from_path(struct fuse_context *fc, const char *path + char *contr, *slash; + + if (strlen(path) < 9) { +- errno = EINVAL; ++ errno = EACCES; + return NULL; + } + if (*(path + 7) != '/') { +@@ -1542,7 +1542,7 @@ static const char *find_cgroup_in_path(const char *path) + const char *p1; + + if (strlen(path) < 9) { +- errno = EINVAL; ++ errno = EACCES; + return NULL; + } + p1 = strstr(path + 8, "/"); +@@ -2910,16 +2910,20 @@ int cg_rmdir(const char *path) + return -EIO; + + controller = pick_controller_from_path(fc, path); +- if (!controller) +- return -errno; ++ if (!controller) /* Someone's trying to delete "/cgroup". */ ++ return -EPERM; + + cgroup = find_cgroup_in_path(path); +- if (!cgroup) +- return -errno; ++ if (!cgroup) /* Someone's trying to delete a controller e.g. "/blkio". */ ++ return -EPERM; + + get_cgdir_and_path(cgroup, &cgdir, &last); + if (!last) { +- ret = -EINVAL; ++ /* Someone's trying to delete a cgroup on the same level as the ++ * "/lxc" cgroup e.g. rmdir "/cgroup/blkio/lxc" or ++ * rmdir "/cgroup/blkio/init.slice". ++ */ ++ ret = -EPERM; + goto out; + } + +-- +2.9.3 + diff --git a/0021-libtool-do-not-link-lxcfs-against-liblxcfs.patch b/0021-libtool-do-not-link-lxcfs-against-liblxcfs.patch new file mode 100644 index 0000000..de3b1a5 --- /dev/null +++ b/0021-libtool-do-not-link-lxcfs-against-liblxcfs.patch @@ -0,0 +1,51 @@ +From 23748216d35bc40c36bc5dd35199fd37f3d3152b Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 29 Aug 2016 10:12:27 +0200 +Subject: [PATCH 21/24] libtool: do not link lxcfs against liblxcfs + +Make liblxcfs a libtool module. Also, stop linking lxcfs against liblxcfs. We do +not really need this since we call dlopen() anyway. Furthermore, this allows us +to make sure that functions marked with __attribute__(constructor) are not run +before we call dlopen() in main() in lxcfs. This has the advantage that we can +show help output without __attribute__(constructor) functions being run. + +Signed-off-by: Christian Brauner +--- + Makefile.am | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index cb4abc1..444eaf5 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -9,15 +9,15 @@ AM_CFLAGS += -DLIBDIR=\"$(LIBDIR)\" + AM_LDFLAGS = $(FUSE_LIBS) -pthread + #AM_CFLAGS += -DDEBUG + +-AM_CFLAGS += -DRUNTIME_PATH=\"$(RUNTIME_PATH)\" ++AM_CFLAGS += -DRUNTIME_PATH=\"$(RUNTIME_PATH)\" + + liblxcfs_la_SOURCES = bindings.c cpuset.c bindings.h + liblxcfs_la_CFLAGS = $(AM_CFLAGS) +-liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -shared ++liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -module -shared + + liblxcfstest_la_SOURCES = bindings.c cpuset.c bindings.h + liblxcfstest_la_CFLAGS = $(AM_CFLAGS) -DRELOADTEST +-liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -shared ++liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -module -shared + + noinst_HEADERS = bindings.h + +@@ -26,7 +26,7 @@ lib_LTLIBRARIES = liblxcfs.la + EXTRA_LTLIBRARIES = liblxcfstest.la + + lxcfs_SOURCES = lxcfs.c +-lxcfs_LDADD = liblxcfs.la -ldl ++lxcfs_LDADD = -ldl + lxcfs_CFLAGS = $(AM_CFLAGS) + lxcfs_LDFLAGS = $(AM_LDFLAGS) + bin_PROGRAMS = lxcfs +-- +2.9.3 + diff --git a/0022-bindings-lxcfs-improve-debugging.patch b/0022-bindings-lxcfs-improve-debugging.patch new file mode 100644 index 0000000..c36b457 --- /dev/null +++ b/0022-bindings-lxcfs-improve-debugging.patch @@ -0,0 +1,943 @@ +From b8defc3d52173e4773de1ab17b873dd79e187dc1 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Mon, 29 Aug 2016 10:33:49 +0200 +Subject: [PATCH 22/24] bindings, lxcfs: improve debugging + +Signed-off-by: Christian Brauner +--- + bindings.c | 188 +++++++++++++++++++++++++++++-------------------------------- + bindings.h | 14 +++++ + lxcfs.c | 56 +++++++++--------- + 3 files changed, 133 insertions(+), 125 deletions(-) + +diff --git a/bindings.c b/bindings.c +index 4413a7d..b2d5553 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -48,16 +48,6 @@ return -1; + extern int pivot_root(const char * new_root, const char * put_old); + #endif + +-#ifdef DEBUG +-#define lxcfs_debug(format, ...) \ +- do { \ +- fprintf(stderr, "%s: %d: %s: " format, __FILE__, __LINE__, \ +- __func__, __VA_ARGS__); \ +- } while (false) +-#else +-#define lxcfs_debug(format, ...) +-#endif /* DEBUG */ +- + enum { + LXC_TYPE_CGDIR, + LXC_TYPE_CGFILE, +@@ -116,7 +106,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); + } + } +@@ -146,7 +136,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); + } + } +@@ -383,12 +373,12 @@ static bool write_string(const char *fnam, const char *string, int fd) + len = strlen(string); + ret = fwrite(string, 1, len, f); + if (ret != len) { +- fprintf(stderr, "Error writing to file: %s\n", strerror(errno)); ++ lxcfs_error("Error writing to file: %s\n", strerror(errno)); + fclose(f); + return false; + } + if (fclose(f) < 0) { +- fprintf(stderr, "Error writing to file: %s\n", strerror(errno)); ++ lxcfs_error("Error writing to file: %s\n", strerror(errno)); + return false; + } + return true; +@@ -408,7 +398,7 @@ static bool store_hierarchy(char *stridx, char *h) + n *= ALLOC_NUM; + char **tmp = realloc(hierarchies, n * sizeof(char *)); + if (!tmp) { +- fprintf(stderr, "Out of memory\n"); ++ lxcfs_error("%s\n", strerror(errno)); + exit(1); + } + hierarchies = tmp; +@@ -425,7 +415,8 @@ static void print_subsystems(void) + fprintf(stderr, "hierarchies:\n"); + for (i = 0; i < num_hierarchies; i++) { + if (hierarchies[i]) +- fprintf(stderr, " %d: %s\n", i, hierarchies[i]); ++ fprintf(stderr, " %2d: fd: %3d: %s\n", i, ++ fd_hierarchies[i], hierarchies[i]); + } + } + +@@ -512,7 +503,7 @@ static void chown_all_cgroup_files(const char *dirname, uid_t uid, gid_t gid, in + + len = strlen(dirname); + if (len >= MAXPATHLEN) { +- fprintf(stderr, "chown_all_cgroup_files: pathname too long: %s\n", dirname); ++ lxcfs_error("Pathname too long: %s\n", dirname); + return; + } + +@@ -522,7 +513,7 @@ static void chown_all_cgroup_files(const char *dirname, uid_t uid, gid_t gid, in + + d = fdopendir(fd1); + if (!d) { +- fprintf(stderr, "chown_all_cgroup_files: failed to open %s\n", dirname); ++ lxcfs_error("Failed to open %s\n", dirname); + return; + } + +@@ -531,11 +522,11 @@ static void chown_all_cgroup_files(const char *dirname, uid_t uid, gid_t gid, in + continue; + ret = snprintf(path, MAXPATHLEN, "%s/%s", dirname, direntp->d_name); + if (ret < 0 || ret >= MAXPATHLEN) { +- fprintf(stderr, "chown_all_cgroup_files: pathname too long under %s\n", dirname); ++ lxcfs_error("Pathname too long under %s\n", dirname); + continue; + } + if (fchownat(fd, path, uid, gid, 0) < 0) +- fprintf(stderr, "Failed to chown file %s to %u:%u", path, uid, gid); ++ lxcfs_error("Failed to chown file %s to %u:%u", path, uid, gid); + } + closedir(d); + } +@@ -600,7 +591,7 @@ static bool recursive_rmdir(const char *dirname, int fd, const int cfd) + + rc = snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name); + if (rc < 0 || rc >= MAXPATHLEN) { +- fprintf(stderr, "pathname too long\n"); ++ lxcfs_error("%s\n", "Pathname too long."); + continue; + } + +@@ -616,7 +607,7 @@ static bool recursive_rmdir(const char *dirname, int fd, const int cfd) + + ret = true; + if (closedir(dir) < 0) { +- fprintf(stderr, "%s: failed to close directory %s: %s\n", __func__, dirname, strerror(errno)); ++ lxcfs_error("Failed to close directory %s: %s\n", dirname, strerror(errno)); + ret = false; + } + +@@ -766,7 +757,7 @@ static bool cgfs_iterate_cgroup(const char *controller, const char *cgroup, bool + cg = alloca(len); + ret = snprintf(cg, len, "%s%s", *cgroup == '/' ? "." : "", cgroup); + if (ret < 0 || (size_t)ret >= len) { +- fprintf(stderr, "%s: pathname too long under %s\n", __func__, cgroup); ++ lxcfs_error("Pathname too long under %s\n", cgroup); + return false; + } + +@@ -787,13 +778,13 @@ static bool cgfs_iterate_cgroup(const char *controller, const char *cgroup, bool + + ret = snprintf(pathname, MAXPATHLEN, "%s/%s", cg, dirent->d_name); + if (ret < 0 || ret >= MAXPATHLEN) { +- fprintf(stderr, "%s: pathname too long under %s\n", __func__, cg); ++ lxcfs_error("Pathname too long under %s\n", cg); + continue; + } + + ret = fstatat(cfd, pathname, &mystat, AT_SYMLINK_NOFOLLOW); + if (ret) { +- fprintf(stderr, "%s: failed to stat %s: %s\n", __func__, pathname, strerror(errno)); ++ lxcfs_error("Failed to stat %s: %s\n", pathname, strerror(errno)); + continue; + } + if ((!directories && !S_ISREG(mystat.st_mode)) || +@@ -813,7 +804,7 @@ static bool cgfs_iterate_cgroup(const char *controller, const char *cgroup, bool + sz++; + } + if (closedir(dir) < 0) { +- fprintf(stderr, "%s: failed closedir for %s: %s\n", __func__, cgroup, strerror(errno)); ++ lxcfs_error("Failed closedir for %s: %s\n", cgroup, strerror(errno)); + return false; + } + return true; +@@ -932,8 +923,8 @@ static void *make_key_list_entry(const char *controller, const char *cgroup, con + { + struct cgfs_files *entry = cgfs_get_key(controller, cgroup, dir_entry); + if (!entry) { +- fprintf(stderr, "%s: Error getting files under %s:%s\n", +- __func__, controller, cgroup); ++ lxcfs_error("Error getting files under %s:%s\n", controller, ++ cgroup); + } + return entry; + } +@@ -1170,7 +1161,7 @@ convert_id_to_ns(FILE *idfile, unsigned int in_id) + * uids wrapped around - unexpected as this is a procfile, + * so just bail. + */ +- fprintf(stderr, "pid wrapparound at entry %u %u %u in %s\n", ++ lxcfs_error("pid wrapparound at entry %u %u %u in %s\n", + nsuid, hostuid, count, line); + return -1; + } +@@ -1276,7 +1267,7 @@ static char *get_next_cgroup_dir(const char *taskcg, const char *querycg) + char *start, *end; + + if (strlen(taskcg) <= strlen(querycg)) { +- fprintf(stderr, "%s: I was fed bad input\n", __func__); ++ lxcfs_error("%s\n", "I was fed bad input."); + return NULL; + } + +@@ -1758,7 +1749,7 @@ int cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset + return -EIO; + + if (d->type != LXC_TYPE_CGDIR) { +- fprintf(stderr, "Internal error: file cache info used in readdir\n"); ++ lxcfs_error("%s\n", "Internal error: file cache info used in readdir."); + return -EIO; + } + if (!d->cgroup && !d->controller) { +@@ -2003,14 +1994,14 @@ static bool wait_for_sock(int sock, int timeout) + return false; + + if ((epfd = epoll_create(1)) < 0) { +- fprintf(stderr, "Failed to create epoll socket: %m\n"); ++ lxcfs_error("%s\n", "Failed to create epoll socket: %m."); + return false; + } + + ev.events = POLLIN_SET; + ev.data.fd = sock; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev) < 0) { +- fprintf(stderr, "Failed adding socket to epoll: %m\n"); ++ lxcfs_error("%s\n", "Failed adding socket to epoll: %m."); + close(epfd); + return false; + } +@@ -2058,8 +2049,7 @@ static int send_creds(int sock, struct ucred *cred, char v, bool pingfirst) + + if (pingfirst) { + if (msgrecv(sock, buf, 1) != 1) { +- fprintf(stderr, "%s: Error getting reply from server over socketpair\n", +- __func__); ++ lxcfs_error("%s\n", "Error getting reply from server over socketpair."); + return SEND_CREDS_FAIL; + } + } +@@ -2083,8 +2073,7 @@ static int send_creds(int sock, struct ucred *cred, char v, bool pingfirst) + msg.msg_iovlen = 1; + + if (sendmsg(sock, &msg, 0) < 0) { +- fprintf(stderr, "%s: failed at sendmsg: %s\n", __func__, +- strerror(errno)); ++ lxcfs_error("Failed at sendmsg: %s.\n",strerror(errno)); + if (errno == 3) + return SEND_CREDS_NOTSK; + return SEND_CREDS_FAIL; +@@ -2110,12 +2099,12 @@ static bool recv_creds(int sock, struct ucred *cred, char *v) + cred->gid = -1; + + if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) { +- fprintf(stderr, "Failed to set passcred: %s\n", strerror(errno)); ++ lxcfs_error("Failed to set passcred: %s\n", strerror(errno)); + return false; + } + buf[0] = '1'; + if (write(sock, buf, 1) != 1) { +- fprintf(stderr, "Failed to start write on scm fd: %s\n", strerror(errno)); ++ lxcfs_error("Failed to start write on scm fd: %s\n", strerror(errno)); + return false; + } + +@@ -2130,14 +2119,12 @@ static bool recv_creds(int sock, struct ucred *cred, char *v) + msg.msg_iovlen = 1; + + if (!wait_for_sock(sock, 2)) { +- fprintf(stderr, "Timed out waiting for scm_cred: %s\n", +- strerror(errno)); ++ lxcfs_error("Timed out waiting for scm_cred: %s\n", strerror(errno)); + return false; + } + ret = recvmsg(sock, &msg, MSG_DONTWAIT); + if (ret < 0) { +- fprintf(stderr, "Failed to receive scm_cred: %s\n", +- strerror(errno)); ++ lxcfs_error("Failed to receive scm_cred: %s\n", strerror(errno)); + return false; + } + +@@ -2170,10 +2157,8 @@ static int pid_ns_clone_wrapper(void *arg) { + char b = '1'; + + close(args->cpipe[0]); +- if (write(args->cpipe[1], &b, sizeof(char)) < 0) { +- fprintf(stderr, "%s (child): error on write: %s\n", +- __func__, strerror(errno)); +- } ++ if (write(args->cpipe[1], &b, sizeof(char)) < 0) ++ lxcfs_error("(child): error on write: %s.\n", strerror(errno)); + close(args->cpipe[1]); + return args->wrapped(args->sock, args->tpid); + } +@@ -2307,13 +2292,11 @@ bool do_read_pids(pid_t tpid, const char *contrl, const char *cg, const char *fi + + // read converted results + if (!wait_for_sock(sock[0], 2)) { +- fprintf(stderr, "%s: timed out waiting for pid from child: %s\n", +- __func__, strerror(errno)); ++ lxcfs_error("Timed out waiting for pid from child: %s.\n", strerror(errno)); + goto out; + } + if (read(sock[0], &qpid, sizeof(qpid)) != sizeof(qpid)) { +- fprintf(stderr, "%s: error reading pid from child: %s\n", +- __func__, strerror(errno)); ++ lxcfs_error("Error reading pid from child: %s.\n", strerror(errno)); + goto out; + } + must_strcat_pid(d, &sz, &asz, qpid); +@@ -2328,8 +2311,7 @@ next: + v = '1'; + if (send_creds(sock[0], &cred, v, true) != SEND_CREDS_OK) { + // failed to ask child to exit +- fprintf(stderr, "%s: failed to ask child to exit: %s\n", +- __func__, strerror(errno)); ++ lxcfs_error("Failed to ask child to exit: %s.\n", strerror(errno)); + goto out; + } + +@@ -2357,7 +2339,7 @@ int cg_read(const char *path, char *buf, size_t size, off_t offset, + bool r; + + if (f->type != LXC_TYPE_CGFILE) { +- fprintf(stderr, "Internal error: directory cache info used in cg_read\n"); ++ lxcfs_error("%s\n", "Internal error: directory cache info used in cg_read."); + return -EIO; + } + +@@ -2424,12 +2406,11 @@ static int pid_from_ns(int sock, pid_t tpid) + cred.gid = 0; + while (1) { + if (!wait_for_sock(sock, 2)) { +- fprintf(stderr, "%s: timeout reading from parent\n", __func__); ++ lxcfs_error("%s\n", "Timeout reading from parent."); + return 1; + } + if ((ret = read(sock, &vpid, sizeof(pid_t))) != sizeof(pid_t)) { +- fprintf(stderr, "%s: bad read from parent: %s\n", +- __func__, strerror(errno)); ++ lxcfs_error("Bad read from parent: %s.\n", strerror(errno)); + return 1; + } + if (vpid == -1) // done +@@ -2530,20 +2511,20 @@ void get_pid_creds(pid_t pid, uid_t *uid, gid_t *gid) + *gid = -1; + sprintf(line, "/proc/%d/status", pid); + if ((f = fopen(line, "r")) == NULL) { +- fprintf(stderr, "Error opening %s: %s\n", line, strerror(errno)); ++ lxcfs_error("Error opening %s: %s\n", line, strerror(errno)); + return; + } + while (fgets(line, 400, f)) { + if (strncmp(line, "Uid:", 4) == 0) { + if (sscanf(line+4, "%u", &u) != 1) { +- fprintf(stderr, "bad uid line for pid %u\n", pid); ++ lxcfs_error("bad uid line for pid %u\n", pid); + fclose(f); + return; + } + *uid = u; + } else if (strncmp(line, "Gid:", 4) == 0) { + if (sscanf(line+4, "%u", &g) != 1) { +- fprintf(stderr, "bad gid line for pid %u\n", pid); ++ lxcfs_error("bad gid line for pid %u\n", pid); + fclose(f); + return; + } +@@ -2615,8 +2596,7 @@ static bool do_write_pids(pid_t tpid, uid_t tuid, const char *contrl, const char + char v; + + if (write(sock[0], &qpid, sizeof(qpid)) != sizeof(qpid)) { +- fprintf(stderr, "%s: error writing pid to child: %s\n", +- __func__, strerror(errno)); ++ lxcfs_error("Error writing pid to child: %s.\n", strerror(errno)); + goto out; + } + +@@ -2640,7 +2620,7 @@ static bool do_write_pids(pid_t tpid, uid_t tuid, const char *contrl, const char + /* All good, write the value */ + qpid = -1; + if (write(sock[0], &qpid ,sizeof(qpid)) != sizeof(qpid)) +- fprintf(stderr, "Warning: failed to ask child to exit\n"); ++ lxcfs_error("%s\n", "Warning: failed to ask child to exit."); + + if (!fail) + answer = true; +@@ -2669,7 +2649,7 @@ int cg_write(const char *path, const char *buf, size_t size, off_t offset, + bool r; + + if (f->type != LXC_TYPE_CGFILE) { +- fprintf(stderr, "Internal error: directory cache info used in cg_write\n"); ++ lxcfs_error("%s\n", "Internal error: directory cache info used in cg_write."); + return -EIO; + } + +@@ -3043,7 +3023,7 @@ static int read_file(const char *path, char *buf, size_t size, + goto err; + } + if (l >= cache_size) { +- fprintf(stderr, "Internal error: truncated write to cache\n"); ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); + rv = 0; + goto err; + } +@@ -3255,7 +3235,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, + + } + if (l >= cache_size) { +- fprintf(stderr, "Internal error: truncated write to cache\n"); ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); + rv = 0; + goto err; + } +@@ -3386,7 +3366,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset, + goto err; + } + if (l >= cache_size) { +- fprintf(stderr, "Internal error: truncated write to cache\n"); ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); + rv = 0; + goto err; + } +@@ -3411,7 +3391,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset, + goto err; + } + if (l >= cache_size) { +- fprintf(stderr, "Internal error: truncated write to cache\n"); ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); + rv = 0; + goto err; + } +@@ -3429,7 +3409,7 @@ static int proc_cpuinfo_read(char *buf, size_t size, off_t offset, + goto err; + } + if (l >= cache_size) { +- fprintf(stderr, "Internal error: truncated write to cache\n"); ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); + rv = 0; + goto err; + } +@@ -3536,7 +3516,7 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, + + //skip first line + if (getline(&line, &linelen, f) < 0) { +- fprintf(stderr, "proc_stat_read read first line failed\n"); ++ lxcfs_error("%s\n", "proc_stat_read read first line failed."); + goto err; + } + +@@ -3557,7 +3537,7 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, + goto err; + } + if (l >= cache_size) { +- fprintf(stderr, "Internal error: truncated write to cache\n"); ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); + rv = 0; + goto err; + } +@@ -3584,7 +3564,7 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, + + } + if (l >= cache_size) { +- fprintf(stderr, "Internal error: truncated write to cache\n"); ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); + rv = 0; + goto err; + } +@@ -3616,7 +3596,7 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, + cache += cpuall_len; + } else{ + /* shouldn't happen */ +- fprintf(stderr, "proc_stat_read copy cpuall failed, cpuall_len=%d\n", cpuall_len); ++ lxcfs_error("proc_stat_read copy cpuall failed, cpuall_len=%d.", cpuall_len); + cpuall_len = 0; + } + +@@ -3848,7 +3828,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset, + goto err; + } + if (l >= cache_size) { +- fprintf(stderr, "Internal error: truncated write to cache\n"); ++ lxcfs_error("%s\n", "Internal error: truncated write to cache."); + rv = 0; + goto err; + } +@@ -4149,7 +4129,7 @@ static bool mkdir_p(const char *dir, mode_t mode) + if (!makeme) + return false; + if (mkdir(makeme, mode) && errno != EEXIST) { +- fprintf(stderr, "failed to create directory '%s': %s", ++ lxcfs_error("Failed to create directory '%s': %s.\n", + makeme, strerror(errno)); + free(makeme); + return false; +@@ -4163,7 +4143,7 @@ static bool mkdir_p(const char *dir, mode_t mode) + static bool umount_if_mounted(void) + { + if (umount2(BASEDIR, MNT_DETACH) < 0 && errno != EINVAL) { +- fprintf(stderr, "failed to unmount %s: %s.\n", BASEDIR, strerror(errno)); ++ lxcfs_error("Failed to unmount %s: %s.\n", BASEDIR, strerror(errno)); + return false; + } + return true; +@@ -4175,25 +4155,25 @@ static int pivot_enter(void) + + oldroot = open("/", O_DIRECTORY | O_RDONLY); + if (oldroot < 0) { +- fprintf(stderr, "%s: Failed to open old root for fchdir.\n", __func__); ++ lxcfs_error("%s\n", "Failed to open old root for fchdir."); + return ret; + } + + newroot = open(ROOTDIR, O_DIRECTORY | O_RDONLY); + if (newroot < 0) { +- fprintf(stderr, "%s: Failed to open new root for fchdir.\n", __func__); ++ lxcfs_error("%s\n", "Failed to open new root for fchdir."); + goto err; + } + + /* change into new root fs */ + if (fchdir(newroot) < 0) { +- fprintf(stderr, "%s: Failed to change directory to new rootfs: %s.\n", __func__, ROOTDIR); ++ lxcfs_error("Failed to change directory to new rootfs: %s.\n", ROOTDIR); + goto err; + } + + /* pivot_root into our new root fs */ + if (pivot_root(".", ".") < 0) { +- fprintf(stderr, "%s: pivot_root() syscall failed: %s.\n", __func__, strerror(errno)); ++ lxcfs_error("pivot_root() syscall failed: %s.\n", strerror(errno)); + goto err; + } + +@@ -4203,16 +4183,16 @@ static int pivot_enter(void) + * to the old-root. + */ + if (fchdir(oldroot) < 0) { +- fprintf(stderr, "%s: Failed to enter old root.\n", __func__); ++ lxcfs_error("%s\n", "Failed to enter old root."); + goto err; + } + if (umount2(".", MNT_DETACH) < 0) { +- fprintf(stderr, "%s: Failed to detach old root.\n", __func__); ++ lxcfs_error("%s\n", "Failed to detach old root."); + goto err; + } + + if (fchdir(newroot) < 0) { +- fprintf(stderr, "%s: Failed to re-enter new root.\n", __func__); ++ lxcfs_error("%s\n", "Failed to re-enter new root."); + goto err; + } + +@@ -4230,22 +4210,22 @@ err: + static int pivot_prepare(void) + { + if (mkdir(ROOTDIR, 0700) < 0 && errno != EEXIST) { +- fprintf(stderr, "%s: Failed to create directory for new root.\n", __func__); ++ lxcfs_error("%s\n", "Failed to create directory for new root."); + return -1; + } + + if (mount("/", ROOTDIR, NULL, MS_BIND, 0) < 0) { +- fprintf(stderr, "%s: Failed to bind-mount / for new root: %s.\n", __func__, strerror(errno)); ++ lxcfs_error("Failed to bind-mount / for new root: %s.\n", strerror(errno)); + return -1; + } + + if (mount(RUNTIME_PATH, ROOTDIR RUNTIME_PATH, NULL, MS_BIND, 0) < 0) { +- fprintf(stderr, "%s: Failed to bind-mount /run into new root: %s.\n", __func__, strerror(errno)); ++ lxcfs_error("Failed to bind-mount /run into new root: %s.\n", strerror(errno)); + return -1; + } + + if (mount(BASEDIR, ROOTDIR BASEDIR, NULL, MS_REC | MS_MOVE, 0) < 0) { +- printf("%s: failed to move " BASEDIR " into new root: %s.\n", __func__, strerror(errno)); ++ printf("Failed to move " BASEDIR " into new root: %s.\n", strerror(errno)); + return -1; + } + +@@ -4268,27 +4248,27 @@ static bool pivot_new_root(void) + static bool setup_cgfs_dir(void) + { + if (!mkdir_p(BASEDIR, 0700)) { +- fprintf(stderr, "Failed to create lxcfs cgroup mountpoint.\n"); ++ lxcfs_error("%s\n", "Failed to create lxcfs cgroup mountpoint."); + return false; + } + + if (!umount_if_mounted()) { +- fprintf(stderr, "Failed to clean up old lxcfs cgroup mountpoint.\n"); ++ lxcfs_error("%s\n", "Failed to clean up old lxcfs cgroup mountpoint."); + return false; + } + + if (unshare(CLONE_NEWNS) < 0) { +- fprintf(stderr, "%s: Failed to unshare mount namespace: %s.\n", __func__, strerror(errno)); ++ lxcfs_error("Failed to unshare mount namespace: %s.\n", strerror(errno)); + return false; + } + + if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) { +- fprintf(stderr, "%s: Failed to remount / private: %s.\n", __func__, strerror(errno)); ++ lxcfs_error("Failed to remount / private: %s.\n", strerror(errno)); + return false; + } + + if (mount("tmpfs", BASEDIR, "tmpfs", 0, "size=100000,mode=700") < 0) { +- fprintf(stderr, "Failed to mount tmpfs over lxcfs cgroup mountpoint.\n"); ++ lxcfs_error("%s\n", "Failed to mount tmpfs over lxcfs cgroup mountpoint."); + return false; + } + +@@ -4318,7 +4298,7 @@ static bool do_mount_cgroups(void) + return false; + } + if (mount(controller, target, "cgroup", 0, controller) < 0) { +- fprintf(stderr, "Failed mounting cgroup %s\n", controller); ++ lxcfs_error("Failed mounting cgroup %s\n", controller); + free(target); + return false; + } +@@ -4339,7 +4319,7 @@ static bool cgfs_setup_controllers(void) + return false; + + if (!do_mount_cgroups()) { +- fprintf(stderr, "Failed to set up private lxcfs cgroup mounts.\n"); ++ lxcfs_error("%s\n", "Failed to set up private lxcfs cgroup mounts."); + return false; + } + +@@ -4370,7 +4350,7 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void) + int i, init_ns = -1; + + if ((f = fopen("/proc/self/cgroup", "r")) == NULL) { +- fprintf(stderr, "Error opening /proc/self/cgroup: %s\n", strerror(errno)); ++ lxcfs_error("Error opening /proc/self/cgroup: %s\n", strerror(errno)); + return; + } + while (getline(&line, &len, f) != -1) { +@@ -4400,23 +4380,31 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void) + + /* Preserve initial namespace. */ + init_ns = preserve_ns(getpid()); +- if (init_ns < 0) ++ if (init_ns < 0) { ++ lxcfs_error("%s\n", "Failed to preserve initial mount namespace."); + goto out; ++ } + + fd_hierarchies = malloc(sizeof(int *) * num_hierarchies); +- if (!fd_hierarchies) ++ if (!fd_hierarchies) { ++ lxcfs_error("%s\n", strerror(errno)); + goto out; ++ } + + for (i = 0; i < num_hierarchies; i++) + fd_hierarchies[i] = -1; + + /* This function calls unshare(CLONE_NEWNS) our initial mount namespace + * to privately mount lxcfs cgroups. */ +- if (!cgfs_setup_controllers()) ++ if (!cgfs_setup_controllers()) { ++ lxcfs_error("%s\n", "Failed to setup private cgroup mounts for lxcfs."); + goto out; ++ } + +- if (setns(init_ns, 0) < 0) ++ if (setns(init_ns, 0) < 0) { ++ lxcfs_error("Failed to switch back to initial mount namespace: %s.\n", strerror(errno)); + goto out; ++ } + + print_subsystems(); + +@@ -4431,6 +4419,8 @@ static void __attribute__((destructor)) free_subsystems(void) + { + int i; + ++ lxcfs_debug("%s\n", "Running destructor for liblxcfs."); ++ + for (i = 0; i < num_hierarchies; i++) { + if (hierarchies[i]) + free(hierarchies[i]); +diff --git a/bindings.h b/bindings.h +index 7cd75be..c295104 100644 +--- a/bindings.h ++++ b/bindings.h +@@ -2,6 +2,20 @@ + #define BASEDIR RUNTIME_PATH "/lxcfs/controllers" + #define ROOTDIR RUNTIME_PATH "/lxcfs/root" + ++#define lxcfs_debug_stream(stream, format, ...) \ ++ do { \ ++ fprintf(stderr, "%s: %d: %s: " format, __FILE__, __LINE__, \ ++ __func__, __VA_ARGS__); \ ++ } while (false) ++ ++#define lxcfs_error(format, ...) lxcfs_debug_stream(stderr, format, __VA_ARGS__) ++ ++#ifdef DEBUG ++#define lxcfs_debug(format, ...) lxcfs_error(format, __VA_ARGS__) ++#else ++#define lxcfs_debug(format, ...) ++#endif /* DEBUG */ ++ + extern int cg_write(const char *path, const char *buf, size_t size, off_t offset, + struct fuse_file_info *fi); + extern int cg_mkdir(const char *path, mode_t mode); +diff --git a/lxcfs.c b/lxcfs.c +index 2500f61..d065125 100644 +--- a/lxcfs.c ++++ b/lxcfs.c +@@ -43,7 +43,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); + } + } +@@ -53,7 +53,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); + } + } +@@ -74,23 +74,27 @@ static volatile sig_atomic_t need_reload; + * lock and when we know the user_count was 0 */ + static void do_reload(void) + { +- if (dlopen_handle) ++ 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; ++ } + + dlopen_handle = dlopen("/usr/lib/lxcfs/liblxcfs.so", RTLD_LAZY); + if (!dlopen_handle) { +- fprintf(stderr, "Failed to open liblxcfs: %s.\n", dlerror()); ++ lxcfs_error("Failed to open liblxcfs.so: %s.\n", dlerror()); + _exit(1); + } + + good: + if (need_reload) +- fprintf(stderr, "lxcfs: reloaded\n"); ++ lxcfs_error("%s\n", "lxcfs: reloaded"); + need_reload = 0; + } + +@@ -124,7 +128,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; + } + +@@ -139,7 +143,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; + } + +@@ -157,7 +161,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; + } + +@@ -175,7 +179,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; + } + +@@ -192,7 +196,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; + } + +@@ -207,7 +211,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; + } + +@@ -222,7 +226,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; + } + +@@ -237,7 +241,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; + } + +@@ -252,7 +256,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; + } + +@@ -270,7 +274,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; + } + +@@ -288,7 +292,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; + } + +@@ -303,7 +307,7 @@ 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; + } + +@@ -318,7 +322,7 @@ static int do_cg_access(const char *path, int mode) + cg_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "cg_access"); + error = dlerror(); + if (error != NULL) { +- fprintf(stderr, "cg_access: %s\n", error); ++ lxcfs_error("%s\n", error); + return -1; + } + +@@ -333,7 +337,7 @@ 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; + } + +@@ -348,7 +352,7 @@ static int do_proc_access(const char *path, int mode) + proc_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "proc_access"); + error = dlerror(); + if (error != NULL) { +- fprintf(stderr, "proc_access: %s\n", error); ++ lxcfs_error("%s\n", error); + return -1; + } + +@@ -363,7 +367,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; + } + +@@ -378,7 +382,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; + } + +@@ -393,7 +397,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; + } + +@@ -408,7 +412,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; + } + +@@ -798,7 +802,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; + } + +-- +2.9.3 + diff --git a/0023-bindings-fix-debug-macro.patch b/0023-bindings-fix-debug-macro.patch new file mode 100644 index 0000000..390285c --- /dev/null +++ b/0023-bindings-fix-debug-macro.patch @@ -0,0 +1,38 @@ +From 3b5a323346f95622d4b97d37a645b468d32a852c Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Tue, 30 Aug 2016 10:26:44 +0200 +Subject: [PATCH 23/24] bindings: fix debug macro + +Signed-off-by: Christian Brauner +--- + bindings.h | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/bindings.h b/bindings.h +index c295104..04d728c 100644 +--- a/bindings.h ++++ b/bindings.h +@@ -1,10 +1,13 @@ ++#ifndef __LXCFS_BINDINGS_H ++#define __LXCFS_BINDINGS_H ++ + /* directory under which we mount the controllers - /run/lxcfs/controllers */ + #define BASEDIR RUNTIME_PATH "/lxcfs/controllers" + #define ROOTDIR RUNTIME_PATH "/lxcfs/root" + + #define lxcfs_debug_stream(stream, format, ...) \ + do { \ +- fprintf(stderr, "%s: %d: %s: " format, __FILE__, __LINE__, \ ++ fprintf(stream, "%s: %d: %s: " format, __FILE__, __LINE__, \ + __func__, __VA_ARGS__); \ + } while (false) + +@@ -41,3 +44,5 @@ extern int proc_open(const char *path, struct fuse_file_info *fi); + extern int proc_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi); + extern int proc_access(const char *path, int mask); ++ ++#endif /* __LXCFS__BINDINGS_H */ +-- +2.9.3 + diff --git a/0024-bindings-restore-original-working-directory.patch b/0024-bindings-restore-original-working-directory.patch new file mode 100644 index 0000000..cbe3ee0 --- /dev/null +++ b/0024-bindings-restore-original-working-directory.patch @@ -0,0 +1,56 @@ +From e58dab009be0efbc2fbf60b4cff50d79d6ffbca8 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Wed, 31 Aug 2016 02:20:09 +0200 +Subject: [PATCH 24/24] bindings: restore original working directory + +Signed-off-by: Christian Brauner +--- + bindings.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/bindings.c b/bindings.c +index b2d5553..ac88f48 100644 +--- a/bindings.c ++++ b/bindings.c +@@ -4345,7 +4345,8 @@ static int preserve_ns(int pid) + static void __attribute__((constructor)) collect_and_mount_subsystems(void) + { + FILE *f; +- char *line = NULL; ++ char *cret, *line = NULL; ++ char cwd[MAXPATHLEN]; + size_t len = 0; + int i, init_ns = -1; + +@@ -4353,6 +4354,7 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void) + lxcfs_error("Error opening /proc/self/cgroup: %s\n", strerror(errno)); + return; + } ++ + while (getline(&line, &len, f) != -1) { + char *p, *p2; + +@@ -4394,6 +4396,10 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void) + for (i = 0; i < num_hierarchies; i++) + fd_hierarchies[i] = -1; + ++ cret = getcwd(cwd, MAXPATHLEN); ++ if (!cret) ++ lxcfs_debug("Could not retrieve current working directory: %s.\n", strerror(errno)); ++ + /* This function calls unshare(CLONE_NEWNS) our initial mount namespace + * to privately mount lxcfs cgroups. */ + if (!cgfs_setup_controllers()) { +@@ -4406,6 +4412,9 @@ static void __attribute__((constructor)) collect_and_mount_subsystems(void) + goto out; + } + ++ if (!cret || chdir(cwd) < 0) ++ lxcfs_debug("Could not change back to original working directory: %s.\n", strerror(errno)); ++ + print_subsystems(); + + out: +-- +2.9.3 + diff --git a/lxcfs-2.0.2.tar.gz b/lxcfs-2.0.2.tar.gz deleted file mode 100644 index cd0301f..0000000 --- a/lxcfs-2.0.2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:74d4e5935510a2e0553f188db796f3689e893537143c08a727e60282446f9621 -size 402563 diff --git a/lxcfs-2.0.3.tar.gz b/lxcfs-2.0.3.tar.gz new file mode 100644 index 0000000..7056fed --- /dev/null +++ b/lxcfs-2.0.3.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd94e19bff202cb9fe2aa7d244b2cccf53cf5d7f6dd76c815e1161e3ba4ce0df +size 403776 diff --git a/lxcfs.changes b/lxcfs.changes index 25ac59a..af875a8 100644 --- a/lxcfs.changes +++ b/lxcfs.changes @@ -1,3 +1,37 @@ +------------------------------------------------------------------- +Wed Aug 31 11:43:16 UTC 2016 - cbrauner@suse.de + +- update lxcfs to 2.0.3 +- add 0001-Fix-test_reload-for-lxcfs-chroot.patch +- add 0002-Virtualize-more-of-the-meminfo-fields.patch +- add 0003-pam-fix-race-in-cgroup-creation.patch +- add 0004-meminfo-don-t-show-negative-swapfree.patch +- add 0005-bindings-improve-debugging.patch +- add 0006-bindings-use-openat-fd-for-fstatat-unlinkat.patch +- add 0007-bindings-close-open-fds-on-error.patch +- add 0008-bindings-grant-access-to-var-lib-lxcfs.patch +- add 0009-bindings-enable-access-to-var-lib-lxcfs-cgroup.patch +- add 0010-bindings-allow-access-to-var-lib-lxcfs-proc.patch +- add 0011-lxcfs-bindings-show-.-and-.-dir-entries.patch +- add 0012-lxcfs-better-fs-behavior-on-var-lib-lxcfs.patch +- add 0013-bindings-non-functional-changes.patch +- add 0014-bindings-set-errno-in-pick_controller_from_path.patch +- add 0015-bindings-more-consistent-fs-behavior.patch +- add 0016-add-pld-linux-support.patch +- add 0017-don-t-use-argv-0-in-usage-output.patch +- add 0018-bindings-revert-cgroup-check.patch +- add 0019-bindings-improve-returned-errnos.patch +- add 0020-bindings-make-rmdir-behave-more-consistently.patch +- add 0021-libtool-do-not-link-lxcfs-against-liblxcfs.patch +- add 0022-bindings-lxcfs-improve-debugging.patch +- add 0023-bindings-fix-debug-macro.patch +- add 0024-bindings-restore-original-working-directory.patch + +------------------------------------------------------------------- +Wed Aug 31 11:37:18 UTC 2016 - cbrauner@suse.de + +- remove 0001-skip-empty-entries-under-proc-self-cgroup.patch + ------------------------------------------------------------------- Sat Jul 23 09:09:44 UTC 2016 - cbrauner@suse.com diff --git a/lxcfs.spec b/lxcfs.spec index a5790c5..56e07d7 100644 --- a/lxcfs.spec +++ b/lxcfs.spec @@ -15,19 +15,46 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # -Name: lxcfs -Version: 2.0.2 -Release: 0 -License: Apache-2.0 -Summary: FUSE filesystem for LXC -Url: http://linuxcontainers.org -Group: System/Management -Source: https://linuxcontainers.org/downloads/%{name}/%{name}-%{version}.tar.gz -Patch: 0001-skip-empty-entries-under-proc-self-cgroup.patch -BuildRequires: pkg-config -BuildRequires: pkgconfig(fuse) -BuildRequires: pam-devel -BuildRequires: help2man + +Name: lxcfs +Version: 2.0.3 +Release: 0 +Summary: FUSE filesystem for LXC +License: Apache-2.0 +Group: System/Management +Url: http://linuxcontainers.org +Source: https://linuxcontainers.org/downloads/%{name}/%{name}-%{version}.tar.gz +Patch0001: 0001-Fix-test_reload-for-lxcfs-chroot.patch +Patch0002: 0002-Virtualize-more-of-the-meminfo-fields.patch +Patch0003: 0003-pam-fix-race-in-cgroup-creation.patch +Patch0004: 0004-meminfo-don-t-show-negative-swapfree.patch +Patch0005: 0005-bindings-improve-debugging.patch +Patch0006: 0006-bindings-use-openat-fd-for-fstatat-unlinkat.patch +Patch0007: 0007-bindings-close-open-fds-on-error.patch +Patch0008: 0008-bindings-grant-access-to-var-lib-lxcfs.patch +Patch0009: 0009-bindings-enable-access-to-var-lib-lxcfs-cgroup.patch +Patch0010: 0010-bindings-allow-access-to-var-lib-lxcfs-proc.patch +Patch0011: 0011-lxcfs-bindings-show-.-and-.-dir-entries.patch +Patch0012: 0012-lxcfs-better-fs-behavior-on-var-lib-lxcfs.patch +Patch0013: 0013-bindings-non-functional-changes.patch +Patch0014: 0014-bindings-set-errno-in-pick_controller_from_path.patch +Patch0015: 0015-bindings-more-consistent-fs-behavior.patch +Patch0016: 0016-add-pld-linux-support.patch +Patch0017: 0017-don-t-use-argv-0-in-usage-output.patch +Patch0018: 0018-bindings-revert-cgroup-check.patch +Patch0019: 0019-bindings-improve-returned-errnos.patch +Patch0020: 0020-bindings-make-rmdir-behave-more-consistently.patch +Patch0021: 0021-libtool-do-not-link-lxcfs-against-liblxcfs.patch +Patch0022: 0022-bindings-lxcfs-improve-debugging.patch +Patch0023: 0023-bindings-fix-debug-macro.patch +Patch0024: 0024-bindings-restore-original-working-directory.patch +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: help2man +BuildRequires: libtool +BuildRequires: pam-devel +BuildRequires: pkg-config +BuildRequires: pkgconfig(fuse) BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -48,8 +75,8 @@ on recent kernels and focus is now on making containers feel more like a real in the proc masking feature. %package -n pam_cgfs -Summary: CGroup FS pam module -Group: System/Libraries +Summary: CGroup FS pam module +Group: System/Libraries %description -n pam_cgfs When a user logs in, this pam module will create cgroups which the user may @@ -57,10 +84,34 @@ administer, either for all controllers or for any controllers listed on the command line. %prep -%setup -q -%patch -p1 +%setup +%patch0001 -p1 +%patch0002 -p1 +%patch0003 -p1 +%patch0004 -p1 +%patch0005 -p1 +%patch0006 -p1 +%patch0007 -p1 +%patch0008 -p1 +%patch0009 -p1 +%patch0010 -p1 +%patch0011 -p1 +%patch0012 -p1 +%patch0013 -p1 +%patch0014 -p1 +%patch0015 -p1 +%patch0016 -p1 +%patch0017 -p1 +%patch0018 -p1 +%patch0019 -p1 +%patch0020 -p1 +%patch0021 -p1 +%patch0022 -p1 +%patch0023 -p1 +%patch0024 -p1 %build +autoreconf --force --install %configure --with-distro=suse make %{?_smp_mflags} @@ -117,3 +168,5 @@ rm -f %{buildroot}%{_libdir}/liblxcfs.la %files -n pam_cgfs %defattr(-,root,root) /%{_lib}/security/pam_cgfs.so + +%changelog