Skip to content

Commit

Permalink
allow sysctl config from env
Browse files Browse the repository at this point in the history
  • Loading branch information
anibalportero committed May 29, 2024
1 parent e25b6ef commit e35c5a9
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 28 deletions.
41 changes: 15 additions & 26 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ typedef enum {
#define UPDATE_TIME POLICY | TRAIL
#define RUN_TIME UPDATE_TIME | META | CMD

#define LEVEL_SYSCTL PV_ENTRY | UPDATE_TIME

// default list
#define CACHE_DEVMETADIR_DEF "/storage/cache/devmeta"
#define CACHE_USRMETADIR_DEF "/storage/cache/meta"
Expand Down Expand Up @@ -696,30 +698,15 @@ static char *_get_value_policy(struct dl_list *config_list)
return strdup(item);
}

static int _apply_config_sysctl(const char *key, const char *value,
void *opaque)
static int _set_config_sysctl_by_key(const char *key, const char *value)
{
const char *start = key + strlen("sysctl");
char *path =
calloc(strlen("/proc/sys") + strlen(start) + 1, sizeof(char));

char *path = pv_config_parser_sysctl_key(key);
if (!path)
return -1;

sprintf(path, "%s", "/proc/sys");

const char *next = start;
char *p = path + strlen("/proc/sys");

for (int i = 0; i < (int)strlen(start); ++i)
p[i] = next[i] == '.' ? '/' : next[i];
return 0;

errno = 0;
int fd = open(path, O_WRONLY | O_SYNC);
if (fd < 0) {
pv_log(ERROR, "open failed for sysctl node %s with '%s'", path,
strerror(errno));

pv_log(WARN, "cannot open '%s': %s", path, strerror(errno));
free(path);
return -1;
}
Expand All @@ -728,7 +715,7 @@ static int _apply_config_sysctl(const char *key, const char *value,
close(fd);
free(path);

return 0;
return 1;
}

static int pv_config_load_policy(const char *policy,
Expand Down Expand Up @@ -872,8 +859,13 @@ static struct pv_config_entry *_search_config_entry_by_alias(const char *alias)

static int _set_config_by_key(const char *key, const char *value, void *opaque)
{
struct pv_config_entry *entry;
level_t *level = (level_t *)opaque;
if (*level & LEVEL_SYSCTL) {
if (_set_config_sysctl_by_key(key, value))
return 0;
}

struct pv_config_entry *entry;
entry = _search_config_entry_by_key(key);
if (!entry) {
entry = _search_config_entry_by_alias(key);
Expand All @@ -885,7 +877,6 @@ static int _set_config_by_key(const char *key, const char *value, void *opaque)
if (!entry)
return 0;

level_t *level = (level_t *)opaque;
if (_set_config_by_entry(entry, value, *level)) {
pv_log(WARN, "cannot set key '%s' in config", key);
return 0;
Expand All @@ -898,8 +889,6 @@ static void _iterate_config_items(struct dl_list *items, level_t level)
{
level_t l = level;
config_iterate_items(items, _set_config_by_key, (void *)&l);
config_iterate_items_prefix(items, _apply_config_sysctl, "sysctl.",
NULL);
}

static int pv_config_load_file(char *path)
Expand Down Expand Up @@ -1248,8 +1237,8 @@ int pv_config_init(char *path)
}

// default core_pattern, overridable by config
_apply_config_sysctl("sysctl.kernel.core_pattern",
"|/lib/pv/pvcrash --skip", NULL);
_set_config_sysctl_by_key("PV_SYSCTL_KERNEL_CORE_PATTERN",
"|/lib/pv/pvcrash --skip");

if (!path)
path = PV_PANTAVISOR_CONFIG_PATH;
Expand Down
69 changes: 69 additions & 0 deletions config_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

#include <sys/types.h>
#include <sys/stat.h>

#include "config_parser.h"
#include "utils/str.h"
#include "utils/fs.h"

#define MODULE_NAME "config_parser"
#define pv_log(level, msg, ...) vlog(MODULE_NAME, level, msg, ##__VA_ARGS__)
Expand Down Expand Up @@ -283,3 +285,70 @@ void config_clear_items(struct dl_list *list)
free(curr);
}
}

static char *_parse_legacy_sysctl_key(const char *key)
{
const char *start = key + strlen("sysctl");
char *path =
calloc(strlen("/proc/sys") + strlen(start) + 1, sizeof(char));
if (!path)
return NULL;

sprintf(path, "%s", "/proc/sys");

char *p = path + strlen("/proc/sys");

for (int i = 0; i < (int)strlen(start); ++i)
p[i] = start[i] == '.' ? '/' : start[i];

return path;
}

static char *_parse_sysctl_key(const char *key)
{
const char *base = "/proc/sys/";
size_t baselen = strlen(base);

const char *k = key + strlen("PV_SYSCTL_");

char *path = calloc(baselen + strlen(k) + 1, sizeof(char));
if (!path)
return NULL;

sprintf(path, "%s%s", base, k);

char *p = path + baselen;
while (*p) {
if (*p == '_') {
// temporary \0 to evaluate if it is a dir
*p = '\0';
if (pv_fs_path_is_directory(path))
*p = '/';
else
*p = '_';
} else
*p = tolower(*p);
p++;
}

return path;
}

char *pv_config_parser_sysctl_key(const char *key)
{
size_t keylen = strlen(key);

const char *lprefix = "sysctl";
size_t lprefixlen = strlen(lprefix);
if ((keylen > lprefixlen) &&
pv_str_startswith(lprefix, lprefixlen, key))
return _parse_legacy_sysctl_key(key);

const char *prefix = "PV_SYSCTL_";
size_t prefixlen = strlen(prefix);
if ((keylen > prefixlen) &&
pv_str_startswith_case(prefix, prefixlen, key))
return _parse_sysctl_key(key);

return NULL;
}
4 changes: 2 additions & 2 deletions config_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ void config_iterate_items(struct dl_list *list,
int (*action)(const char *key, const char *value,
void *opaque),
void *opaque);

void config_iterate_items_prefix(struct dl_list *list,
int (*action)(const char *key,
const char *value, void *opaque),
char *prefix, void *opaque);

void config_clear_items(struct dl_list *list);

char *pv_config_parser_sysctl_key(const char *key);

#endif

0 comments on commit e35c5a9

Please sign in to comment.