implement coldpluggin

This commit is contained in:
Lennart Poettering 2010-01-29 03:18:09 +01:00
parent b08d03ffe5
commit f50e0a0123
14 changed files with 224 additions and 173 deletions

View File

@ -21,7 +21,6 @@ COMMON= \
snapshot.o \
socket.o \
timer.o \
load-fstab.o \
load-dropin.o \
execute.o

View File

@ -20,10 +20,6 @@ static int automount_init(Unit *u) {
if ((r = unit_load_fragment(u)) < 0)
return r;
/* Load entry from /etc/fstab */
if ((r = unit_load_fstab(u)) < 0)
return r;
/* Load drop-in directory data */
if ((r = unit_load_dropin(u)) < 0)
return r;

View File

@ -8,6 +8,16 @@
#include "strv.h"
#include "log.h"
static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
[DEVICE_DEAD] = UNIT_INACTIVE,
[DEVICE_AVAILABLE] = UNIT_ACTIVE
};
static const char* const state_string_table[_DEVICE_STATE_MAX] = {
[DEVICE_DEAD] = "dead",
[DEVICE_AVAILABLE] = "available"
};
static void device_done(Unit *u) {
Device *d = DEVICE(u);
@ -15,13 +25,31 @@ static void device_done(Unit *u) {
free(d->sysfs);
}
static void device_set_state(Device *d, DeviceState state) {
DeviceState old_state;
assert(d);
old_state = d->state;
d->state = state;
log_debug("%s changed %s → %s", unit_id(UNIT(d)), state_string_table[old_state], state_string_table[state]);
unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state]);
}
static int device_coldplug(Unit *u) {
Device *d = DEVICE(u);
assert(d);
assert(d->state == DEVICE_DEAD);
if (d->sysfs)
device_set_state(d, DEVICE_AVAILABLE);
return 0;
}
static void device_dump(Unit *u, FILE *f, const char *prefix) {
static const char* const state_table[_DEVICE_STATE_MAX] = {
[DEVICE_DEAD] = "dead",
[DEVICE_AVAILABLE] = "available"
};
Device *d = DEVICE(u);
assert(d);
@ -29,8 +57,14 @@ static void device_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sDevice State: %s\n"
"%sSysfs Path: %s\n",
prefix, state_table[d->state],
prefix, d->sysfs);
prefix, state_string_table[d->state],
prefix, strna(d->sysfs));
}
static UnitActiveState device_active_state(Unit *u) {
assert(u);
return state_translation_table[DEVICE(u)->state];
}
static int device_add_escaped_name(Unit *u, const char *prefix, const char *dn, bool make_id) {
@ -108,11 +142,9 @@ static int device_process_device(Manager *m, struct udev_device *dev) {
}
if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
(model = udev_device_get_property_value(dev, "ID_MODEL")))
if (!(u->meta.description = strdup(model))) {
r = -ENOMEM;
(model = udev_device_get_property_value(dev, "ID_MODEL")))
if ((r = unit_set_description(u, model)) < 0)
goto fail;
}
} else {
delete = false;
@ -229,19 +261,17 @@ fail:
return r;
}
static UnitActiveState device_active_state(Unit *u) {
return DEVICE(u)->state == DEVICE_DEAD ? UNIT_INACTIVE : UNIT_ACTIVE;
}
const UnitVTable device_vtable = {
.suffix = ".device",
.init = unit_load_fragment_and_dropin,
.done = device_done,
.coldplug = device_coldplug,
.dump = device_dump,
.enumerate = device_enumerate,
.shutdown = device_shutdown,
.active_state = device_active_state,
.active_state = device_active_state
.enumerate = device_enumerate,
.shutdown = device_shutdown
};

9
job.c
View File

