mirror of
https://github.com/systemd/systemd.git
synced 2025-02-04 21:47:31 +03:00
util: split out some stuff into a new file limits-util.[ch]
This commit is contained in:
parent
0cb8e3d118
commit
eefc66aa8f
156
src/basic/limits-util.c
Normal file
156
src/basic/limits-util.c
Normal file
@ -0,0 +1,156 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "limits-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "procfs-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
uint64_t physical_memory(void) {
|
||||
_cleanup_free_ char *root = NULL, *value = NULL;
|
||||
uint64_t mem, lim;
|
||||
size_t ps;
|
||||
long sc;
|
||||
int r;
|
||||
|
||||
/* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
|
||||
* memory.
|
||||
*
|
||||
* In order to support containers nicely that have a configured memory limit we'll take the minimum of the
|
||||
* physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
|
||||
|
||||
sc = sysconf(_SC_PHYS_PAGES);
|
||||
assert(sc > 0);
|
||||
|
||||
ps = page_size();
|
||||
mem = (uint64_t) sc * (uint64_t) ps;
|
||||
|
||||
r = cg_get_root_path(&root);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
}
|
||||
|
||||
r = cg_all_unified();
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
}
|
||||
if (r > 0) {
|
||||
r = cg_get_attribute("memory", root, "memory.max", &value);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
}
|
||||
|
||||
if (streq(value, "max"))
|
||||
return mem;
|
||||
} else {
|
||||
r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
r = safe_atou64(value, &lim);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
|
||||
return mem;
|
||||
}
|
||||
if (lim == UINT64_MAX)
|
||||
return mem;
|
||||
|
||||
/* Make sure the limit is a multiple of our own page size */
|
||||
lim /= ps;
|
||||
lim *= ps;
|
||||
|
||||
return MIN(mem, lim);
|
||||
}
|
||||
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
|
||||
uint64_t p, m, ps, r;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
|
||||
* the result is a multiple of the page size (rounds down). */
|
||||
|
||||
ps = page_size();
|
||||
assert(ps > 0);
|
||||
|
||||
p = physical_memory() / ps;
|
||||
assert(p > 0);
|
||||
|
||||
m = p * v;
|
||||
if (m / p != v)
|
||||
return UINT64_MAX;
|
||||
|
||||
m /= max;
|
||||
|
||||
r = m * ps;
|
||||
if (r / ps != m)
|
||||
return UINT64_MAX;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t system_tasks_max(void) {
|
||||
|
||||
uint64_t a = TASKS_MAX, b = TASKS_MAX;
|
||||
_cleanup_free_ char *root = NULL;
|
||||
int r;
|
||||
|
||||
/* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
|
||||
* limit:
|
||||
*
|
||||
* a) the maximum tasks value the kernel allows on this architecture
|
||||
* b) the cgroups pids_max attribute for the system
|
||||
* c) the kernel's configured maximum PID value
|
||||
*
|
||||
* And then pick the smallest of the three */
|
||||
|
||||
r = procfs_tasks_get_limit(&a);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m");
|
||||
|
||||
r = cg_get_root_path(&root);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
|
||||
else {
|
||||
_cleanup_free_ char *value = NULL;
|
||||
|
||||
r = cg_get_attribute("pids", root, "pids.max", &value);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m");
|
||||
else if (!streq(value, "max")) {
|
||||
r = safe_atou64(value, &b);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m");
|
||||
}
|
||||
}
|
||||
|
||||
return MIN3(TASKS_MAX,
|
||||
a <= 0 ? TASKS_MAX : a,
|
||||
b <= 0 ? TASKS_MAX : b);
|
||||
}
|
||||
|
||||
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
|
||||
uint64_t t, m;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
|
||||
* relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
|
||||
|
||||
t = system_tasks_max();
|
||||
assert(t > 0);
|
||||
|
||||
m = t * v;
|
||||
if (m / t != v) /* overflow? */
|
||||
return UINT64_MAX;
|
||||
|
||||
return m / max;
|
||||
}
|
10
src/basic/limits-util.h
Normal file
10
src/basic/limits-util.h
Normal file
@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
uint64_t physical_memory(void);
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
|
||||
|
||||
uint64_t system_tasks_max(void);
|
||||
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
|
@ -79,6 +79,8 @@ basic_sources = files('''
|
||||
khash.h
|
||||
label.c
|
||||
label.h
|
||||
limits-util.c
|
||||
limits-util.h
|
||||
list.h
|
||||
locale-util.c
|
||||
locale-util.h
|
||||
|
148
src/basic/util.c
148
src/basic/util.c
@ -19,7 +19,6 @@
|
||||
#include "alloc-util.h"
|
||||
#include "btrfs-util.h"
|
||||
#include "build.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "def.h"
|
||||
#include "device-nodes.h"
|
||||
#include "dirent-util.h"
|
||||
@ -294,153 +293,6 @@ int container_get_leader(const char *machine, pid_t *pid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t physical_memory(void) {
|
||||
_cleanup_free_ char *root = NULL, *value = NULL;
|
||||
uint64_t mem, lim;
|
||||
size_t ps;
|
||||
long sc;
|
||||
int r;
|
||||
|
||||
/* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
|
||||
* memory.
|
||||
*
|
||||
* In order to support containers nicely that have a configured memory limit we'll take the minimum of the
|
||||
* physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
|
||||
|
||||
sc = sysconf(_SC_PHYS_PAGES);
|
||||
assert(sc > 0);
|
||||
|
||||
ps = page_size();
|
||||
mem = (uint64_t) sc * (uint64_t) ps;
|
||||
|
||||
r = cg_get_root_path(&root);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
}
|
||||
|
||||
r = cg_all_unified();
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
}
|
||||
if (r > 0) {
|
||||
r = cg_get_attribute("memory", root, "memory.max", &value);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
}
|
||||
|
||||
if (streq(value, "max"))
|
||||
return mem;
|
||||
} else {
|
||||
r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
r = safe_atou64(value, &lim);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
|
||||
return mem;
|
||||
}
|
||||
if (lim == UINT64_MAX)
|
||||
return mem;
|
||||
|
||||
/* Make sure the limit is a multiple of our own page size */
|
||||
lim /= ps;
|
||||
lim *= ps;
|
||||
|
||||
return MIN(mem, lim);
|
||||
}
|
||||
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
|
||||
uint64_t p, m, ps, r;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
|
||||
* the result is a multiple of the page size (rounds down). */
|
||||
|
||||
ps = page_size();
|
||||
assert(ps > 0);
|
||||
|
||||
p = physical_memory() / ps;
|
||||
assert(p > 0);
|
||||
|
||||
m = p * v;
|
||||
if (m / p != v)
|
||||
return UINT64_MAX;
|
||||
|
||||
m /= max;
|
||||
|
||||
r = m * ps;
|
||||
if (r / ps != m)
|
||||
return UINT64_MAX;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t system_tasks_max(void) {
|
||||
|
||||
uint64_t a = TASKS_MAX, b = TASKS_MAX;
|
||||
_cleanup_free_ char *root = NULL;
|
||||
int r;
|
||||
|
||||
/* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
|
||||
* limit:
|
||||
*
|
||||
* a) the maximum tasks value the kernel allows on this architecture
|
||||
* b) the cgroups pids_max attribute for the system
|
||||
* c) the kernel's configured maximum PID value
|
||||
*
|
||||
* And then pick the smallest of the three */
|
||||
|
||||
r = procfs_tasks_get_limit(&a);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m");
|
||||
|
||||
r = cg_get_root_path(&root);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
|
||||
else {
|
||||
_cleanup_free_ char *value = NULL;
|
||||
|
||||
r = cg_get_attribute("pids", root, "pids.max", &value);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m");
|
||||
else if (!streq(value, "max")) {
|
||||
r = safe_atou64(value, &b);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m");
|
||||
}
|
||||
}
|
||||
|
||||
return MIN3(TASKS_MAX,
|
||||
a <= 0 ? TASKS_MAX : a,
|
||||
b <= 0 ? TASKS_MAX : b);
|
||||
}
|
||||
|
||||
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
|
||||
uint64_t t, m;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
|
||||
* relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
|
||||
|
||||
t = system_tasks_max();
|
||||
assert(t > 0);
|
||||
|
||||
m = t * v;
|
||||
if (m / t != v) /* overflow? */
|
||||
return UINT64_MAX;
|
||||
|
||||
return m / max;
|
||||
}
|
||||
|
||||
int version(void) {
|
||||
puts("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n"
|
||||
SYSTEMD_FEATURES);
|
||||
|
@ -237,12 +237,6 @@ static inline unsigned log2u_round_up(unsigned x) {
|
||||
|
||||
int container_get_leader(const char *machine, pid_t *pid);
|
||||
|
||||
uint64_t physical_memory(void);
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
|
||||
|
||||
uint64_t system_tasks_max(void);
|
||||
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
|
||||
|
||||
int version(void);
|
||||
|
||||
int str_verscmp(const char *s1, const char *s2);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "dbus-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "limits-util.h"
|
||||
#include "path-util.h"
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "ioprio.h"
|
||||
#include "ip-protocol-list.h"
|
||||
#include "journal-util.h"
|
||||
#include "limits-util.h"
|
||||
#include "load-fragment.h"
|
||||
#include "log.h"
|
||||
#include "missing.h"
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "ima-setup.h"
|
||||
#include "killall.h"
|
||||
#include "kmod-setup.h"
|
||||
#include "limits-util.h"
|
||||
#include "load-fragment.h"
|
||||
#include "log.h"
|
||||
#include "loopback-setup.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "conf-parser.h"
|
||||
#include "device-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "limits-util.h"
|
||||
#include "logind.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "label.h"
|
||||
#include "limits-util.h"
|
||||
#include "logind-user.h"
|
||||
#include "mkdir.h"
|
||||
#include "parse-util.h"
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "def.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "limits-util.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "hashmap.h"
|
||||
#include "io-util.h"
|
||||
#include "libudev-device-internal.h"
|
||||
#include "limits-util.h"
|
||||
#include "list.h"
|
||||
#include "main-func.h"
|
||||
#include "mkdir.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user