#include "json-util.h"
#include "in-addr-prefix-util.h"
#include "ip-protocol-list.h"
+#include "path-util.h"
#include "set.h"
#include "unit.h"
#include "varlink-cgroup.h"
/* Others */
SD_JSON_BUILD_PAIR_BOOLEAN("CoredumpReceive", c->coredump_receive));
}
+
+static int memory_accounting_metric_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ CGroupMemoryAccountingMetric metric;
+ uint64_t value;
+ int r;
+
+ assert(ret);
+ assert(name);
+
+ metric = cgroup_memory_accounting_metric_from_string(name);
+ assert(metric >= 0);
+
+ r = unit_get_memory_accounting(u, metric, &value);
+ if (r == -ENODATA)
+ goto empty;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get value for '%s': %m", name);
+
+ if (value == UINT64_MAX)
+ goto empty;
+
+ return sd_json_variant_new_unsigned(ret, value);
+
+empty:
+ *ret = NULL;
+ return 0;
+}
+
+static int memory_available_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ uint64_t value;
+ int r;
+
+ assert(ret);
+ assert(name);
+
+ r = unit_get_memory_available(u, &value);
+ if (r == -ENODATA)
+ goto empty;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get value of available memory: %m");
+
+ if (value == UINT64_MAX)
+ goto empty;
+
+ return sd_json_variant_new_unsigned(ret, value);
+
+empty:
+ *ret = NULL;
+ return 0;
+}
+
+static int effective_limit_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ CGroupLimitType type;
+ uint64_t value;
+ int r;
+
+ assert(ret);
+ assert(name);
+
+ type = cgroup_effective_limit_type_from_string(name);
+ assert(type >= 0);
+
+ r = unit_get_effective_limit(u, type, &value);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get value for '%s': %m", name);
+
+ if (value == UINT64_MAX) {
+ *ret = NULL;
+ return 0;
+ }
+
+ return sd_json_variant_new_unsigned(ret, value);
+}
+
+static int cpu_usage_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ nsec_t ns;
+ int r;
+
+ assert(ret);
+ assert(name);
+
+ r = unit_get_cpu_usage(u, &ns);
+ if (r == -ENODATA)
+ goto empty;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get cpu usage: %m");
+
+ if (ns == NSEC_INFINITY)
+ goto empty;
+
+ return sd_json_variant_new_unsigned(ret, ns);
+
+empty:
+ *ret = NULL;
+ return 0;
+}
+
+static int effective_cpuset_build_json(sd_json_variant **ret, const char *name, void *userdata, const char *cpuset_name) {
+ Unit *u = ASSERT_PTR(userdata);
+ _cleanup_(cpu_set_reset) CPUSet cpus = {};
+ int r;
+
+ assert(ret);
+ assert(name);
+ assert(cpuset_name);
+
+ r = unit_get_cpuset(u, &cpus, cpuset_name);
+ if (r == -ENODATA) {
+ *ret = NULL;
+ return 0;
+ }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get cpu set '%s': %m", cpuset_name);
+
+ return cpu_set_build_json(ret, name, &cpus);
+}
+
+static inline int effective_cpus_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ return effective_cpuset_build_json(ret, name, userdata, "cpuset.cpus.effective");
+}
+
+static inline int effective_mems_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ return effective_cpuset_build_json(ret, name, userdata, "cpuset.mems.effective");
+}
+
+static int tasks_current_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ uint64_t cn;
+ int r;
+
+ assert(ret);
+ assert(name);
+
+ r = unit_get_tasks_current(u, &cn);
+ if (r == -ENODATA)
+ goto empty;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get count of current tasks: %m");
+
+ if (cn == UINT64_MAX)
+ goto empty;
+
+ return sd_json_variant_new_unsigned(ret, cn);
+
+empty:
+ *ret = NULL;
+ return 0;
+}
+
+static int get_ip_counter_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ CGroupIPAccountingMetric metric;
+ uint64_t value;
+ int r;
+
+ assert(ret);
+ assert(name);
+
+ metric = cgroup_ip_accounting_metric_from_string(name);
+ assert(metric >= 0);
+
+ r = unit_get_ip_accounting(u, metric, &value);
+ if (r == -ENODATA)
+ goto empty;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get value for '%s': %m", name);
+
+ if (value == UINT64_MAX)
+ goto empty;
+
+ return sd_json_variant_new_unsigned(ret, value);
+
+empty:
+ *ret = NULL;
+ return 0;
+}
+
+static int get_io_counter_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ CGroupIOAccountingMetric metric;
+ uint64_t value;
+ int r;
+
+ assert(ret);
+ assert(name);
+
+ metric = cgroup_io_accounting_metric_from_string(name);
+ assert(metric >= 0);
+
+ r = unit_get_io_accounting(u, metric, &value);
+ if (r == -ENODATA)
+ goto empty;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to get value for '%s': %m", name);
+
+ if (value == UINT64_MAX)
+ goto empty;
+
+ return sd_json_variant_new_unsigned(ret, value);
+
+empty:
+ *ret = NULL;
+ return 0;
+}
+
+int unit_cgroup_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+
+ assert(ret);
+ assert(name);
+
+ CGroupRuntime *crt = unit_get_cgroup_runtime(u);
+ if (!crt) {
+ *ret = NULL;
+ return 0;
+ }
+
+ return sd_json_buildo(
+ ret,
+
+ /* ID */
+ JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("ID", crt->cgroup_id),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("Path", crt->cgroup_path ? empty_to_root(crt->cgroup_path) : NULL),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("Slice", unit_slice_name(u)),
+
+ /* Memory */
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("MemoryCurrent", memory_accounting_metric_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("MemoryPeak", memory_accounting_metric_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("MemorySwapCurrent", memory_accounting_metric_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("MemorySwapPeak", memory_accounting_metric_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("MemoryZSwapCurrent", memory_accounting_metric_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("MemoryAvailable", memory_available_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("EffectiveMemoryMax", effective_limit_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("EffectiveMemoryHigh", effective_limit_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("EffectiveMemoryNodes", effective_mems_build_json, u),
+
+ /* CPU */
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("CPUUsageNSec", cpu_usage_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("EffectiveCPUs", effective_cpus_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("TasksCurrent", tasks_current_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("EffectiveTasksMax", effective_limit_build_json, u),
+
+ /* IP */
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("IPIngressBytes", get_ip_counter_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("IPIngressPackets", get_ip_counter_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("IPEgressBytes", get_ip_counter_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("IPEgressPackets", get_ip_counter_build_json, u),
+
+ /* IO */
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOReadBytes", get_io_counter_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOReadOperations", get_io_counter_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOWriteBytes", get_io_counter_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOWriteOperations", get_io_counter_build_json, u));
+}
SD_VARLINK_FIELD_COMMENT("Trigger unit name"),
SD_VARLINK_DEFINE_FIELD(name, SD_VARLINK_STRING, 0));
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+ CGroupRuntime,
+
+ /* ID */
+ SD_VARLINK_FIELD_COMMENT("ID of the CGroup"),
+ SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path of the CGroup"),
+ SD_VARLINK_DEFINE_FIELD(Path, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Slice of the CGroup"),
+ SD_VARLINK_DEFINE_FIELD(Slice, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+
+ /* Memory */
+ SD_VARLINK_FIELD_COMMENT("The current amount of memory used by the cgroup, in bytes"),
+ SD_VARLINK_DEFINE_FIELD(MemoryCurrent, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The peak amount of memory used by the cgroup since its creation, in bytes"),
+ SD_VARLINK_DEFINE_FIELD(MemoryPeak, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The current amount of swap space used by the cgroup, in bytes"),
+ SD_VARLINK_DEFINE_FIELD(MemorySwapCurrent, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The peak amount of swap space used by the cgroup since its creation, in bytes"),
+ SD_VARLINK_DEFINE_FIELD(MemorySwapPeak, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The current amount of zswap space used by the cgroup, in bytes"),
+ SD_VARLINK_DEFINE_FIELD(MemoryZSwapCurrent, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The available memory for the cgroup, in bytes."),
+ SD_VARLINK_DEFINE_FIELD(MemoryAvailable, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The effective maximum amount of memory allowed for the cgroup, in bytes"),
+ SD_VARLINK_DEFINE_FIELD(EffectiveMemoryMax, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The effective high watermark for memory usage by the cgroup, in bytes"),
+ SD_VARLINK_DEFINE_FIELD(EffectiveMemoryHigh, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Memory NUMA nodes that the cgroup is allowed to use"),
+ SD_VARLINK_DEFINE_FIELD(EffectiveMemoryNodes, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+
+ /* CPU */
+ SD_VARLINK_FIELD_COMMENT("The total CPU usage time in nanoseconds (ns) for the cgroup"),
+ SD_VARLINK_DEFINE_FIELD(CPUUsageNSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("NUMA nodes that the cgroup is allowed to use"),
+ SD_VARLINK_DEFINE_FIELD(EffectiveCPUs, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The current number of tasks (i.e., processes or threads) running within the cgroup"),
+ SD_VARLINK_DEFINE_FIELD(TasksCurrent, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The maximum number of tasks that the cgroup is allowed to run concurrently"),
+ SD_VARLINK_DEFINE_FIELD(EffectiveTasksMax, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+
+ /* IP */
+ SD_VARLINK_FIELD_COMMENT("The total number of bytes received by the cgroup's IP stack"),
+ SD_VARLINK_DEFINE_FIELD(IPIngressBytes, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The total number of incoming packets received by the cgroup's IP stack"),
+ SD_VARLINK_DEFINE_FIELD(IPIngressPackets, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("iThe total number of bytes sent by the cgroup's IP stack"),
+ SD_VARLINK_DEFINE_FIELD(IPEgressBytes, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The total number of outgoing packets sent by the cgroup's IP stack"),
+ SD_VARLINK_DEFINE_FIELD(IPEgressPackets, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+
+ /* IO */
+ SD_VARLINK_FIELD_COMMENT("The total number of bytes read from block devices by the cgroup"),
+ SD_VARLINK_DEFINE_FIELD(IOReadBytes, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The total number of read operations performed on block devices by the cgroup"),
+ SD_VARLINK_DEFINE_FIELD(IOReadOperations, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The total number of bytes written to block devices by the cgroup"),
+ SD_VARLINK_DEFINE_FIELD(IOWriteBytes, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The total number of write operations performed on block devices by the cgroup"),
+ SD_VARLINK_DEFINE_FIELD(IOWriteOperations, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+
static SD_VARLINK_DEFINE_STRUCT_TYPE(
UnitRuntime,
SD_VARLINK_FIELD_COMMENT("If not empty, the field contains the name of another unit that this unit follows in state"),
SD_VARLINK_FIELD_COMMENT("Provides details about why a unit was activated"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(ActivationDetails, ActivationDetails, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("When true, logs about this unit will be at debug level regardless of other log level settings"),
- SD_VARLINK_DEFINE_FIELD(DebugInvocation, SD_VARLINK_BOOL, 0));
+ SD_VARLINK_DEFINE_FIELD(DebugInvocation, SD_VARLINK_BOOL, 0),
+ SD_VARLINK_FIELD_COMMENT("The cgroup runtime of the unit"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(CGroup, CGroupRuntime, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_ERROR(NoSuchUnit);
&vl_type_CGroupDeviceAllow,
SD_VARLINK_SYMBOL_COMMENT("CGroup context of a unit"),
&vl_type_CGroupContext,
+ SD_VARLINK_SYMBOL_COMMENT("CGroup runtime of a unit"),
+ &vl_type_CGroupRuntime,
SD_VARLINK_SYMBOL_COMMENT("No matching unit found"),
&vl_error_NoSuchUnit);