#include "bpf-program.h"
#include "condition.h"
#include "emergency-action.h"
-#include "install.h"
#include "list.h"
-#include "unit-name.h"
+#include "set.h"
+#include "unit-file.h"
#include "cgroup.h"
typedef struct UnitRef UnitRef;
* use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be
* created as a result of multiple "reasons", hence the bitmask. */
typedef enum UnitDependencyMask {
- /* Configured directly by the unit file, .wants/.requries symlink or drop-in, or as an immediate result of a
+ /* Configured directly by the unit file, .wants/.requires symlink or drop-in, or as an immediate result of a
* non-dependency option configured that way. */
UNIT_DEPENDENCY_FILE = 1 << 0,
/* The slot used for watching NameOwnerChanged signals */
sd_bus_slot *match_bus_slot;
+ sd_bus_slot *get_name_owner_slot;
/* References to this unit from clients */
sd_bus_track *bus_track;
/* cgroup empty queue */
LIST_FIELDS(Unit, cgroup_empty_queue);
+ /* cgroup OOM queue */
+ LIST_FIELDS(Unit, cgroup_oom_queue);
+
/* Target dependencies queue */
LIST_FIELDS(Unit, target_deps_queue);
nsec_t cpu_usage_base;
nsec_t cpu_usage_last; /* the most recently read value */
+ /* The current counter of the oom_kill field in the memory.events cgroup attribute */
+ uint64_t oom_kill_last;
+
+ /* Where the io.stat data was at the time the unit was started */
+ uint64_t io_accounting_base[_CGROUP_IO_ACCOUNTING_METRIC_MAX];
+ uint64_t io_accounting_last[_CGROUP_IO_ACCOUNTING_METRIC_MAX]; /* the most recently read value */
+
/* Counterparts in the cgroup filesystem */
char *cgroup_path;
CGroupMask cgroup_realized_mask; /* In which hierarchies does this unit's cgroup exist? (only relevant on cgroup v1) */
CGroupMask cgroup_enabled_mask; /* Which controllers are enabled (or more correctly: enabled for the children) for this unit's cgroup? (only relevant on cgroup v2) */
- CGroupMask cgroup_invalidated_mask; /* A mask specifiying controllers which shall be considered invalidated, and require re-realization */
+ CGroupMask cgroup_invalidated_mask; /* A mask specifying controllers which shall be considered invalidated, and require re-realization */
CGroupMask cgroup_members_mask; /* A cache for the controllers required by all children of this cgroup (only relevant for slice units) */
- int cgroup_inotify_wd;
+
+ /* Inotify watch descriptors for watching cgroup.events and memory.events on cgroupv2 */
+ int cgroup_control_inotify_wd;
+ int cgroup_memory_inotify_wd;
/* Device Controller BPF program */
BPFProgram *bpf_device_control_installed;
BPFProgram *ip_bpf_ingress, *ip_bpf_ingress_installed;
BPFProgram *ip_bpf_egress, *ip_bpf_egress_installed;
+ Set *ip_bpf_custom_ingress;
+ Set *ip_bpf_custom_ingress_installed;
+ Set *ip_bpf_custom_egress;
+ Set *ip_bpf_custom_egress_installed;
uint64_t ip_accounting_extra[_CGROUP_IP_ACCOUNTING_METRIC_MAX];
bool in_gc_queue:1;
bool in_cgroup_realize_queue:1;
bool in_cgroup_empty_queue:1;
+ bool in_cgroup_oom_queue:1;
bool in_target_deps_queue:1;
bool in_stop_when_unneeded_queue:1;
int (*kill)(Unit *u, KillWho w, int signo, sd_bus_error *error);
+ /* Clear out the various runtime/state/cache/logs/configuration data */
+ int (*clean)(Unit *u, ExecCleanMask m);
+
+ /* Return which kind of data can be cleaned */
+ int (*can_clean)(Unit *u, ExecCleanMask *ret);
+
bool (*can_reload)(Unit *u);
/* Write all data that cannot be restored from other sources
/* Reset failed state if we are in failed state */
void (*reset_failed)(Unit *u);
- /* Called whenever any of the cgroups this unit watches for
- * ran empty */
+ /* Called whenever any of the cgroups this unit watches for ran empty */
void (*notify_cgroup_empty)(Unit *u);
+ /* Called whenever an OOM kill event on this unit was seen */
+ void (*notify_cgroup_oom)(Unit *u);
+
/* Called whenever a process of this unit sends us a message */
void (*notify_message)(Unit *u, const struct ucred *ucred, char **tags, FDSet *fds);
/* Called whenever a name this Unit registered for comes or goes away. */
- void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
+ void (*bus_name_owner_change)(Unit *u, const char *old_owner, const char *new_owner);
/* Called for each property that is being set */
int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int unit_set_default_slice(Unit *u);
const char *unit_description(Unit *u) _pure_;
+const char *unit_status_string(Unit *u) _pure_;
bool unit_has_name(const Unit *u, const char *name);
typedef enum UnitNotifyFlags {
UNIT_NOTIFY_RELOAD_FAILURE = 1 << 0,
UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1,
+ UNIT_NOTIFY_SKIP_CONDITION = 1 << 2,
} UnitNotifyFlags;
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags);
-int unit_watch_pid(Unit *u, pid_t pid);
+int unit_watch_pid(Unit *u, pid_t pid, bool exclusive);
void unit_unwatch_pid(Unit *u, pid_t pid);
void unit_unwatch_all_pids(Unit *u);
bool unit_stop_pending(Unit *u) _pure_;
bool unit_inactive_or_pending(Unit *u) _pure_;
bool unit_active_or_pending(Unit *u);
+bool unit_will_restart_default(Unit *u);
bool unit_will_restart(Unit *u);
int unit_add_default_target_dependency(Unit *u, Unit *target);
pid_t unit_control_pid(Unit *u);
pid_t unit_main_pid(Unit *u);
-static inline bool unit_supported(Unit *u) {
- return unit_type_supported(u->type);
-}
-
void unit_warn_if_dir_nonempty(Unit *u, const char* where);
int unit_fail_if_noncanonical(Unit *u, const char* where);
-int unit_start_limit_test(Unit *u);
+int unit_test_start_limit(Unit *u);
void unit_unref_uid(Unit *u, bool destroy_now);
int unit_ref_uid(Unit *u, uid_t uid, bool clean_ipc);
int unit_set_exec_params(Unit *s, ExecParameters *p);
int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret);
+int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid);
void unit_remove_dependencies(Unit *u, UnitDependencyMask mask);
int unit_pid_attachable(Unit *unit, pid_t pid, sd_bus_error *error);
+/* unit_log_skip is for cases like ExecCondition= where a unit is considered "done"
+ * after some execution, rather than succeeded or failed. */
+void unit_log_skip(Unit *u, const char *result);
void unit_log_success(Unit *u);
void unit_log_failure(Unit *u, const char *result);
static inline void unit_log_result(Unit *u, bool success, const char *result) {
unit_log_failure(u, result);
}
-void unit_log_process_exit(Unit *u, int level, const char *kind, const char *command, int code, int status);
+void unit_log_process_exit(Unit *u, const char *kind, const char *command, bool success, int code, int status);
int unit_exit_status(Unit *u);
int unit_success_action_exit_status(Unit *u);
int unit_failure_action_exit_status(Unit *u);
+int unit_test_trigger_loaded(Unit *u);
+
+void unit_destroy_runtime_directory(Unit *u, const ExecContext *context);
+int unit_clean(Unit *u, ExecCleanMask mask);
+int unit_can_clean(Unit *u, ExecCleanMask *ret_mask);
+
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full(unit, level, error, ...) \
({ \
const Unit *_u = (unit); \
- _u ? log_object_internal(level, error, __FILE__, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \
- log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
+ _u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \
+ log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
})
#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__)