Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package lxcfs for openSUSE:Factory checked 
in at 2026-03-10 17:57:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lxcfs (Old)
 and      /work/SRC/openSUSE:Factory/.lxcfs.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "lxcfs"

Tue Mar 10 17:57:18 2026 rev:29 rq:1337887 version:6.0.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/lxcfs/lxcfs.changes      2025-08-17 
14:50:30.836936443 +0200
+++ /work/SRC/openSUSE:Factory/.lxcfs.new.8177/lxcfs.changes    2026-03-10 
18:01:56.608901093 +0100
@@ -1,0 +2,30 @@
+Thu Feb 26 08:46:36 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- update to 6.0.6:
+  https://discuss.linuxcontainers.org/t/lxcfs-6-0-6-lts-has-been-released/26263
+  The highlights for this release are:
+  * Fix issue with CPU count in /proc/stat
+  * Fix issue causing the cgroup2 mount flags to be changed on
+    startup
+  Detailed changelog
+  * proc_fuse: fix proc_stat_read reporting host cpu count under
+    cgroup v2
+  * cgroups: extract cgfsng_can_use_memory_feature() util function
+  * cgroups: replace dup() call with openat_safe()
+  * src/utils: fix in_same_namespace helper
+  * bindings: add private_data field to struct file_info
+  * meson: add “mocks” option for CI/testing purposes
+  * github: enable mocks for CI builds
+  * lxcfs: use macro to generate liblxcfs call helpers
+  * lxcfs: wire up ->write callback for /proc
+  * lxcfs: wire up ->poll callback for /proc
+  * proc_fuse: move release/releasedir at the end
+  * cgroups/cgfsng: fix whitespace errors in __cg_mount_direct
+  * cgroups/cgfsng: do not change host-wide cgroup2 superblock
+    options
+  * github: pass LIBFUSE env variable to upgrade tests
+  * github: enable mocks for CI upgrade tests
+  * meson: don’t forget to set PSI trigger mocks for liblxcfstest
+  * cgroups/cgfsng: check memory allocation in add_hierarchy
+
+-------------------------------------------------------------------

Old:
----
  lxcfs-6.0.5.tar.gz
  lxcfs-6.0.5.tar.gz.asc

New:
----
  lxcfs-6.0.6.tar.gz
  lxcfs-6.0.6.tar.gz.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ lxcfs.spec ++++++
--- /var/tmp/diff_new_pack.u1iKhf/_old  2026-03-10 18:01:57.236926914 +0100
+++ /var/tmp/diff_new_pack.u1iKhf/_new  2026-03-10 18:01:57.240927078 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package lxcfs
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# Copyright (c) 2026 SUSE LLC and contributors
 # Copyright (c) 2025 Andreas Stieger <[email protected]>
 #
 # All modifications and additions to the file contributed by third parties
@@ -18,7 +18,7 @@
 
 
 Name:           lxcfs
-Version:        6.0.5
+Version:        6.0.6
 Release:        0
 Summary:        FUSE filesystem for LXC
 License:        Apache-2.0

++++++ lxcfs-6.0.5.tar.gz -> lxcfs-6.0.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/.github/actions/build/action.yml 
new/lxcfs-6.0.6/.github/actions/build/action.yml
--- old/lxcfs-6.0.5/.github/actions/build/action.yml    2025-08-15 
06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/.github/actions/build/action.yml    2026-02-23 
20:21:25.000000000 +0100
@@ -48,6 +48,7 @@
         meson setup build \
             -Ddocs=false \
             -Dtests=true \
+            -Dmocks=true \
             -Dinit-script=systemd \
             -Dprefix=/usr \
             -Db_sanitize=address,undefined
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/.github/workflows/tests.yml 
new/lxcfs-6.0.6/.github/workflows/tests.yml
--- old/lxcfs-6.0.5/.github/workflows/tests.yml 2025-08-15 06:47:54.000000000 
+0200
+++ new/lxcfs-6.0.6/.github/workflows/tests.yml 2026-02-23 20:21:25.000000000 
+0100
@@ -75,12 +75,14 @@
         run: |
           git clone -b stable-6.0 https://github.com/lxc/lxcfs.git 
../upstream-lxcfs
           cd ../upstream-lxcfs
+          meson setup -Ddocs=false -Dtests=true -Dmocks=true 
-Dinit-script=systemd -Dprefix=/usr -Db_sanitize=address,undefined build/ || \
           meson setup -Ddocs=false -Dtests=true -Dinit-script=systemd 
-Dprefix=/usr -Db_sanitize=address,undefined build/
           meson compile -C build
 
       - name: Test
         env:
           CC: ${{ matrix.compiler }}
