#include "utils.h"
static bool can_use_pidfd;
+static bool can_use_swap;
static volatile sig_atomic_t reload_successful;
return reload_successful != 0;
}
+bool liblxcfs_can_use_swap(void)
+{
+ return can_use_swap;
+}
+
/* 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)
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]);
extern void prune_init_slice(char *cg);
extern bool supports_pidfd(void);
extern bool liblxcfs_functional(void);
+extern bool liblxcfs_can_use_swap(void);
static inline int install_signal_handler(int signo,
void (*handler)(int, siginfo_t *, void *))
return cgfsng_get_memory(ops, cgroup, "memory.swap.max", value);
}
+static bool cgfsng_can_use_swap(struct cgroup_ops *ops)
+{
+ bool has_swap = false;
+ struct hierarchy *h;
+
+ h = ops->get_hierarchy(ops, "memory");
+ if (!h)
+ return false;
+
+ if (is_unified_hierarchy(h)) {
+ if (faccessat(h->fd, "memory.swap.max", F_OK, 0))
+ return false;
+
+ if (faccessat(h->fd, "memory.swap.current", F_OK, 0))
+ return false;
+
+ has_swap = true;
+ } else {
+ if (faccessat(h->fd, "memory.memsw.limit_in_bytes", F_OK, 0))
+ return false;
+
+ if (faccessat(h->fd, "memory.memsw.usage_in_bytes", F_OK, 0))
+ return false;
+
+ has_swap = true;
+ }
+
+ return has_swap;
+}
+
static int cgfsng_get_memory_stats(struct cgroup_ops *ops, const char *cgroup,
char **value)
{
cgfsng_ops->get_memory_swap_max = cgfsng_get_memory_swap_max;
cgfsng_ops->get_memory_current = cgfsng_get_memory_current;
cgfsng_ops->get_memory_swap_current = cgfsng_get_memory_swap_current;
+ cgfsng_ops->can_use_swap = cgfsng_can_use_swap;
/* cpuset */
cgfsng_ops->get_cpuset_cpus = cgfsng_get_cpuset_cpus;
char **value);
int (*get_memory_swap_max)(struct cgroup_ops *ops, const char *cgroup,
char **value);
+ bool (*can_use_swap)(struct cgroup_ops *ops);
/* cpuset */
int (*get_cpuset_cpus)(struct cgroup_ops *ops, const char *cgroup,
*memswusage_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;
+ 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, swfree = 0, swusage = 0;
__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, host_swap = false;
+ bool wants_swap = opts && !opts->swap_off && liblxcfs_can_use_swap(), host_swap = false;
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;