Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package lxcfs for openSUSE:Factory checked in at 2023-08-01 14:15:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/lxcfs (Old) and /work/SRC/openSUSE:Factory/.lxcfs.new.32662 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "lxcfs" Tue Aug 1 14:15:44 2023 rev:21 rq:1101531 version:5.0.4 Changes: -------- --- /work/SRC/openSUSE:Factory/lxcfs/lxcfs.changes 2023-03-01 16:14:34.474761921 +0100 +++ /work/SRC/openSUSE:Factory/.lxcfs.new.32662/lxcfs.changes 2023-08-01 14:15:49.883593914 +0200 @@ -1,0 +2,7 @@ +Mon Jul 31 12:32:38 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 5.0.4: + * Fixed the output format of /proc/diskstats + * Fixed an issue with cpuset path tracking when used with containerd + +------------------------------------------------------------------- Old: ---- lxcfs-5.0.2.tar.gz lxcfs-5.0.2.tar.gz.asc New: ---- lxcfs-5.0.4.tar.gz lxcfs-5.0.4.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ lxcfs.spec ++++++ --- /var/tmp/diff_new_pack.5H7Mfq/_old 2023-08-01 14:15:51.019600588 +0200 +++ /var/tmp/diff_new_pack.5H7Mfq/_new 2023-08-01 14:15:51.051600775 +0200 @@ -1,7 +1,7 @@ # # spec file for package lxcfs # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,7 +22,7 @@ %endif Name: lxcfs -Version: 5.0.2 +Version: 5.0.4 Release: 0 Summary: FUSE filesystem for LXC License: Apache-2.0 ++++++ lxcfs-5.0.2.tar.gz -> lxcfs-5.0.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/.github/workflows/builds.yml new/lxcfs-5.0.4/.github/workflows/builds.yml --- old/lxcfs-5.0.2/.github/workflows/builds.yml 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/.github/workflows/builds.yml 2023-07-25 23:58:55.000000000 +0200 @@ -36,11 +36,9 @@ export PATH="$(pwd)/cov-analysis-linux64/bin:${PATH}" meson setup -Ddocs=false -Dtests=true -Dinit-script=systemd -Dprefix=/usr build/ - meson compile -C build - cd build # Build - cov-build --dir cov-int make -j4 + cov-build --dir cov-int ninja -C build tar czvf lxcfs.tgz cov-int # Submit the results diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/.github/workflows/commits.yml new/lxcfs-5.0.4/.github/workflows/commits.yml --- old/lxcfs-5.0.2/.github/workflows/commits.yml 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/.github/workflows/commits.yml 2023-07-25 23:58:55.000000000 +0200 @@ -10,7 +10,7 @@ permissions: pull-requests: read # for tim-actions/get-pr-commits to get list of commits from the PR name: Signed-off-by (DCO) - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Get PR Commits id: 'get-pr-commits' @@ -27,14 +27,14 @@ permissions: contents: none name: Branch target - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Check branch target env: TARGET: ${{ github.event.pull_request.base.ref }} run: | set -x - [ "${TARGET}" = "master" ] && exit 0 + [ "${TARGET}" = "main" ] && exit 0 echo "Invalid branch target: ${TARGET}" exit 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/.github/workflows/tests.yml new/lxcfs-5.0.4/.github/workflows/tests.yml --- old/lxcfs-5.0.2/.github/workflows/tests.yml 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/.github/workflows/tests.yml 2023-07-25 23:58:55.000000000 +0200 @@ -16,8 +16,8 @@ - gcc - clang os: - - ubuntu-18.04 - ubuntu-20.04 + - ubuntu-22.04 runs-on: ${{ matrix.os }} steps: - name: Checkout code @@ -41,7 +41,7 @@ env: CC: ${{ matrix.compiler }} run: | - meson setup -Ddocs=false -Dtests=true -Dinit-script=systemd -Dprefix=/usr build/ + meson setup -Ddocs=false -Dtests=true -Dinit-script=systemd -Dprefix=/usr -Db_sanitize=address,undefined build/ meson compile -C build - name: Test env: @@ -60,6 +60,7 @@ - clang os: - ubuntu-20.04 + - ubuntu-22.04 runs-on: ${{ matrix.os }} steps: - name: Checkout code @@ -84,7 +85,7 @@ env: CC: ${{ matrix.compiler }} run: | - meson setup -Ddocs=false -Dtests=true -Dinit-script=systemd -Dprefix=/usr build/ + meson setup -Ddocs=false -Dtests=true -Dinit-script=systemd -Dprefix=/usr -Db_sanitize=address,undefined build/ meson compile -C build - name: Test env: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/README.md new/lxcfs-5.0.4/README.md --- old/lxcfs-5.0.2/README.md 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/README.md 2023-07-25 23:58:55.000000000 +0200 @@ -16,7 +16,6 @@ /proc/swaps /proc/uptime /proc/slabinfo -/sys/devices/system/cpu /sys/devices/system/cpu/online ``` @@ -71,6 +70,12 @@ meson compile -C build/ sudo meson install -C build/ +To build with sanitizers you have to specify `-Db_sanitize=...` option to `meson setup`. +For example, to enable ASAN and UBSAN: + + meson setup -Dinit-script=systemd --prefix=/usr build/ -Db_sanitize=address,undefined + meson compile -C build/ + ## Usage The recommended command to run lxcfs is: @@ -104,6 +109,7 @@ -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \ -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \ -v /var/lib/lxcfs/proc/slabinfo:/proc/slabinfo:rw \ + -v /var/lib/lxcfs/sys/devices/system/cpu:/sys/devices/system/cpu:rw \ ubuntu:18.04 /bin/bash ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/config/init/systemd/lxcfs.service.in new/lxcfs-5.0.4/config/init/systemd/lxcfs.service.in --- old/lxcfs-5.0.2/config/init/systemd/lxcfs.service.in 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/config/init/systemd/lxcfs.service.in 2023-07-25 23:58:55.000000000 +0200 @@ -5,6 +5,7 @@ Documentation=man:lxcfs(1) [Service] +OOMScoreAdjust=-1000 ExecStart=/usr/bin/lxcfs {{LXCFSTARGETDIR}} KillMode=process Restart=on-failure diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/config/init/sysvinit/lxcfs new/lxcfs-5.0.4/config/init/sysvinit/lxcfs --- old/lxcfs-5.0.2/config/init/sysvinit/lxcfs 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/config/init/sysvinit/lxcfs 2023-07-25 23:58:55.000000000 +0200 @@ -16,6 +16,7 @@ NAME=lxcfs DESC="FUSE filesystem for LXC" PIDFILE=/var/run/lxcfs.pid +OOM_SCORE_ADJ="-1000" . /lib/lsb/init-functions @@ -41,6 +42,7 @@ echo -n "Starting $DESC: " if start-stop-daemon ${START} -- /var/lib/lxcfs >/dev/null 2>&1 ; then echo "${NAME}." + echo ${OOM_SCORE_ADJ} > /proc/`cat ${PIDFILE}`/oom_score_adj else if start-stop-daemon --test ${START} >/dev/null 2>&1; then echo "(failed)." diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/config/init/upstart/lxcfs.conf new/lxcfs-5.0.4/config/init/upstart/lxcfs.conf --- old/lxcfs-5.0.2/config/init/upstart/lxcfs.conf 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/config/init/upstart/lxcfs.conf 2023-07-25 23:58:55.000000000 +0200 @@ -4,6 +4,7 @@ start on starting lxc or starting lxd or runlevel [2345] stop on runlevel [06] +oom score -1000 respawn pre-start script diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/meson.build new/lxcfs-5.0.4/meson.build --- old/lxcfs-5.0.2/meson.build 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/meson.build 2023-07-25 23:58:55.000000000 +0200 @@ -4,7 +4,7 @@ project( 'lxcfs', 'c', - version: '5.0.2', + version: '5.0.4', license: 'LGPLv2+', default_options: [ 'b_colorout=always', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/bindings.c new/lxcfs-5.0.4/src/bindings.c --- old/lxcfs-5.0.2/src/bindings.c 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/bindings.c 2023-07-25 23:58:55.000000000 +0200 @@ -45,6 +45,7 @@ static bool can_use_sys_cpu; static bool has_versioned_opts; static bool memory_is_cgroupv2; +static __u32 host_personality; static volatile sig_atomic_t reload_successful; @@ -73,6 +74,11 @@ return memory_is_cgroupv2; } +__u32 liblxcfs_personality(void) +{ + return host_personality; +} + /* Define pivot_root() if missing from the C library */ #ifndef HAVE_PIVOT_ROOT static int pivot_root(const char *new_root, const char *put_old) @@ -424,7 +430,7 @@ } #elif defined(__ia64__) /* On ia64 the stack and stack size are passed as separate arguments. */ - return syscall(__NR_clone, flags | SIGCHLD, NULL, prctl_arg(0), pidfd); + return syscall(__NR_clone, flags | SIGCHLD, NULL, 0, pidfd); #else return syscall(__NR_clone, flags | SIGCHLD, NULL, pidfd); #endif @@ -919,6 +925,11 @@ goto broken_upgrade; } + if (get_task_personality(getpid(), &host_personality) < 0) { + lxcfs_info("Failed to retrieve host personality"); + goto broken_upgrade; + } + reload_successful = 1; return; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/bindings.h new/lxcfs-5.0.4/src/bindings.h --- old/lxcfs-5.0.2/src/bindings.h 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/bindings.h 2023-07-25 23:58:55.000000000 +0200 @@ -30,6 +30,8 @@ /* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */ #define LXCFS_NUMSTRLEN64 21 +/* The definitions here are well-ordered. New values should go directly + * above LXC_TYPE_MAX only. */ enum lxcfs_virt_t { LXC_TYPE_CGDIR, LXC_TYPE_CGFILE, @@ -67,8 +69,15 @@ LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE, #define LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE_PATH "/sys/devices/system/cpu/online" + LXC_TYPE_MAX, }; +/* Macros below used to check the class from the file types above */ +#define LXCFS_TYPE_CGROUP(type) (type >= LXC_TYPE_CGDIR && type <= LXC_TYPE_CGFILE) +#define LXCFS_TYPE_PROC(type) (type >= LXC_TYPE_PROC_MEMINFO && type <= LXC_TYPE_PROC_SLABINFO) +#define LXCFS_TYPE_SYS(type) (type >= LXC_TYPE_SYS && type <= LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_ONLINE) +#define LXCFS_TYPE_OK(type) (type >= LXC_TYPE_CGDIR && type < LXC_TYPE_MAX) + struct file_info { char *controller; char *cgroup; @@ -107,6 +116,7 @@ extern bool liblxcfs_memory_is_cgroupv2(void); extern bool liblxcfs_can_use_sys_cpu(void); extern bool liblxcfs_has_versioned_opts(void); +extern __u32 liblxcfs_personality(void); static inline bool lxcfs_has_opt(struct lxcfs_opts *opts, lxcfs_opt_t opt) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/cpuset_parse.c new/lxcfs-5.0.4/src/cpuset_parse.c --- old/lxcfs-5.0.2/src/cpuset_parse.c 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/cpuset_parse.c 2023-07-25 23:58:55.000000000 +0200 @@ -18,6 +18,9 @@ { char *r; + if (!strlen(c)) + return NULL; + r = strchr(c + 1, ','); return r ? (r + 1) : NULL; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/lxcfs.c new/lxcfs-5.0.4/src/lxcfs.c --- old/lxcfs-5.0.2/src/lxcfs.c 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/lxcfs.c 2023-07-25 23:58:55.000000000 +0200 @@ -8,6 +8,7 @@ #include <errno.h> #include <fcntl.h> #include <getopt.h> +#include <inttypes.h> #include <libgen.h> #include <pthread.h> #include <sched.h> @@ -65,6 +66,22 @@ unlock_mutex(&user_count_mutex); } +/* Returns file info type of custom type declaration carried + * in fuse_file_info */ +static inline enum lxcfs_virt_t file_info_type(struct fuse_file_info *fi) +{ + struct file_info *f; + + f = INTTYPE_TO_PTR(fi->fh); + if (!f) + return -1; + + if (!LXCFS_TYPE_OK(f->type)) + return -1; + + return f->type; +} + static pthread_t loadavg_pid = 0; /* Returns zero on success */ @@ -770,27 +787,34 @@ static int lxcfs_releasedir(const char *path, struct fuse_file_info *fi) { int ret; + enum lxcfs_virt_t type; - if (strcmp(path, "/") == 0) - return 0; + type = file_info_type(fi); - if (strncmp(path, "/cgroup", 7) == 0) { + if (LXCFS_TYPE_CGROUP(type)) { up_users(); ret = do_cg_releasedir(path, fi); down_users(); return ret; } - if (strcmp(path, "/proc") == 0) - return 0; - - if (strncmp(path, "/sys", 4) == 0) { + if (LXCFS_TYPE_SYS(type)) { up_users(); ret = do_sys_releasedir(path, fi); down_users(); return ret; } + if (path) { + if (strcmp(path, "/") == 0) + return 0; + if (strcmp(path, "/proc") == 0) + return 0; + } + + lxcfs_error("unknown file type: path=%s, type=%d, fi->fh=%" PRIu64, + path, type, fi->fh); + return -EINVAL; } @@ -895,28 +919,34 @@ static int lxcfs_release(const char *path, struct fuse_file_info *fi) { int ret; + enum lxcfs_virt_t type; - if (strncmp(path, "/cgroup", 7) == 0) { + type = file_info_type(fi); + + if (LXCFS_TYPE_CGROUP(type)) { up_users(); ret = do_cg_release(path, fi); down_users(); return ret; } - if (strncmp(path, "/proc", 5) == 0) { + if (LXCFS_TYPE_PROC(type)) { up_users(); ret = do_proc_release(path, fi); down_users(); return ret; } - if (strncmp(path, "/sys", 4) == 0) { + if (LXCFS_TYPE_SYS(type)) { up_users(); ret = do_sys_release(path, fi); down_users(); return ret; } + lxcfs_error("unknown file type: path=%s, type=%d, fi->fh=%" PRIu64, + path, type, fi->fh); + return -EINVAL; } @@ -1030,6 +1060,10 @@ if (lxcfs_init_library() < 0) return NULL; +#if HAVE_FUSE3 + cfg->direct_io = 1; +#endif + return fuse_get_context()->private_data; } @@ -1343,7 +1377,7 @@ } if (append_comma_separate(&new_fuse_opts, "direct_io")) { - lxcfs_error("Failed to copy fuse argument \"nonempty\""); + lxcfs_error("Failed to copy fuse argument \"direct_io\""); goto out; } #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/macro.h new/lxcfs-5.0.4/src/macro.h --- old/lxcfs-5.0.2/src/macro.h 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/macro.h 2023-07-25 23:58:55.000000000 +0200 @@ -77,6 +77,15 @@ ? 20 \ : sizeof(int[-2 * (sizeof(type) > 8)]))) +#define strnprintf(buf, buf_size, ...) \ + ({ \ + int __ret_strnprintf; \ + __ret_strnprintf = snprintf(buf, buf_size, ##__VA_ARGS__); \ + if (__ret_strnprintf < 0 || (size_t)__ret_strnprintf >= (size_t)buf_size) \ + __ret_strnprintf = ret_errno(EIO); \ + __ret_strnprintf; \ + }) + #define move_ptr(ptr) \ ({ \ __typeof__(ptr) __internal_ptr__ = (ptr); \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/proc_cpuview.c new/lxcfs-5.0.4/src/proc_cpuview.c --- old/lxcfs-5.0.2/src/proc_cpuview.c 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/proc_cpuview.c 2023-07-25 23:58:55.000000000 +0200 @@ -171,6 +171,7 @@ } out_rwlock_unlock: + pthread_mutex_lock(&rv->lock); pthread_rwlock_unlock(&head->lock); return move_ptr(rv); } @@ -224,6 +225,7 @@ return faccessat(cfd, path, F_OK, 0) == 0; } +/* should be called with wr-locked list */ static struct cg_proc_stat *prune_proc_stat_list(struct cg_proc_stat *node) { struct cg_proc_stat *first = NULL; @@ -232,6 +234,31 @@ if (!cgroup_supports("cpu", node->cg, "cpu.shares")) { struct cg_proc_stat *cur = node; + /* + * We need to ensure that no one referenced this node, + * because we are going to remove it from the list and free memory. + * + * If we can't grab the lock then just keep this node for now. + */ + if (pthread_mutex_trylock(&cur->lock)) + goto next; + + /* + * Yes, we can put lock back just after taking it, as we ensured + * that we are only one user of it right now. + * + * It follows from three facts: + * - we are under pthread_rwlock_wrlock(hash_table_bucket) + * - pthread_mutex_lock is taken by find_proc_stat_node() + * with pthread_rwlock_rdlock(hash_table_bucket) held. + * - pthread_mutex_lock is taken by add_proc_stat_node() + * with pthread_rwlock_wrlock(hash_table_bucket) held. + * + * It means that nobody can get a pointer to (cur) node in a parallel + * thread and all old users of (cur) node have released pthread_mutex_lock(cur). + */ + pthread_mutex_unlock(&cur->lock); + if (prev) prev->next = node->next; else @@ -242,6 +269,7 @@ free_proc_stat_node(cur); } else { +next: if (!first) first = node; prev = node; @@ -279,6 +307,7 @@ { struct cg_proc_stat *node; + prune_proc_stat_history(); pthread_rwlock_rdlock(&head->lock); if (!head->next) { @@ -289,15 +318,16 @@ node = head->next; do { - if (strcmp(cg, node->cg) == 0) + if (strcmp(cg, node->cg) == 0) { + pthread_mutex_lock(&node->lock); goto out; + } } while ((node = node->next)); node = NULL; out: pthread_rwlock_unlock(&head->lock); - prune_proc_stat_history(); return node; } @@ -318,8 +348,6 @@ lxcfs_debug("New stat node (%d) for %s\n", cpu_count, cg); } - pthread_mutex_lock(&node->lock); - /* * If additional CPUs on the host have been enabled, CPU usage counter * arrays have to be expanded. @@ -468,20 +496,20 @@ * Return the maximum number of visible CPUs based on CPU quotas. * If there is no quota set, cpu number in cpuset value is returned. */ -int max_cpu_count(const char *cg) +int max_cpu_count(const char *cpuset_cg, const char *cpu_cg) { __do_free char *cpuset = NULL; int rv, nprocs; int64_t cfs_quota, cfs_period; int nr_cpus_in_cpuset = 0; - if (!read_cpu_cfs_param(cg, "quota", &cfs_quota)) + if (!read_cpu_cfs_param(cpu_cg, "quota", &cfs_quota)) cfs_quota = 0; - if (!read_cpu_cfs_param(cg, "period", &cfs_period)) + if (!read_cpu_cfs_param(cpu_cg, "period", &cfs_period)) cfs_period = 0; - cpuset = get_cpuset(cg); + cpuset = get_cpuset(cpuset_cg); if (cpuset) nr_cpus_in_cpuset = cpu_number_in_cpuset(cpuset); @@ -512,7 +540,7 @@ return rv; } -int cpuview_proc_stat(const char *cg, const char *cpuset, +int cpuview_proc_stat(const char *cg, const char *cpu_cg, const char *cpuset, struct cpuacct_usage *cg_cpu_usage, int cg_cpu_usage_size, FILE *f, char *buf, size_t buf_size) { @@ -600,7 +628,7 @@ } /* Cannot use more CPUs than is available in cpuset. */ - max_cpus = max_cpu_count(cg); + max_cpus = max_cpu_count(cg, cpu_cg); if (max_cpus > cpu_cnt || !max_cpus) max_cpus = cpu_cnt; @@ -908,7 +936,7 @@ int proc_cpuinfo_read(char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { - __do_free char *cg = NULL, *cpuset = NULL, *line = NULL; + __do_free char *cg = NULL, *cpuset = NULL, *line = NULL, *cpu_cg = NULL; __do_free void *fopen_cache = NULL; __do_fclose FILE *f = NULL; struct fuse_context *fc = fuse_get_context(); @@ -945,7 +973,10 @@ if (!cg) return read_file_fuse("proc/cpuinfo", buf, size, d); prune_init_slice(cg); - + cpu_cg = get_pid_cgroup(initpid, "cpu"); + if (!cpu_cg) + return read_file_fuse("proc/cpuinfo", buf, size, d); + prune_init_slice(cpu_cg); cpuset = get_cpuset(cg); if (!cpuset) return 0; @@ -955,7 +986,7 @@ else use_view = false; if (use_view) - max_cpus = max_cpu_count(cg); + max_cpus = max_cpu_count(cg, cpu_cg); f = fopen_cached("/proc/cpuinfo", "re", &fopen_cache); if (!f) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/proc_cpuview.h new/lxcfs-5.0.4/src/proc_cpuview.h --- old/lxcfs-5.0.2/src/proc_cpuview.h 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/proc_cpuview.h 2023-07-25 23:58:55.000000000 +0200 @@ -21,7 +21,7 @@ bool online; }; -extern int cpuview_proc_stat(const char *cg, const char *cpuset, +extern int cpuview_proc_stat(const char *cg, const char *cpu_cg, const char *cpuset, struct cpuacct_usage *cg_cpu_usage, int cg_cpu_usage_size, FILE *f, char *buf, size_t buf_size); @@ -31,7 +31,7 @@ struct cpuacct_usage **return_usage, int *size); extern bool init_cpuview(void); extern void free_cpuview(void); -extern int max_cpu_count(const char *cg); +extern int max_cpu_count(const char *cpuset_cg, const char *cpu_cg); #endif /* __LXCFS_PROC_CPUVIEW_FUSE_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/proc_fuse.c new/lxcfs-5.0.4/src/proc_fuse.c --- old/lxcfs-5.0.2/src/proc_fuse.c 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/proc_fuse.c 2023-07-25 23:58:55.000000000 +0200 @@ -24,6 +24,7 @@ #include <sys/mman.h> #include <sys/mount.h> #include <sys/param.h> +#include <sys/personality.h> #include <sys/socket.h> #include <sys/syscall.h> #include <sys/sysinfo.h> @@ -617,14 +618,14 @@ get_blkio_io_value(io_service_time_str, stats.major, stats.minor, "Total", &stats.total_ticks); stats.total_ticks = stats.total_ticks / 1000000; - memset(lbuf, 0, 256); + memset(lbuf, 0, sizeof(lbuf)); if (stats.read || stats.write || stats.read_merged || stats.write_merged || stats.read_sectors || stats.write_sectors || stats.read_ticks || - stats.write_ticks || stats.ios_pgr || stats.total_ticks || stats.rq_ticks || - stats.discard_merged || stats.discard_sectors || stats.discard_ticks) - snprintf( + stats.write_ticks || stats.ios_pgr || stats.total_ticks || stats.rq_ticks || stats.discard || + stats.discard_merged || stats.discard_sectors || stats.discard_ticks) { + ret = strnprintf( lbuf, - 256, + sizeof(lbuf), "%u %u" /* major, minor */ " %s" /* dev_name */ " %" PRIu64 /* read */ @@ -638,6 +639,7 @@ " %" PRIu64 /* ios_pgr */ " %" PRIu64 /* total_ticks */ " %" PRIu64 /* rq_ticks */ + " %" PRIu64 /* discard */ " %" PRIu64 /* discard_merged */ " %" PRIu64 /* discard_sectors */ " %" PRIu64 /* discard_ticks */ @@ -656,11 +658,18 @@ stats.ios_pgr, stats.total_ticks, stats.rq_ticks, + stats.discard, stats.discard_merged, stats.discard_sectors, stats.discard_ticks); - else + if (ret < 0) { + lxcfs_error("Insufficient buffer for %u:%u %s diskstats", + stats.major, stats.minor, stats.dev_name); + continue; + } + } else { continue; + } l = snprintf(cache, cache_size, "%s", lbuf); if (l < 0) @@ -885,7 +894,7 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { - __do_free char *cg = NULL, *cpuset = NULL, *line = NULL; + __do_free char *cg = NULL, *cpu_cg = NULL, *cpuset = NULL, *line = NULL; __do_free void *fopen_cache = NULL; __do_free struct cpuacct_usage *cg_cpu_usage = NULL; __do_fclose FILE *f = NULL; @@ -938,7 +947,10 @@ if (!cg) return read_file_fuse("/proc/stat", buf, size, d); prune_init_slice(cg); - + cpu_cg = get_pid_cgroup(initpid, "cpu"); + if (!cpu_cg) + return read_file_fuse("/proc/stat", buf, size, d); + prune_init_slice(cpu_cg); cpuset = get_cpuset(cg); if (!cpuset) return 0; @@ -958,7 +970,7 @@ */ if (read_cpuacct_usage_all(cg, cpuset, &cg_cpu_usage, &cg_cpu_usage_size) == 0) { if (cgroup_ops->can_use_cpuview(cgroup_ops) && opts && opts->use_cfs) { - total_len = cpuview_proc_stat(cg, cpuset, cg_cpu_usage, + total_len = cpuview_proc_stat(cg, cpu_cg, cpuset, cg_cpu_usage, cg_cpu_usage_size, f, d->buf, d->buflen); goto out; @@ -972,7 +984,7 @@ char cpu_char[10]; /* That's a lot of cores */ char *c; uint64_t all_used, cg_used, new_idle; - int ret; + int ret, cpu_to_render; if (strlen(line) == 0) continue; @@ -999,6 +1011,11 @@ curcpu++; + if (cgroup_ops->can_use_cpuview(cgroup_ops) && opts && opts->use_cfs) + cpu_to_render = curcpu; + else + cpu_to_render = physcpu; + ret = sscanf( line, "%*s" /* <skip> */ @@ -1027,7 +1044,7 @@ if (!c) continue; - l = snprintf(cache, cache_size, "cpu%d%s", curcpu, c); + l = snprintf(cache, cache_size, "cpu%d%s", cpu_to_render, c); if (l < 0) return log_error(0, "Failed to write cache"); if ((size_t)l >= cache_size) @@ -1052,13 +1069,13 @@ new_idle = idle + (all_used - cg_used); } else { lxcfs_debug("cpu%d from %s has unexpected cpu time: %" PRIu64 " in /proc/stat, %" PRIu64 " in cpuacct.usage_all; unable to determine idle time", - curcpu, cg, all_used, cg_used); + cpu_to_render, cg, all_used, cg_used); new_idle = idle; } l = snprintf(cache, cache_size, "cpu%d %" PRIu64 " 0 %" PRIu64 " %" PRIu64 " 0 0 0 0 0 0\n", - curcpu, cg_cpu_usage[physcpu].user, + cpu_to_render, cg_cpu_usage[physcpu].user, cg_cpu_usage[physcpu].system, new_idle); if (l < 0) return log_error(0, "Failed to write cache"); @@ -1500,6 +1517,46 @@ return total_len; } +static int proc_read_with_personality(int (*do_proc_read)(char *, size_t, off_t, + struct fuse_file_info *), char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + struct fuse_context *fc = fuse_get_context(); + __u32 host_personality = liblxcfs_personality(), caller_personality; + bool change_personality; + int ret, read_ret; + + if (get_task_personality(fc->pid, &caller_personality) < 0) + return log_error(0, "Failed to get caller process (pid: %d) personality", fc->pid); + + /* do we need to change thread personality? */ + change_personality = host_personality != caller_personality; + + if (change_personality) { + ret = personality(caller_personality); + if (ret == -1) + return log_error(0, "Call to personality(%d) failed: %s\n", + caller_personality, strerror(errno)); + + lxcfs_debug("task (tid: %d) personality was changed %d -> %d\n", + (int)syscall(SYS_gettid), ret, caller_personality); + } + + read_ret = do_proc_read(buf, size, offset, fi); + + if (change_personality) { + ret = personality(host_personality); + if (ret == -1) + return log_error(0, "Call to personality(%d) failed: %s\n", + host_personality, strerror(errno)); + + lxcfs_debug("task (tid: %d) personality was restored %d -> %d\n", + (int)syscall(SYS_gettid), ret, host_personality); + } + + return read_ret; +} + __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { @@ -1514,7 +1571,7 @@ buf, size, offset, f); case LXC_TYPE_PROC_CPUINFO: if (liblxcfs_functional()) - return proc_cpuinfo_read(buf, size, offset, fi); + return proc_read_with_personality(&proc_cpuinfo_read, buf, size, offset, fi); return read_file_fuse_with_offset(LXC_TYPE_PROC_CPUINFO_PATH, buf, size, offset, f); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/sysfs_fuse.c new/lxcfs-5.0.4/src/sysfs_fuse.c --- old/lxcfs-5.0.2/src/sysfs_fuse.c 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/sysfs_fuse.c 2023-07-25 23:58:55.000000000 +0200 @@ -38,161 +38,7 @@ #include "utils.h" static off_t get_sysfile_size(const char *which); -/* Create cpumask from cpulist aka turn: - * - * 0,2-3 - * - * into bit array - * - * 1 0 1 1 - */ -static int lxc_cpumask(char *buf, __u32 **bitarr, __u32 *last_set_bit) -{ - __do_free __u32 *arr_u32 = NULL; - __u32 cur_last_set_bit = 0, nbits = 256; - __u32 nr_u32; - char *token; - - nr_u32 = BITS_TO_LONGS(nbits); - arr_u32 = zalloc(nr_u32 * sizeof(__u32)); - if (!arr_u32) - return ret_errno(ENOMEM); - - lxc_iterate_parts(token, buf, ",") { - __u32 last_bit, first_bit; - char *range; - - errno = 0; - first_bit = strtoul(token, NULL, 0); - last_bit = first_bit; - range = strchr(token, '-'); - if (range) - last_bit = strtoul(range + 1, NULL, 0); - - if (!(first_bit <= last_bit)) - return ret_errno(EINVAL); - - if (last_bit >= nbits) { - __u32 add_bits = last_bit - nbits + 32; - __u32 new_nr_u32; - __u32 *p; - - new_nr_u32 = BITS_TO_LONGS(nbits + add_bits); - p = realloc(arr_u32, new_nr_u32 * sizeof(uint32_t)); - if (!p) - return ret_errno(ENOMEM); - arr_u32 = move_ptr(p); - - memset(arr_u32 + nr_u32, 0, - (new_nr_u32 - nr_u32) * sizeof(uint32_t)); - nbits += add_bits; - } - - while (first_bit <= last_bit) - set_bit(first_bit++, arr_u32); - - if (last_bit > cur_last_set_bit) - cur_last_set_bit = last_bit; - } - - *last_set_bit = cur_last_set_bit; - *bitarr = move_ptr(arr_u32); - return 0; -} - -static int lxc_cpumask_update(char *buf, __u32 *bitarr, __u32 last_set_bit, - bool clear) -{ - bool flipped = false; - char *token; - - lxc_iterate_parts(token, buf, ",") { - __u32 last_bit, first_bit; - char *range; - - errno = 0; - first_bit = strtoul(token, NULL, 0); - last_bit = first_bit; - range = strchr(token, '-'); - if (range) - last_bit = strtoul(range + 1, NULL, 0); - - if (!(first_bit <= last_bit)) { - lxcfs_debug("The cup range seems to be inverted: %u-%u", first_bit, last_bit); - continue; - } - - if (last_bit > last_set_bit) - continue; - - while (first_bit <= last_bit) { - if (clear && is_set(first_bit, bitarr)) { - flipped = true; - clear_bit(first_bit, bitarr); - } else if (!clear && !is_set(first_bit, bitarr)) { - flipped = true; - set_bit(first_bit, bitarr); - } - - first_bit++; - } - } - - if (flipped) - return 1; - - return 0; -} - -#define __ISOL_CPUS "/sys/devices/system/cpu/isolated" -#define __OFFLINE_CPUS "/sys/devices/system/cpu/offline" -static int cpumask(char *posscpus, __u32 **bitarr, __u32 *last_set_bit) -{ - __do_free char *isolcpus = NULL, *offlinecpus = NULL; - __do_free __u32 *possmask = NULL; - int ret; - __u32 poss_last_set_bit = 0; - - if (file_exists(__ISOL_CPUS)) { - isolcpus = read_file_at(-EBADF, __ISOL_CPUS, PROTECT_OPEN); - if (!isolcpus) - return -1; - - if (!isdigit(isolcpus[0])) - free_disarm(isolcpus); - } else { - lxcfs_debug("The path \""__ISOL_CPUS"\" to read isolated cpus from does not exist"); - } - - if (file_exists(__OFFLINE_CPUS)) { - offlinecpus = read_file_at(-EBADF, __OFFLINE_CPUS, PROTECT_OPEN); - if (!offlinecpus) - return -1; - - if (!isdigit(offlinecpus[0])) - free_disarm(offlinecpus); - } else { - lxcfs_debug("The path \""__OFFLINE_CPUS"\" to read offline cpus from does not exist"); - } - - ret = lxc_cpumask(posscpus, &possmask, &poss_last_set_bit); - if (ret) - return ret; - - if (isolcpus) - ret = lxc_cpumask_update(isolcpus, possmask, poss_last_set_bit, true); - - if (offlinecpus) - ret |= lxc_cpumask_update(offlinecpus, possmask, poss_last_set_bit, true); - if (ret) - return ret; - - *bitarr = move_ptr(possmask); - *last_set_bit = poss_last_set_bit; - return 0; -} - -static int do_cpuset_read(char *cg, char *buf, size_t buflen) +static int do_cpuset_read(char *cg, char *cpu_cg, char *buf, size_t buflen) { __do_free char *cpuset = NULL; struct fuse_context *fc = fuse_get_context(); @@ -211,7 +57,7 @@ use_view = false; if (use_view) - max_cpus = max_cpu_count(cg); + max_cpus = max_cpu_count(cg, cpu_cg); if (use_view) { if (max_cpus > 1) @@ -231,7 +77,7 @@ off_t offset, struct fuse_file_info *fi) { - __do_free char *cg = NULL; + __do_free char *cg = NULL, *cpu_cg = NULL; struct fuse_context *fc = fuse_get_context(); struct file_info *d = INTTYPE_TO_PTR(fi->fh); char *cache = d->buf; @@ -262,8 +108,11 @@ if (!cg) return read_file_fuse("/sys/devices/system/cpu/online", buf, size, d); prune_init_slice(cg); - - total_len = do_cpuset_read(cg, d->buf, d->buflen); + cpu_cg = get_pid_cgroup(initpid, "cpu"); + if (!cpu_cg) + return read_file_fuse("/sys/devices/system/cpu/online", buf, size, d); + prune_init_slice(cpu_cg); + total_len = do_cpuset_read(cg, cpu_cg, d->buf, d->buflen); d->size = (int)total_len; d->cached = 1; @@ -278,7 +127,7 @@ static int sys_devices_system_cpu_online_getsize(const char *path) { - __do_free char *cg = NULL; + __do_free char *cg = NULL, *cpu_cg = NULL; struct fuse_context *fc = fuse_get_context(); pid_t initpid; char buf[BUF_RESERVE_SIZE]; @@ -291,69 +140,26 @@ cg = get_pid_cgroup(initpid, "cpuset"); if (!cg) return get_sysfile_size(path); + cpu_cg = get_pid_cgroup(initpid, "cpu"); + if (!cpu_cg) + return get_sysfile_size(path); prune_init_slice(cg); + prune_init_slice(cpu_cg); - return do_cpuset_read(cg, buf, buflen); + return do_cpuset_read(cg, cpu_cg, buf, buflen); } static int filler_sys_devices_system_cpu(const char *path, void *buf, fuse_fill_dir_t filler) { - __do_free __u32 *bitarr = NULL; - __do_free char *cg = NULL, *cpuset = NULL; __do_closedir DIR *dirp = NULL; - struct fuse_context *fc = fuse_get_context(); - __u32 last_set_bit = 0; - int ret; struct dirent *dirent; - pid_t initpid; - - initpid = lookup_initpid_in_store(fc->pid); - if (initpid <= 1 || is_shared_pidns(initpid)) - initpid = fc->pid; - - cg = get_pid_cgroup(initpid, "cpuset"); - if (!cg) - return 0; - prune_init_slice(cg); - - cpuset = get_cpuset(cg); - if (!cpuset) - return 0; - - ret = cpumask(cpuset, &bitarr, &last_set_bit); - if (ret) - return ret; dirp = opendir(path); if (!dirp) return -ENOENT; - for (__u32 bit = 0; bit <= last_set_bit; bit++) { - char cpu[100]; - - if (!is_set(bit, bitarr)) - continue; - - ret = snprintf(cpu, sizeof(cpu), "cpu%u", bit); - if (ret < 0 || (size_t)ret >= sizeof(cpu)) - continue; - - if (dir_fillerat(filler, dirp, cpu, buf, 0) != 0) - return -ENOENT; - } - while ((dirent = readdir(dirp))) { - char *entry = dirent->d_name; - - if (strlen(entry) > 3) { - entry += 3; - - /* Don't emit entries we already filtered above. */ - if (isdigit(*entry)) - continue; - } - if (dirent_fillerat(filler, dirp, dirent, buf, 0) != 0) return -ENOENT; } @@ -590,10 +396,10 @@ return -ENOENT; return 0; case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU: - if (dir_filler(filler, buf, ".", 0) != 0 || - dir_filler(filler, buf, "..", 0) != 0) + if (dir_filler(filler, buf, ".", 0) != 0 || + dir_filler(filler, buf, "..", 0) != 0 || + dirent_filler(filler, path, "online", buf, 0) != 0) return -ENOENT; - return filler_sys_devices_system_cpu(path, buf, filler); case LXC_TYPE_SYS_DEVICES_SYSTEM_CPU_SUBDIR: dirp = opendir_flags(path, O_CLOEXEC | O_NOFOLLOW); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/utils.c new/lxcfs-5.0.4/src/utils.c --- old/lxcfs-5.0.2/src/utils.c 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/utils.c 2023-07-25 23:58:55.000000000 +0200 @@ -529,6 +529,29 @@ return 0; } +int safe_uint32(const char *numstr, uint32_t *converted, int base) +{ + char *err = NULL; + unsigned long uli; + + while (isspace(*numstr)) + numstr++; + + if (*numstr == '-') + return -EINVAL; + + errno = 0; + uli = strtoul(numstr, &err, base); + if (errno == ERANGE && uli == UINT32_MAX) + return -ERANGE; + + if (err == numstr || *err != '\0') + return -EINVAL; + + *converted = (uint32_t)uli; + return 0; +} + static int char_left_gc(const char *buffer, size_t len) { size_t i; @@ -642,3 +665,29 @@ return dirp; } + +int get_task_personality(pid_t pid, __u32 *personality) +{ + __do_close int fd = -EBADF; + int ret = -1; + char path[STRLITERALLEN("/proc//personality") + INTTYPE_TO_STRLEN(pid_t) + 1]; + /* seq_printf(m, "%08x\n", task->personality); */ + char buf[8 + 1]; + + ret = strnprintf(path, sizeof(path), "/proc/%d/personality", pid); + if (ret < 0) + return -1; + + fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return -1; + + ret = read_nointr(fd, buf, sizeof(buf) - 1); + if (ret >= 0) { + buf[ret] = '\0'; + if (safe_uint32(buf, personality, 16) < 0) + return log_error(-1, "Failed to convert personality %s", buf); + } + + return ret; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/src/utils.h new/lxcfs-5.0.4/src/utils.h --- old/lxcfs-5.0.2/src/utils.h 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/src/utils.h 2023-07-25 23:58:55.000000000 +0200 @@ -62,6 +62,7 @@ extern DIR *opendir_flags(const char *path, int oflags); extern ssize_t write_nointr(int fd, const void *buf, size_t count); extern int safe_uint64(const char *numstr, uint64_t *converted, int base); +extern int safe_uint32(const char *numstr, uint32_t *converted, int base); extern char *trim_whitespace_in_place(char *buffer); static inline bool file_exists(const char *f) @@ -75,4 +76,7 @@ #define PROTECT_OPEN (PROTECT_OPEN_WITH_TRAILING_SYMLINKS | O_NOFOLLOW) extern char *read_file_at(int dfd, const char *fnam, unsigned int o_flags); +extern int get_task_personality(pid_t pid, __u32 *personality); +extern int get_host_personality(__u32 *personality); + #endif /* __LXCFS_UTILS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/tests/main.sh.in new/lxcfs-5.0.4/tests/main.sh.in --- old/lxcfs-5.0.2/tests/main.sh.in 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/tests/main.sh.in 2023-07-25 23:58:55.000000000 +0200 @@ -82,8 +82,6 @@ RUNTEST ${dirname}/test_readdir TESTCASE="test_proc" RUNTEST ${dirname}/test_proc -TESTCASE="test_sysfs" -RUNTEST ${dirname}/test_sysfs TESTCASE="test_cgroup" RUNTEST ${dirname}/test_cgroup TESTCASE="test_read_proc.sh" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/tests/meson.build new/lxcfs-5.0.4/tests/meson.build --- old/lxcfs-5.0.2/tests/meson.build 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/tests/meson.build 2023-07-25 23:58:55.000000000 +0200 @@ -61,18 +61,6 @@ ]) test_programs += custom_target( - 'test_sysfs', - build_by_default: want_tests != false, - input: 'test_sysfs.in', - output: 'test_sysfs', - command: [ - meson_render_jinja2, - config_h, - '@INPUT@', - '@OUTPUT@', - ]) - -test_programs += custom_target( 'test_read_proc.sh', build_by_default: want_tests != false, input: 'test_read_proc.sh.in', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/tests/test_cgroup.in new/lxcfs-5.0.4/tests/test_cgroup.in --- old/lxcfs-5.0.2/tests/test_cgroup.in 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/tests/test_cgroup.in 2023-07-25 23:58:55.000000000 +0200 @@ -20,6 +20,17 @@ exit 1 fi +IS_CGROUP_V2=0 +grep -qF 'cgroup cgroup' /proc/1/mountinfo || IS_CGROUP_V2=1 + +# +# LXCFS cgroupfs emulation doesn't make any sense with cgroup2 +# +if [ "$IS_CGROUP_V2" = "1" ]; then + PASS=1 + exit 0 +fi + echo "==> Setting up memory, freeze and cpuset cgroups" for c in memory freezer cpuset; do [ ! -d /sys/fs/cgroup/${c} ] && exit 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/tests/test_meminfo_hierarchy.sh.in new/lxcfs-5.0.4/tests/test_meminfo_hierarchy.sh.in --- old/lxcfs-5.0.2/tests/test_meminfo_hierarchy.sh.in 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/tests/test_meminfo_hierarchy.sh.in 2023-07-25 23:58:55.000000000 +0200 @@ -19,23 +19,46 @@ FAILED=1 trap cleanup EXIT HUP INT TERM -[ ! -d /sys/fs/cgroup/memory ] && exit 0 -echo "==> Setting up memory cgroup" -initmemory=`awk -F: '/memory/ { print $3 }' /proc/1/cgroup` -mempath=/sys/fs/cgroup/memory/${initmemory} +IS_CGROUP_V2=0 +grep -qF 'cgroup cgroup' /proc/1/mountinfo || IS_CGROUP_V2=1 + +if [ "$IS_CGROUP_V2" = "1" ]; then + [ ! -d /sys/fs/cgroup ] && exit 0 + echo "==> Setting up cgroup" + mempath=/sys/fs/cgroup/ + + memory_limit_file=memory.max + tasks_file=cgroup.procs +else + [ ! -d /sys/fs/cgroup/memory ] && exit 0 + echo "==> Setting up memory cgroup" + initmemory=$(awk -F: '/memory/ { print $3 }' /proc/1/cgroup) + mempath=/sys/fs/cgroup/memory/${initmemory} + + memory_limit_file=memory.limit_in_bytes + tasks_file=tasks +fi + rmdir ${mempath}/${cg1} 2>/dev/null || true rmdir ${mempath}/${cg2} 2>/dev/null || true echo "==> Testing /proc/meminfo with limit" mkdir ${mempath}/${cg1} -echo 500000000 > ${mempath}/${cg1}/memory.limit_in_bytes -echo 1 > ${mempath}/${cg1}/tasks -m1=`awk '/^MemTotal:/ { print $2 }' ${LXCFSDIR}/proc/meminfo` +echo 500000000 > ${mempath}/${cg1}/${memory_limit_file} +echo 1 > ${mempath}/${cg1}/${tasks_file} +m1=$(awk '/^MemTotal:/ { print $2 }' ${LXCFSDIR}/proc/meminfo) + +if [ "$IS_CGROUP_V2" = "1" ]; then + # temporary move to the root cgroup because of + # "no internal process" constraint + echo 1 > ${mempath}/${tasks_file} + echo '+memory' > ${mempath}/${cg1}/cgroup.subtree_control +fi echo "==> Testing /proc/meminfo with sub-cgroup" mkdir ${mempath}/${cg1}/${cg2} -echo 1 > ${mempath}/${cg1}/${cg2}/tasks -m2=`awk '/^MemTotal:/ { print $2 }' ${LXCFSDIR}/proc/meminfo` +echo 1 > ${mempath}/${cg1}/${cg2}/${tasks_file} +m2=$(awk '/^MemTotal:/ { print $2 }' ${LXCFSDIR}/proc/meminfo) echo "==> Confirming same limits" [ $m1 -eq $m2 ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/tests/test_proc.in new/lxcfs-5.0.4/tests/test_proc.in --- old/lxcfs-5.0.2/tests/test_proc.in 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/tests/test_proc.in 2023-07-25 23:58:55.000000000 +0200 @@ -19,25 +19,50 @@ exit 1 fi -echo "==> Setting up memory/cpuset cgroup in lxcfs_test_proc" -[ ! -d /sys/fs/cgroup/memory ] && exit 0 -[ ! -d /sys/fs/cgroup/cpuset ] && exit 0 +IS_CGROUP_V2=0 +grep -qF 'cgroup cgroup' /proc/1/mountinfo || IS_CGROUP_V2=1 -initcpuset=`awk -F: '/cpuset/ { print $3 }' /proc/1/cgroup` -initmemory=`awk -F: '/memory/ { print $3 }' /proc/1/cgroup` +if [ "$IS_CGROUP_V2" = "1" ]; then + echo "==> Setting up cgroup in lxcfs_test_proc" + [ ! -d /sys/fs/cgroup ] && exit 0 -cpupath=/sys/fs/cgroup/cpuset/${initcpuset} -mempath=/sys/fs/cgroup/memory/${initmemory} + default_hierarchy="/" -rmdir ${cpupath}/lxcfs_test_proc 2>/dev/null || true -rmdir ${mempath}/lxcfs_test_proc 2>/dev/null || true -mkdir ${cpupath}/lxcfs_test_proc -mkdir ${mempath}/lxcfs_test_proc + hierarchy_path=/sys/fs/cgroup/${default_hierarchy} + cpupath=${hierarchy_path} + mempath=${hierarchy_path} -echo 1 > ${cpupath}/lxcfs_test_proc/tasks -echo 1 > ${mempath}/lxcfs_test_proc/tasks + rmdir ${hierarchy_path}/lxcfs_test_proc 2>/dev/null || true + mkdir ${hierarchy_path}/lxcfs_test_proc -echo $((64*1024*1024)) > ${mempath}/lxcfs_test_proc/memory.limit_in_bytes + echo 1 > ${hierarchy_path}/lxcfs_test_proc/cgroup.procs + + echo '+cpu +memory' > ${hierarchy_path}/cgroup.subtree_control + + memory_limit_file=memory.max +else + echo "==> Setting up memory/cpuset cgroup in lxcfs_test_proc" + [ ! -d /sys/fs/cgroup/memory ] && exit 0 + [ ! -d /sys/fs/cgroup/cpuset ] && exit 0 + + initcpuset=$(awk -F: '/cpuset/ { print $3 }' /proc/1/cgroup) + initmemory=$(awk -F: '/memory/ { print $3 }' /proc/1/cgroup) + + cpupath=/sys/fs/cgroup/cpuset/${initcpuset} + mempath=/sys/fs/cgroup/memory/${initmemory} + + rmdir ${cpupath}/lxcfs_test_proc 2>/dev/null || true + rmdir ${mempath}/lxcfs_test_proc 2>/dev/null || true + mkdir ${cpupath}/lxcfs_test_proc + mkdir ${mempath}/lxcfs_test_proc + + echo 1 > ${cpupath}/lxcfs_test_proc/tasks + echo 1 > ${mempath}/lxcfs_test_proc/tasks + + memory_limit_file=memory.limit_in_bytes +fi + +echo $((64*1024*1024)) > ${mempath}/lxcfs_test_proc/${memory_limit_file} echo 0 > ${cpupath}/lxcfs_test_proc/cpuset.cpus # Test uptime diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/tests/test_sigusr2.sh.in new/lxcfs-5.0.4/tests/test_sigusr2.sh.in --- old/lxcfs-5.0.2/tests/test_sigusr2.sh.in 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/tests/test_sigusr2.sh.in 2023-07-25 23:58:55.000000000 +0200 @@ -19,16 +19,34 @@ exit 1 fi -echo "==> Setting up memory cgroup in lxcfs_test_proc" -[ ! -d /sys/fs/cgroup/memory ] && exit 0 +IS_CGROUP_V2=0 +grep -qF 'cgroup cgroup' /proc/1/mountinfo || IS_CGROUP_V2=1 -initmemory=`awk -F: '/memory/ { print $3 }' /proc/1/cgroup` -mempath=/sys/fs/cgroup/memory/${initmemory} -rmdir ${mempath}/lxcfs_test_proc 2>/dev/null || true -mkdir ${mempath}/lxcfs_test_proc -echo 1 > ${mempath}/lxcfs_test_proc/tasks +if [ "$IS_CGROUP_V2" = "1" ]; then + echo "==> Setting up cgroup in lxcfs_test_proc" + [ ! -d /sys/fs/cgroup ] && exit 0 -echo $((64*1024*1024)) > ${mempath}/lxcfs_test_proc/memory.limit_in_bytes + mempath=/sys/fs/cgroup + rmdir ${mempath}/lxcfs_test_proc 2>/dev/null || true + mkdir ${mempath}/lxcfs_test_proc + + memory_limit_file=memory.max + tasks_file=cgroup.procs +else + echo "==> Setting up memory cgroup in lxcfs_test_proc" + [ ! -d /sys/fs/cgroup/memory ] && exit 0 + + initmemory=$(awk -F: '/memory/ { print $3 }' /proc/1/cgroup) + mempath=/sys/fs/cgroup/memory/${initmemory} + rmdir ${mempath}/lxcfs_test_proc 2>/dev/null || true + mkdir ${mempath}/lxcfs_test_proc + + memory_limit_file=memory.limit_in_bytes + tasks_file=tasks +fi + +echo 1 > ${mempath}/lxcfs_test_proc/${tasks_file} +echo $((64*1024*1024)) > ${mempath}/lxcfs_test_proc/${memory_limit_file} # Test meminfo echo "==> Testing /proc/meminfo" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/tests/test_sysfs.in new/lxcfs-5.0.4/tests/test_sysfs.in --- old/lxcfs-5.0.2/tests/test_sysfs.in 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/tests/test_sysfs.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,37 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: LGPL-2.1+ - -set -eu -[ -n "${DEBUG:-}" ] && set -x - -PASS=0 - -cleanup() { - [ "$PASS" = "1" ] || (echo FAIL && exit 1) -} - -trap cleanup EXIT HUP INT TERM - -LXCFSDIR=${LXCFSDIR:-/var/lib/lxcfs} - -if ! mountpoint -q ${LXCFSDIR}; then - echo "lxcfs isn't mounted on ${LXCFSDIR}" - exit 1 -fi - -if [ "{{ HAVE_FUSE_RETURNS_DT_TYPE }}" != "1" ]; then - echo "FUSE3 version doesn't support what's needed for sysfs cpu" - PASS=1 - exit 0 -fi - -echo "==> Setting up memory/cpuset cgroup in lxcfs_test_proc" -[ ! -d /sys/devices/system/cpu ] && exit 0 -mount -o bind "${LXCFSDIR}/sys/devices/system/cpu" "/sys/devices/system/cpu" -num_cpus="$(getconf _NPROCESSORS_CONF)" -umount -l "/sys/devices/system/cpu" - -echo "Detected ${num_cpus} cpus" -[ "${num_cpus}" != "0" ] - -PASS=1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lxcfs-5.0.2/tools/meson-render-jinja2.py new/lxcfs-5.0.4/tools/meson-render-jinja2.py --- old/lxcfs-5.0.2/tools/meson-render-jinja2.py 2022-08-09 23:24:16.000000000 +0200 +++ new/lxcfs-5.0.4/tools/meson-render-jinja2.py 2023-07-25 23:58:55.000000000 +0200 @@ -23,7 +23,12 @@ def render(filename, defines): text = open(filename).read() - template = jinja2.Template(text, trim_blocks=True, undefined=jinja2.StrictUndefined) + template = jinja2.Template( + text, + trim_blocks=True, + keep_trailing_newline=True, + undefined=jinja2.StrictUndefined, + ) return template.render(defines) if __name__ == '__main__':