@ -5,6 +5,7 @@
#include "macro.h"
#include "job.h"
#include "log.h"
Job* job_new(Manager *m, JobType type, Unit *unit) {
Job *j;
@ -405,10 +406,18 @@ int job_finish_and_invalidate(Job *j, bool success) {
assert(j);
assert(j->installed);
log_debug("Job %s/%s finished, success=%s", unit_id(j->unit), job_type_to_string(j->type), yes_no(success));
/* Patch restart jobs so that they become normal start jobs */
if (success && (j->type == JOB_RESTART || j->type == JOB_TRY_RESTART)) {
log_debug("Converting job %s/%s → %s/%s",
unit_id(j->unit), job_type_to_string(j->type),
unit_id(j->unit), job_type_to_string(JOB_START));
j->state = JOB_RUNNING;
j->type = JOB_START;
job_schedule_run(j);
return 0;
}

View File

@ -807,10 +807,11 @@ static int load_from_path(Unit *u, const char *path) {
goto finish;
if (id == k)
unit_choose_id(u, id);
free(k);
}
unit_choose_id(u, id);
free(u->meta.load_path);
u->meta.load_path = filename;
@ -860,10 +861,10 @@ int unit_load_fragment(Unit *u) {
/* If syslog or kernel logging is requested, make sure
* our own logging daemon is run first. */
if ((k = unit_add_dependency(u, UNIT_AFTER, u->meta.manager->special_units[SPECIAL_LOGGER_SOCKET])) < 0)
if ((k = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_LOGGER_SOCKET)) < 0)
return k;
if ((k = unit_add_dependency(u, UNIT_REQUIRES, u->meta.manager->special_units[SPECIAL_LOGGER_SOCKET])) < 0)
if ((k = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_LOGGER_SOCKET)) < 0)
return k;
}

View File

@ -1,11 +0,0 @@
/*-*- Mode: C; c-basic-offset: 8 -*-*/
#include "load-fstab.h"
int unit_load_fstab(Unit *u) {
assert(u);
/* Load dependencies from /etc/fstab */
return 0;
}

View File

@ -1,12 +0,0 @@
/*-*- Mode: C; c-basic-offset: 8 -*-*/
#ifndef fooloadfstabhfoo
#define fooloadfstabhfoo
#include "unit.h"
/* Read service data from /etc/fstab */
int unit_load_fstab(Unit *u);
#endif

15
main.c
View File

