Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

static bool can_use_pidfd;
static bool can_use_swap;
static bool can_use_zswap;
static bool can_use_sys_cpu;
static bool has_versioned_opts;
static bool memory_is_cgroupv2;
Expand Down Expand Up @@ -77,6 +78,11 @@ bool liblxcfs_can_use_swap(void)
return can_use_swap;
}

bool liblxcfs_can_use_zswap(void)
{
return can_use_zswap;
}

bool liblxcfs_can_use_sys_cpu(void)
{
return can_use_sys_cpu;
Expand Down Expand Up @@ -980,6 +986,12 @@ void lxcfslib_init(void)
hierarchy = cgroup_ops->get_hierarchy(cgroup_ops, "memory");
memory_is_cgroupv2 = hierarchy && is_unified_hierarchy(hierarchy);

can_use_zswap = cgroup && cgroup_ops->can_use_zswap(cgroup_ops, cgroup);
if (can_use_zswap)
lxcfs_info("Kernel supports zswap accounting");
else
lxcfs_info("Kernel does not support zswap accounting");

lxcfs_info("api_extensions:");
for (size_t nr = 0; nr < nr_api_extensions; nr++)
lxcfs_info("- %s", api_extensions[nr]);
Expand Down
10 changes: 9 additions & 1 deletion src/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,15 @@ struct lxcfs_opts {
__u32 version;
// As of opts version 2.
char runtime_path[PATH_MAX];
bool zswap_off;
};

typedef enum lxcfs_opt_t {
LXCFS_SWAP_ON = 0,
LXCFS_PIDFD_ON = 1,
LXCFS_CFS_ON = 2,
LXCFS_OPTS_MAX = LXCFS_CFS_ON,
LXCFS_ZSWAP_ON = 3,
LXCFS_OPTS_MAX = LXCFS_ZSWAP_ON,
} lxcfs_opt_t;


Expand All @@ -142,6 +144,7 @@ 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_zswap(void);
extern bool liblxcfs_memory_is_cgroupv2(void);
extern bool liblxcfs_can_use_sys_cpu(void);
extern bool liblxcfs_has_versioned_opts(void);
Expand All @@ -164,6 +167,11 @@ static inline bool lxcfs_has_opt(struct lxcfs_opts *opts, lxcfs_opt_t opt)
return opts->use_pidfd;
case LXCFS_CFS_ON:
return opts->use_cfs;
case LXCFS_ZSWAP_ON:
/* Check opts version before accessing zswap_off (added in version 3) */
if (opts->version >= 3 && !opts->zswap_off)
return liblxcfs_can_use_zswap();
return false;
}

