mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-11-04 15:34:49 +00:00
This patch prepares infrastructure for matching sockets by cgroups. Two helper functions are added for transformation between cgroup v2 ID and pathname. Cgroup v2 cache is implemented as hash table indexed by ID. This cache is needed for faster lookups of socket cgroup. v2: - style fixes (David Ahern) Signed-off-by: Dmitry Yakunin <zeil@yandex-team.ru> Signed-off-by: David Ahern <dsahern@gmail.com>
136 lines
2.3 KiB
C
136 lines
2.3 KiB
C
/*
|
|
* cg_map.c cgroup v2 cache
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*
|
|
* Authors: Dmitry Yakunin <zeil@yandex-team.ru>
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <linux/types.h>
|
|
#include <linux/limits.h>
|
|
#include <ftw.h>
|
|
|
|
#include "cg_map.h"
|
|
#include "list.h"
|
|
#include "utils.h"
|
|
|
|
struct cg_cache {
|
|
struct hlist_node id_hash;
|
|
__u64 id;
|
|
char path[];
|
|
};
|
|
|
|
#define IDMAP_SIZE 1024
|
|
static struct hlist_head id_head[IDMAP_SIZE];
|
|
|
|
static struct cg_cache *cg_get_by_id(__u64 id)
|
|
{
|
|
unsigned int h = id & (IDMAP_SIZE - 1);
|
|
struct hlist_node *n;
|
|
|
|
hlist_for_each(n, &id_head[h]) {
|
|
struct cg_cache *cg;
|
|
|
|
cg = container_of(n, struct cg_cache, id_hash);
|
|
if (cg->id == id)
|
|
return cg;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static struct cg_cache *cg_entry_create(__u64 id, const char *path)
|
|
{
|
|
unsigned int h = id & (IDMAP_SIZE - 1);
|
|
struct cg_cache *cg;
|
|
|
|
cg = malloc(sizeof(*cg) + strlen(path) + 1);
|
|
if (!cg) {
|
|
fprintf(stderr,
|
|
"Failed to allocate memory for cgroup2 cache entry");
|
|
return NULL;
|
|
}
|
|
cg->id = id;
|
|
strcpy(cg->path, path);
|
|
|
|
hlist_add_head(&cg->id_hash, &id_head[h]);
|
|
|
|
return cg;
|
|
}
|
|
|
|
static int mntlen;
|
|
|
|
static int nftw_fn(const char *fpath, const struct stat *sb,
|
|
int typeflag, struct FTW *ftw)
|
|
{
|
|
const char *path;
|
|
__u64 id;
|
|
|
|
if (typeflag != FTW_D)
|
|
return 0;
|
|
|
|
id = get_cgroup2_id(fpath);
|
|
if (!id)
|
|
return -1;
|
|
|
|
path = fpath + mntlen;
|
|
if (*path == '\0')
|
|
/* root cgroup */
|
|
path = "/";
|
|
if (!cg_entry_create(id, path))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cg_init_map(void)
|
|
{
|
|
char *mnt;
|
|
|
|
mnt = find_cgroup2_mount(false);
|
|
if (!mnt)
|
|
exit(1);
|
|
|
|
mntlen = strlen(mnt);
|
|
if (nftw(mnt, nftw_fn, 1024, FTW_MOUNT) < 0)
|
|
exit(1);
|
|
|
|
free(mnt);
|
|
}
|
|
|
|
const char *cg_id_to_path(__u64 id)
|
|
{
|
|
static int initialized;
|
|
static char buf[64];
|
|
|
|
const struct cg_cache *cg;
|
|
char *path;
|
|
|
|
if (!initialized) {
|
|
cg_init_map();
|
|
initialized = 1;
|
|
}
|
|
|
|
cg = cg_get_by_id(id);
|
|
if (cg)
|
|
return cg->path;
|
|
|
|
path = get_cgroup2_path(id, false);
|
|
if (path) {
|
|
cg = cg_entry_create(id, path);
|
|
free(path);
|
|
if (cg)
|
|
return cg->path;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "unreachable:%llx", id);
|
|
return buf;
|
|
}
|