+          LIBFUSE: ${{ matrix.fuse }}
           WORKSPACE_PATH: ${{ github.workspace }}
         run: |
           UPSTREAM_LXCFS_TREE=$(realpath ${WORKSPACE_PATH}/../upstream-lxcfs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/meson.build new/lxcfs-6.0.6/meson.build
--- old/lxcfs-6.0.5/meson.build 2025-08-15 06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/meson.build 2026-02-23 20:21:25.000000000 +0100
@@ -4,7 +4,7 @@
 project(
     'lxcfs',
     'c',
-    version: '6.0.5',
+    version: '6.0.6',
     license: 'LGPLv2+',
     default_options: [
         'b_colorout=always',
@@ -69,6 +69,7 @@
 # Custom configuration.
 init_script = get_option('init-script')
 want_tests = get_option('tests')
+want_mocks = get_option('mocks')
 want_docs = get_option('docs')
 
 # Build flags.
@@ -232,12 +233,20 @@
         libfuse,
     ])
 
+liblxcfs_cargs = []
+liblxcfstest_cargs = ['-DRELOADTEST', '-DDEBUG']
+if want_mocks == true
+    liblxcfs_cargs = ['-DPSITRIGGERTEST', '-DDEBUG']
+    liblxcfstest_cargs += ['-DPSITRIGGERTEST']
+endif
+
 liblxcfs = shared_module(
     'lxcfs',
     liblxcfs_sources,
     dependencies: liblxcfs_common_dependencies,
     install: true,
-    install_dir: lxcfsdir)
+    install_dir: lxcfsdir,
+    c_args: liblxcfs_cargs)
 
 # Tests.
 test_programs = []
@@ -248,7 +257,7 @@
         dependencies: liblxcfs_common_dependencies,
         install: false,
         install_dir: lxcfsdir,
-        c_args: '-DRELOADTEST -DDEBUG')
+        c_args: liblxcfstest_cargs)
 endif
 
 # RPM spec.
@@ -306,6 +315,7 @@
     'lxcfs source root directory:      @0@'.format(project_source_root),
     'init system(s):           @0@'.format(init_script),
     'tests:                            @0@'.format(want_tests),
+    'mocks:                            @0@'.format(want_mocks),
     'documentation:                    @0@'.format(want_docs),
 ]
 message('\n         '.join(status))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/meson_options.txt 
new/lxcfs-6.0.6/meson_options.txt
--- old/lxcfs-6.0.5/meson_options.txt   2025-08-15 06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/meson_options.txt   2026-02-23 20:21:25.000000000 +0100
@@ -3,6 +3,9 @@
 option('tests', type : 'boolean', value: 'false',
        description : 'enable tests')
 
+option('mocks', type : 'boolean', value: 'false',
+       description : 'enable CI-only features (mocks some things in LXCFS for 
CI/testing purposes)')
+
 option('runtime-path', type : 'string', value : '/run',
        description : 'the runtime directory')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/bindings.h 