@ -21,7 +21,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
if ((r = manager_load_unit(m, "default.target", &target)) < 0) {
if ((r = manager_coldplug(m)) < 0) {
log_error("Failed to retrieve coldplug information: %s", strerror(-r));
goto finish;
}
if ((r = manager_load_unit(m, SPECIAL_DEFAULT_TARGET, &target)) < 0) {
log_error("Failed to load default target: %s", strerror(-r));
goto finish;
}
@ -37,10 +42,10 @@ int main(int argc, char *argv[]) {
printf("→ By jobs:\n");
manager_dump_jobs(m, stdout, "\t");
if ((r = manager_loop(m)) < 0) {
log_error("Failed to run mainloop: %s", strerror(-r));
goto finish;
}
/* if ((r = manager_loop(m)) < 0) { */
/* log_error("Failed to run mainloop: %s", strerror(-r)); */
/* goto finish; */
/* } */
retval = 0;

View File

@ -17,14 +17,6 @@
#include "log.h"
#include "util.h"
static const char * const special_table[_SPECIAL_UNIT_MAX] = {
[SPECIAL_SYSLOG_SERVICE] = "syslog.service",
[SPECIAL_DBUS_SERVICE] = "messagebus.service",
[SPECIAL_LOGGER_SOCKET] = "systemd-logger.socket",
[SPECIAL_KBREQUEST_TARGET] = "kbrequest.target",
[SPECIAL_CTRL_ALT_DEL_TARGET] = "ctrl-alt-del.target"
};
static int manager_setup_signals(Manager *m) {
sigset_t mask;
struct epoll_event ev;
@ -58,35 +50,6 @@ static int manager_setup_signals(Manager *m) {
return 0;
}
static int manager_load_special_units(Manager *m) {
SpecialUnit c;
int r;
assert(m);
/* Loads all 'special' units, so that we have easy access to them later */
for (c = 0; c < _SPECIAL_UNIT_MAX; c++)
if ((r = manager_load_unit(m, special_table[c], m->special_units+c)) < 0)
return r;
return 0;
}
static int manager_enumerate(Manager *m) {
int r;
UnitType c;
assert(m);
for (c = 0; c < _UNIT_TYPE_MAX; c++)
if (unit_vtable[c]->enumerate)
if ((r = unit_vtable[c]->enumerate(m)) < 0)
return r;
return 0;
}
Manager* manager_new(void) {
Manager *m;
@ -113,12 +76,6 @@ Manager* manager_new(void) {
if (manager_setup_signals(m) < 0)
goto fail;
if (manager_load_special_units(m) < 0)
goto fail;
if (manager_enumerate(m) < 0)
goto fail;
return m;
fail:
@ -156,6 +113,39 @@ void manager_free(Manager *m) {
free(m);
}
int manager_coldplug(Manager *m) {
int r;
UnitType c;
Iterator i;
Unit *u;
char *k;
assert(m);
/* First, let's ask every type to load all units from
* disk/kernel that it might know */
for (c = 0; c < _UNIT_TYPE_MAX; c++)
if (unit_vtable[c]->enumerate)
if ((r = unit_vtable[c]->enumerate(m)) < 0)
return r;
manager_dispatch_load_queue(m);
/* Then, let's set up their initial state. */
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
/* ignore aliases */
if (unit_id(u) != k)
continue;
if (UNIT_VTABLE(u)->coldplug)
if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0)
return r;
}
return 0;
}
static void transaction_delete_job(Manager *m, Job *j) {
assert(m);
assert(j);
@ -874,6 +864,8 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool for
if ((r = transaction_activate(m, mode)) < 0)
return r;
log_debug("Enqueued job %s/%s", unit_id(unit), job_type_to_string(type));
if (_ret)
*_ret = ret;
@ -893,7 +885,7 @@ Unit *manager_get_unit(Manager *m, const char *name) {
return hashmap_get(m->units, name);
}
static void dispatch_load_queue(Manager *m) {
void manager_dispatch_load_queue(Manager *m) {
Meta *meta;
assert(m);
@ -951,7 +943,7 @@ int manager_load_unit(Manager *m, const char *path, Unit **_ret) {
}
unit_add_to_load_queue(ret);
dispatch_load_queue(m);
manager_dispatch_load_queue(m);
*_ret = ret;
return 0;

View File

@ -30,14 +30,12 @@ struct Watch {
#include "list.h"
#include "set.h"
typedef enum SpecialUnit {
SPECIAL_SYSLOG_SERVICE,
SPECIAL_DBUS_SERVICE,
SPECIAL_LOGGER_SOCKET,
SPECIAL_CTRL_ALT_DEL_TARGET,
SPECIAL_KBREQUEST_TARGET,
_SPECIAL_UNIT_MAX
} SpecialUnit;
#define SPECIAL_DEFAULT_TARGET "default.target"
#define SPECIAL_SYSLOG_SERVICE "syslog.service"
#define SPECIAL_DBUS_SERVICE "messagebus.service"
#define SPECIAL_LOGGER_SOCKET "systemd-logger.socket"
#define SPECIAL_KBREQUEST_TARGET "kbrequest.target"
#define SPECIAL_CTRL_ALT_DEL_TARGET "ctrl-alt-del.target"
struct Manager {
uint32_t current_job_id;
@ -69,14 +67,14 @@ struct Manager {
Watch signal_watch;
Unit *special_units[_SPECIAL_UNIT_MAX]; /* some special units */
struct udev* udev;
};
Manager* manager_new(void);
void manager_free(Manager *m);
int manager_coldplug(Manager *m);
Job *manager_get_job(Manager *m, uint32_t id);
Unit *manager_get_unit(Manager *m, const char *name);
@ -90,7 +88,9 @@ void manager_transaction_unlink_job(Manager *m, Job *j);
void manager_clear_jobs(Manager *m);
void manager_dispatch_load_queue(Manager *m);
void manager_dispatch_run_queue(Manager *m);
int manager_loop(Manager *m);
#endif

141
mount.c
View File

@ -7,30 +7,24 @@
#include "unit.h"
#include "mount.h"
#include "load-fragment.h"
#include "load-fstab.h"
#include "load-dropin.h"
#include "log.h"
static int mount_init(Unit *u) {
int r;
Mount *m = MOUNT(u);
static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
[MOUNT_DEAD] = UNIT_INACTIVE,
[MOUNT_MOUNTING] = UNIT_ACTIVATING,
[MOUNT_MOUNTED] = UNIT_ACTIVE,
[MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
[MOUNT_MAINTAINANCE] = UNIT_INACTIVE,
};
assert(m);
/* Load a .mount file */
if ((r = unit_load_fragment(u)) < 0)
return r;
/* Load entry from /etc/fstab */
if ((r = unit_load_fstab(u)) < 0)
return r;
/* Load drop-in directory data */
if ((r = unit_load_dropin(u)) < 0)
return r;
return r;
}
static const char* const state_string_table[_MOUNT_STATE_MAX] = {
[MOUNT_DEAD] = "dead",
[MOUNT_MOUNTING] = "mounting",
[MOUNT_MOUNTED] = "mounted",
[MOUNT_UNMOUNTING] = "unmounting",
[MOUNT_MAINTAINANCE] = "maintainance"
};
static void mount_done(Unit *u) {
Mount *d = MOUNT(u);
@ -40,16 +34,31 @@ static void mount_done(Unit *u) {
free(d->where);
}
static void mount_set_state(Mount *m, MountState state) {
MountState old_state;
assert(m);
old_state = m->state;
m->state = state;
log_debug("%s changed %s → %s", unit_id(UNIT(m)), state_string_table[old_state], state_string_table[state]);
unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state]);
}
static int mount_coldplug(Unit *u) {
Mount *m = MOUNT(u);
assert(m);
assert(m->state == MOUNT_DEAD);
if (m->from_proc_self_mountinfo)
mount_set_state(m, MOUNT_MOUNTED);
return 0;
}
static void mount_dump(Unit *u, FILE *f, const char *prefix) {
static const char* const state_table[_MOUNT_STATE_MAX] = {
[MOUNT_DEAD] = "dead",
[MOUNT_MOUNTING] = "mounting",
[MOUNT_MOUNTED] = "mounted",
[MOUNT_UNMOUNTING] = "unmounting",
[MOUNT_MAINTAINANCE] = "maintainance"
};
Mount *s = MOUNT(u);
assert(s);
@ -57,10 +66,20 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sMount State: %s\n"
"%sWhere: %s\n"
"%sWhat: %s\n",
prefix, state_table[s->state],
"%sWhat: %s\n"
"%sFrom /etc/fstab: %s\n"
"%sFrom /proc/self/mountinfo: %s\n",
prefix, state_string_table[s->state],
prefix, s->where,
prefix, s->what);
prefix, s->what,
prefix, yes_no(s->from_etc_fstab),
prefix, yes_no(s->from_proc_self_mountinfo));
}
static UnitActiveState mount_active_state(Unit *u) {
assert(u);
return state_translation_table[MOUNT(u)->state];
}
static void mount_shutdown(Manager *m) {
@ -136,12 +155,13 @@ static int mount_add_path_links(Mount *m) {
return 0;
}
static int mount_add_one(Manager *m, const char *what, const char *where) {
static int mount_add_one(Manager *m, const char *what, const char *where, bool live) {
char *e;
int r;
Unit *u;
bool delete;
assert(m);
assert(what);
assert(where);
@ -172,16 +192,23 @@ static int mount_add_one(Manager *m, const char *what, const char *where) {
goto fail;
if (!(MOUNT(u)->what = strdup(what)) ||
!(MOUNT(u)->where = strdup(where)) ||
!(u->meta.description = strdup(where))) {
r = -ENOMEM;
!(MOUNT(u)->where = strdup(where))) {
r = -ENOMEM;
goto fail;
}
if ((r = unit_set_description(u, where)) < 0)
goto fail;
}
} else {
delete = false;
free(e);
}
if (live)
MOUNT(u)->from_proc_self_mountinfo = true;
else
MOUNT(u)->from_etc_fstab = true;
if ((r = mount_add_node_links(MOUNT(u))) < 0)
goto fail;
@ -189,6 +216,7 @@ static int mount_add_one(Manager *m, const char *what, const char *where) {
goto fail;
unit_add_to_load_queue(u);
return 0;
fail:
@ -207,10 +235,10 @@ static char *fstab_node_to_udev_node(char *p) {
if (startswith(p, "LABEL=")) {
if (!(t = strdup(p+6)))
if (!(t = xescape(p+6, "/ ")))
return NULL;
r = asprintf(&dn, "/dev/disk/by-label/%s", xescape(t, "/ "));
r = asprintf(&dn, "/dev/disk/by-label/%s", t);
free(t);
if (r < 0)
@ -221,10 +249,10 @@ static char *fstab_node_to_udev_node(char *p) {
if (startswith(p, "UUID=")) {
if (!(t = strdup(p+5)))
if (!(t = xescape(p+5, "/ ")))
return NULL;
r = asprintf(&dn, "/dev/disk/by-uuid/%s", ascii_strlower(xescape(t, "/ ")));
r = asprintf(&dn, "/dev/disk/by-uuid/%s", ascii_strlower(t));
free(t);
if (r < 0)
@ -267,7 +295,7 @@ static int mount_load_etc_fstab(Manager *m) {
if (where[0] == '/')
path_kill_slashes(where);
r = mount_add_one(m, what, where);
r = mount_add_one(m, what, where, false);
free(what);
free(where);
@ -282,7 +310,7 @@ finish:
return r;
}
static int mount_load_proc_mounts(Manager *m) {
static int mount_load_proc_self_mountinfo(Manager *m) {
FILE *f;
int r;
@ -338,7 +366,7 @@ static int mount_load_proc_mounts(Manager *m) {
}
free(path);
r = mount_add_one(m, d, p);
r = mount_add_one(m, d, p, true);
free(d);
free(p);
@ -361,7 +389,7 @@ static int mount_enumerate(Manager *m) {
if ((r = mount_load_etc_fstab(m)) < 0)
goto fail;
if ((r = mount_load_proc_mounts(m)) < 0)
if ((r = mount_load_proc_self_mountinfo(m)) < 0)
goto fail;
return 0;
@ -371,28 +399,17 @@ fail:
return r;
}
static UnitActiveState mount_active_state(Unit *u) {
static const UnitActiveState table[_MOUNT_STATE_MAX] = {
[MOUNT_DEAD] = UNIT_INACTIVE,
[MOUNT_MOUNTING] = UNIT_ACTIVATING,
[MOUNT_MOUNTED] = UNIT_ACTIVE,
[MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
[MOUNT_MAINTAINANCE] = UNIT_INACTIVE,
};
return table[MOUNT(u)->state];
}
const UnitVTable mount_vtable = {
.suffix = ".mount",
.init = mount_init,
.init = unit_load_fragment_and_dropin,
.done = mount_done,
.coldplug = mount_coldplug,
.dump = mount_dump,
.enumerate = mount_enumerate,
.shutdown = mount_shutdown,
.active_state = mount_active_state,
.active_state = mount_active_state
.enumerate = mount_enumerate,
.shutdown = mount_shutdown
};

View File

@ -22,6 +22,9 @@ struct Mount {
MountState state;
char *what, *where;
bool from_etc_fstab:1;
bool from_proc_self_mountinfo:1;
};
extern const UnitVTable mount_vtable;

15
unit.c
View File

@ -170,6 +170,19 @@ int unit_choose_id(Unit *u, const char *name) {
return 0;
}
int unit_set_description(Unit *u, const char *description) {
char *s;
assert(u);
if (!(s = strdup(description)))
return -ENOMEM;
free(u->meta.description);
u->meta.description = s;
return 0;
}
void unit_add_to_load_queue(Unit *u) {
assert(u);
@ -586,7 +599,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
else {
assert(u->meta.job->state == JOB_RUNNING);
/* Let's check of this state change
/* Let's check whether this state change
* constitutes a finished job, or maybe
* cotradicts a running job and hence needs to
* invalidate jobs. */

9
unit.h
View File

@ -144,6 +144,7 @@ struct UnitVTable {
int (*init)(Unit *u);
void (*done)(Unit *u);
int (*coldplug)(Unit *u);
void (*dump)(Unit *u, FILE *f, const char *prefix);
@ -161,7 +162,14 @@ struct UnitVTable {
void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
/* This is called for each unit type and should be used to
* enumerate existing devices and load them. However,
* everything that is loaded here should still stay in
* inactive state. It is the job of the coldplug() call above
* to put the units into the initial state. */
int (*enumerate)(Manager *m);
/* Type specific cleanups. */
void (*shutdown)(Manager *m);
};
@ -202,6 +210,7 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other);
int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name);
int unit_choose_id(Unit *u, const char *name);
int unit_set_description(Unit *u, const char *description);
void unit_add_to_load_queue(Unit *u);