Add quota support for systemctl

This commit is contained in:
Andres Beltran
2025-07-01 17:41:31 +00:00
parent a89afe1948
commit e8e274c8da

View File

@@ -15,8 +15,10 @@
#include "cgroup-show.h"
#include "cpu-set-util.h"
#include "errno-util.h"
#include "exec-directory-util.h"
#include "exec-util.h"
#include "exit-status.h"
#include "extract-word.h"
#include "format-util.h"
#include "hexdecoct.h"
#include "hostname-setup.h"
@@ -33,6 +35,7 @@
#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
#include "percent-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "set.h"
@@ -161,6 +164,13 @@ typedef struct UnitCondition {
LIST_FIELDS(struct UnitCondition, conditions);
} UnitCondition;
typedef struct QuotaInfo {
bool quota_enforce;
bool quota_accounting;
uint64_t quota_usage;
uint64_t quota_limit;
} QuotaInfo;
static UnitCondition* unit_condition_free(UnitCondition *c) {
if (!c)
return NULL;
@@ -299,6 +309,9 @@ typedef struct UnitStatusInfo {
uint64_t default_memory_low;
uint64_t default_startup_memory_low;
/* Exec Quotas */
QuotaInfo exec_directories_quota[_EXEC_DIRECTORY_TYPE_MAX];
LIST_HEAD(ExecStatusInfo, exec_status_info_list);
} UnitStatusInfo;
@@ -338,6 +351,22 @@ static void format_enable_state(const char *enable_state, const char **enable_on
*enable_on = *enable_off = "";
}
static void print_exec_directory_quota(UnitStatusInfo *i, ExecDirectoryType dt) {
assert(i);
if (!IN_SET(dt, EXEC_DIRECTORY_STATE, EXEC_DIRECTORY_CACHE, EXEC_DIRECTORY_LOGS))
return;
if (i->exec_directories_quota[dt].quota_accounting) {
printf(" %s: %s", exec_directory_type_to_string(dt), FORMAT_BYTES(i->exec_directories_quota[dt].quota_usage));
if (i->exec_directories_quota[dt].quota_enforce)
printf(" (max: %s)", FORMAT_BYTES(i->exec_directories_quota[dt].quota_limit));
printf("\n");
}
}
static void print_status_info(
sd_bus *bus,
UnitStatusInfo *i,
@@ -877,6 +906,9 @@ static void print_status_info(
if (i->cpu_usage_nsec != UINT64_MAX)
printf(" CPU: %s\n", FORMAT_TIMESPAN(i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++)
print_exec_directory_quota(i, dt);
if (i->control_group) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
static const char prefix[] = " ";
@@ -1122,6 +1154,25 @@ static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_e
return 0;
}
static int map_quota(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
int r;
QuotaInfo *qi = ASSERT_PTR(userdata);
uint64_t quota_usage, quota_limit;
r = sd_bus_message_read(m, "(tt)", &quota_usage, &quota_limit);
if (r < 0)
return r;
*qi = (QuotaInfo) {
.quota_enforce = quota_limit != UINT64_MAX,
.quota_accounting = quota_usage != UINT64_MAX,
.quota_usage = quota_usage,
.quota_limit = quota_limit
};
return 0;
}
static int print_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) {
char bus_type;
const char *contents;
@@ -1338,6 +1389,27 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
fputc('\n', stdout);
}
return 1;
} else if (STR_IN_SET(name, "StateDirectoryQuota", "CacheDirectoryQuota", "LogsDirectoryQuota")) {
uint64_t quota_absolute;
uint32_t quota_scale;
const char *quota_enforce;
r = sd_bus_message_read(m, "(tus)", &quota_absolute, &quota_scale, &quota_enforce);
if (r < 0)
return r;
r = parse_boolean(quota_enforce);
if (r < 0)
return r;
if (!r)
bus_print_property_value(name, expected_value, flags, "[not set]");
else if (quota_absolute != UINT64_MAX)
bus_print_property_valuef(name, expected_value, flags, "%" PRIu64, quota_absolute);
else
bus_print_property_valuef(name, expected_value, flags, "%d%%", UINT32_SCALE_TO_PERCENT(quota_scale));
return 1;
}
break;
@@ -2201,6 +2273,9 @@ static int show_one(
{ "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) },
{ "IOReadBytes", "t", NULL, offsetof(UnitStatusInfo, io_read_bytes) },
{ "IOWriteBytes", "t", NULL, offsetof(UnitStatusInfo, io_write_bytes) },
{ "StateDirectoryQuotaUsage", "(tt)", map_quota, offsetof(UnitStatusInfo, exec_directories_quota[EXEC_DIRECTORY_STATE]) },
{ "CacheDirectoryQuotaUsage", "(tt)", map_quota, offsetof(UnitStatusInfo, exec_directories_quota[EXEC_DIRECTORY_CACHE]) },
{ "LogsDirectoryQuotaUsage", "(tt)", map_quota, offsetof(UnitStatusInfo, exec_directories_quota[EXEC_DIRECTORY_LOGS]) },
{ "ExecCondition", "a(sasbttttuii)", map_exec, 0 },
{ "ExecConditionEx", "a(sasasttttuii)", map_exec, 0 },
{ "ExecStartPre", "a(sasbttttuii)", map_exec, 0 },