new/lxcfs-6.0.6/src/bindings.h
--- old/lxcfs-6.0.5/src/bindings.h      2025-08-15 06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/src/bindings.h      2026-02-23 20:21:25.000000000 +0100
@@ -94,13 +94,20 @@
 extern int rwlock_wrlock_interruptible(pthread_rwlock_t *l);
 
 struct file_info {
-       char *controller;
-       char *cgroup;
-       char *file;
+       union {
+               struct {
+                       char *controller;
+                       char *cgroup;
+                       char *file;
+               };
+               struct {
+                       void *private_data;
+               };
+       };
        int type;
        char *buf; /* unused */
        int buflen;
-       int size; /*actual data size */
+       int size; /* actual data size */
        int cached;
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/cgroups/cgfsng.c 
new/lxcfs-6.0.6/src/cgroups/cgfsng.c
--- old/lxcfs-6.0.5/src/cgroups/cgfsng.c        2025-08-15 06:47:54.000000000 
+0200
+++ new/lxcfs-6.0.6/src/cgroups/cgfsng.c        2026-02-23 20:21:25.000000000 
+0100
@@ -285,7 +285,8 @@
        struct hierarchy *new;
        int newentry;
 
-       new = zalloc(sizeof(*new));
+       new = must_realloc(NULL, sizeof(*new));
+       memset(new, 0, sizeof(*new));
        new->controllers = clist;
        new->mountpoint = mountpoint;
        new->base_path = base_path;
@@ -399,24 +400,39 @@
  */
 static int __cg_mount_direct(struct hierarchy *h, const char *controllerpath)
 {
-        __do_free char *controllers = NULL;
-        char *fstype = "cgroup2";
-        unsigned long flags = 0;
-        int ret;
-
-        flags |= MS_NOSUID;
-        flags |= MS_NOEXEC;
-        flags |= MS_NODEV;
-        flags |= MS_RELATIME;
-
-        if (h->version != CGROUP2_SUPER_MAGIC) {
-                controllers = lxc_string_join(",", (const char 
**)h->controllers, false);
-                if (!controllers)
-                        return -ENOMEM;
-                fstype = "cgroup";
+       __do_free char *controllers = NULL;
+       char *fstype = "cgroup2";
+       unsigned long flags = 0;
+       int ret;
+
+       flags |= MS_NOSUID;
+       flags |= MS_NOEXEC;
+       flags |= MS_NODEV;
+       flags |= MS_RELATIME;
+
+       if (h->version != CGROUP2_SUPER_MAGIC) {
+               controllers = lxc_string_join(",", (const char 
**)h->controllers, false);
+               if (!controllers)
+                       return -ENOMEM;
+               fstype = "cgroup";
+               ret = mount("cgroup", controllerpath, fstype, flags, 
controllers);
+       } else {
+               __do_free const char *sb_opts = NULL;
+
+               /*
+                * Before mounting cgroup2 fs we have to try out best to find
+                * an existing mount and extract mount existing mount options 
from it.
+                * It is important because otherwise we can change cgroup2 
superblock
+                * options. See kernel logic in apply_cgroup_root_flags for 
more details:
+                * 
https://github.com/torvalds/linux/blob/18f7fcd5e69a04df57b563360b88be72471d6b62/kernel/cgroup/cgroup.c#L2047
+                *
+                * If we haven't found an existing mount, just mount a new one 
with
+                * an empty list of options.
+                */
+               sb_opts = cgroup2_extract_sb_opts(DEFAULT_CGROUP_MOUNTPOINT);
+               ret = mount(fstype, controllerpath, fstype, flags, sb_opts);
        }
 
-       ret = mount("cgroup", controllerpath, fstype, flags, controllers);
        if (ret < 0)
                return -1;
 
@@ -631,22 +647,16 @@
        return openat(h->fd, path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
 }
 
-static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
+static bool cgfsng_can_use_memory_feature(struct cgroup_ops *ops,
+                               struct hierarchy *h, const char *cgroup, const 
char *file)
 {
        __do_free char *cgroup_rel = NULL, *junk_value = NULL;
-       const char *file;
-       struct hierarchy *h;
        bool ret;
 
-       h = ops->get_hierarchy(ops, "memory");
-       if (!h)
-               return false;
-
        cgroup_rel = must_make_path_relative(cgroup, NULL);
-       file = is_unified_hierarchy(h) ? "memory.swap.current" : 
"memory.memsw.usage_in_bytes";
 
        /* For v2, we need to look at the lower levels of the hierarchy because
-        * no 'memory.swap.current' file exists at the root. We must search
+        * no 'memory.<feature>.current' file exists at the root. We must search
         * upwards in the hierarchy in case memory accounting is disabled via
         * cgroup.subtree_control for the given cgroup itself.
         */
@@ -663,7 +673,7 @@
                __do_closedir DIR *dir = NULL;
                struct dirent *dent;
 
-               fd = dup(h->fd);
+               fd = openat_safe(h->fd, ".");
                if (fd < 0)
                        return false;
 
@@ -684,7 +694,7 @@
                        if (dent->d_type == DT_DIR) {
                                __do_free char *path;
 
-                               path = must_make_path_relative(dent->d_name, 
"memory.swap.current", NULL);
+                               path = must_make_path_relative(dent->d_name, 
file, NULL);
 
                                if (!faccessat(h->fd, path, F_OK, 0)) {
                                        /* We found it. Exit. */
@@ -704,6 +714,17 @@
        return ret;
 }
 
+static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
+{
+       struct hierarchy *h;
+
+       h = ops->get_hierarchy(ops, "memory");
+       if (!h)
+               return false;
+
+       return cgfsng_can_use_memory_feature(ops, h, cgroup, 
is_unified_hierarchy(h) ? "memory.swap.current" : 
"memory.memsw.usage_in_bytes");
+}
+
 static int cgfsng_get_memory_stats(struct cgroup_ops *ops, const char *cgroup,
                                   char **value)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/cgroups/cgroup_utils.c 
new/lxcfs-6.0.6/src/cgroups/cgroup_utils.c
--- old/lxcfs-6.0.5/src/cgroups/cgroup_utils.c  2025-08-15 06:47:54.000000000 
+0200
+++ new/lxcfs-6.0.6/src/cgroups/cgroup_utils.c  2026-02-23 20:21:25.000000000 
+0100
@@ -13,6 +13,7 @@
 #include <sys/types.h>
 #include <sys/vfs.h>
 #include <unistd.h>
+#include <mntent.h>
 
 #include "../macro.h"
 #include "../memory_utils.h"
@@ -810,3 +811,88 @@
 
        return log_error_errno(-ELOOP, ELOOP, "To many nested cgroups or 
invalid mount tree. Terminating walk");
 }
+
+/**
+ * get_mount_opts() - Returns the mount options for a given mnt and with 
fs_type
+ *
+ * @mnt:       Mount point.
+ * @fs_type:   File system type.
+ *
+ * Returns: mount options if success, NULL if mount is not found or error 
occurred.
+ */
+static char *get_mount_opts(const char *mnt, const char *fs_type) {
+       FILE *fp;
+       char *mnt_opts = NULL;
+       struct mntent *ent;
+
+       if (mnt == NULL || fs_type == NULL)
+               return NULL;
+
+       fp = setmntent("/proc/self/mounts", "r");
+       if (!fp)
+               return NULL;
+
+       while ((ent = getmntent(fp)) != NULL) {
+               if (strncmp(ent->mnt_dir, mnt, strlen(mnt)) == 0 &&
+                   strncmp(ent->mnt_type, fs_type, strlen(fs_type)) == 0) {
+                       mnt_opts = strdup(ent->mnt_opts); /* allocate, caller 
frees */
+                       goto out;
+               }
+       }
+
+out:
+       endmntent(fp);
+       return mnt_opts;
+}
+
+/**
+ * cgroup2_extract_sb_opts() - Returns cgroup2 fs superblock options for a 
given mount point
+ *
+ * @mnt:       cgroup2 fs mount point.
+ *
+ * Returns: sb options if success, NULL if mount is not found or error 
occurred.
+ */
+const char *cgroup2_extract_sb_opts(const char *mnt)
+{
+       __do_free char *mnt_opts = NULL;
+       char *tok;
+       char *buf;
+       size_t buf_len = 0;
+       static const char *wanted_opts[] = {
+               "nsdelegate",
+               "favordynmods",
+               "memory_localevents",
+               "memory_recursiveprot",
+               "memory_hugetlb_accounting",
+               "pids_localevents",
+               NULL
+       };
+
+       mnt_opts = get_mount_opts(mnt, "cgroup2");
+       if (mnt_opts == NULL) {
+               /* report as info, because it is not critical */
+               lxcfs_info("Failed to find an existing cgroup2 mount and get 
mount options from it");
+               return NULL;
+       }
+
+       for (int i = 0; wanted_opts[i] != NULL; i++)
+               buf_len += strlen(wanted_opts[i]) + 1; /* for comma or null 
terminator */
+
+       buf = calloc(buf_len, 1);
+       if (!buf)
+               return NULL;
+       buf[0] = '\0';
+
+       lxc_iterate_parts(tok, mnt_opts, ",") {
+               for (int i = 0; wanted_opts[i] != NULL; i++) {
+                       if (strcmp(tok, wanted_opts[i]) != 0)
+                               continue;
+
+                       if (buf[0] != '\0')
+                               (void)strlcat(buf, ",", buf_len);
+                       (void)strlcat(buf, tok, buf_len);
+               }
+       }
+
+       return buf;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/cgroups/cgroup_utils.h 
new/lxcfs-6.0.6/src/cgroups/cgroup_utils.h
--- old/lxcfs-6.0.5/src/cgroups/cgroup_utils.h  2025-08-15 06:47:54.000000000 
+0200
+++ new/lxcfs-6.0.6/src/cgroups/cgroup_utils.h  2026-02-23 20:21:25.000000000 
+0100
@@ -98,4 +98,6 @@
        return !s || strcmp(s, "") == 0;
 }
 
+const char *cgroup2_extract_sb_opts(const char *mnt);
+
 #endif /* __LXC_CGROUP_UTILS_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/lxcfs.c new/lxcfs-6.0.6/src/lxcfs.c
--- old/lxcfs-6.0.5/src/lxcfs.c 2025-08-15 06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/src/lxcfs.c 2026-02-23 20:21:25.000000000 +0100
@@ -243,427 +243,101 @@
 }
 
 /* Functions to run the library methods */
-static int do_cg_getattr(const char *path, struct stat *sb)
-{
-       char *error;
-       int (*__cg_getattr)(const char *path, struct stat *sb);
-
-       dlerror();
-       __cg_getattr = (int (*)(const char *, struct stat 
*))dlsym(dlopen_handle, "cg_getattr");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_getattr()", error);
-
-       return __cg_getattr(path, sb);
-}
-
-static int do_proc_getattr(const char *path, struct stat *sb)
-{
-       char *error;
-       int (*__proc_getattr)(const char *path, struct stat *sb);
-
-       dlerror();
-       __proc_getattr = (int (*)(const char *, struct stat *)) 
dlsym(dlopen_handle, "proc_getattr");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find proc_getattr()", 
error);
-
-       return __proc_getattr(path, sb);
-}
-
-static int do_sys_getattr(const char *path, struct stat *sb)
-{
-       char *error;
-       int (*__sys_getattr)(const char *path, struct stat *sb);
-
-       dlerror();
-       __sys_getattr = (int (*)(const char *, struct stat *)) 
dlsym(dlopen_handle, "sys_getattr");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_getattr()", 
error);
-
-       return __sys_getattr(path, sb);
-}
-
-static int do_cg_read(const char *path, char *buf, size_t size, off_t offset,
-                     struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__cg_read)(const char *path, char *buf, size_t size, off_t offset,
-                        struct fuse_file_info *fi);
-
-       dlerror();
-       __cg_read = (int (*)(const char *, char *, size_t, off_t, struct 
fuse_file_info *))dlsym(dlopen_handle, "cg_read");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_read()", error);
-
-       return __cg_read(path, buf, size, offset, fi);
-}
-
-static int do_proc_read(const char *path, char *buf, size_t size, off_t offset,
-                       struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__proc_read)(const char *path, char *buf, size_t size,
-                          off_t offset, struct fuse_file_info *fi);
-
-       dlerror();
-       __proc_read = (int (*)(const char *, char *, size_t, off_t, struct 
fuse_file_info *))dlsym(dlopen_handle, "proc_read");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find proc_read()", error);
-
-       return __proc_read(path, buf, size, offset, fi);
-}
-
-static int do_sys_read(const char *path, char *buf, size_t size, off_t offset,
-                      struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__sys_read)(const char *path, char *buf, size_t size,
-                         off_t offset, struct fuse_file_info *fi);
-
-       dlerror();
-       __sys_read = (int (*)(const char *, char *, size_t, off_t, struct 
fuse_file_info *))dlsym(dlopen_handle, "sys_read");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_read()", error);
-
-       return __sys_read(path, buf, size, offset, fi);
-}
-
-static int do_cg_write(const char *path, const char *buf, size_t size,
-                      off_t offset, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__cg_write)(const char *path, const char *buf, size_t size,
-                         off_t offset, struct fuse_file_info *fi);
-
-       dlerror();
-       __cg_write = (int (*)(const char *, const char *, size_t, off_t, struct 
fuse_file_info *))dlsym(dlopen_handle, "cg_write");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_write()", error);
-
-       return __cg_write(path, buf, size, offset, fi);
-}
-
-static int do_sys_write(const char *path, const char *buf, size_t size,
-                      off_t offset, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__sys_write)(const char *path, const char *buf, size_t size,
-                         off_t offset, struct fuse_file_info *fi);
-
-       dlerror();
-       __sys_write = (int (*)(const char *, const char *, size_t, off_t, 
struct fuse_file_info *))dlsym(dlopen_handle, "sys_write");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_write()", error);
-
-       return __sys_write(path, buf, size, offset, fi);
-}
-
-static int do_cg_mkdir(const char *path, mode_t mode)
-{
-       char *error;
-       int (*__cg_mkdir)(const char *path, mode_t mode);
-
-       dlerror();
-       __cg_mkdir = (int (*)(const char *, mode_t))dlsym(dlopen_handle, 
"cg_mkdir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_mkdir()", error);
-
-       return __cg_mkdir(path, mode);
-}
-
-static int do_cg_chown(const char *path, uid_t uid, gid_t gid)
-{
-       char *error;
-       int (*__cg_chown)(const char *path, uid_t uid, gid_t gid);
-
-       dlerror();
-       __cg_chown = (int (*)(const char *, uid_t, gid_t))dlsym(dlopen_handle, 
"cg_chown");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_chown()", error);
-
-       return __cg_chown(path, uid, gid);
-}
-
-static int do_cg_rmdir(const char *path)
-{
-       char *error;
-       int (*__cg_rmdir)(const char *path);
-
-       dlerror();
-       __cg_rmdir = (int (*)(const char *path))dlsym(dlopen_handle, 
"cg_rmdir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_rmdir()", error);
-
-       return __cg_rmdir(path);
-}
-
-static int do_cg_chmod(const char *path, mode_t mode)
-{
-       char *error;
-       int (*__cg_chmod)(const char *path, mode_t mode);
-
-       dlerror();
-       __cg_chmod = (int (*)(const char *, mode_t))dlsym(dlopen_handle, 
"cg_chmod");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_chmod()", error);
-
-       return __cg_chmod(path, mode);
-}
-
-static int do_cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-                        off_t offset, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__cg_readdir)(const char *path, void *buf, fuse_fill_dir_t filler,
-                           off_t offset, struct fuse_file_info *fi);
-
-       dlerror();
-       __cg_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, 
struct fuse_file_info *))dlsym(dlopen_handle, "cg_readdir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_readdir()", error);
-
-       return __cg_readdir(path, buf, filler, offset, fi);
-}
-
-static int do_proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-                          off_t offset, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__proc_readdir)(const char *path, void *buf, fuse_fill_dir_t 
filler,
-                             off_t offset, struct fuse_file_info *fi);
-
-       dlerror();
-       __proc_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, 
struct fuse_file_info *))dlsym(dlopen_handle, "proc_readdir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find proc_readdir()", 
error);
-
-       return __proc_readdir(path, buf, filler, offset, fi);
-}
-
-static int do_sys_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-                         off_t offset, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__sys_readdir)(const char *path, void *buf, fuse_fill_dir_t 
filler,
-                            off_t offset, struct fuse_file_info *fi);
-
-       dlerror();
-       __sys_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, 
struct fuse_file_info *))dlsym(dlopen_handle, "sys_readdir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_readdir()", 
error);
-
-       return __sys_readdir(path, buf, filler, offset, fi);
-}
-
-static int do_sys_readlink(const char *path, char *buf, size_t size)
-{
-       char *error;
-       int (*__sys_readlink)(const char *path, char *buf, size_t size);
-
-       dlerror();
-       __sys_readlink = (int (*)(const char *, char *, 
size_t))dlsym(dlopen_handle, "sys_readlink");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_readlink()", 
error);
-
-       return __sys_readlink(path, buf, size);
-}
-
-static int do_cg_open(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__cg_open)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __cg_open = (int (*)(const char *, struct fuse_file_info 
*))dlsym(dlopen_handle, "cg_open");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_open()", error);
 
