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__':

Reply via email to