[lxc-devel] [lxcfs/master] Support /sys/devices/system/cpu/online
wavezhang on Github
lxc-bot at linuxcontainers.org
Fri Mar 22 07:46:59 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 438 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190322/22bf290f/attachment.bin>
-------------- next part --------------
From 6ac2c98a13ed750f3b46eab7f22626e4ba3d5da4 Mon Sep 17 00:00:00 2001
From: Sam <baoyafei at gmail.com>
Date: Fri, 22 Mar 2019 15:28:29 +0800
Subject: [PATCH 1/2] support /sys/devices/system/cpu/online
---
bindings.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++++
bindings.h | 11 +++
lxcfs.c | 171 +++++++++++++++++++++++++++++++++
3 files changed, 455 insertions(+)
diff --git a/bindings.c b/bindings.c
index 049418c..c1dbaa6 100644
--- a/bindings.c
+++ b/bindings.c
@@ -67,6 +67,10 @@ enum {
LXC_TYPE_PROC_DISKSTATS,
LXC_TYPE_PROC_SWAPS,
LXC_TYPE_PROC_LOADAVG,
+ LXC_TYPE_SYS_DEVICES,
+ LXC_TYPE_SYS_DEVICES_SYSTEM,
+ LXC_TYPE_SYS_DEVICES_SYSTEM_CPU,
+ LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE,
};
struct file_info {
@@ -5874,6 +5878,275 @@ int proc_read(const char *path, char *buf, size_t size, off_t offset,
}
}
+static int sys_devices_system_cpu_read(char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ struct fuse_context *fc = fuse_get_context();
+ struct file_info *d = (struct file_info *)fi->fh;
+ char *cache = d->buf;
+ ssize_t total_len = 0;
+ if (offset){
+ if (!d->cached)
+ return 0;
+ if (offset > d->size)
+ return -EINVAL;
+ int left = d->size - offset;
+ total_len = left > size ? size: left;
+ memcpy(buf, cache + offset, total_len);
+ return total_len;
+ }
+
+ total_len = snprintf(d->buf, d->buflen, "0-1\n");
+ if (total_len < 0 || total_len >= d->buflen){
+ lxcfs_error("%s\n", "failed to write to cache");
+ return 0;
+ }
+
+ d->size = (int)total_len;
+ d->cached = 1;
+
+ if (total_len > size) total_len = size;
+
+ memcpy(buf, d->buf, total_len);
+ return total_len;
+}
+
+static int sys_devices_system_cpu_online_read(char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ struct fuse_context *fc = fuse_get_context();
+ struct file_info *d = (struct file_info *)fi->fh;
+ char *cache = d->buf;
+ char *cg;
+ char *cpuset = NULL;
+ bool use_view;
+
+ int max_cpus = 0;
+ ssize_t total_len = 0;
+ if (offset){
+ if (!d->cached)
+ return 0;
+ if (offset > d->size)
+ return -EINVAL;
+ int left = d->size - offset;
+ total_len = left > size ? size: left;
+ memcpy(buf, cache + offset, total_len);
+ return total_len;
+ }
+ pid_t initpid = lookup_initpid_in_store(fc->pid);
+ if (initpid <= 0)
+ initpid = fc->pid;
+ cg = get_pid_cgroup(initpid, "cpuset");
+ if (!cg)
+ return read_file("/sys/devices/system/cpu/online", buf, size, d);
+ prune_init_slice(cg);
+
+ cpuset = get_cpuset(cg);
+ if (!cpuset)
+ goto err;
+
+ use_view = use_cpuview(cg);
+
+ if (use_view)
+ max_cpus = max_cpu_count(cg);
+
+
+ if (max_cpus == 0)
+ return read_file("/sys/devices/system/cpu/online", buf, size, d);
+ if (max_cpus > 1)
+ total_len = snprintf(d->buf, d->buflen, "0-%d\n", max_cpus - 1);
+ else
+ total_len = snprintf(d->buf, d->buflen, "0\n");
+ if (total_len < 0 || total_len >= d->buflen){
+ lxcfs_error("%s\n", "failed to write to cache");
+ return 0;
+ }
+
+ d->size = (int)total_len;
+ d->cached = 1;
+
+ if (total_len > size) total_len = size;
+
+ memcpy(buf, d->buf, total_len);
+err:
+ free(cpuset);
+ free(cg);
+ return total_len;
+}
+
+static off_t get_sysfile_size(const char *which)
+{
+ FILE *f = fopen(which, "r");
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t sz, answer = 0;
+ if (!f)
+ return 0;
+
+ while ((sz = getline(&line, &len, f)) != -1)
+ answer += sz;
+ fclose (f);
+ free(line);
+
+ return answer;
+}
+
+int sys_getattr(const char *path, struct stat *sb)
+{
+ struct timespec now;
+
+ memset(sb, 0, sizeof(struct stat));
+ 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;
+ if (strcmp(path, "/sys") == 0) {
+ sb->st_mode = S_IFDIR | 00555;
+ sb->st_nlink = 2;
+ return 0;
+ }
+ if (strcmp(path, "/sys/devices") == 0) {
+ sb->st_mode = S_IFDIR | 00555;
+ sb->st_nlink = 2;
+ return 0;
+ }
+ if (strcmp(path, "/sys/devices/system") == 0) {
+ sb->st_mode = S_IFDIR | 00555;
+ sb->st_nlink = 2;
+ return 0;
+ }
+ if (strcmp(path, "/sys/devices/system/cpu") == 0) {
+ sb->st_mode = S_IFDIR | 00555;
+ sb->st_nlink = 2;
+ return 0;
+ }
+ if (strcmp(path, "/sys/devices/system/cpu/online") == 0) {
+ sb->st_size = 0;
+ sb->st_mode = S_IFREG | 00444;
+ sb->st_nlink = 1;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+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 ||
+ filler(buf, "..", NULL, 0) != 0 ||
+ filler(buf, "devices", NULL, 0) != 0)
+ return -ENOENT;
+ return 0;
+ }
+ if (strcmp(path, "/sys/devices") == 0) {
+ if (filler(buf, ".", NULL, 0) != 0 ||
+ filler(buf, "..", NULL, 0) != 0 ||
+ filler(buf, "system", NULL, 0) != 0)
+ return -ENOENT;
+ return 0;
+ }
+ if (strcmp(path, "/sys/devices/system") == 0) {
+ if (filler(buf, ".", NULL, 0) != 0 ||
+ filler(buf, "..", NULL, 0) != 0 ||
+ filler(buf, "cpu", NULL, 0) != 0)
+ return -ENOENT;
+ return 0;
+ }
+ if (strcmp(path, "/sys/devices/system/cpu") == 0) {
+ if (filler(buf, ".", NULL, 0) != 0 ||
+ filler(buf, "..", NULL, 0) != 0 ||
+ filler(buf, "online", NULL, 0) != 0)
+ return -ENOENT;
+ return 0;
+ }
+
+ return 0;
+}
+
+int sys_open(const char *path, struct fuse_file_info *fi)
+{
+ int type = -1;
+ struct file_info *info;
+
+ if (strcmp(path, "/sys/devices") == 0)
+ type = LXC_TYPE_SYS_DEVICES;
+ if (strcmp(path, "/sys/devices/system") == 0)
+ type = LXC_TYPE_SYS_DEVICES_SYSTEM;
+ if (strcmp(path, "/sys/devices/system/cpu") == 0)
+ type = LXC_TYPE_SYS_DEVICES_SYSTEM_CPU;
+ if (strcmp(path, "/sys/devices/system/cpu/online") == 0)
+ type = LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE;
+ if (type == -1)
+ return -ENOENT;
+
+ info = malloc(sizeof(*info));
+ if (!info)
+ return -ENOMEM;
+
+ memset(info, 0, sizeof(*info));
+ info->type = type;
+
+ info->buflen = get_sysfile_size(path) + BUF_RESERVE_SIZE;
+ do {
+ info->buf = malloc(info->buflen);
+ } while (!info->buf);
+ memset(info->buf, 0, info->buflen);
+ /* set actual size to buffer size */
+ info->size = info->buflen;
+
+ fi->fh = (unsigned long)info;
+ return 0;
+}
+
+int sys_access(const char *path, int mask)
+{
+ if (strcmp(path, "/sys") == 0 && access(path, R_OK) == 0)
+ return 0;
+ if (strcmp(path, "/sys/devices") == 0 && access(path, R_OK) == 0)
+ return 0;
+ if (strcmp(path, "/sys/devices/system") == 0 && access(path, R_OK) == 0)
+ return 0;
+ if (strcmp(path, "/sys/devices/system/cpu") == 0 && access(path, R_OK) == 0)
+ return 0;
+ /* these are all read-only */
+ if ((mask & ~R_OK) != 0)
+ return -EACCES;
+ return 0;
+}
+
+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)
+{
+ 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)
+{
+ struct file_info *f = (struct file_info *) fi->fh;
+
+ switch (f->type) {
+ case LXC_TYPE_SYS_DEVICES:
+ return sys_devices_read(buf, size, offset, fi);
+ case LXC_TYPE_SYS_DEVICES_SYSTEM:
+ return sys_devices_system_read(buf, size, offset, fi);
+ case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU:
+ return sys_devices_system_cpu_read(buf, size, offset, fi);
+ case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE:
+ return sys_devices_system_cpu_online_read(buf, size, offset, fi);
+ default:
+ return -EINVAL;
+ }
+}
+
/*
* Functions needed to setup cgroups in the __constructor__.
*/
diff --git a/bindings.h b/bindings.h
index 20df78c..88e6915 100644
--- a/bindings.h
+++ b/bindings.h
@@ -36,6 +36,17 @@ 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);
+
+extern int sys_getattr(const char *path, struct stat *sb);
+extern int sys_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
+ struct fuse_file_info *fi);
+extern int sys_release(const char *path, struct fuse_file_info *fi);
+extern int sys_releasedir(const char *path, struct fuse_file_info *fi);
+extern int sys_open(const char *path, struct fuse_file_info *fi);
+extern int sys_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi);
+extern int sys_access(const char *path, int mask);
+
extern pthread_t load_daemon(int load_use);
extern int stop_load_daemon(pthread_t pid);
diff --git a/lxcfs.c b/lxcfs.c
index 2247fcb..ee94b75 100644
--- a/lxcfs.c
+++ b/lxcfs.c
@@ -205,6 +205,21 @@ static int do_proc_getattr(const char *path, struct stat *sb)
return proc_getattr(path, sb);
}
+static int do_sys_getattr(const char *path, struct stat *sb)
+{
+ int (*sys_getattr)(const char *path, struct stat *sb);
+ char *error;
+ dlerror(); /* Clear any existing error */
+ sys_getattr = (int (*)(const char *, struct stat *)) dlsym(dlopen_handle, "sys_getattr");
+ error = dlerror();
+ if (error != NULL) {
+ lxcfs_error("%s\n", error);
+ return -1;
+ }
+
+ return sys_getattr(path, sb);
+}
+
static int do_cg_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
@@ -241,6 +256,24 @@ static int do_proc_read(const char *path, char *buf, size_t size, off_t offset,
return proc_read(path, buf, size, offset, fi);
}
+static int do_sys_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int (*sys_read)(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi);
+ char *error;
+
+ dlerror(); /* Clear any existing error */
+ sys_read = (int (*)(const char *, char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "sys_read");
+ error = dlerror();
+ if (error != NULL) {
+ lxcfs_error("%s\n", error);
+ return -1;
+ }
+
+ return sys_read(path, buf, size, offset, fi);
+}
+
static int do_cg_write(const char *path, const char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
@@ -354,6 +387,25 @@ static int do_proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
return proc_readdir(path, buf, filler, offset, fi);
}
+static int do_sys_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int (*sys_readdir)(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
+ struct fuse_file_info *fi);
+ char *error;
+
+ dlerror(); /* Clear any existing error */
+ sys_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "sys_readdir");
+ error = dlerror();
+ if (error != NULL) {
+ lxcfs_error("%s\n", error);
+ return -1;
+ }
+
+ return sys_readdir(path, buf, filler, offset, fi);
+}
+
+
static int do_cg_open(const char *path, struct fuse_file_info *fi)
{
int (*cg_open)(const char *path, struct fuse_file_info *fi);
@@ -414,6 +466,37 @@ static int do_proc_access(const char *path, int mode)
return proc_access(path, mode);
}
+static int do_sys_open(const char *path, struct fuse_file_info *fi)
+{
+ int (*sys_open)(const char *path, struct fuse_file_info *fi);
+ char *error;
+ dlerror(); /* Clear any existing error */
+ sys_open = (int (*)(const char *path, struct fuse_file_info *fi)) dlsym(dlopen_handle, "sys_open");
+ error = dlerror();
+ if (error != NULL) {
+ lxcfs_error("%s\n", error);
+ return -1;
+ }
+
+ return sys_open(path, fi);
+}
+
+static int do_sys_access(const char *path, int mode)
+{
+ int (*sys_access)(const char *path, int mode);
+ char *error;
+ dlerror(); /* Clear any existing error */
+ sys_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "sys_access");
+ error = dlerror();
+ if (error != NULL) {
+ lxcfs_error("%s\n", error);
+ return -1;
+ }
+
+ return sys_access(path, mode);
+}
+
+
static int do_cg_release(const char *path, struct fuse_file_info *fi)
{
int (*cg_release)(const char *path, struct fuse_file_info *fi);
@@ -444,6 +527,21 @@ static int do_proc_release(const char *path, struct fuse_file_info *fi)
return proc_release(path, fi);
}
+static int do_sys_release(const char *path, struct fuse_file_info *fi)
+{
+ int (*sys_release)(const char *path, struct fuse_file_info *fi);
+ char *error;
+ dlerror(); /* Clear any existing error */
+ sys_release = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "sys_release");
+ error = dlerror();
+ if (error != NULL) {
+ lxcfs_error("%s\n", error);
+ return -1;
+ }
+
+ return sys_release(path, fi);
+}
+
static int do_cg_opendir(const char *path, struct fuse_file_info *fi)
{
int (*cg_opendir)(const char *path, struct fuse_file_info *fi);
@@ -474,6 +572,21 @@ static int do_cg_releasedir(const char *path, struct fuse_file_info *fi)
return cg_releasedir(path, fi);
}
+static int do_sys_releasedir(const char *path, struct fuse_file_info *fi)
+{
+ int (*sys_releasedir)(const char *path, struct fuse_file_info *fi);
+ char *error;
+ dlerror(); /* Clear any existing error */
+ sys_releasedir = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "sys_releasedir");
+ error = dlerror();
+ if (error != NULL) {
+ lxcfs_error("%s\n", error);
+ return -1;
+ }
+
+ return sys_releasedir(path, fi);
+}
+
/*
* FUSE ops for /
* these just delegate to the /proc and /cgroup ops as
@@ -508,6 +621,12 @@ static int lxcfs_getattr(const char *path, struct stat *sb)
down_users();
return ret;
}
+ if (strncmp(path, "/sys", 4) == 0) {
+ up_users();
+ ret = do_sys_getattr(path, sb);
+ down_users();
+ return ret;
+ }
return -ENOENT;
}
@@ -525,6 +644,9 @@ static int lxcfs_opendir(const char *path, struct fuse_file_info *fi)
}
if (strcmp(path, "/proc") == 0)
return 0;
+ if (strncmp(path, "/sys", 4) == 0)
+ return 0;
+
return -ENOENT;
}
@@ -536,6 +658,7 @@ static int lxcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of
if (filler(buf, ".", NULL, 0) != 0 ||
filler(buf, "..", NULL, 0) != 0 ||
filler(buf, "proc", NULL, 0) != 0 ||
+ filler(buf, "sys", NULL, 0) != 0 ||
filler(buf, "cgroup", NULL, 0) != 0)
return -ENOMEM;
return 0;
@@ -552,6 +675,14 @@ static int lxcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of
down_users();
return ret;
}
+
+ if (strncmp(path, "/sys", 4) == 0) {
+ up_users();
+ ret = do_sys_readdir(path, buf, filler, offset, fi);
+ down_users();
+ return ret;
+ }
+
return -ENOENT;
}
@@ -574,6 +705,13 @@ static int lxcfs_access(const char *path, int mode)
down_users();
return ret;
}
+ if (strncmp(path, "/sys", 4) == 0) {
+ up_users();
+ ret = do_sys_access(path, mode);
+ down_users();
+ return ret;
+ }
+
return -EACCES;
}
@@ -591,6 +729,13 @@ static int lxcfs_releasedir(const char *path, struct fuse_file_info *fi)
}
if (strcmp(path, "/proc") == 0)
return 0;
+ if (strncmp(path, "/sys", 4) == 0){
+ up_users();
+ ret = do_sys_releasedir(path, fi);
+ down_users();
+ return ret;
+ }
+
return -EINVAL;
}
@@ -609,6 +754,13 @@ static int lxcfs_open(const char *path, struct fuse_file_info *fi)
down_users();
return ret;
}
+ if (strncmp(path, "/sys", 4) == 0) {
+ up_users();
+ ret = do_sys_open(path, fi);
+ down_users();
+ return ret;
+ }
+
return -EACCES;
}
@@ -629,6 +781,13 @@ static int lxcfs_read(const char *path, char *buf, size_t size, off_t offset,
down_users();
return ret;
}
+ if (strncmp(path, "/sys", 4) == 0) {
+ up_users();
+ ret = do_sys_read(path, buf, size, offset, fi);
+ down_users();
+ return ret;
+ }
+
return -EINVAL;
}
@@ -667,6 +826,13 @@ static int lxcfs_release(const char *path, struct fuse_file_info *fi)
down_users();
return ret;
}
+ if (strncmp(path, "/sys", 4) == 0) {
+ up_users();
+ ret = do_sys_release(path, fi);
+ down_users();
+ return ret;
+ }
+
return -EINVAL;
}
@@ -702,6 +868,8 @@ int lxcfs_chown(const char *path, uid_t uid, gid_t gid)
if (strncmp(path, "/proc", 5) == 0)
return -EPERM;
+ if (strncmp(path, "/sys", 4) == 0)
+ return -EPERM;
return -ENOENT;
}
@@ -742,6 +910,9 @@ int lxcfs_chmod(const char *path, mode_t mode)
if (strncmp(path, "/proc", 5) == 0)
return -EPERM;
+ if (strncmp(path, "/sys", 4) == 0)
+ return -EPERM;
+
return -ENOENT;
}
From 3304c65245cde645d9e7637029f74911dcdc84d3 Mon Sep 17 00:00:00 2001
From: wavezhang <baoyafei at gmail.com>
Date: Fri, 22 Mar 2019 15:30:20 +0800
Subject: [PATCH 2/2] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 7ff2ec9..d4ece85 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ such as:
/proc/stat
/proc/swaps
/proc/uptime
+/sys/devices/system/cpu/online
```
are container aware such that the values displayed (e.g. in `/proc/uptime`)
More information about the lxc-devel
mailing list