-       return __cg_open(path, fi);
-}
-
-static int do_cg_access(const char *path, int mode)
-{
-       char *error;
-       int (*__cg_access)(const char *path, int mode);
-
-       dlerror();
-       __cg_access = (int (*)(const char *, int mode))dlsym(dlopen_handle, 
"cg_access");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_access()", error);
-
-       return __cg_access(path, mode);
-}
-
-static int do_proc_open(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__proc_open)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __proc_open = (int (*)(const char *path, struct fuse_file_info 
*fi))dlsym(dlopen_handle, "proc_open");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find proc_open()", error);
-
-       return __proc_open(path, fi);
-}
-
-static int do_proc_access(const char *path, int mode)
-{
-       char *error;
-       int (*__proc_access)(const char *path, int mode);
-
-       dlerror();
-       __proc_access = (int (*)(const char *, int mode))dlsym(dlopen_handle, 
"proc_access");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find proc_access()", 
error);
-
-       return __proc_access(path, mode);
-}
-
-static int do_sys_open(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__sys_open)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __sys_open = (int (*)(const char *path, struct fuse_file_info 
*fi))dlsym(dlopen_handle, "sys_open");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_open()", error);
-
-       return __sys_open(path, fi);
-}
-
-static int do_sys_opendir(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__sys_opendir)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __sys_opendir = (int (*)(const char *path, struct fuse_file_info 
*fi))dlsym(dlopen_handle, "sys_opendir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_opendir()", 
error);
-
-       return __sys_opendir(path, fi);
-}
-
-static int do_sys_access(const char *path, int mode)
-{
-       char *error;
-       int (*__sys_access)(const char *path, int mode);
-
-       dlerror();
-       __sys_access = (int (*)(const char *, int mode))dlsym(dlopen_handle, 
"sys_access");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_access()", error);
-
-       return __sys_access(path, mode);
-}
-
-static int do_cg_release(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__cg_release)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __cg_release = (int (*)(const char *path, struct fuse_file_info 
*))dlsym(dlopen_handle, "cg_release");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_release()", error);
-
-       return __cg_release(path, fi);
-}
-
-static int do_proc_release(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__proc_release)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __proc_release = (int (*)(const char *path, struct fuse_file_info *)) 
dlsym(dlopen_handle, "proc_release");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find proc_release()", 
error);
-
-       return __proc_release(path, fi);
-}
-
-static int do_sys_release(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__sys_release)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __sys_release = (int (*)(const char *path, struct fuse_file_info 
*))dlsym(dlopen_handle, "sys_release");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_release()", 
error);
-
-       return __sys_release(path, fi);
-}
-
-static int do_cg_opendir(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__cg_opendir)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __cg_opendir = (int (*)(const char *path, struct fuse_file_info 
*fi))dlsym(dlopen_handle, "cg_opendir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_opendir()", error);
-
-       return __cg_opendir(path, fi);
-}
-
-static int do_cg_releasedir(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__cg_releasedir)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __cg_releasedir = (int (*)(const char *path, struct fuse_file_info 
*))dlsym(dlopen_handle, "cg_releasedir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find cg_releasedir()", 
error);
-
-       return __cg_releasedir(path, fi);
-}
-
-static int do_sys_releasedir(const char *path, struct fuse_file_info *fi)
-{
-       char *error;
-       int (*__sys_releasedir)(const char *path, struct fuse_file_info *fi);
-
-       dlerror();
-       __sys_releasedir = (int (*)(const char *path, struct fuse_file_info 
*))dlsym(dlopen_handle, "sys_releasedir");
-       error = dlerror();
-       if (error)
-               return log_error(-1, "%s - Failed to find sys_releasedir()", 
error);
-
-       return __sys_releasedir(path, fi);
-}
+#define DEF_LIB_FS_OP(type, fsop)                                      \
+static int do_##type##_##fsop(LIB_FS_##fsop##_OP_ARGS_TYPE)    \
+{                                                                      \
+       char *error;                                                    \
+       int (*__##type##_##fsop)(LIB_FS_##fsop##_OP_ARGS_TYPE); \
+                                                                       \
+       dlerror();                                                      \
+       __##type##_##fsop = (int 
(*)(LIB_FS_##fsop##_OP_ARGS_TYPE))dlsym(dlopen_handle, #type"_"#fsop); \
+       error = dlerror();                                              \
+       if (error)                                                      \
+               return log_error(-1, "%s - Failed to find "#type"_"#fsop"()", 
error); \
+                                                                       \
+       return __##type##_##fsop(LIB_FS_##fsop##_OP_ARGS);                      
        \
+}
+
+#define LIB_FS_getattr_OP_ARGS_TYPE const char *path, struct stat *sb
+#define LIB_FS_getattr_OP_ARGS     path, sb
+DEF_LIB_FS_OP(cg   , getattr)
+DEF_LIB_FS_OP(proc , getattr)
+DEF_LIB_FS_OP(sys  , getattr)
+
+#define LIB_FS_read_OP_ARGS_TYPE       const char *path, char *buf, size_t 
size, \
+                                       off_t offset, struct fuse_file_info *fi
+#define LIB_FS_read_OP_ARGS            path, buf, size, offset, fi
+DEF_LIB_FS_OP(cg   , read)
+DEF_LIB_FS_OP(proc , read)
+DEF_LIB_FS_OP(sys  , read)
+
+#define LIB_FS_write_OP_ARGS_TYPE      const char *path, const char *buf, 
size_t size, \
+                                       off_t offset, struct fuse_file_info *fi
+#define LIB_FS_write_OP_ARGS           path, buf, size, offset, fi
+DEF_LIB_FS_OP(cg   , write)
+DEF_LIB_FS_OP(proc , write)
+DEF_LIB_FS_OP(sys  , write)
+
+#define LIB_FS_poll_OP_ARGS_TYPE       const char *path, struct fuse_file_info 
*fi, \
+                                       struct fuse_pollhandle *ph, unsigned 
*reventsp
+#define LIB_FS_poll_OP_ARGS            path, fi, ph, reventsp
+DEF_LIB_FS_OP(proc , poll)
+
+#define LIB_FS_mkdir_OP_ARGS_TYPE      const char *path, mode_t mode
+#define LIB_FS_mkdir_OP_ARGS           path, mode
+DEF_LIB_FS_OP(cg, mkdir)
+
+#define LIB_FS_chown_OP_ARGS_TYPE      const char *path, uid_t uid, gid_t gid
+#define LIB_FS_chown_OP_ARGS           path, uid, gid
+DEF_LIB_FS_OP(cg, chown)
+
+#define LIB_FS_rmdir_OP_ARGS_TYPE      const char *path
+#define LIB_FS_rmdir_OP_ARGS           path
+DEF_LIB_FS_OP(cg, rmdir)
+
+#define LIB_FS_chmod_OP_ARGS_TYPE      const char *path, mode_t mode
+#define LIB_FS_chmod_OP_ARGS           path, mode
+DEF_LIB_FS_OP(cg, chmod)
+
+#define LIB_FS_readdir_OP_ARGS_TYPE    const char *path, void *buf, 
fuse_fill_dir_t filler, \
+                                       off_t offset, struct fuse_file_info *fi
+#define LIB_FS_readdir_OP_ARGS         path, buf, filler, offset, fi
+DEF_LIB_FS_OP(cg   , readdir)
+DEF_LIB_FS_OP(proc , readdir)
+DEF_LIB_FS_OP(sys  , readdir)
+
+#define LIB_FS_readlink_OP_ARGS_TYPE   const char *path, char *buf, size_t size
+#define LIB_FS_readlink_OP_ARGS                path, buf, size
+DEF_LIB_FS_OP(sys  , readlink)
+
+#define LIB_FS_open_OP_ARGS_TYPE       const char *path, struct fuse_file_info 
*fi
+#define LIB_FS_open_OP_ARGS            path, fi
+DEF_LIB_FS_OP(cg   , open)
+DEF_LIB_FS_OP(proc , open)
+DEF_LIB_FS_OP(sys  , open)
+
+#define LIB_FS_access_OP_ARGS_TYPE     const char *path, int mode
+#define LIB_FS_access_OP_ARGS          path, mode
+DEF_LIB_FS_OP(cg   , access)
+DEF_LIB_FS_OP(proc , access)
+DEF_LIB_FS_OP(sys  , access)
+
+#define LIB_FS_opendir_OP_ARGS_TYPE    const char *path, struct fuse_file_info 
*fi
+#define LIB_FS_opendir_OP_ARGS         path, fi
+DEF_LIB_FS_OP(cg   , opendir)
+DEF_LIB_FS_OP(sys  , opendir)
+
+#define LIB_FS_release_OP_ARGS_TYPE    const char *path, struct fuse_file_info 
*fi
+#define LIB_FS_release_OP_ARGS         path, fi
+DEF_LIB_FS_OP(cg   , release)
+DEF_LIB_FS_OP(proc , release)
+DEF_LIB_FS_OP(sys  , release)
+
+#define LIB_FS_releasedir_OP_ARGS_TYPE const char *path, struct fuse_file_info 
*fi
+#define LIB_FS_releasedir_OP_ARGS              path, fi
+DEF_LIB_FS_OP(cg   , releasedir)
+DEF_LIB_FS_OP(sys  , releasedir)
 
 static bool cgroup_is_enabled = false;
 
@@ -929,6 +603,13 @@
                return ret;
        }
 
+       if (LXCFS_TYPE_PROC(type)) {
+               up_users();
+               ret = do_proc_write(path, buf, size, offset, fi);
+               down_users();
+               return ret;
+       }
+
        if (LXCFS_TYPE_SYS(type)) {
                up_users();
                ret = do_sys_write(path, buf, size, offset, fi);
@@ -939,6 +620,27 @@
        return -EINVAL;
 }
 
+int lxcfs_poll(const char *path, struct fuse_file_info *fi,
+              struct fuse_pollhandle *ph, unsigned *reventsp)
+{
+       int ret;
+       enum lxcfs_virt_t type;
+
+       type = file_info_type(fi);
+
+       if (LXCFS_TYPE_PROC(type)) {
+               up_users();
+               ret = do_proc_poll(path, fi, ph, reventsp);
+               down_users();
+               return ret;
+       }
+
+       /* default f_op->poll() behavior when not supported */
+       fuse_pollhandle_destroy(ph);
+       *reventsp = DEFAULT_POLLMASK;
+       return 0;
+}
+
 int lxcfs_readlink(const char *path, char *buf, size_t size)
 {
        int ret;
@@ -1166,6 +868,9 @@
        .truncate       = lxcfs_truncate,
        .write          = lxcfs_write,
        .readlink       = lxcfs_readlink,
+#if HAVE_FUSE3
+       .poll           = lxcfs_poll,
+#endif
 
        .create         = NULL,
        .destroy        = NULL,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/macro.h new/lxcfs-6.0.6/src/macro.h
--- old/lxcfs-6.0.5/src/macro.h 2025-08-15 06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/src/macro.h 2026-02-23 20:21:25.000000000 +0100
@@ -20,6 +20,8 @@
 #define CGROUP2_SUPER_MAGIC 0x63677270
 #endif
 
+#define DEFAULT_POLLMASK (EPOLLIN | EPOLLOUT | EPOLLRDNORM | EPOLLWRNORM)
+
 #define lxcfs_debug_stream(stream, format, ...)                       \
        do {                                                          \
                fprintf(stream, "%s: %d: %s: " format "\n", __FILE__, \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/proc_fuse.c 
new/lxcfs-6.0.6/src/proc_fuse.c
--- old/lxcfs-6.0.5/src/proc_fuse.c     2025-08-15 06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/src/proc_fuse.c     2026-02-23 20:21:25.000000000 +0100
@@ -7,6 +7,7 @@
 #include <fcntl.h>
 #include <inttypes.h>
 #include <libgen.h>
+#include <poll.h>
 #include <pthread.h>
 #include <sched.h>
 #include <stdarg.h>
@@ -242,12 +243,6 @@
        return 0;
 }
 
-__lxcfs_fuse_ops int proc_release(const char *path, struct fuse_file_info *fi)
-{
-       do_release_file_info(fi);
-       return 0;
-}
-
 /**
  * Gets a non-hierarchical memory controller limit, or UINT64_MAX if no limit 
is
  * in place. If `swap` is true, reads 'swap' (v2) or 'memsw' (v1); otherwise
@@ -999,6 +994,8 @@
        char *cache = d->buf + CPUALL_MAX_SIZE;
        size_t cache_size = d->buflen - CPUALL_MAX_SIZE;
        int cg_cpu_usage_size = 0;
+       bool use_view;
+       int max_cpus = 0;
 
        if (offset) {
                size_t left;
@@ -1064,6 +1061,13 @@
                lxcfs_v("proc_stat_read failed to read from cpuacct, falling 
back to the host's /proc/stat");
        }
 
+       if (cgroup_ops->can_use_cpuview(cgroup_ops) && opts && opts->use_cfs)
+               use_view = true;
+       else
+               use_view = false;
+       if (use_view)
+               max_cpus = max_cpu_count(cg, cpu_cg);
+
        while (getline(&line, &linelen, f) != -1) {
                ssize_t l;
                char cpu_char[10]; /* That's a lot of cores */
@@ -1091,12 +1095,15 @@
                if (sscanf(cpu_char, "%d", &physcpu) != 1)
                        continue;
 
+               if (use_view && max_cpus > 0 && (curcpu + 1) == max_cpus)
+                       continue;       // cannot break here because we need to 
consume all non-cpu lines
+
                if (!cpu_in_cpuset(physcpu, cpuset))
                        continue;
 
                curcpu++;
 
-               if (cgroup_ops->can_use_cpuview(cgroup_ops) && opts && 
opts->use_cfs)
+               if (use_view)
                        cpu_to_render = curcpu;
                else
                        cpu_to_render = physcpu;
@@ -1710,3 +1717,23 @@
 
        return -EINVAL;
 }
+
+__lxcfs_fuse_ops int proc_write(const char *path, const char *buf, size_t size,
+                               off_t offset, struct fuse_file_info *fi)
+{
+       return -EINVAL;
+}
+
+__lxcfs_fuse_ops int proc_poll(const char *path, struct fuse_file_info *fi,
+                              struct fuse_pollhandle *ph, unsigned *reventsp)
+{
+       fuse_pollhandle_destroy(ph);
+       *reventsp = DEFAULT_POLLMASK;
+       return 0;
+}
+
+__lxcfs_fuse_ops int proc_release(const char *path, struct fuse_file_info *fi)
+{
+       do_release_file_info(fi);
+       return 0;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/proc_fuse.h 
new/lxcfs-6.0.6/src/proc_fuse.h
--- old/lxcfs-6.0.5/src/proc_fuse.h     2025-08-15 06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/src/proc_fuse.h     2026-02-23 20:21:25.000000000 +0100
@@ -20,6 +20,8 @@
 __visible extern int proc_open(const char *path, struct fuse_file_info *fi);
 __visible extern int proc_access(const char *path, int mask);
 __visible extern int proc_read(const char *path, char *buf, size_t size, off_t 
offset, struct fuse_file_info *fi);
+__visible extern int proc_write(const char *path, const char *buf, size_t 
size, off_t offset, struct fuse_file_info *fi);
+__visible extern int proc_poll(const char *path, struct fuse_file_info *fi, 
struct fuse_pollhandle *ph, unsigned *reventsp);
 __visible extern int proc_release(const char *path, struct fuse_file_info *fi);
 
 #endif /* __LXCFS_PROC_FUSE_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lxcfs-6.0.5/src/utils.c new/lxcfs-6.0.6/src/utils.c
--- old/lxcfs-6.0.5/src/utils.c 2025-08-15 06:47:54.000000000 +0200
+++ new/lxcfs-6.0.6/src/utils.c 2026-02-23 20:21:25.000000000 +0100
@@ -113,7 +113,7 @@
                return false;
 
        fd = in_same_namespace(pid, getpid(), "pid");
-       if (fd == EINVAL)
+       if (fd == -EINVAL)
                return true;
 
        return false;

Reply via email to