Systemd/src/home/homed-home.h
Lennart Poettering 9796a9fbad homed: make sure our worker processes finish before we exit
When exiting, let's explicitly wait for our worker processes to finish
first. That's useful if unmounting of /home/ is scheduled to happen
right after homed is down, as we then can be sure that the home
directories are properly unmounted and detached by the time homed is
fully terminated (otherwise it might happen that our worker gets killed
by the service manager, thus leaving the home directory and its backing
devices up/left for auto-clean which might be async).

Likely fixes #16842
2020-09-18 22:35:36 +02:00

172 lines
6.9 KiB
C

/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
typedef struct Home Home;
#include "homed-manager.h"
#include "homed-operation.h"
#include "list.h"
#include "ordered-set.h"
#include "user-record.h"
typedef enum HomeState {
HOME_UNFIXATED, /* home exists, but local record does not */
HOME_ABSENT, /* local record exists, but home does not */
HOME_INACTIVE, /* record and home exist, but is not logged in */
HOME_DIRTY, /* like HOME_INACTIVE, but the home directory wasn't cleanly deactivated */
HOME_FIXATING, /* generating local record from home */
HOME_FIXATING_FOR_ACTIVATION, /* fixating in order to activate soon */
HOME_FIXATING_FOR_ACQUIRE, /* fixating because Acquire() was called */
HOME_ACTIVATING,
HOME_ACTIVATING_FOR_ACQUIRE, /* activating because Acquire() was called */
HOME_DEACTIVATING,
HOME_ACTIVE, /* logged in right now */
HOME_LOCKING,
HOME_LOCKED,
HOME_UNLOCKING,
HOME_UNLOCKING_FOR_ACQUIRE, /* unlocking because Acquire() was called */
HOME_CREATING,
HOME_REMOVING,
HOME_UPDATING,
HOME_UPDATING_WHILE_ACTIVE,
HOME_RESIZING,
HOME_RESIZING_WHILE_ACTIVE,
HOME_PASSWD,
HOME_PASSWD_WHILE_ACTIVE,
HOME_AUTHENTICATING,
HOME_AUTHENTICATING_WHILE_ACTIVE,
HOME_AUTHENTICATING_FOR_ACQUIRE, /* authenticating because Acquire() was called */
_HOME_STATE_MAX,
_HOME_STATE_INVALID = -1
} HomeState;
static inline bool HOME_STATE_IS_ACTIVE(HomeState state) {
return IN_SET(state,
HOME_ACTIVE,
HOME_UPDATING_WHILE_ACTIVE,
HOME_RESIZING_WHILE_ACTIVE,
HOME_PASSWD_WHILE_ACTIVE,
HOME_AUTHENTICATING_WHILE_ACTIVE,
HOME_AUTHENTICATING_FOR_ACQUIRE);
}
static inline bool HOME_STATE_IS_EXECUTING_OPERATION(HomeState state) {
return IN_SET(state,
HOME_FIXATING,
HOME_FIXATING_FOR_ACTIVATION,
HOME_FIXATING_FOR_ACQUIRE,
HOME_ACTIVATING,
HOME_ACTIVATING_FOR_ACQUIRE,
HOME_DEACTIVATING,
HOME_LOCKING,
HOME_UNLOCKING,
HOME_UNLOCKING_FOR_ACQUIRE,
HOME_CREATING,
HOME_REMOVING,
HOME_UPDATING,
HOME_UPDATING_WHILE_ACTIVE,
HOME_RESIZING,
HOME_RESIZING_WHILE_ACTIVE,
HOME_PASSWD,
HOME_PASSWD_WHILE_ACTIVE,
HOME_AUTHENTICATING,
HOME_AUTHENTICATING_WHILE_ACTIVE,
HOME_AUTHENTICATING_FOR_ACQUIRE);
}
struct Home {
Manager *manager;
char *user_name;
uid_t uid;
char *sysfs; /* When found via plugged in device, the sysfs path to it */
/* Note that the 'state' field is only set to a state while we are doing something (i.e. activating,
* deactivating, creating, removing, and such), or when the home is an "unfixated" one. When we are
* done with an operation we invalidate the state. This is hint for home_get_state() to check the
* state on request as needed from the mount table and similar.*/
HomeState state;
int signed_locally; /* signed only by us */
UserRecord *record;
pid_t worker_pid;
int worker_stdout_fd;
sd_event_source *worker_event_source;
int worker_error_code;
/* The message we are currently processing, and thus need to reply to on completion */
Operation *current_operation;
/* Stores the raw, plaintext passwords, but only for short periods of time */
UserRecord *secret;
/* When we create a home area and that fails, we should possibly unregister the record altogether
* again, which is remembered in this boolean. */
bool unregister_on_failure;
/* The reading side of a FIFO stored in /run/systemd/home/, the writing side being used for reference
* counting. The references dropped to zero as soon as we see EOF. This concept exists twice: once
* for clients that are fine if we suspend the home directory on system suspend, and once for cliets
* that are not ok with that. This allows us to determine for each home whether there are any clients
* that support unsuspend. */
sd_event_source *ref_event_source_please_suspend;
sd_event_source *ref_event_source_dont_suspend;
/* Any pending operations we still need to execute. These are for operations we want to queue if we
* can't execute them right-away. */
OrderedSet *pending_operations;
/* A defer event source that processes pending acquire/release/eof events. We have a common
* dispatcher that processes all three kinds of events. */
sd_event_source *pending_event_source;
/* Did we send out a D-Bus notification about this entry? */
bool announced;
/* Used to coalesce bus PropertiesChanged events */
sd_event_source *deferred_change_event_source;
};
int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret);
Home *home_free(Home *h);
DEFINE_TRIVIAL_CLEANUP_FUNC(Home*, home_free);
int home_set_record(Home *h, UserRecord *hr);
int home_save_record(Home *h);
int home_unlink_record(Home *h);
int home_fixate(Home *h, UserRecord *secret, sd_bus_error *error);
int home_activate(Home *h, UserRecord *secret, sd_bus_error *error);
int home_authenticate(Home *h, UserRecord *secret, sd_bus_error *error);
int home_deactivate(Home *h, bool force, sd_bus_error *error);
int home_create(Home *h, UserRecord *secret, sd_bus_error *error);
int home_remove(Home *h, sd_bus_error *error);
int home_update(Home *h, UserRecord *new_record, sd_bus_error *error);
int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, sd_bus_error *error);
int home_passwd(Home *h, UserRecord *new_secret, UserRecord *old_secret, sd_bus_error *error);
int home_unregister(Home *h, sd_bus_error *error);
int home_lock(Home *h, sd_bus_error *error);
int home_unlock(Home *h, UserRecord *secret, sd_bus_error *error);
HomeState home_get_state(Home *h);
void home_process_notify(Home *h, char **l);
int home_killall(Home *h);
int home_augment_status(Home *h, UserRecordLoadFlags flags, UserRecord **ret);
int home_create_fifo(Home *h, bool please_suspend);
int home_schedule_operation(Home *h, Operation *o, sd_bus_error *error);
int home_auto_login(Home *h, char ***ret_seats);
int home_set_current_message(Home *h, sd_bus_message *m);
int home_wait_for_worker(Home *h);
const char *home_state_to_string(HomeState state);
HomeState home_state_from_string(const char *s);