|
Packit Service |
3880ab |
/*
|
|
Packit Service |
3880ab |
* cg_map.c cgroup v2 cache
|
|
Packit Service |
3880ab |
*
|
|
Packit Service |
3880ab |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
3880ab |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
3880ab |
* as published by the Free Software Foundation; either version
|
|
Packit Service |
3880ab |
* 2 of the License, or (at your option) any later version.
|
|
Packit Service |
3880ab |
*
|
|
Packit Service |
3880ab |
* Authors: Dmitry Yakunin <zeil@yandex-team.ru>
|
|
Packit Service |
3880ab |
*/
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#include <stdlib.h>
|
|
Packit Service |
3880ab |
#include <string.h>
|
|
Packit Service |
3880ab |
#include <stdio.h>
|
|
Packit Service |
3880ab |
#include <stdbool.h>
|
|
Packit Service |
3880ab |
#include <linux/types.h>
|
|
Packit Service |
3880ab |
#include <linux/limits.h>
|
|
Packit Service |
3880ab |
#include <ftw.h>
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#include "cg_map.h"
|
|
Packit Service |
3880ab |
#include "list.h"
|
|
Packit Service |
3880ab |
#include "utils.h"
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
struct cg_cache {
|
|
Packit Service |
3880ab |
struct hlist_node id_hash;
|
|
Packit Service |
3880ab |
__u64 id;
|
|
Packit Service |
3880ab |
char path[];
|
|
Packit Service |
3880ab |
};
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
#define IDMAP_SIZE 1024
|
|
Packit Service |
3880ab |
static struct hlist_head id_head[IDMAP_SIZE];
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static struct cg_cache *cg_get_by_id(__u64 id)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
unsigned int h = id & (IDMAP_SIZE - 1);
|
|
Packit Service |
3880ab |
struct hlist_node *n;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
hlist_for_each(n, &id_head[h]) {
|
|
Packit Service |
3880ab |
struct cg_cache *cg;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
cg = container_of(n, struct cg_cache, id_hash);
|
|
Packit Service |
3880ab |
if (cg->id == id)
|
|
Packit Service |
3880ab |
return cg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return NULL;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static struct cg_cache *cg_entry_create(__u64 id, const char *path)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
unsigned int h = id & (IDMAP_SIZE - 1);
|
|
Packit Service |
3880ab |
struct cg_cache *cg;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
cg = malloc(sizeof(*cg) + strlen(path) + 1);
|
|
Packit Service |
3880ab |
if (!cg) {
|
|
Packit Service |
3880ab |
fprintf(stderr,
|
|
Packit Service |
3880ab |
"Failed to allocate memory for cgroup2 cache entry");
|
|
Packit Service |
3880ab |
return NULL;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
cg->id = id;
|
|
Packit Service |
3880ab |
strcpy(cg->path, path);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
hlist_add_head(&cg->id_hash, &id_head[h]);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return cg;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int mntlen;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static int nftw_fn(const char *fpath, const struct stat *sb,
|
|
Packit Service |
3880ab |
int typeflag, struct FTW *ftw)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
const char *path;
|
|
Packit Service |
3880ab |
__u64 id;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (typeflag != FTW_D)
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
id = get_cgroup2_id(fpath);
|
|
Packit Service |
3880ab |
if (!id)
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
path = fpath + mntlen;
|
|
Packit Service |
3880ab |
if (*path == '\0')
|
|
Packit Service |
3880ab |
/* root cgroup */
|
|
Packit Service |
3880ab |
path = "/";
|
|
Packit Service |
3880ab |
if (!cg_entry_create(id, path))
|
|
Packit Service |
3880ab |
return -1;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
return 0;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
static void cg_init_map(void)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
char *mnt;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
mnt = find_cgroup2_mount(false);
|
|
Packit Service |
3880ab |
if (!mnt)
|
|
Packit Service |
3880ab |
return;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
mntlen = strlen(mnt);
|
|
Packit Service |
3880ab |
(void) nftw(mnt, nftw_fn, 1024, FTW_MOUNT);
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
free(mnt);
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
const char *cg_id_to_path(__u64 id)
|
|
Packit Service |
3880ab |
{
|
|
Packit Service |
3880ab |
static int initialized;
|
|
Packit Service |
3880ab |
static char buf[64];
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
const struct cg_cache *cg;
|
|
Packit Service |
3880ab |
char *path;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
if (!initialized) {
|
|
Packit Service |
3880ab |
cg_init_map();
|
|
Packit Service |
3880ab |
initialized = 1;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
cg = cg_get_by_id(id);
|
|
Packit Service |
3880ab |
if (cg)
|
|
Packit Service |
3880ab |
return cg->path;
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
path = get_cgroup2_path(id, false);
|
|
Packit Service |
3880ab |
if (path) {
|
|
Packit Service |
3880ab |
cg = cg_entry_create(id, path);
|
|
Packit Service |
3880ab |
free(path);
|
|
Packit Service |
3880ab |
if (cg)
|
|
Packit Service |
3880ab |
return cg->path;
|
|
Packit Service |
3880ab |
}
|
|
Packit Service |
3880ab |
|
|
Packit Service |
3880ab |
snprintf(buf, sizeof(buf), "unreachable:%llx", id);
|
|
Packit Service |
3880ab |
return buf;
|
|
Packit Service |
3880ab |
}
|