return false;
Expand Down
43 changes: 32 additions & 11 deletions src/cgroups/cgfsng.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,22 +631,16 @@ static int cgfsng_get_memory_slabinfo_fd(struct cgroup_ops *ops, const char *cgr
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.
*/
Expand All @@ -663,7 +657,7 @@ static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
__do_closedir DIR *dir = NULL;
struct dirent *dent;

fd = dup(h->fd);
fd = openat_safe(h->fd, ".");
if (fd < 0)
return false;

Expand All @@ -684,7 +678,7 @@ static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
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. */
Expand All @@ -704,6 +698,32 @@ static bool cgfsng_can_use_swap(struct cgroup_ops *ops, const char *cgroup)
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 bool cgfsng_can_use_zswap(struct cgroup_ops *ops, const char *cgroup)
{
struct hierarchy *h;

h = ops->get_hierarchy(ops, "memory");
if (!h)
return false;

/* zswap is only available in cgroupv2 */
if (!is_unified_hierarchy(h))
return false;

return cgfsng_can_use_memory_feature(ops, h, cgroup, "memory.zswap.current");
}

static int cgfsng_get_memory_stats(struct cgroup_ops *ops, const char *cgroup,
char **value)
{
Expand Down Expand Up @@ -1110,6 +1130,7 @@ struct cgroup_ops *cgfsng_ops_init(void)
cgfsng_ops->get_memory_swap_current = cgfsng_get_memory_swap_current;
cgfsng_ops->get_memory_slabinfo_fd = cgfsng_get_memory_slabinfo_fd;
cgfsng_ops->can_use_swap = cgfsng_can_use_swap;
cgfsng_ops->can_use_zswap = cgfsng_can_use_zswap;

/* cpuset */
cgfsng_ops->get_cpuset_cpus = cgfsng_get_cpuset_cpus;
Expand Down
1 change: 1 addition & 0 deletions src/cgroups/cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ struct cgroup_ops {
int (*get_memory_slabinfo_fd)(struct cgroup_ops *ops,
const char *cgroup);
bool (*can_use_swap)(struct cgroup_ops *ops, const char *cgroup);
bool (*can_use_zswap)(struct cgroup_ops *ops, const char *cgroup);

/* cpuset */
int (*get_cpuset_cpus)(struct cgroup_ops *ops, const char *cgroup,
Expand Down
7 changes: 6 additions & 1 deletion src/lxcfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,7 @@ static int set_pidfile(char *pidfile)
static const struct option long_options[] = {
{"debug", no_argument, 0, 'd' },
{"disable-swap", no_argument, 0, 'u' },
{"disable-zswap", no_argument, 0, 'z' },
{"enable-loadavg", no_argument, 0, 'l' },
{"foreground", no_argument, 0, 'f' },
{"help", no_argument, 0, 'h' },
Expand Down Expand Up @@ -1365,9 +1366,10 @@ int main(int argc, char *argv[])
}

opts->swap_off = false;
opts->zswap_off = false;
opts->use_pidfd = false;
opts->use_cfs = false;
opts->version = 2;
opts->version = 3;

while ((c = getopt_long(argc, argv, "dulfhvso:p:", long_options, &idx)) != -1) {
switch (c) {
Expand Down Expand Up @@ -1409,6 +1411,9 @@ int main(int argc, char *argv[])
case 'u':
opts->swap_off = true;
break;
case 'z':
opts->zswap_off = true;
break;
case 'v':
lxcfs_info("%s", STRINGIFY(PROJECT_VERSION));
exit(EXIT_SUCCESS);
Expand Down
13 changes: 13 additions & 0 deletions src/proc_fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ struct memory_stat {
uint64_t slab;
uint64_t slab_reclaimable;
uint64_t slab_unreclaimable;
uint64_t zswapped;
uint64_t zswap;
};

static off_t get_procfile_size(const char *path)
Expand Down Expand Up @@ -1377,6 +1379,10 @@ static bool cgroup_parse_memory_stat(const char *cgroup, struct memory_stat *mst
sscanf(line, "slab_reclaimable %" PRIu64, &(mstat->slab_reclaimable));
} else if (unified && startswith(line, "slab_unreclaimable")) {
sscanf(line, "slab_unreclaimable %" PRIu64, &(mstat->slab_unreclaimable));
} else if (unified && startswith(line, "zswapped")) {
sscanf(line, "zswapped %" PRIu64, &(mstat->zswapped));
} else if (unified && startswith(line, "zswap")) {
sscanf(line, "zswap %" PRIu64, &(mstat->zswap));
}
}

Expand All @@ -1392,6 +1398,7 @@ 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();
bool wants_swap = lxcfs_has_opt(fuse_get_context()->private_data, LXCFS_SWAP_ON);
bool wants_zswap = lxcfs_has_opt(fuse_get_context()->private_data, LXCFS_ZSWAP_ON);
struct file_info *d = INTTYPE_TO_PTR(fi->fh);
uint64_t memlimit = 0, memusage = 0,
hosttotal = 0, swfree = 0, swusage = 0, swtotal = 0,
Expand Down Expand Up @@ -1508,6 +1515,12 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,

snprintf(lbuf, 100, "SwapFree: %8" PRIu64 " kB\n", swfree);
printme = lbuf;
} else if (startswith(line, "Zswap:")) {
snprintf(lbuf, 100, "Zswap: %8" PRIu64 " kB\n", wants_zswap ? mstat.zswap / 1024 : 0);
printme = lbuf;
} else if (startswith(line, "Zswapped:")) {
snprintf(lbuf, 100, "Zswapped: %8" PRIu64 " kB\n", wants_zswap ? mstat.zswapped / 1024 : 0);
printme = lbuf;
} else if (startswith(line, "Slab:")) {
snprintf(lbuf, 100, "Slab: %8" PRIu64 " kB\n", mstat.slab / 1024);
printme = lbuf;
Expand Down