[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