[lxc-devel] [lxcfs/master] liblxcfs: handle broken upgrades gracefully

brauner on Github lxc-bot at linuxcontainers.org
Fri Mar 13 12:26:18 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 365 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200313/914ae8e0/attachment.bin>
-------------- next part --------------
From 7689e7a469c85e227235bd57c6d2fcfeb70cbde2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 13 Mar 2020 12:22:26 +0100
Subject: [PATCH 1/3] tree-wide: mark lxcfs fuse ops

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/cgroup_fuse.c | 33 +++++++++++++++++----------------
 src/macro.h       |  2 ++
 src/proc_fuse.c   | 17 +++++++++--------
 src/sysfs_fuse.c  | 19 ++++++++++---------
 4 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/src/cgroup_fuse.c b/src/cgroup_fuse.c
index 46a7a2f..2ca7139 100644
--- a/src/cgroup_fuse.c
+++ b/src/cgroup_fuse.c
@@ -499,7 +499,7 @@ static bool fc_may_access(struct fuse_context *fc, const char *contrl, const cha
 	return ret;
 }
 
-int cg_getattr(const char *path, struct stat *sb)
+__lxcfs_fuse_ops int cg_getattr(const char *path, struct stat *sb)
 {
 	struct timespec now;
 	struct fuse_context *fc = fuse_get_context();
@@ -682,7 +682,7 @@ static int cgfs_create(const char *controller, const char *cg, uid_t uid, gid_t
 	return 0;
 }
 
-int cg_mkdir(const char *path, mode_t mode)
+__lxcfs_fuse_ops int cg_mkdir(const char *path, mode_t mode)
 {
 	struct fuse_context *fc = fuse_get_context();
 	char *last = NULL, *path1, *cgdir = NULL, *controller, *next = NULL;
@@ -822,7 +822,7 @@ static bool cgfs_remove(const char *controller, const char *cg)
 	return bret;
 }
 
-int cg_rmdir(const char *path)
+__lxcfs_fuse_ops int cg_rmdir(const char *path)
 {
 	struct fuse_context *fc = fuse_get_context();
 	char *last = NULL, *cgdir = NULL, *controller, *next = NULL;
@@ -904,7 +904,7 @@ static bool cgfs_chmod_file(const char *controller, const char *file, mode_t mod
 	return true;
 }
 
-int cg_chmod(const char *path, mode_t mode)
+__lxcfs_fuse_ops int cg_chmod(const char *path, mode_t mode)
 {
 	struct fuse_context *fc = fuse_get_context();
 	char * cgdir = NULL, *last = NULL, *path1, *path2, *controller;
@@ -1024,7 +1024,7 @@ static int cgfs_chown_file(const char *controller, const char *file, uid_t uid,
 	return 0;
 }
 
-int cg_chown(const char *path, uid_t uid, gid_t gid)
+__lxcfs_fuse_ops int cg_chown(const char *path, uid_t uid, gid_t gid)
 {
 	struct fuse_context *fc = fuse_get_context();
 	char *cgdir = NULL, *last = NULL, *path1, *path2, *controller;
@@ -1090,7 +1090,7 @@ int cg_chown(const char *path, uid_t uid, gid_t gid)
 	return ret;
 }
 
-int cg_open(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int cg_open(const char *path, struct fuse_file_info *fi)
 {
 	const char *cgroup;
 	char *last = NULL, *path1, *path2, * cgdir = NULL, *controller;
@@ -1354,8 +1354,8 @@ static bool do_read_pids(pid_t tpid, const char *contrl, const char *cg,
 	return answer;
 }
 
-int cg_read(const char *path, char *buf, size_t size, off_t offset,
-	    struct fuse_file_info *fi)
+__lxcfs_fuse_ops int cg_read(const char *path, char *buf, size_t size,
+			     off_t offset, struct fuse_file_info *fi)
 {
 	struct fuse_context *fc = fuse_get_context();
 	struct file_info *f = INTTYPE_TO_PTR(fi->fh);
@@ -1421,7 +1421,7 @@ int cg_read(const char *path, char *buf, size_t size, off_t offset,
 	return ret;
 }
 
-int cg_opendir(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int cg_opendir(const char *path, struct fuse_file_info *fi)
 {
 	struct fuse_context *fc = fuse_get_context();
 	const char *cgroup;
@@ -1472,13 +1472,13 @@ int cg_opendir(const char *path, struct fuse_file_info *fi)
 	return 0;
 }
 
-int cg_release(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int cg_release(const char *path, struct fuse_file_info *fi)
 {
 	do_release_file_info(fi);
 	return 0;
 }
 
-int cg_releasedir(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int cg_releasedir(const char *path, struct fuse_file_info *fi)
 {
 	do_release_file_info(fi);
 	return 0;
@@ -1805,8 +1805,8 @@ static bool cgfs_set_value(const char *controller, const char *cgroup,
 	return write_string(fnam, value, fd);
 }
 
-int cg_write(const char *path, const char *buf, size_t size, off_t offset,
-	     struct fuse_file_info *fi)
+__lxcfs_fuse_ops int cg_write(const char *path, const char *buf, size_t size,
+			      off_t offset, struct fuse_file_info *fi)
 {
 	struct fuse_context *fc = fuse_get_context();
 	char *localbuf = NULL;
@@ -1974,8 +1974,9 @@ static void free_keys(struct cgfs_files **keys)
 	free_disarm(keys);
 }
 
-int cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-	       off_t offset, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int cg_readdir(const char *path, void *buf,
+				fuse_fill_dir_t filler, off_t offset,
+				struct fuse_file_info *fi)
 {
 	struct file_info *d = INTTYPE_TO_PTR(fi->fh);
 	struct cgfs_files **list = NULL;
@@ -2065,7 +2066,7 @@ int cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 	return ret;
 }
 
-int cg_access(const char *path, int mode)
+__lxcfs_fuse_ops int cg_access(const char *path, int mode)
 {
 	int ret;
 	const char *cgroup;
diff --git a/src/macro.h b/src/macro.h
index ce08510..29b5ed7 100644
--- a/src/macro.h
+++ b/src/macro.h
@@ -123,4 +123,6 @@
 
 #define __visible __attribute__((visibility("default")))
 
+#define __lxcfs_fuse_ops
+
 #endif /* __LXCFS_MACRO_H */
diff --git a/src/proc_fuse.c b/src/proc_fuse.c
index b62d6e4..ae557a9 100644
--- a/src/proc_fuse.c
+++ b/src/proc_fuse.c
@@ -72,7 +72,7 @@ struct memory_stat {
 	uint64_t total_unevictable;
 };
 
-int proc_getattr(const char *path, struct stat *sb)
+__lxcfs_fuse_ops int proc_getattr(const char *path, struct stat *sb)
 {
 	struct timespec now;
 
@@ -104,8 +104,9 @@ int proc_getattr(const char *path, struct stat *sb)
 	return -ENOENT;
 }
 
-int proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-		 off_t offset, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int proc_readdir(const char *path, void *buf,
+				  fuse_fill_dir_t filler, off_t offset,
+				  struct fuse_file_info *fi)
 {
 	if (filler(buf, ".",		NULL, 0) != 0 ||
 	    filler(buf, "..",		NULL, 0) != 0 ||
@@ -138,7 +139,7 @@ static off_t get_procfile_size(const char *path)
 	return answer;
 }
 
-int proc_open(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int proc_open(const char *path, struct fuse_file_info *fi)
 {
 	__do_free struct file_info *info = NULL;
 	int type = -1;
@@ -181,7 +182,7 @@ int proc_open(const char *path, struct fuse_file_info *fi)
 	return 0;
 }
 
-int proc_access(const char *path, int mask)
+__lxcfs_fuse_ops int proc_access(const char *path, int mask)
 {
 	if (strcmp(path, "/proc") == 0 && access(path, R_OK) == 0)
 		return 0;
@@ -193,7 +194,7 @@ int proc_access(const char *path, int mask)
 	return 0;
 }
 
-int proc_release(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int proc_release(const char *path, struct fuse_file_info *fi)
 {
 	do_release_file_info(fi);
 	return 0;
@@ -1248,8 +1249,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
 	return total_len;
 }
 
-int proc_read(const char *path, char *buf, size_t size, off_t offset,
-	      struct fuse_file_info *fi)
+__lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
+			       off_t offset, struct fuse_file_info *fi)
 {
 	struct file_info *f = INTTYPE_TO_PTR(fi->fh);
 
diff --git a/src/sysfs_fuse.c b/src/sysfs_fuse.c
index 3114e4f..85bc12c 100644
--- a/src/sysfs_fuse.c
+++ b/src/sysfs_fuse.c
@@ -133,7 +133,7 @@ static off_t get_sysfile_size(const char *which)
 	return answer;
 }
 
-int sys_getattr(const char *path, struct stat *sb)
+__lxcfs_fuse_ops int sys_getattr(const char *path, struct stat *sb)
 {
 	struct timespec now;
 
@@ -177,8 +177,9 @@ int sys_getattr(const char *path, struct stat *sb)
 	return -ENOENT;
 }
 
-int sys_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-		off_t offset, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int sys_readdir(const char *path, void *buf,
+				 fuse_fill_dir_t filler, off_t offset,
+				 struct fuse_file_info *fi)
 {
 	if (strcmp(path, "/sys") == 0) {
 		if (filler(buf, ".",		NULL, 0) != 0 ||
@@ -216,7 +217,7 @@ int sys_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 	return 0;
 }
 
-int sys_open(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int sys_open(const char *path, struct fuse_file_info *fi)
 {
 	__do_free struct file_info *info = NULL;
 	int type = -1;
@@ -253,7 +254,7 @@ int sys_open(const char *path, struct fuse_file_info *fi)
 	return 0;
 }
 
-int sys_access(const char *path, int mask)
+__lxcfs_fuse_ops int sys_access(const char *path, int mask)
 {
 	if (strcmp(path, "/sys") == 0 && access(path, R_OK) == 0)
 		return 0;
@@ -275,20 +276,20 @@ int sys_access(const char *path, int mask)
 	return 0;
 }
 
-int sys_release(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int sys_release(const char *path, struct fuse_file_info *fi)
 {
 	do_release_file_info(fi);
 	return 0;
 }
 
-int sys_releasedir(const char *path, struct fuse_file_info *fi)
+__lxcfs_fuse_ops int sys_releasedir(const char *path, struct fuse_file_info *fi)
 {
 	do_release_file_info(fi);
 	return 0;
 }
 
-int sys_read(const char *path, char *buf, size_t size, off_t offset,
-	     struct fuse_file_info *fi)
+__lxcfs_fuse_ops int sys_read(const char *path, char *buf, size_t size,
+			      off_t offset, struct fuse_file_info *fi)
 {
 	struct file_info *f = INTTYPE_TO_PTR(fi->fh);
 

From 2c7dd60d9f08e7f33eb55dd70fbef31093426651 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 13 Mar 2020 12:24:41 +0100
Subject: [PATCH 2/3] bindings: make constructor failures non-fatal

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/bindings.c | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/src/bindings.c b/src/bindings.c
index 26ff9bf..28d252c 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -722,28 +722,38 @@ static void __attribute__((constructor)) lxcfs_init(void)
 	int i = 0;
 	pid_t pid;
 
-	lxcfs_info("Running constructor %s", __func__);
+	lxcfs_info("Running constructor %s to reload liblxcfs with count", __func__);
 
 	cgroup_ops = cgroup_init();
-	if (!cgroup_ops)
-		log_exit("Failed to initialize cgroup support");
+	if (!cgroup_ops) {
+		lxcfs_info("Failed to initialize cgroup support");
+		goto broken_upgrade;
+	}
 
 	/* Preserve initial namespace. */
 	pid = getpid();
 	init_ns = preserve_ns(pid, "mnt");
-	if (init_ns < 0)
-		log_exit("Failed to preserve initial mount namespace");
+	if (init_ns < 0) {
+		lxcfs_info("Failed to preserve initial mount namespace");
+		goto broken_upgrade;
+	}
 
 	/* This function calls unshare(CLONE_NEWNS) our initial mount namespace
 	 * to privately mount lxcfs cgroups. */
-	if (!cgfs_setup_controllers())
+	if (!cgfs_setup_controllers()) {
 		log_exit("Failed to setup private cgroup mounts for lxcfs");
+		goto broken_upgrade;
+	}
 
-	if (setns(init_ns, 0) < 0)
+	if (setns(init_ns, 0) < 0) {
 		log_exit("%s - Failed to switch back to initial mount namespace", strerror(errno));
+		goto broken_upgrade;
+	}
 
-	if (!init_cpuview())
+	if (!init_cpuview()) {
 		log_exit("Failed to init CPU view");
+		goto broken_upgrade;
+	}
 
 	lxcfs_info("mount namespace: %d", cgroup_ops->mntns_fd);
 	lxcfs_info("hierarchies:");
@@ -767,13 +777,15 @@ static void __attribute__((constructor)) lxcfs_init(void)
 		lxcfs_info("- %s", api_extensions[i]);
 
 	root_fd = open("/", O_PATH | O_CLOEXEC);
-	if (root_fd < 0) {
-		lxcfs_error("%s - Failed to open root directory", strerror(errno));
-		return;
-	}
+	if (root_fd < 0)
+		lxcfs_info("%s - Failed to open root directory", strerror(errno));
+	else if (fchdir(root_fd) < 0)
+		lxcfs_info("%s - Failed to change to root directory", strerror(errno));
+
+	return;
 
-	if (fchdir(root_fd) < 0)
-		lxcfs_error("%s - Failed to change to root directory", strerror(errno));
+broken_upgrade:
+	lxcfs_info("Failed to run constructor %s to reload liblxcfs", __func__);
 }
 
 static void __attribute__((destructor)) lxcfs_exit(void)

From 5f0c2794798625107aa9148bf5bfdc03053942d5 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 13 Mar 2020 13:24:59 +0100
Subject: [PATCH 3/3] liblxcfs: handle broken upgrade gracefully

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/bindings.c    | 10 +++++++++-
 src/bindings.h    | 18 ++++++++++++++++++
 src/cgroup_fuse.c | 32 ++++++++++++++++++++++++++++++++
 src/macro.h       | 10 ++++++++++
 src/proc_fuse.c   | 47 ++++++++++++++++++++++++++++++++++++++---------
 src/sysfs_fuse.c  |  6 +++++-
 src/utils.c       | 25 +++++++++++++++++++++++++
 src/utils.h       |  2 ++
 8 files changed, 139 insertions(+), 11 deletions(-)

diff --git a/src/bindings.c b/src/bindings.c
index 28d252c..bcee24c 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -50,6 +50,12 @@
 #include "utils.h"
 
 static bool can_use_pidfd;
+static bool reload_successful;
+
+bool liblxcfs_functional(void)
+{
+	return reload_successful;
+}
 
 /* Define pivot_root() if missing from the C library */
 #ifndef HAVE_PIVOT_ROOT
@@ -722,7 +728,7 @@ static void __attribute__((constructor)) lxcfs_init(void)
 	int i = 0;
 	pid_t pid;
 
-	lxcfs_info("Running constructor %s to reload liblxcfs with count", __func__);
+	lxcfs_info("Running constructor %s to reload liblxcfs", __func__);
 
 	cgroup_ops = cgroup_init();
 	if (!cgroup_ops) {
@@ -782,9 +788,11 @@ static void __attribute__((constructor)) lxcfs_init(void)
 	else if (fchdir(root_fd) < 0)
 		lxcfs_info("%s - Failed to change to root directory", strerror(errno));
 
+	reload_successful = true;
 	return;
 
 broken_upgrade:
+	reload_successful = false;
 	lxcfs_info("Failed to run constructor %s to reload liblxcfs", __func__);
 }
 
diff --git a/src/bindings.h b/src/bindings.h
index b4bc0e5..43dc258 100644
--- a/src/bindings.h
+++ b/src/bindings.h
@@ -39,17 +39,34 @@
 enum lxcfs_virt_t {
 	LXC_TYPE_CGDIR,
 	LXC_TYPE_CGFILE,
+
 	LXC_TYPE_PROC_MEMINFO,
+#define LXC_TYPE_PROC_MEMINFO_PATH "/proc/meminfo"
+
 	LXC_TYPE_PROC_CPUINFO,
+#define LXC_TYPE_PROC_CPUINFO_PATH "/proc/cpuinfo"
+
 	LXC_TYPE_PROC_UPTIME,
+#define LXC_TYPE_PROC_UPTIME_PATH "/proc/uptime"
+
 	LXC_TYPE_PROC_STAT,
+#define LXC_TYPE_PROC_STAT_PATH "/proc/stat"
+
 	LXC_TYPE_PROC_DISKSTATS,
+#define LXC_TYPE_PROC_DISKSTATS_PATH "/proc/diskstats"
+
 	LXC_TYPE_PROC_SWAPS,
+#define LXC_TYPE_PROC_SWAPS_PATH "/proc/swaps"
+
 	LXC_TYPE_PROC_LOADAVG,
+#define LXC_TYPE_PROC_LOADAVG_PATH "/proc/loadavg"
+
 	LXC_TYPE_SYS_DEVICES,
 	LXC_TYPE_SYS_DEVICES_SYSTEM,
 	LXC_TYPE_SYS_DEVICES_SYSTEM_CPU,
+
 	LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE,
+#define LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE_PATH "/sys/devices/system/cpu/online"
 };
 
 struct file_info {
@@ -72,5 +89,6 @@ struct lxcfs_opts {
 extern pid_t lookup_initpid_in_store(pid_t qpid);
 extern void prune_init_slice(char *cg);
 extern bool supports_pidfd(void);
+extern bool liblxcfs_functional(void);
 
 #endif /* __LXCFS_BINDINGS_H */
diff --git a/src/cgroup_fuse.c b/src/cgroup_fuse.c
index 2ca7139..2130d7a 100644
--- a/src/cgroup_fuse.c
+++ b/src/cgroup_fuse.c
@@ -510,6 +510,8 @@ __lxcfs_fuse_ops int cg_getattr(const char *path, struct stat *sb)
 	const char *controller = NULL;
 	int ret = -ENOENT;
 
+	if (!liblxcfs_functional())
+		return -EIO;
 
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
@@ -689,6 +691,9 @@ __lxcfs_fuse_ops int cg_mkdir(const char *path, mode_t mode)
 	const char *cgroup;
 	int ret;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -829,6 +834,9 @@ __lxcfs_fuse_ops int cg_rmdir(const char *path)
 	const char *cgroup;
 	int ret;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -912,6 +920,9 @@ __lxcfs_fuse_ops int cg_chmod(const char *path, mode_t mode)
 	const char *cgroup;
 	int ret;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -1032,6 +1043,9 @@ __lxcfs_fuse_ops int cg_chown(const char *path, uid_t uid, gid_t gid)
 	const char *cgroup;
 	int ret;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -1099,6 +1113,9 @@ __lxcfs_fuse_ops int cg_open(const char *path, struct fuse_file_info *fi)
 	struct fuse_context *fc = fuse_get_context();
 	int ret;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -1364,6 +1381,9 @@ __lxcfs_fuse_ops int cg_read(const char *path, char *buf, size_t size,
 	int ret, s;
 	bool r;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -1428,6 +1448,9 @@ __lxcfs_fuse_ops int cg_opendir(const char *path, struct fuse_file_info *fi)
 	struct file_info *dir_info;
 	char *controller = NULL;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -1814,6 +1837,9 @@ __lxcfs_fuse_ops int cg_write(const char *path, const char *buf, size_t size,
 	struct file_info *f = INTTYPE_TO_PTR(fi->fh);
 	bool r;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -1985,6 +2011,9 @@ __lxcfs_fuse_ops int cg_readdir(const char *path, void *buf,
 	struct fuse_context *fc = fuse_get_context();
 	char **clist = NULL;
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
@@ -2075,6 +2104,9 @@ __lxcfs_fuse_ops int cg_access(const char *path, int mode)
 	struct cgfs_files *k = NULL;
 	struct fuse_context *fc = fuse_get_context();
 
+	if (!liblxcfs_functional())
+		return -EIO;
+
 	if (!fc || !cgroup_ops || pure_unified_layout(cgroup_ops))
 		return -EIO;
 
diff --git a/src/macro.h b/src/macro.h
index 29b5ed7..8ad7984 100644
--- a/src/macro.h
+++ b/src/macro.h
@@ -125,4 +125,14 @@
 
 #define __lxcfs_fuse_ops
 
+#ifndef thread_local
+#if __STDC_VERSION__ >= 201112L &&    \
+    !(defined(__STDC_NO_THREADS__) || \
+      (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16))
+#define thread_local _Thread_local
+#else
+#define thread_local __thread
+#endif
+#endif
+
 #endif /* __LXCFS_MACRO_H */
diff --git a/src/proc_fuse.c b/src/proc_fuse.c
index ae557a9..9652163 100644
--- a/src/proc_fuse.c
+++ b/src/proc_fuse.c
@@ -398,7 +398,7 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 	int ret;
 	char dev_name[72];
 
-	if (offset){
+	if (offset) {
 		int left;
 
 		if (offset > d->size)
@@ -510,7 +510,8 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
 
 	d->cached = 1;
 	d->size = total_len;
-	if (total_len > size ) total_len = size;
+	if (total_len > size)
+		total_len = size;
 	memcpy(buf, d->buf, total_len);
 
 	return total_len;
@@ -1256,19 +1257,47 @@ __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
 
 	switch (f->type) {
 	case LXC_TYPE_PROC_MEMINFO:
-		return proc_meminfo_read(buf, size, offset, fi);
+		if (liblxcfs_functional())
+			return proc_meminfo_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_PROC_MEMINFO_PATH,
+						  buf, size, offset, f);
 	case LXC_TYPE_PROC_CPUINFO:
-		return proc_cpuinfo_read(buf, size, offset, fi);
+		if (liblxcfs_functional())
+			return proc_cpuinfo_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_PROC_CPUINFO_PATH,
+						  buf, size, offset, f);
 	case LXC_TYPE_PROC_UPTIME:
-		return proc_uptime_read(buf, size, offset, fi);
+		if (liblxcfs_functional())
+			return proc_uptime_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_PROC_UPTIME_PATH,
+						  buf, size, offset, f);
 	case LXC_TYPE_PROC_STAT:
-		return proc_stat_read(buf, size, offset, fi);
+		if (liblxcfs_functional())
+			return proc_stat_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_PROC_STAT_PATH, buf,
+						  size, offset, f);
 	case LXC_TYPE_PROC_DISKSTATS:
-		return proc_diskstats_read(buf, size, offset, fi);
+		if (liblxcfs_functional())
+			return proc_diskstats_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_PROC_DISKSTATS_PATH,
+						  buf, size, offset, f);
 	case LXC_TYPE_PROC_SWAPS:
-		return proc_swaps_read(buf, size, offset, fi);
+		if (liblxcfs_functional())
+			return proc_swaps_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_PROC_SWAPS_PATH, buf,
+						  size, offset, f);
 	case LXC_TYPE_PROC_LOADAVG:
-		return proc_loadavg_read(buf, size, offset, fi);
+		if (liblxcfs_functional())
+			return proc_loadavg_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_PROC_LOADAVG_PATH,
+						  buf, size, offset, f);
 	}
 
 	return -EINVAL;
diff --git a/src/sysfs_fuse.c b/src/sysfs_fuse.c
index 85bc12c..5bdb2ce 100644
--- a/src/sysfs_fuse.c
+++ b/src/sysfs_fuse.c
@@ -295,7 +295,11 @@ __lxcfs_fuse_ops int sys_read(const char *path, char *buf, size_t size,
 
 	switch (f->type) {
 	case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE:
-		return sys_devices_system_cpu_online_read(buf, size, offset, fi);
+		if (liblxcfs_functional())
+			return sys_devices_system_cpu_online_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE_PATH,
+						  buf, size, offset, f);
 	case LXC_TYPE_SYS_DEVICES:
 		break;
 	case LXC_TYPE_SYS_DEVICES_SYSTEM:
diff --git a/src/utils.c b/src/utils.c
index ccbb50b..5b5e076 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -344,9 +344,34 @@ int read_file_fuse(const char *path, char *buf, size_t size, struct file_info *d
 
 	if (d->size > total_len)
 		d->cached = d->size - total_len;
+
 	return total_len;
 }
 
+int read_file_fuse_with_offset(const char *path, char *buf, size_t size,
+			       off_t offset, struct file_info *d)
+{
+	if (offset) {
+		ssize_t total_len = 0;
+		char *cache = d->buf;
+		int left;
+
+		if (offset > d->size)
+			return -EINVAL;
+
+		if (!d->cached)
+			return 0;
+
+		left = d->size - offset;
+		total_len = left > size ? size : left;
+		memcpy(buf, cache + offset, total_len);
+
+		return total_len;
+	}
+
+	return read_file_fuse(path, buf, size, d);
+}
+
 #define INITSCOPE "/init.scope"
 void prune_init_slice(char *cg)
 {
diff --git a/src/utils.h b/src/utils.h
index d1effc6..8ac6676 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -45,6 +45,8 @@ extern int send_creds(int sock, struct ucred *cred, char v, bool pingfirst);
 extern bool wait_for_sock(int sock, int timeout);
 extern int read_file_fuse(const char *path, char *buf, size_t size,
 			  struct file_info *d);
+extern int read_file_fuse_with_offset(const char *path, char *buf, size_t size,
+				      off_t offset, struct file_info *d);
 extern void prune_init_slice(char *cg);
 extern int wait_for_pid(pid_t pid);
 


More information about the lxc-devel mailing list