]> git.proxmox.com Git - lxcfs.git/commitdiff
add meminfo/swaps cgroupv2 patch
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Thu, 8 Jul 2021 10:05:12 +0000 (12:05 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Thu, 8 Jul 2021 11:16:26 +0000 (13:16 +0200)
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
debian/patches/0001-delay-check-for-swap-accounting.patch [new file with mode: 0644]
debian/patches/0002-make-meminfo-and-swaps-cgroupv2-aware.patch [new file with mode: 0644]
debian/patches/series

diff --git a/debian/patches/0001-delay-check-for-swap-accounting.patch b/debian/patches/0001-delay-check-for-swap-accounting.patch
new file mode 100644 (file)
index 0000000..1400927
--- /dev/null
@@ -0,0 +1,179 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Thu, 8 Jul 2021 12:54:01 +0200
+Subject: [PATCH lxcfs] delay check for swap accounting
+
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ src/bindings.c       | 20 ++++++++++----------
+ src/bindings.h       |  2 +-
+ src/cgroups/cgfsng.c | 13 ++++++++++---
+ src/cgroups/cgroup.h |  2 +-
+ src/proc_fuse.c      |  8 ++++++--
+ 5 files changed, 28 insertions(+), 17 deletions(-)
+
+diff --git a/src/bindings.c b/src/bindings.c
+index 6f395fb..b169af4 100644
+--- a/src/bindings.c
++++ b/src/bindings.c
+@@ -57,7 +57,8 @@
+ #include "utils.h"
+ static bool can_use_pidfd;
+-static bool can_use_swap;
++static int can_use_swap = -1;
++struct cgroup_ops *cgroup_ops;
+ static volatile sig_atomic_t reload_successful;
+@@ -66,8 +67,15 @@ bool liblxcfs_functional(void)
+       return reload_successful != 0;
+ }
+-bool liblxcfs_can_use_swap(void)
++bool liblxcfs_can_use_swap(const char *cgroup)
+ {
++      if (can_use_swap < 0) {
++              can_use_swap = cgroup_ops->can_use_swap(cgroup_ops, cgroup);
++              if (can_use_swap > 0)
++                      lxcfs_info("Kernel supports swap accounting");
++              else if (can_use_swap == 0)
++                      lxcfs_info("Kernel does not support swap accounting");
++      }
+       return can_use_swap;
+ }
+@@ -120,8 +128,6 @@ static void mutex_lock(pthread_mutex_t *l)
+               log_exit("%s - returned %d\n", strerror(ret), ret);
+ }
+-struct cgroup_ops *cgroup_ops;
+-
+ static void mutex_unlock(pthread_mutex_t *l)
+ {
+       int ret;
+@@ -892,12 +898,6 @@ static void __attribute__((constructor)) lxcfs_init(void)
+               lxcfs_info("Kernel supports pidfds");
+       }
+-      can_use_swap = cgroup_ops->can_use_swap(cgroup_ops);
+-      if (can_use_swap)
+-              lxcfs_info("Kernel supports swap accounting");
+-      else
+-              lxcfs_info("Kernel does not support swap accounting");
+-
+       lxcfs_info("api_extensions:");
+       for (i = 0; i < nr_api_extensions; i++)
+               lxcfs_info("- %s", api_extensions[i]);
+diff --git a/src/bindings.h b/src/bindings.h
+index e260902..a334947 100644
+--- a/src/bindings.h
++++ b/src/bindings.h
+@@ -91,7 +91,7 @@ extern pid_t lookup_initpid_in_store(pid_t qpid);
+ extern void prune_init_slice(char *cg);
+ extern bool supports_pidfd(void);
+ extern bool liblxcfs_functional(void);
+-extern bool liblxcfs_can_use_swap(void);
++extern bool liblxcfs_can_use_swap(const char *cgroup);
+ static inline int install_signal_handler(int signo,
+                                        void (*handler)(int, siginfo_t *, void *))
+diff --git a/src/cgroups/cgfsng.c b/src/cgroups/cgfsng.c
+index d772f25..8072017 100644
+--- a/src/cgroups/cgfsng.c
++++ b/src/cgroups/cgfsng.c
+@@ -632,7 +632,7 @@ static int cgfsng_get_memory_swap_max(struct cgroup_ops *ops,
+       return cgfsng_get_memory(ops, cgroup, "memory.swap.max", value);
+ }
+-static bool cgfsng_can_use_swap(struct cgroup_ops *ops)
++static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
+ {
+       bool has_swap = false;
+       struct hierarchy *h;
+@@ -642,10 +642,17 @@ static bool cgfsng_can_use_swap(struct cgroup_ops *ops)
+               return false;
+       if (is_unified_hierarchy(h)) {
+-              if (faccessat(h->fd, "memory.swap.max", F_OK, 0))
++              __do_free char *path = must_make_path_relative(cgroup, NULL);
++              __do_close int cgroup_fd = openat_safe(h->fd, path);
++              if (cgroup_fd < 0) {
++                      lxcfs_error("failed to check for swap accounting, disabling");
++                      return false;
++              }
++
++              if (faccessat(cgroup_fd, "memory.swap.max", F_OK, 0))
+                       return false;
+-              if (faccessat(h->fd, "memory.swap.current", F_OK, 0))
++              if (faccessat(cgroup_fd, "memory.swap.current", F_OK, 0))
+                       return false;
+               has_swap = true;
+diff --git a/src/cgroups/cgroup.h b/src/cgroups/cgroup.h
+index f4b5d19..330f37c 100644
+--- a/src/cgroups/cgroup.h
++++ b/src/cgroups/cgroup.h
+@@ -155,7 +155,7 @@ struct cgroup_ops {
+                             char **value);
+       int (*get_memory_swap_max)(struct cgroup_ops *ops, const char *cgroup,
+                                  char **value);
+-      bool (*can_use_swap)(struct cgroup_ops *ops);
++      bool (*can_use_swap)(struct cgroup_ops *ops, const char *cgroup);
+       /* cpuset */
+       int (*get_cpuset_cpus)(struct cgroup_ops *ops, const char *cgroup,
+diff --git a/src/proc_fuse.c b/src/proc_fuse.c
+index 06ec2d9..9a5915c 100644
+--- a/src/proc_fuse.c
++++ b/src/proc_fuse.c
+@@ -322,7 +322,6 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
+                *memswusage_str = NULL, *memswpriority_str = NULL;
+       struct fuse_context *fc = fuse_get_context();
+       struct lxcfs_opts *opts = (struct lxcfs_opts *)fuse_get_context()->private_data;
+-      bool wants_swap = opts && !opts->swap_off && liblxcfs_can_use_swap();
+       struct file_info *d = INTTYPE_TO_PTR(fi->fh);
+       uint64_t memswlimit = 0, memlimit = 0, memusage = 0, memswusage = 0,
+                swtotal = 0, swusage = 0, memswpriority = 1,
+@@ -330,6 +329,7 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
+       ssize_t total_len = 0;
+       ssize_t l = 0;
+       char *cache = d->buf;
++      bool wants_swap;
+       int ret;
+       __do_free char *line = NULL;
+       __do_free void *fopen_cache = NULL;
+@@ -359,6 +359,9 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
+       cgroup = get_pid_cgroup(initpid, "memory");
+       if (!cgroup)
+               return read_file_fuse("/proc/swaps", buf, size, d);
++
++      wants_swap = opts && !opts->swap_off && liblxcfs_can_use_swap(cgroup);
++
+       prune_init_slice(cgroup);
+       memlimit = get_min_memlimit(cgroup, false);
+@@ -1158,13 +1161,13 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
+       __do_fclose FILE *f = NULL;
+       struct fuse_context *fc = fuse_get_context();
+       struct lxcfs_opts *opts = (struct lxcfs_opts *)fuse_get_context()->private_data;
+-      bool wants_swap = opts && !opts->swap_off && liblxcfs_can_use_swap();
+       struct file_info *d = INTTYPE_TO_PTR(fi->fh);
+       uint64_t memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0,
+                hosttotal = 0, swfree = 0, swusage = 0, swtotal = 0,
+                memswpriority = 1;
+       struct memory_stat mstat = {};
+       size_t linelen = 0, total_len = 0;
++      bool wants_swap;
+       char *cache = d->buf;
+       size_t cache_size = d->buflen;
+       int ret;
+@@ -1192,6 +1195,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
+       cgroup = get_pid_cgroup(initpid, "memory");
+       if (!cgroup)
+               return read_file_fuse("/proc/meminfo", buf, size, d);
++      wants_swap = opts && !opts->swap_off && liblxcfs_can_use_swap(cgroup);
+       prune_init_slice(cgroup);
diff --git a/debian/patches/0002-make-meminfo-and-swaps-cgroupv2-aware.patch b/debian/patches/0002-make-meminfo-and-swaps-cgroupv2-aware.patch
new file mode 100644 (file)
index 0000000..821eb1b
--- /dev/null
@@ -0,0 +1,203 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Thu, 8 Jul 2021 12:04:05 +0200
+Subject: [PATCH lxcfs] make meminfo and swaps cgroupv2 aware
+
+and deduplicate the corresponding code
+
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ src/bindings.c  | 10 ++++++
+ src/bindings.h  |  1 +
+ src/proc_fuse.c | 89 +++++++++++++++++++++++++------------------------
+ 3 files changed, 57 insertions(+), 43 deletions(-)
+
+diff --git a/src/bindings.c b/src/bindings.c
+index b169af4..d4da43e 100644
+--- a/src/bindings.c
++++ b/src/bindings.c
+@@ -59,6 +59,7 @@
+ static bool can_use_pidfd;
+ static int can_use_swap = -1;
+ struct cgroup_ops *cgroup_ops;
++static bool memory_is_cgroupv2;
+ static volatile sig_atomic_t reload_successful;
+@@ -79,6 +80,11 @@ bool liblxcfs_can_use_swap(const char *cgroup)
+       return can_use_swap;
+ }
++bool liblxcfs_memory_is_cgroupv2(void)
++{
++      return memory_is_cgroupv2;
++}
++
+ /* 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)
+@@ -847,6 +853,7 @@ static void __attribute__((constructor)) lxcfs_init(void)
+                                 pidfd = -EBADF;
+       int i = 0;
+       pid_t pid;
++      struct hierarchy *hierarchy;
+       lxcfs_info("Running constructor %s to reload liblxcfs", __func__);
+@@ -898,6 +905,9 @@ static void __attribute__((constructor)) lxcfs_init(void)
+               lxcfs_info("Kernel supports pidfds");
+       }
++      hierarchy = cgroup_ops->get_hierarchy(cgroup_ops, "memory");
++      memory_is_cgroupv2 = hierarchy && is_unified_hierarchy(hierarchy);
++
+       lxcfs_info("api_extensions:");
+       for (i = 0; i < nr_api_extensions; i++)
+               lxcfs_info("- %s", api_extensions[i]);
+diff --git a/src/bindings.h b/src/bindings.h
+index a334947..9ab989a 100644
+--- a/src/bindings.h
++++ b/src/bindings.h
+@@ -92,6 +92,7 @@ extern void prune_init_slice(char *cg);
+ extern bool supports_pidfd(void);
+ extern bool liblxcfs_functional(void);
+ extern bool liblxcfs_can_use_swap(const char *cgroup);
++extern bool liblxcfs_memory_is_cgroupv2(void);
+ static inline int install_signal_handler(int signo,
+                                        void (*handler)(int, siginfo_t *, void *))
+diff --git a/src/proc_fuse.c b/src/proc_fuse.c
+index 9a5915c..6371b2c 100644
+--- a/src/proc_fuse.c
++++ b/src/proc_fuse.c
+@@ -315,6 +315,43 @@ static inline bool startswith(const char *line, const char *pref)
+       return strncmp(line, pref, strlen(pref)) == 0;
+ }
++static void get_swap_info(const char *cgroup, uint64_t memlimit,
++                        uint64_t memusage, uint64_t *swtotal,
++                        uint64_t *swusage, uint64_t *memswpriority)
++{
++      __do_free char *memswusage_str = NULL, *memswpriority_str = NULL;
++      size_t memswlimit = 0, memswusage = 0;
++      int ret;
++
++      *swtotal = *swusage = 0;
++      *memswpriority = 1;
++
++      memswlimit = get_min_memlimit(cgroup, true);
++      if (memswlimit > 0) {
++              ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str);
++              if (ret < 0 || safe_uint64(memswusage_str, &memswusage, 10) != 0)
++                      return;
++
++              if (liblxcfs_memory_is_cgroupv2()) {
++                      *swtotal = memswlimit / 1024;
++                      *swusage = memswusage / 1024;
++              } else {
++                      if (memlimit > memswlimit)
++                              *swtotal = 0;
++                      else
++                              *swtotal = (memswlimit - memlimit) / 1024;
++                      if (memusage > memswusage || swtotal == 0)
++                              *swusage = 0;
++                      else
++                              *swusage = (memswusage - memusage) / 1024;
++              }
++
++              ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str);
++              if (ret >= 0)
++                      safe_uint64(memswpriority_str, memswpriority, 10);
++      }
++}
++
+ static int proc_swaps_read(char *buf, size_t size, off_t offset,
+                          struct fuse_file_info *fi)
+ {
+@@ -323,7 +360,7 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
+       struct fuse_context *fc = fuse_get_context();
+       struct lxcfs_opts *opts = (struct lxcfs_opts *)fuse_get_context()->private_data;
+       struct file_info *d = INTTYPE_TO_PTR(fi->fh);
+-      uint64_t memswlimit = 0, memlimit = 0, memusage = 0, memswusage = 0,
++      uint64_t memlimit = 0, memusage = 0,
+                swtotal = 0, swusage = 0, memswpriority = 1,
+                hostswtotal = 0, hostswfree = 0;
+       ssize_t total_len = 0;
+@@ -373,26 +410,8 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
+       if (safe_uint64(memusage_str, &memusage, 10) < 0)
+               lxcfs_error("Failed to convert memusage %s", memusage_str);
+-      if (wants_swap) {
+-              memswlimit = get_min_memlimit(cgroup, true);
+-              if (memswlimit > 0) {
+-                      ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str);
+-                      if (ret >= 0 && safe_uint64(memswusage_str, &memswusage, 10) == 0) {
+-                              if (memlimit > memswlimit)
+-                                      swtotal = 0;
+-                              else
+-                                      swtotal = (memswlimit - memlimit) / 1024;
+-                              if (memusage > memswusage || swtotal == 0)
+-                                      swusage = 0;
+-                              else
+-                                      swusage = (memswusage - memusage) / 1024;
+-                      }
+-
+-                      ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str);
+-                      if (ret >= 0)
+-                              safe_uint64(memswpriority_str, &memswpriority, 10);
+-              }
+-      }
++      if (wants_swap)
++              get_swap_info(cgroup, memlimit, memusage, &swtotal, &swusage, &memswpriority);
+       total_len = snprintf(d->buf, d->size, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
+@@ -1162,7 +1181,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
+       struct fuse_context *fc = fuse_get_context();
+       struct lxcfs_opts *opts = (struct lxcfs_opts *)fuse_get_context()->private_data;
+       struct file_info *d = INTTYPE_TO_PTR(fi->fh);
+-      uint64_t memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0,
++      uint64_t memlimit = 0, memusage = 0,
+                hosttotal = 0, swfree = 0, swusage = 0, swtotal = 0,
+                memswpriority = 1;
+       struct memory_stat mstat = {};
+@@ -1216,26 +1235,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
+        * Following values are allowed to fail, because swapaccount might be
+        * turned off for current kernel.
+        */
+-      if (wants_swap) {
+-              memswlimit = get_min_memlimit(cgroup, true);
+-              if (memswlimit > 0) {
+-                      ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str);
+-                      if (ret >= 0 && safe_uint64(memswusage_str, &memswusage, 10) == 0) {
+-                              if (memlimit > memswlimit)
+-                                      swtotal = 0;
+-                              else
+-                                      swtotal = (memswlimit - memlimit) / 1024;
+-                              if (memusage > memswusage || swtotal == 0)
+-                                      swusage = 0;
+-                              else
+-                                      swusage = (memswusage - memusage) / 1024;
+-                      }
+-              }
+-
+-              ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str);
+-              if (ret >= 0)
+-                      safe_uint64(memswpriority_str, &memswpriority, 10);
+-      }
++      if (wants_swap)
++              get_swap_info(cgroup, memlimit, memusage, &swtotal, &swusage, &memswpriority);
+       f = fopen_cached("/proc/meminfo", "re", &fopen_cache);
+       if (!f)
+@@ -1274,7 +1275,9 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
+                                  This is because the kernel can swap as much as it
+                                  wants and not only up to swtotal. */
+-                              swtotal = memlimit + swtotal;
++                              if (!liblxcfs_memory_is_cgroupv2())
++                                      swtotal += memlimit;
++
+                               if (hostswtotal < swtotal) {
+                                       swtotal = hostswtotal;
+                               }
index bf650b42b1037ca3c7f99c19421c9e1728402554..c5b084c31fe07f5fbc6723cc591299318894769e 100644 (file)
@@ -1 +1,3 @@
 do-not-start-without-lxcfs.patch
+./0001-delay-check-for-swap-accounting.patch
+./0002-make-meminfo-and-swaps-cgroupv2-aware.patch