mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2024-11-28 22:57:37 +00:00
core/systemd to 221-1
This commit is contained in:
parent
70e64d53ae
commit
79153f2d6a
15 changed files with 47 additions and 2307 deletions
|
@ -1,376 +0,0 @@
|
|||
From 6e392c9c45643d106673c6643ac8bf4e65da13c1 Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Shapovalov <intelfx100@gmail.com>
|
||||
Date: Sat, 7 Mar 2015 08:44:52 -0500
|
||||
Subject: [PATCH] core: do not spawn jobs or touch other units during
|
||||
coldplugging
|
||||
|
||||
Because the order of coldplugging is not defined, we can reference a
|
||||
not-yet-coldplugged unit and read its state while it has not yet been
|
||||
set to a meaningful value.
|
||||
|
||||
This way, already active units may get started again.
|
||||
|
||||
We fix this by deferring such actions until all units have been at
|
||||
least somehow coldplugged.
|
||||
|
||||
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=88401
|
||||
---
|
||||
src/core/automount.c | 2 +-
|
||||
src/core/busname.c | 2 +-
|
||||
src/core/device.c | 2 +-
|
||||
src/core/manager.c | 35 +++++++++++++++++++++++++++++++++--
|
||||
src/core/mount.c | 2 +-
|
||||
src/core/path.c | 14 ++++++++++----
|
||||
src/core/scope.c | 2 +-
|
||||
src/core/service.c | 2 +-
|
||||
src/core/slice.c | 2 +-
|
||||
src/core/snapshot.c | 2 +-
|
||||
src/core/socket.c | 2 +-
|
||||
src/core/swap.c | 2 +-
|
||||
src/core/target.c | 2 +-
|
||||
src/core/timer.c | 14 ++++++++++----
|
||||
src/core/unit.c | 25 ++++++++++++++++---------
|
||||
src/core/unit.h | 12 +++++++++---
|
||||
16 files changed, 89 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/src/core/automount.c b/src/core/automount.c
|
||||
index 4a509ef..0539fbb 100644
|
||||
--- a/src/core/automount.c
|
||||
+++ b/src/core/automount.c
|
||||
@@ -233,7 +233,7 @@ static void automount_set_state(Automount *a, AutomountState state) {
|
||||
unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
|
||||
}
|
||||
|
||||
-static int automount_coldplug(Unit *u) {
|
||||
+static int automount_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Automount *a = AUTOMOUNT(u);
|
||||
int r;
|
||||
|
||||
diff --git a/src/core/busname.c b/src/core/busname.c
|
||||
index 1d77292..43d7607 100644
|
||||
--- a/src/core/busname.c
|
||||
+++ b/src/core/busname.c
|
||||
@@ -335,7 +335,7 @@ static void busname_set_state(BusName *n, BusNameState state) {
|
||||
unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
|
||||
}
|
||||
|
||||
-static int busname_coldplug(Unit *u) {
|
||||
+static int busname_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
BusName *n = BUSNAME(u);
|
||||
int r;
|
||||
|
||||
diff --git a/src/core/device.c b/src/core/device.c
|
||||
index eb976b8..6b489a4 100644
|
||||
--- a/src/core/device.c
|
||||
+++ b/src/core/device.c
|
||||
@@ -140,7 +140,7 @@ static void device_set_state(Device *d, DeviceState state) {
|
||||
unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
|
||||
}
|
||||
|
||||
-static int device_coldplug(Unit *u) {
|
||||
+static int device_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Device *d = DEVICE(u);
|
||||
|
||||
assert(d);
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 7a6d519..3e87aa9 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -975,7 +975,28 @@ static int manager_coldplug(Manager *m) {
|
||||
Unit *u;
|
||||
char *k;
|
||||
|
||||
- assert(m);
|
||||
+ /*
|
||||
+ * Some unit types tend to spawn jobs or check other units' state
|
||||
+ * during coldplug. This is wrong because it is undefined whether the
|
||||
+ * units in question have been already coldplugged (i. e. their state
|
||||
+ * restored). This way, we can easily re-start an already started unit
|
||||
+ * or otherwise make a wrong decision based on the unit's state.
|
||||
+ *
|
||||
+ * Solve this by providing a way for coldplug functions to defer
|
||||
+ * such actions until after all units have been coldplugged.
|
||||
+ *
|
||||
+ * We store Unit* -> int(*)(Unit*).
|
||||
+ *
|
||||
+ * https://bugs.freedesktop.org/show_bug.cgi?id=88401
|
||||
+ */
|
||||
+ _cleanup_hashmap_free_ Hashmap *deferred_work = NULL;
|
||||
+ int(*proc)(Unit*);
|
||||
+
|
||||
+ assert(m);
|
||||
+
|
||||
+ deferred_work = hashmap_new(&trivial_hash_ops);
|
||||
+ if (!deferred_work)
|
||||
+ return -ENOMEM;
|
||||
|
||||
/* Then, let's set up their initial state. */
|
||||
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
|
||||
@@ -985,7 +1006,17 @@ static int manager_coldplug(Manager *m) {
|
||||
if (u->id != k)
|
||||
continue;
|
||||
|
||||
- q = unit_coldplug(u);
|
||||
+ q = unit_coldplug(u, deferred_work);
|
||||
+ if (q < 0)
|
||||
+ r = q;
|
||||
+ }
|
||||
+
|
||||
+ /* After coldplugging and setting up initial state of the units,
|
||||
+ * let's perform operations which spawn jobs or query units' state. */
|
||||
+ HASHMAP_FOREACH_KEY(proc, u, deferred_work, i) {
|
||||
+ int q;
|
||||
+
|
||||
+ q = proc(u);
|
||||
if (q < 0)
|
||||
r = q;
|
||||
}
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 5ee679d..1251c94 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -612,7 +612,7 @@ static void mount_set_state(Mount *m, MountState state) {
|
||||
m->reload_result = MOUNT_SUCCESS;
|
||||
}
|
||||
|
||||
-static int mount_coldplug(Unit *u) {
|
||||
+static int mount_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Mount *m = MOUNT(u);
|
||||
MountState new_state = MOUNT_DEAD;
|
||||
int r;
|
||||
diff --git a/src/core/path.c b/src/core/path.c
|
||||
index fbb695d..6be9ac8 100644
|
||||
--- a/src/core/path.c
|
||||
+++ b/src/core/path.c
|
||||
@@ -438,7 +438,12 @@ static void path_set_state(Path *p, PathState state) {
|
||||
|
||||
static void path_enter_waiting(Path *p, bool initial, bool recheck);
|
||||
|
||||
-static int path_coldplug(Unit *u) {
|
||||
+static int path_enter_waiting_coldplug(Unit *u) {
|
||||
+ path_enter_waiting(PATH(u), true, true);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int path_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Path *p = PATH(u);
|
||||
|
||||
assert(p);
|
||||
@@ -447,9 +452,10 @@ static int path_coldplug(Unit *u) {
|
||||
if (p->deserialized_state != p->state) {
|
||||
|
||||
if (p->deserialized_state == PATH_WAITING ||
|
||||
- p->deserialized_state == PATH_RUNNING)
|
||||
- path_enter_waiting(p, true, true);
|
||||
- else
|
||||
+ p->deserialized_state == PATH_RUNNING) {
|
||||
+ hashmap_put(deferred_work, u, &path_enter_waiting_coldplug);
|
||||
+ path_set_state(p, PATH_WAITING);
|
||||
+ } else
|
||||
path_set_state(p, p->deserialized_state);
|
||||
}
|
||||
|
||||
diff --git a/src/core/scope.c b/src/core/scope.c
|
||||
index 1c3c6bb..8b2bb29 100644
|
||||
--- a/src/core/scope.c
|
||||
+++ b/src/core/scope.c
|
||||
@@ -171,7 +171,7 @@ static int scope_load(Unit *u) {
|
||||
return scope_verify(s);
|
||||
}
|
||||
|
||||
-static int scope_coldplug(Unit *u) {
|
||||
+static int scope_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Scope *s = SCOPE(u);
|
||||
int r;
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index a89ff3f..cc4ea19 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -878,7 +878,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
s->reload_result = SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
-static int service_coldplug(Unit *u) {
|
||||
+static int service_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Service *s = SERVICE(u);
|
||||
int r;
|
||||
|
||||
diff --git a/src/core/slice.c b/src/core/slice.c
|
||||
index 0bebdbc..0285c49 100644
|
||||
--- a/src/core/slice.c
|
||||
+++ b/src/core/slice.c
|
||||
@@ -150,7 +150,7 @@ static int slice_load(Unit *u) {
|
||||
return slice_verify(s);
|
||||
}
|
||||
|
||||
-static int slice_coldplug(Unit *u) {
|
||||
+static int slice_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Slice *t = SLICE(u);
|
||||
|
||||
assert(t);
|
||||
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
|
||||
index b70c3be..b1d8448 100644
|
||||
--- a/src/core/snapshot.c
|
||||
+++ b/src/core/snapshot.c
|
||||
@@ -75,7 +75,7 @@ static int snapshot_load(Unit *u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int snapshot_coldplug(Unit *u) {
|
||||
+static int snapshot_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Snapshot *s = SNAPSHOT(u);
|
||||
|
||||
assert(s);
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index 9606ac2..f67370b 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -1322,7 +1322,7 @@ static void socket_set_state(Socket *s, SocketState state) {
|
||||
unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
|
||||
}
|
||||
|
||||
-static int socket_coldplug(Unit *u) {
|
||||
+static int socket_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Socket *s = SOCKET(u);
|
||||
int r;
|
||||
|
||||
diff --git a/src/core/swap.c b/src/core/swap.c
|
||||
index 4dd6be8..bb1398f 100644
|
||||
--- a/src/core/swap.c
|
||||
+++ b/src/core/swap.c
|
||||
@@ -506,7 +506,7 @@ static void swap_set_state(Swap *s, SwapState state) {
|
||||
job_add_to_run_queue(UNIT(other)->job);
|
||||
}
|
||||
|
||||
-static int swap_coldplug(Unit *u) {
|
||||
+static int swap_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Swap *s = SWAP(u);
|
||||
SwapState new_state = SWAP_DEAD;
|
||||
int r;
|
||||
diff --git a/src/core/target.c b/src/core/target.c
|
||||
index 8817ef2..5f64402 100644
|
||||
--- a/src/core/target.c
|
||||
+++ b/src/core/target.c
|
||||
@@ -103,7 +103,7 @@ static int target_load(Unit *u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int target_coldplug(Unit *u) {
|
||||
+static int target_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Target *t = TARGET(u);
|
||||
|
||||
assert(t);
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index 9405501..79a7540 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -267,7 +267,12 @@ static void timer_set_state(Timer *t, TimerState state) {
|
||||
|
||||
static void timer_enter_waiting(Timer *t, bool initial);
|
||||
|
||||
-static int timer_coldplug(Unit *u) {
|
||||
+static int timer_enter_waiting_coldplug(Unit *u) {
|
||||
+ timer_enter_waiting(TIMER(u), false);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int timer_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
Timer *t = TIMER(u);
|
||||
|
||||
assert(t);
|
||||
@@ -275,9 +280,10 @@ static int timer_coldplug(Unit *u) {
|
||||
|
||||
if (t->deserialized_state != t->state) {
|
||||
|
||||
- if (t->deserialized_state == TIMER_WAITING)
|
||||
- timer_enter_waiting(t, false);
|
||||
- else
|
||||
+ if (t->deserialized_state == TIMER_WAITING) {
|
||||
+ hashmap_put(deferred_work, u, &timer_enter_waiting_coldplug);
|
||||
+ timer_set_state(t, TIMER_WAITING);
|
||||
+ } else
|
||||
timer_set_state(t, t->deserialized_state);
|
||||
}
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index b639d68..ec4fa82 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -2856,27 +2856,34 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int unit_coldplug(Unit *u) {
|
||||
+static int unit_add_deserialized_job_coldplug(Unit *u) {
|
||||
+ int r;
|
||||
+
|
||||
+ r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ u->deserialized_job = _JOB_TYPE_INVALID;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int unit_coldplug(Unit *u, Hashmap *deferred_work) {
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
||||
if (UNIT_VTABLE(u)->coldplug)
|
||||
- if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0)
|
||||
+ if ((r = UNIT_VTABLE(u)->coldplug(u, deferred_work)) < 0)
|
||||
return r;
|
||||
|
||||
if (u->job) {
|
||||
r = job_coldplug(u->job);
|
||||
if (r < 0)
|
||||
return r;
|
||||
- } else if (u->deserialized_job >= 0) {
|
||||
+ } else if (u->deserialized_job >= 0)
|
||||
/* legacy */
|
||||
- r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
-
|
||||
- u->deserialized_job = _JOB_TYPE_INVALID;
|
||||
- }
|
||||
+ hashmap_put(deferred_work, u, &unit_add_deserialized_job_coldplug);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index ac5647a..11242c2 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -301,8 +301,14 @@ struct UnitVTable {
|
||||
int (*load)(Unit *u);
|
||||
|
||||
/* If a lot of units got created via enumerate(), this is
|
||||
- * where to actually set the state and call unit_notify(). */
|
||||
- int (*coldplug)(Unit *u);
|
||||
+ * where to actually set the state and call unit_notify().
|
||||
+ *
|
||||
+ * This must not reference other units (maybe implicitly through spawning
|
||||
+ * jobs), because it is possible that they are not yet coldplugged.
|
||||
+ * Such actions must be deferred until the end of coldplug bу adding
|
||||
+ * a "Unit* -> int(*)(Unit*)" entry into the hashmap.
|
||||
+ */
|
||||
+ int (*coldplug)(Unit *u, Hashmap *deferred_work);
|
||||
|
||||
void (*dump)(Unit *u, FILE *f, const char *prefix);
|
||||
|
||||
@@ -538,7 +544,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
|
||||
|
||||
int unit_add_node_link(Unit *u, const char *what, bool wants);
|
||||
|
||||
-int unit_coldplug(Unit *u);
|
||||
+int unit_coldplug(Unit *u, Hashmap *deferred_work);
|
||||
|
||||
void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0);
|
||||
|
||||
--
|
||||
2.3.2
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
From 496068a8288084ab3ecf8b179a8403ecff1a6be8 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Pitt <martin.pitt@ubuntu.com>
|
||||
Date: Fri, 13 Mar 2015 08:35:59 +0100
|
||||
Subject: [PATCH] core: don't change removed devices to state "tentative"
|
||||
|
||||
Commit 628c89c introduced the "tentative" device state, which caused
|
||||
devices to go from "plugged" to "tentative" on a remove uevent. This
|
||||
breaks the cleanup of stale mounts (see commit 3b48ce4), as that only
|
||||
applies to "dead" devices.
|
||||
|
||||
The "tentative" state only really makes sense on adding a device when
|
||||
we don't know where it was coming from (i. e. not from udev). But when
|
||||
we get a device removal from udev we definitively know that it's gone,
|
||||
so change the device state back to "dead" as before 628c89c.
|
||||
---
|
||||
src/core/device.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/device.c b/src/core/device.c
|
||||
index 4bfd71f..b5d9d82 100644
|
||||
--- a/src/core/device.c
|
||||
+++ b/src/core/device.c
|
||||
@@ -419,7 +419,7 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool
|
||||
if (now) {
|
||||
if (d->found & DEVICE_FOUND_UDEV)
|
||||
device_set_state(d, DEVICE_PLUGGED);
|
||||
- else if (d->found != DEVICE_NOT_FOUND)
|
||||
+ else if (add && d->found != DEVICE_NOT_FOUND)
|
||||
device_set_state(d, DEVICE_TENTATIVE);
|
||||
else
|
||||
device_set_state(d, DEVICE_DEAD);
|
||||
--
|
||||
2.3.5
|
||||
|
|
@ -1,910 +0,0 @@
|
|||
From 628c89cc68ab96fce2de7ebba5933725d147aecc Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 27 Feb 2015 21:55:08 +0100
|
||||
Subject: [PATCH] core: rework device state logic
|
||||
|
||||
This change introduces a new state "tentative" for device units. Device
|
||||
units are considered "plugged" when udev announced them, "dead" when
|
||||
they are not available in the kernel, and "tentative" when they are
|
||||
referenced in /proc/self/mountinfo or /proc/swaps but not (yet)
|
||||
announced via udev.
|
||||
|
||||
This should fix a race when device nodes (like loop devices) are created
|
||||
and immediately mounted. Previously, systemd might end up seeing the
|
||||
mount unit before the device, and would thus pull down the mount because
|
||||
its BindTo dependency on the device would not be fulfilled.
|
||||
---
|
||||
src/core/device.c | 368 +++++++++++++++++++++++++++++++++---------------------
|
||||
src/core/device.h | 14 ++-
|
||||
src/core/mount.c | 46 ++++---
|
||||
src/core/swap.c | 32 +++--
|
||||
src/core/swap.h | 4 +-
|
||||
src/core/unit.c | 1 -
|
||||
6 files changed, 285 insertions(+), 180 deletions(-)
|
||||
|
||||
diff --git a/src/core/device.c b/src/core/device.c
|
||||
index 2d983cc..e41ed41 100644
|
||||
--- a/src/core/device.c
|
||||
+++ b/src/core/device.c
|
||||
@@ -34,7 +34,8 @@
|
||||
|
||||
static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
|
||||
[DEVICE_DEAD] = UNIT_INACTIVE,
|
||||
- [DEVICE_PLUGGED] = UNIT_ACTIVE
|
||||
+ [DEVICE_TENTATIVE] = UNIT_ACTIVATING,
|
||||
+ [DEVICE_PLUGGED] = UNIT_ACTIVE,
|
||||
};
|
||||
|
||||
static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
|
||||
@@ -63,6 +64,41 @@ static void device_unset_sysfs(Device *d) {
|
||||
d->sysfs = NULL;
|
||||
}
|
||||
|
||||
+static int device_set_sysfs(Device *d, const char *sysfs) {
|
||||
+ Device *first;
|
||||
+ char *copy;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(d);
|
||||
+
|
||||
+ if (streq_ptr(d->sysfs, sysfs))
|
||||
+ return 0;
|
||||
+
|
||||
+ r = hashmap_ensure_allocated(&UNIT(d)->manager->devices_by_sysfs, &string_hash_ops);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ copy = strdup(sysfs);
|
||||
+ if (!copy)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ device_unset_sysfs(d);
|
||||
+
|
||||
+ first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, sysfs);
|
||||
+ LIST_PREPEND(same_sysfs, first, d);
|
||||
+
|
||||
+ r = hashmap_replace(UNIT(d)->manager->devices_by_sysfs, copy, first);
|
||||
+ if (r < 0) {
|
||||
+ LIST_REMOVE(same_sysfs, first, d);
|
||||
+ free(copy);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ d->sysfs = copy;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void device_init(Unit *u) {
|
||||
Device *d = DEVICE(u);
|
||||
|
||||
@@ -110,8 +146,13 @@ static int device_coldplug(Unit *u) {
|
||||
assert(d);
|
||||
assert(d->state == DEVICE_DEAD);
|
||||
|
||||
- if (d->sysfs)
|
||||
+ if (d->found & DEVICE_FOUND_UDEV)
|
||||
+ /* If udev says the device is around, it's around */
|
||||
device_set_state(d, DEVICE_PLUGGED);
|
||||
+ else if (d->found != DEVICE_NOT_FOUND)
|
||||
+ /* If a device is found in /proc/self/mountinfo or
|
||||
+ * /proc/swaps, it's "tentatively" around. */
|
||||
+ device_set_state(d, DEVICE_TENTATIVE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -140,49 +181,9 @@ _pure_ static const char *device_sub_state_to_string(Unit *u) {
|
||||
return device_state_to_string(DEVICE(u)->state);
|
||||
}
|
||||
|
||||
-static int device_add_escaped_name(Unit *u, const char *dn) {
|
||||
- _cleanup_free_ char *e = NULL;
|
||||
- int r;
|
||||
-
|
||||
- assert(u);
|
||||
- assert(dn);
|
||||
- assert(dn[0] == '/');
|
||||
-
|
||||
- e = unit_name_from_path(dn, ".device");
|
||||
- if (!e)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- r = unit_add_name(u, e);
|
||||
- if (r < 0 && r != -EEXIST)
|
||||
- return r;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
|
||||
- _cleanup_free_ char *e = NULL;
|
||||
- Unit *u;
|
||||
-
|
||||
- assert(m);
|
||||
- assert(dn);
|
||||
- assert(dn[0] == '/');
|
||||
- assert(_u);
|
||||
-
|
||||
- e = unit_name_from_path(dn, ".device");
|
||||
- if (!e)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- u = manager_get_unit(m, e);
|
||||
- if (u) {
|
||||
- *_u = u;
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int device_make_description(Unit *u, struct udev_device *dev, const char *path) {
|
||||
+static int device_update_description(Unit *u, struct udev_device *dev, const char *path) {
|
||||
const char *model;
|
||||
+ int r;
|
||||
|
||||
assert(u);
|
||||
assert(dev);
|
||||
@@ -207,13 +208,16 @@ static int device_make_description(Unit *u, struct udev_device *dev, const char
|
||||
|
||||
j = strjoin(model, " ", label, NULL);
|
||||
if (j)
|
||||
- return unit_set_description(u, j);
|
||||
- }
|
||||
+ r = unit_set_description(u, j);
|
||||
+ } else
|
||||
+ r = unit_set_description(u, model);
|
||||
+ } else
|
||||
+ r = unit_set_description(u, path);
|
||||
|
||||
- return unit_set_description(u, model);
|
||||
- }
|
||||
+ if (r < 0)
|
||||
+ log_unit_error_errno(u->id, r, "Failed to set device description: %m");
|
||||
|
||||
- return unit_set_description(u, path);
|
||||
+ return r;
|
||||
}
|
||||
|
||||
static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
|
||||
@@ -240,20 +244,20 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
|
||||
|
||||
n = unit_name_mangle(e, MANGLE_NOGLOB);
|
||||
if (!n)
|
||||
- return -ENOMEM;
|
||||
+ return log_oom();
|
||||
|
||||
r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true);
|
||||
if (r < 0)
|
||||
- return r;
|
||||
+ return log_unit_error_errno(u->id, r, "Failed to add wants dependency: %m");
|
||||
}
|
||||
if (!isempty(state))
|
||||
- log_unit_warning(u->id, "Property %s on %s has trailing garbage, ignoring.",
|
||||
- property, strna(udev_device_get_syspath(dev)));
|
||||
+ log_unit_warning(u->id, "Property %s on %s has trailing garbage, ignoring.", property, strna(udev_device_get_syspath(dev)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
|
||||
+static int device_setup_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
|
||||
+ _cleanup_free_ char *e = NULL;
|
||||
const char *sysfs;
|
||||
Unit *u = NULL;
|
||||
bool delete;
|
||||
@@ -267,12 +271,18 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
|
||||
if (!sysfs)
|
||||
return 0;
|
||||
|
||||
- r = device_find_escape_name(m, path, &u);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ e = unit_name_from_path(path, ".device");
|
||||
+ if (!e)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ u = manager_get_unit(m, e);
|
||||
|
||||
- if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
|
||||
+ if (u &&
|
||||
+ DEVICE(u)->sysfs &&
|
||||
+ !path_equal(DEVICE(u)->sysfs, sysfs)) {
|
||||
+ log_unit_error(u->id, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs);
|
||||
return -EEXIST;
|
||||
+ }
|
||||
|
||||
if (!u) {
|
||||
delete = true;
|
||||
@@ -281,7 +291,7 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
|
||||
if (!u)
|
||||
return log_oom();
|
||||
|
||||
- r = device_add_escaped_name(u, path);
|
||||
+ r = unit_add_name(u, e);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@@ -293,37 +303,16 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
|
||||
* actually been seen yet ->sysfs will not be
|
||||
* initialized. Hence initialize it if necessary. */
|
||||
|
||||
- if (!DEVICE(u)->sysfs) {
|
||||
- Device *first;
|
||||
-
|
||||
- DEVICE(u)->sysfs = strdup(sysfs);
|
||||
- if (!DEVICE(u)->sysfs) {
|
||||
- r = -ENOMEM;
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- r = hashmap_ensure_allocated(&m->devices_by_sysfs, &string_hash_ops);
|
||||
- if (r < 0)
|
||||
- goto fail;
|
||||
-
|
||||
- first = hashmap_get(m->devices_by_sysfs, sysfs);
|
||||
- LIST_PREPEND(same_sysfs, first, DEVICE(u));
|
||||
-
|
||||
- r = hashmap_replace(m->devices_by_sysfs, DEVICE(u)->sysfs, first);
|
||||
- if (r < 0)
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- device_make_description(u, dev, path);
|
||||
+ r = device_set_sysfs(DEVICE(u), sysfs);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
|
||||
- if (main) {
|
||||
- /* The additional systemd udev properties we only
|
||||
- * interpret for the main object */
|
||||
+ (void) device_update_description(u, dev, path);
|
||||
|
||||
- r = device_add_udev_wants(u, dev);
|
||||
- if (r < 0)
|
||||
- goto fail;
|
||||
- }
|
||||
+ /* The additional systemd udev properties we only interpret
|
||||
+ * for the main object */
|
||||
+ if (main)
|
||||
+ (void) device_add_udev_wants(u, dev);
|
||||
|
||||
/* Note that this won't dispatch the load queue, the caller
|
||||
* has to do that if needed and appropriate */
|
||||
@@ -332,7 +321,7 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
- log_warning_errno(r, "Failed to load device unit: %m");
|
||||
+ log_unit_warning_errno(u->id, r, "Failed to set up device unit: %m");
|
||||
|
||||
if (delete && u)
|
||||
unit_free(u);
|
||||
@@ -340,7 +329,7 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
-static int device_process_new_device(Manager *m, struct udev_device *dev) {
|
||||
+static int device_process_new(Manager *m, struct udev_device *dev) {
|
||||
const char *sysfs, *dn, *alias;
|
||||
struct udev_list_entry *item = NULL, *first = NULL;
|
||||
int r;
|
||||
@@ -352,14 +341,14 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
|
||||
return 0;
|
||||
|
||||
/* Add the main unit named after the sysfs path */
|
||||
- r = device_update_unit(m, dev, sysfs, true);
|
||||
+ r = device_setup_unit(m, dev, sysfs, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Add an additional unit for the device node */
|
||||
dn = udev_device_get_devnode(dev);
|
||||
if (dn)
|
||||
- device_update_unit(m, dev, dn, false);
|
||||
+ (void) device_setup_unit(m, dev, dn, false);
|
||||
|
||||
/* Add additional units for all symlinks */
|
||||
first = udev_device_get_devlinks_list_entry(dev);
|
||||
@@ -386,7 +375,7 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
|
||||
st.st_rdev != udev_device_get_devnum(dev))
|
||||
continue;
|
||||
|
||||
- device_update_unit(m, dev, p, false);
|
||||
+ (void) device_setup_unit(m, dev, p, false);
|
||||
}
|
||||
|
||||
/* Add additional units for all explicitly configured
|
||||
@@ -403,7 +392,7 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
|
||||
e[l] = 0;
|
||||
|
||||
if (path_is_absolute(e))
|
||||
- device_update_unit(m, dev, e, false);
|
||||
+ (void) device_setup_unit(m, dev, e, false);
|
||||
else
|
||||
log_warning("SYSTEMD_ALIAS for %s is not an absolute path, ignoring: %s", sysfs, e);
|
||||
}
|
||||
@@ -414,39 +403,62 @@ static int device_process_new_device(Manager *m, struct udev_device *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void device_set_path_plugged(Manager *m, struct udev_device *dev) {
|
||||
- const char *sysfs;
|
||||
+static void device_update_found_one(Device *d, bool add, DeviceFound found, bool now) {
|
||||
+ DeviceFound n;
|
||||
+
|
||||
+ assert(d);
|
||||
+
|
||||
+ n = add ? (d->found | found) : (d->found & ~found);
|
||||
+ if (n == d->found)
|
||||
+ return;
|
||||
+
|
||||
+ d->found = n;
|
||||
+
|
||||
+ if (now) {
|
||||
+ if (d->found & DEVICE_FOUND_UDEV)
|
||||
+ device_set_state(d, DEVICE_PLUGGED);
|
||||
+ else if (d->found != DEVICE_NOT_FOUND)
|
||||
+ device_set_state(d, DEVICE_TENTATIVE);
|
||||
+ else
|
||||
+ device_set_state(d, DEVICE_DEAD);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) {
|
||||
Device *d, *l;
|
||||
|
||||
assert(m);
|
||||
- assert(dev);
|
||||
+ assert(sysfs);
|
||||
|
||||
- sysfs = udev_device_get_syspath(dev);
|
||||
- if (!sysfs)
|
||||
- return;
|
||||
+ if (found == DEVICE_NOT_FOUND)
|
||||
+ return 0;
|
||||
|
||||
l = hashmap_get(m->devices_by_sysfs, sysfs);
|
||||
LIST_FOREACH(same_sysfs, d, l)
|
||||
- device_set_state(d, DEVICE_PLUGGED);
|
||||
+ device_update_found_one(d, add, found, now);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-static int device_process_removed_device(Manager *m, struct udev_device *dev) {
|
||||
- const char *sysfs;
|
||||
- Device *d;
|
||||
+static int device_update_found_by_name(Manager *m, const char *path, bool add, DeviceFound found, bool now) {
|
||||
+ _cleanup_free_ char *e = NULL;
|
||||
+ Unit *u;
|
||||
|
||||
assert(m);
|
||||
- assert(dev);
|
||||
+ assert(path);
|
||||
|
||||
- sysfs = udev_device_get_syspath(dev);
|
||||
- if (!sysfs)
|
||||
- return -ENOMEM;
|
||||
+ if (found == DEVICE_NOT_FOUND)
|
||||
+ return 0;
|
||||
|
||||
- /* Remove all units of this sysfs path */
|
||||
- while ((d = hashmap_get(m->devices_by_sysfs, sysfs))) {
|
||||
- device_unset_sysfs(d);
|
||||
- device_set_state(d, DEVICE_DEAD);
|
||||
- }
|
||||
+ e = unit_name_from_path(path, ".device");
|
||||
+ if (!e)
|
||||
+ return log_oom();
|
||||
|
||||
+ u = manager_get_unit(m, e);
|
||||
+ if (!u)
|
||||
+ return 0;
|
||||
+
|
||||
+ device_update_found_one(DEVICE(u), add, found, now);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -462,22 +474,6 @@ static bool device_is_ready(struct udev_device *dev) {
|
||||
return parse_boolean(ready) != 0;
|
||||
}
|
||||
|
||||
-static int device_process_new_path(Manager *m, const char *path) {
|
||||
- _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
|
||||
-
|
||||
- assert(m);
|
||||
- assert(path);
|
||||
-
|
||||
- dev = udev_device_new_from_syspath(m->udev, path);
|
||||
- if (!dev)
|
||||
- return log_oom();
|
||||
-
|
||||
- if (!device_is_ready(dev))
|
||||
- return 0;
|
||||
-
|
||||
- return device_process_new_device(m, dev);
|
||||
-}
|
||||
-
|
||||
static Unit *device_following(Unit *u) {
|
||||
Device *d = DEVICE(u);
|
||||
Device *other, *first = NULL;
|
||||
@@ -604,12 +600,31 @@ static int device_enumerate(Manager *m) {
|
||||
goto fail;
|
||||
|
||||
first = udev_enumerate_get_list_entry(e);
|
||||
- udev_list_entry_foreach(item, first)
|
||||
- device_process_new_path(m, udev_list_entry_get_name(item));
|
||||
+ udev_list_entry_foreach(item, first) {
|
||||
+ _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
|
||||
+ const char *sysfs;
|
||||
+
|
||||
+ sysfs = udev_list_entry_get_name(item);
|
||||
+
|
||||
+ dev = udev_device_new_from_syspath(m->udev, sysfs);
|
||||
+ if (!dev) {
|
||||
+ log_oom();
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!device_is_ready(dev))
|
||||
+ continue;
|
||||
+
|
||||
+ (void) device_process_new(m, dev);
|
||||
+
|
||||
+ device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, false);
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
+ log_error_errno(r, "Failed to enumerate devices: %m");
|
||||
+
|
||||
device_shutdown(m);
|
||||
return r;
|
||||
}
|
||||
@@ -617,7 +632,7 @@ fail:
|
||||
static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
|
||||
_cleanup_udev_device_unref_ struct udev_device *dev = NULL;
|
||||
Manager *m = userdata;
|
||||
- const char *action;
|
||||
+ const char *action, *sysfs;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@@ -639,33 +654,47 @@ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
+ sysfs = udev_device_get_syspath(dev);
|
||||
+ if (!sysfs) {
|
||||
+ log_error("Failed to get udev sys path.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
action = udev_device_get_action(dev);
|
||||
if (!action) {
|
||||
log_error("Failed to get udev action string.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (streq(action, "remove") || !device_is_ready(dev)) {
|
||||
- r = device_process_removed_device(m, dev);
|
||||
- if (r < 0)
|
||||
- log_error_errno(r, "Failed to process device remove event: %m");
|
||||
-
|
||||
- r = swap_process_removed_device(m, dev);
|
||||
+ if (streq(action, "remove")) {
|
||||
+ r = swap_process_device_remove(m, dev);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to process swap device remove event: %m");
|
||||
|
||||
- } else {
|
||||
- r = device_process_new_device(m, dev);
|
||||
- if (r < 0)
|
||||
- log_error_errno(r, "Failed to process device new event: %m");
|
||||
+ /* If we get notified that a device was removed by
|
||||
+ * udev, then it's completely gone, hence unset all
|
||||
+ * found bits */
|
||||
+ device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP, true);
|
||||
|
||||
- r = swap_process_new_device(m, dev);
|
||||
+ } else if (device_is_ready(dev)) {
|
||||
+
|
||||
+ (void) device_process_new(m, dev);
|
||||
+
|
||||
+ r = swap_process_device_new(m, dev);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to process swap device new event: %m");
|
||||
|
||||
manager_dispatch_load_queue(m);
|
||||
|
||||
- device_set_path_plugged(m, dev);
|
||||
+ /* The device is found now, set the udev found bit */
|
||||
+ device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, true);
|
||||
+
|
||||
+ } else {
|
||||
+ /* The device is nominally around, but not ready for
|
||||
+ * us. Hence unset the udev bit, but leave the rest
|
||||
+ * around. */
|
||||
+
|
||||
+ device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -684,9 +713,58 @@ static bool device_supported(Manager *m) {
|
||||
return read_only <= 0;
|
||||
}
|
||||
|
||||
+int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now) {
|
||||
+ _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
|
||||
+ struct stat st;
|
||||
+
|
||||
+ assert(m);
|
||||
+ assert(node);
|
||||
+
|
||||
+ /* This is called whenever we find a device referenced in
|
||||
+ * /proc/swaps or /proc/self/mounts. Such a device might be
|
||||
+ * mounted/enabled at a time where udev has not finished
|
||||
+ * probing it yet, and we thus haven't learned about it
|
||||
+ * yet. In this case we will set the device unit to
|
||||
+ * "tentative" state. */
|
||||
+
|
||||
+ if (add) {
|
||||
+ if (!path_startswith(node, "/dev"))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (stat(node, &st) < 0) {
|
||||
+ if (errno == ENOENT)
|
||||
+ return 0;
|
||||
+
|
||||
+ return log_error_errno(errno, "Failed to stat device node file %s: %m", node);
|
||||
+ }
|
||||
+
|
||||
+ if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
|
||||
+ return 0;
|
||||
+
|
||||
+ dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
|
||||
+ if (!dev) {
|
||||
+ if (errno == ENOENT)
|
||||
+ return 0;
|
||||
+
|
||||
+ return log_oom();
|
||||
+ }
|
||||
+
|
||||
+ /* If the device is known in the kernel and newly
|
||||
+ * appeared, then we'll create a device unit for it,
|
||||
+ * under the name referenced in /proc/swaps or
|
||||
+ * /proc/self/mountinfo. */
|
||||
+
|
||||
+ (void) device_setup_unit(m, dev, node, false);
|
||||
+ }
|
||||
+
|
||||
+ /* Update the device unit's state, should it exist */
|
||||
+ return device_update_found_by_name(m, node, add, found, now);
|
||||
+}
|
||||
+
|
||||
static const char* const device_state_table[_DEVICE_STATE_MAX] = {
|
||||
[DEVICE_DEAD] = "dead",
|
||||
- [DEVICE_PLUGGED] = "plugged"
|
||||
+ [DEVICE_TENTATIVE] = "tentative",
|
||||
+ [DEVICE_PLUGGED] = "plugged",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
|
||||
diff --git a/src/core/device.h b/src/core/device.h
|
||||
index 9065085..9f46e08 100644
|
||||
--- a/src/core/device.h
|
||||
+++ b/src/core/device.h
|
||||
@@ -28,20 +28,28 @@ typedef struct Device Device;
|
||||
* simplifies the state engine greatly */
|
||||
typedef enum DeviceState {
|
||||
DEVICE_DEAD,
|
||||
- DEVICE_PLUGGED,
|
||||
+ DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */
|
||||
+ DEVICE_PLUGGED, /* announced by udev */
|
||||
_DEVICE_STATE_MAX,
|
||||
_DEVICE_STATE_INVALID = -1
|
||||
} DeviceState;
|
||||
|
||||
+typedef enum DeviceFound {
|
||||
+ DEVICE_NOT_FOUND = 0,
|
||||
+ DEVICE_FOUND_UDEV = 1,
|
||||
+ DEVICE_FOUND_MOUNT = 2,
|
||||
+ DEVICE_FOUND_SWAP = 4,
|
||||
+} DeviceFound;
|
||||
+
|
||||
struct Device {
|
||||
Unit meta;
|
||||
|
||||
char *sysfs;
|
||||
+ DeviceFound found;
|
||||
|
||||
/* In order to be able to distinguish dependencies on
|
||||
different device nodes we might end up creating multiple
|
||||
devices for the same sysfs path. We chain them up here. */
|
||||
-
|
||||
LIST_FIELDS(struct Device, same_sysfs);
|
||||
|
||||
DeviceState state;
|
||||
@@ -51,3 +59,5 @@ extern const UnitVTable device_vtable;
|
||||
|
||||
const char* device_state_to_string(DeviceState i) _const_;
|
||||
DeviceState device_state_from_string(const char *s) _pure_;
|
||||
+
|
||||
+int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now);
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 40037e7..8e4a376 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -1386,7 +1386,7 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int mount_add_one(
|
||||
+static int mount_setup_unit(
|
||||
Manager *m,
|
||||
const char *what,
|
||||
const char *where,
|
||||
@@ -1429,7 +1429,7 @@ static int mount_add_one(
|
||||
|
||||
u = unit_new(m, sizeof(Mount));
|
||||
if (!u)
|
||||
- return -ENOMEM;
|
||||
+ return log_oom();
|
||||
|
||||
r = unit_add_name(u, e);
|
||||
if (r < 0)
|
||||
@@ -1542,6 +1542,8 @@ static int mount_add_one(
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
+ log_warning_errno(r, "Failed to set up mount unit: %m");
|
||||
+
|
||||
if (delete && u)
|
||||
unit_free(u);
|
||||
|
||||
@@ -1549,33 +1551,36 @@ fail:
|
||||
}
|
||||
|
||||
static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
|
||||
- _cleanup_(mnt_free_tablep) struct libmnt_table *tb = NULL;
|
||||
- _cleanup_(mnt_free_iterp) struct libmnt_iter *itr = NULL;
|
||||
- struct libmnt_fs *fs;
|
||||
+ _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
|
||||
+ _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
|
||||
int r = 0;
|
||||
|
||||
assert(m);
|
||||
|
||||
- tb = mnt_new_table();
|
||||
- itr = mnt_new_iter(MNT_ITER_FORWARD);
|
||||
- if (!tb || !itr)
|
||||
+ t = mnt_new_table();
|
||||
+ if (!t)
|
||||
return log_oom();
|
||||
|
||||
- r = mnt_table_parse_mtab(tb, NULL);
|
||||
+ i = mnt_new_iter(MNT_ITER_FORWARD);
|
||||
+ if (!i)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ r = mnt_table_parse_mtab(t, NULL);
|
||||
if (r < 0)
|
||||
- return r;
|
||||
+ return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
|
||||
|
||||
r = 0;
|
||||
for (;;) {
|
||||
const char *device, *path, *options, *fstype;
|
||||
_cleanup_free_ const char *d = NULL, *p = NULL;
|
||||
+ struct libmnt_fs *fs;
|
||||
int k;
|
||||
|
||||
- k = mnt_table_next_fs(tb, itr, &fs);
|
||||
+ k = mnt_table_next_fs(t, i, &fs);
|
||||
if (k == 1)
|
||||
break;
|
||||
- else if (k < 0)
|
||||
- return log_error_errno(k, "Failed to get next entry from /etc/fstab: %m");
|
||||
+ if (k < 0)
|
||||
+ return log_error_errno(k, "Failed to get next entry from /proc/self/mountinfo: %m");
|
||||
|
||||
device = mnt_fs_get_source(fs);
|
||||
path = mnt_fs_get_target(fs);
|
||||
@@ -1583,11 +1588,16 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
|
||||
fstype = mnt_fs_get_fstype(fs);
|
||||
|
||||
d = cunescape(device);
|
||||
+ if (!d)
|
||||
+ return log_oom();
|
||||
+
|
||||
p = cunescape(path);
|
||||
- if (!d || !p)
|
||||
+ if (!p)
|
||||
return log_oom();
|
||||
|
||||
- k = mount_add_one(m, d, p, options, fstype, set_flags);
|
||||
+ (void) device_found_node(m, d, true, DEVICE_FOUND_MOUNT, set_flags);
|
||||
+
|
||||
+ k = mount_setup_unit(m, d, p, options, fstype, set_flags);
|
||||
if (r == 0 && k < 0)
|
||||
r = k;
|
||||
}
|
||||
@@ -1731,8 +1741,6 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
|
||||
|
||||
r = mount_load_proc_self_mountinfo(m, true);
|
||||
if (r < 0) {
|
||||
- log_error_errno(r, "Failed to reread /proc/self/mountinfo: %m");
|
||||
-
|
||||
/* Reset flags, just in case, for later calls */
|
||||
LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
|
||||
Mount *mount = MOUNT(u);
|
||||
@@ -1765,6 +1773,10 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (mount->parameters_proc_self_mountinfo.what)
|
||||
+ (void) device_found_node(m, mount->parameters_proc_self_mountinfo.what, false, DEVICE_FOUND_MOUNT, true);
|
||||
+
|
||||
+
|
||||
} else if (mount->just_mounted || mount->just_changed) {
|
||||
|
||||
/* New or changed mount entry */
|
||||
diff --git a/src/core/swap.c b/src/core/swap.c
|
||||
index f73a8e6..de3a5d8 100644
|
||||
--- a/src/core/swap.c
|
||||
+++ b/src/core/swap.c
|
||||
@@ -331,7 +331,7 @@ static int swap_load(Unit *u) {
|
||||
return swap_verify(s);
|
||||
}
|
||||
|
||||
-static int swap_add_one(
|
||||
+static int swap_setup_unit(
|
||||
Manager *m,
|
||||
const char *what,
|
||||
const char *what_proc_swaps,
|
||||
@@ -356,8 +356,10 @@ static int swap_add_one(
|
||||
|
||||
if (u &&
|
||||
SWAP(u)->from_proc_swaps &&
|
||||
- !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
|
||||
+ !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps)) {
|
||||
+ log_error("Swap %s appeared twice with different device paths %s and %s", e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
|
||||
return -EEXIST;
|
||||
+ }
|
||||
|
||||
if (!u) {
|
||||
delete = true;
|
||||
@@ -372,7 +374,7 @@ static int swap_add_one(
|
||||
|
||||
SWAP(u)->what = strdup(what);
|
||||
if (!SWAP(u)->what) {
|
||||
- r = log_oom();
|
||||
+ r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -400,7 +402,6 @@ static int swap_add_one(
|
||||
p->priority = priority;
|
||||
|
||||
unit_add_to_dbus_queue(u);
|
||||
-
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -412,7 +413,7 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
-static int swap_process_new_swap(Manager *m, const char *device, int prio, bool set_flags) {
|
||||
+static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
|
||||
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
|
||||
struct udev_list_entry *item = NULL, *first = NULL;
|
||||
const char *dn;
|
||||
@@ -421,7 +422,7 @@ static int swap_process_new_swap(Manager *m, const char *device, int prio, bool
|
||||
|
||||
assert(m);
|
||||
|
||||
- r = swap_add_one(m, device, device, prio, set_flags);
|
||||
+ r = swap_setup_unit(m, device, device, prio, set_flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -437,7 +438,7 @@ static int swap_process_new_swap(Manager *m, const char *device, int prio, bool
|
||||
/* Add the main device node */
|
||||
dn = udev_device_get_devnode(d);
|
||||
if (dn && !streq(dn, device))
|
||||
- swap_add_one(m, dn, device, prio, set_flags);
|
||||
+ swap_setup_unit(m, dn, device, prio, set_flags);
|
||||
|
||||
/* Add additional units for all symlinks */
|
||||
first = udev_device_get_devlinks_list_entry(d);
|
||||
@@ -458,7 +459,7 @@ static int swap_process_new_swap(Manager *m, const char *device, int prio, bool
|
||||
st.st_rdev != udev_device_get_devnum(d))
|
||||
continue;
|
||||
|
||||
- swap_add_one(m, p, device, prio, set_flags);
|
||||
+ swap_setup_unit(m, p, device, prio, set_flags);
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -1084,15 +1085,17 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
|
||||
if (k == EOF)
|
||||
break;
|
||||
|
||||
- log_warning("Failed to parse /proc/swaps:%u", i);
|
||||
+ log_warning("Failed to parse /proc/swaps:%u.", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
d = cunescape(dev);
|
||||
if (!d)
|
||||
- return -ENOMEM;
|
||||
+ return log_oom();
|
||||
+
|
||||
+ device_found_node(m, d, true, DEVICE_FOUND_SWAP, set_flags);
|
||||
|
||||
- k = swap_process_new_swap(m, d, prio, set_flags);
|
||||
+ k = swap_process_new(m, d, prio, set_flags);
|
||||
if (k < 0)
|
||||
r = k;
|
||||
}
|
||||
@@ -1144,6 +1147,9 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (swap->what)
|
||||
+ device_found_node(m, swap->what, false, DEVICE_FOUND_SWAP, true);
|
||||
+
|
||||
} else if (swap->just_activated) {
|
||||
|
||||
/* New swap entry */
|
||||
@@ -1291,7 +1297,7 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
-int swap_process_new_device(Manager *m, struct udev_device *dev) {
|
||||
+int swap_process_device_new(Manager *m, struct udev_device *dev) {
|
||||
struct udev_list_entry *item = NULL, *first = NULL;
|
||||
_cleanup_free_ char *e = NULL;
|
||||
const char *dn;
|
||||
@@ -1334,7 +1340,7 @@ int swap_process_new_device(Manager *m, struct udev_device *dev) {
|
||||
return r;
|
||||
}
|
||||
|
||||
-int swap_process_removed_device(Manager *m, struct udev_device *dev) {
|
||||
+int swap_process_device_remove(Manager *m, struct udev_device *dev) {
|
||||
const char *dn;
|
||||
int r = 0;
|
||||
Swap *s;
|
||||
diff --git a/src/core/swap.h b/src/core/swap.h
|
||||
index c36c6f2..5de8c20 100644
|
||||
--- a/src/core/swap.h
|
||||
+++ b/src/core/swap.h
|
||||
@@ -115,8 +115,8 @@ struct Swap {
|
||||
|
||||
extern const UnitVTable swap_vtable;
|
||||
|
||||
-int swap_process_new_device(Manager *m, struct udev_device *dev);
|
||||
-int swap_process_removed_device(Manager *m, struct udev_device *dev);
|
||||
+int swap_process_device_new(Manager *m, struct udev_device *dev);
|
||||
+int swap_process_device_remove(Manager *m, struct udev_device *dev);
|
||||
|
||||
const char* swap_state_to_string(SwapState i) _const_;
|
||||
SwapState swap_state_from_string(const char *s) _pure_;
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 63ccd67..7cd7043 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -2834,7 +2834,6 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
|
||||
return -ENOMEM;
|
||||
|
||||
r = manager_load_unit(u->manager, e, NULL, NULL, &device);
|
||||
-
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
--
|
||||
2.3.5
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
From c78e47a61fa8d9a21fece01c83e4c26ce0938d27 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Schmidt <mschmidt@redhat.com>
|
||||
Date: Thu, 19 Feb 2015 23:12:38 +0100
|
||||
Subject: [PATCH] core, shared: in deserializing, match same files reached via
|
||||
different paths
|
||||
|
||||
When dbus.socket is updated like this:
|
||||
-ListenStream=/var/run/dbus/system_bus_socket
|
||||
+ListenStream=/run/dbus/system_bus_socket
|
||||
... and daemon-reload is performed, bad things happen.
|
||||
During deserialization systemd does not recognize that the two paths
|
||||
refer to the same named socket and replaces the socket file with a new
|
||||
one. As a result, applications hang when they try talking to dbus.
|
||||
|
||||
Fix this by finding a match not only when the path names are equal, but
|
||||
also when they point to the same inode.
|
||||
In socket_address_equal() it is necessary to move the address size
|
||||
comparison into the abstract sockets branch. For path name sockets the
|
||||
comparison must not be done and for other families it is redundant
|
||||
(their sizes are constant and checked by socket_address_verify()).
|
||||
|
||||
FIFOs and special files can also have multiple pathnames, so compare the
|
||||
inodes for them as well. Note that previously the pathname checks used
|
||||
streq_ptr(), but the paths cannot be NULL.
|
||||
|
||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1186018
|
||||
---
|
||||
src/core/socket.c | 6 +++---
|
||||
src/shared/path-util.c | 4 ++++
|
||||
src/shared/path-util.h | 1 +
|
||||
src/shared/socket-util.c | 10 ++++------
|
||||
4 files changed, 12 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index 48c43a2..88aae48 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -2100,7 +2100,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
|
||||
|
||||
LIST_FOREACH(port, p, s->ports)
|
||||
if (p->type == SOCKET_FIFO &&
|
||||
- streq_ptr(p->path, value+skip))
|
||||
+ path_equal_or_files_same(p->path, value+skip))
|
||||
break;
|
||||
|
||||
if (p) {
|
||||
@@ -2119,7 +2119,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
|
||||
|
||||
LIST_FOREACH(port, p, s->ports)
|
||||
if (p->type == SOCKET_SPECIAL &&
|
||||
- streq_ptr(p->path, value+skip))
|
||||
+ path_equal_or_files_same(p->path, value+skip))
|
||||
break;
|
||||
|
||||
if (p) {
|
||||
@@ -2138,7 +2138,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
|
||||
|
||||
LIST_FOREACH(port, p, s->ports)
|
||||
if (p->type == SOCKET_MQUEUE &&
|
||||
- streq_ptr(p->path, value+skip))
|
||||
+ streq(p->path, value+skip))
|
||||
break;
|
||||
|
||||
if (p) {
|
||||
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
|
||||
index b9db7f1..70bc1ca 100644
|
||||
--- a/src/shared/path-util.c
|
||||
+++ b/src/shared/path-util.c
|
||||
@@ -436,6 +436,10 @@ bool path_equal(const char *a, const char *b) {
|
||||
}
|
||||
}
|
||||
|
||||
+bool path_equal_or_files_same(const char *a, const char *b) {
|
||||
+ return path_equal(a, b) || files_same(a, b) > 0;
|
||||
+}
|
||||
+
|
||||
char* path_join(const char *root, const char *path, const char *rest) {
|
||||
assert(path);
|
||||
|
||||
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
|
||||
index bd0d324..bcf116e 100644
|
||||
--- a/src/shared/path-util.h
|
||||
+++ b/src/shared/path-util.h
|
||||
@@ -45,6 +45,7 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r);
|
||||
char* path_kill_slashes(char *path);
|
||||
char* path_startswith(const char *path, const char *prefix) _pure_;
|
||||
bool path_equal(const char *a, const char *b) _pure_;
|
||||
+bool path_equal_or_files_same(const char *a, const char *b);
|
||||
char* path_join(const char *root, const char *path, const char *rest);
|
||||
|
||||
char** path_strv_make_absolute_cwd(char **l);
|
||||
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
|
||||
index c6f6487..c278d6f 100644
|
||||
--- a/src/shared/socket-util.c
|
||||
+++ b/src/shared/socket-util.c
|
||||
@@ -325,9 +325,6 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
|
||||
if (a->type != b->type)
|
||||
return false;
|
||||
|
||||
- if (a->size != b->size)
|
||||
- return false;
|
||||
-
|
||||
if (socket_address_family(a) != socket_address_family(b))
|
||||
return false;
|
||||
|
||||
@@ -352,14 +349,16 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
|
||||
break;
|
||||
|
||||
case AF_UNIX:
|
||||
-
|
||||
if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
|
||||
return false;
|
||||
|
||||
if (a->sockaddr.un.sun_path[0]) {
|
||||
- if (!strneq(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, sizeof(a->sockaddr.un.sun_path)))
|
||||
+ if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path))
|
||||
return false;
|
||||
} else {
|
||||
+ if (a->size != b->size)
|
||||
+ return false;
|
||||
+
|
||||
if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
|
||||
return false;
|
||||
}
|
||||
@@ -367,7 +366,6 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
|
||||
break;
|
||||
|
||||
case AF_NETLINK:
|
||||
-
|
||||
if (a->protocol != b->protocol)
|
||||
return false;
|
||||
|
||||
--
|
||||
2.3.2
|
||||
|
|
@ -1,293 +0,0 @@
|
|||
From 9c857b9d160c10b4454fc9f83442c1878343422f Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 18 Feb 2015 23:32:55 +0100
|
||||
Subject: [PATCH] nspawn: when connected to pipes for stdin/stdout, pass them
|
||||
as-is to PID 1
|
||||
|
||||
Previously we always invoked the container PID 1 on /dev/console of the
|
||||
container. With this change we do so only if nspawn was invoked
|
||||
interactively (i.e. its stdin/stdout was connected to a TTY). In all other
|
||||
cases we directly pass through the fds unmodified.
|
||||
|
||||
This has the benefit that nspawn can be added into shell pipelines.
|
||||
|
||||
https://bugs.freedesktop.org/show_bug.cgi?id=87732
|
||||
---
|
||||
src/machine/machinectl.c | 2 +-
|
||||
src/nspawn/nspawn.c | 48 +++++++++++++++++--------------
|
||||
src/run/run.c | 2 +-
|
||||
src/shared/ptyfwd.c | 75 ++++++++++++++++++++++++++++--------------------
|
||||
src/shared/ptyfwd.h | 2 +-
|
||||
5 files changed, 74 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
|
||||
index 053c8fb..55cd854 100644
|
||||
--- a/src/machine/machinectl.c
|
||||
+++ b/src/machine/machinectl.c
|
||||
@@ -1150,7 +1150,7 @@ static int login_machine(int argc, char *argv[], void *userdata) {
|
||||
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
|
||||
sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
|
||||
|
||||
- r = pty_forward_new(event, master, true, &forward);
|
||||
+ r = pty_forward_new(event, master, true, false, &forward);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create PTY forwarder: %m");
|
||||
|
||||
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
|
||||
index 232629d..c84ed11 100644
|
||||
--- a/src/nspawn/nspawn.c
|
||||
+++ b/src/nspawn/nspawn.c
|
||||
@@ -3606,6 +3606,7 @@ int main(int argc, char *argv[]) {
|
||||
int ret = EXIT_SUCCESS;
|
||||
union in_addr_union exposed = {};
|
||||
_cleanup_release_lock_file_ LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT;
|
||||
+ bool interactive;
|
||||
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
@@ -3779,6 +3780,8 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
+ interactive = isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0;
|
||||
+
|
||||
master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
|
||||
if (master < 0) {
|
||||
r = log_error_errno(errno, "Failed to acquire pseudo tty: %m");
|
||||
@@ -3791,15 +3794,15 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
- if (!arg_quiet)
|
||||
- log_info("Spawning container %s on %s.\nPress ^] three times within 1s to kill container.",
|
||||
- arg_machine, arg_image ?: arg_directory);
|
||||
-
|
||||
if (unlockpt(master) < 0) {
|
||||
r = log_error_errno(errno, "Failed to unlock tty: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
+ if (!arg_quiet)
|
||||
+ log_info("Spawning container %s on %s.\nPress ^] three times within 1s to kill container.",
|
||||
+ arg_machine, arg_image ?: arg_directory);
|
||||
+
|
||||
assert_se(sigemptyset(&mask) == 0);
|
||||
sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
|
||||
assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
|
||||
@@ -3885,9 +3888,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
master = safe_close(master);
|
||||
|
||||
- close_nointr(STDIN_FILENO);
|
||||
- close_nointr(STDOUT_FILENO);
|
||||
- close_nointr(STDERR_FILENO);
|
||||
|
||||
kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]);
|
||||
rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
|
||||
@@ -3895,21 +3895,27 @@ int main(int argc, char *argv[]) {
|
||||
reset_all_signal_handlers();
|
||||
reset_signal_mask();
|
||||
|
||||
- r = open_terminal(console, O_RDWR);
|
||||
- if (r != STDIN_FILENO) {
|
||||
- if (r >= 0) {
|
||||
- safe_close(r);
|
||||
- r = -EINVAL;
|
||||
- }
|
||||
+ if (interactive) {
|
||||
+ close_nointr(STDIN_FILENO);
|
||||
+ close_nointr(STDOUT_FILENO);
|
||||
+ close_nointr(STDERR_FILENO);
|
||||
|
||||
- log_error_errno(r, "Failed to open console: %m");
|
||||
- _exit(EXIT_FAILURE);
|
||||
- }
|
||||
+ r = open_terminal(console, O_RDWR);
|
||||
+ if (r != STDIN_FILENO) {
|
||||
+ if (r >= 0) {
|
||||
+ safe_close(r);
|
||||
+ r = -EINVAL;
|
||||
+ }
|
||||
|
||||
- if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
|
||||
- dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) {
|
||||
- log_error_errno(errno, "Failed to duplicate console: %m");
|
||||
- _exit(EXIT_FAILURE);
|
||||
+ log_error_errno(r, "Failed to open console: %m");
|
||||
+ _exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
|
||||
+ dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) {
|
||||
+ log_error_errno(errno, "Failed to duplicate console: %m");
|
||||
+ _exit(EXIT_FAILURE);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
@@ -4252,7 +4258,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
|
||||
|
||||
- r = pty_forward_new(event, master, true, &forward);
|
||||
+ r = pty_forward_new(event, master, true, !interactive, &forward);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to create PTY forwarder: %m");
|
||||
goto finish;
|
||||
diff --git a/src/run/run.c b/src/run/run.c
|
||||
index 32191a6..3ded2c7 100644
|
||||
--- a/src/run/run.c
|
||||
+++ b/src/run/run.c
|
||||
@@ -776,7 +776,7 @@ static int start_transient_service(
|
||||
if (!arg_quiet)
|
||||
log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
|
||||
|
||||
- r = pty_forward_new(event, master, false, &forward);
|
||||
+ r = pty_forward_new(event, master, false, false, &forward);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create PTY forwarder: %m");
|
||||
|
||||
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
|
||||
index 31274a1..164c9b6 100644
|
||||
--- a/src/shared/ptyfwd.c
|
||||
+++ b/src/shared/ptyfwd.c
|
||||
@@ -42,6 +42,8 @@ struct PTYForward {
|
||||
struct termios saved_stdin_attr;
|
||||
struct termios saved_stdout_attr;
|
||||
|
||||
+ bool read_only:1;
|
||||
+
|
||||
bool saved_stdin:1;
|
||||
bool saved_stdout:1;
|
||||
|
||||
@@ -298,7 +300,13 @@ static int on_sigwinch_event(sd_event_source *e, const struct signalfd_siginfo *
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward **ret) {
|
||||
+int pty_forward_new(
|
||||
+ sd_event *event,
|
||||
+ int master,
|
||||
+ bool ignore_vhangup,
|
||||
+ bool read_only,
|
||||
+ PTYForward **ret) {
|
||||
+
|
||||
_cleanup_(pty_forward_freep) PTYForward *f = NULL;
|
||||
struct winsize ws;
|
||||
int r;
|
||||
@@ -307,6 +315,7 @@ int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
+ f->read_only = read_only;
|
||||
f->ignore_vhangup = ignore_vhangup;
|
||||
|
||||
if (event)
|
||||
@@ -317,13 +326,15 @@ int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward
|
||||
return r;
|
||||
}
|
||||
|
||||
- r = fd_nonblock(STDIN_FILENO, true);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ if (!read_only) {
|
||||
+ r = fd_nonblock(STDIN_FILENO, true);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
|
||||
- r = fd_nonblock(STDOUT_FILENO, true);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ r = fd_nonblock(STDOUT_FILENO, true);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
|
||||
r = fd_nonblock(master, true);
|
||||
if (r < 0)
|
||||
@@ -334,36 +345,34 @@ int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
|
||||
(void)ioctl(master, TIOCSWINSZ, &ws);
|
||||
|
||||
- if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) {
|
||||
- struct termios raw_stdin_attr;
|
||||
-
|
||||
- f->saved_stdin = true;
|
||||
+ if (!read_only) {
|
||||
+ if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) {
|
||||
+ struct termios raw_stdin_attr;
|
||||
|
||||
- raw_stdin_attr = f->saved_stdin_attr;
|
||||
- cfmakeraw(&raw_stdin_attr);
|
||||
- raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag;
|
||||
- tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr);
|
||||
- }
|
||||
+ f->saved_stdin = true;
|
||||
|
||||
- if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) {
|
||||
- struct termios raw_stdout_attr;
|
||||
+ raw_stdin_attr = f->saved_stdin_attr;
|
||||
+ cfmakeraw(&raw_stdin_attr);
|
||||
+ raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag;
|
||||
+ tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr);
|
||||
+ }
|
||||
|
||||
- f->saved_stdout = true;
|
||||
+ if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) {
|
||||
+ struct termios raw_stdout_attr;
|
||||
|
||||
- raw_stdout_attr = f->saved_stdout_attr;
|
||||
- cfmakeraw(&raw_stdout_attr);
|
||||
- raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag;
|
||||
- raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag;
|
||||
- tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr);
|
||||
- }
|
||||
+ f->saved_stdout = true;
|
||||
|
||||
- r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ raw_stdout_attr = f->saved_stdout_attr;
|
||||
+ cfmakeraw(&raw_stdout_attr);
|
||||
+ raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag;
|
||||
+ raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag;
|
||||
+ tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr);
|
||||
+ }
|
||||
|
||||
- r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f);
|
||||
- if (r < 0 && r != -EPERM)
|
||||
- return r;
|
||||
+ r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f);
|
||||
+ if (r < 0 && r != -EPERM)
|
||||
+ return r;
|
||||
+ }
|
||||
|
||||
r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f);
|
||||
if (r == -EPERM)
|
||||
@@ -372,6 +381,10 @@ int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward
|
||||
else if (r < 0)
|
||||
return r;
|
||||
|
||||
+ r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h
|
||||
index d3e229b..6208a54 100644
|
||||
--- a/src/shared/ptyfwd.h
|
||||
+++ b/src/shared/ptyfwd.h
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
typedef struct PTYForward PTYForward;
|
||||
|
||||
-int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, PTYForward **f);
|
||||
+int pty_forward_new(sd_event *event, int master, bool ignore_vhangup, bool read_only, PTYForward **f);
|
||||
PTYForward *pty_forward_free(PTYForward *f);
|
||||
|
||||
int pty_forward_get_last_char(PTYForward *f, char *ch);
|
||||
--
|
||||
2.3.2
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
From 6487ada88d63e4998113f4c57fa10b7c865f8026 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Pitt <martin.pitt@ubuntu.com>
|
||||
Date: Thu, 5 Mar 2015 14:58:56 +0100
|
||||
Subject: [PATCH] tmpfiles: Fix handling of duplicate lines
|
||||
|
||||
Commit 3f93da987 accidentally dropped the "return 0" after detection of a
|
||||
duplicate line. Put it back, to get back the documented and intended "first
|
||||
match wins" behaviour.
|
||||
|
||||
https://launchpad.net/bugs/1428540
|
||||
---
|
||||
src/tmpfiles/tmpfiles.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
|
||||
index 917bb3c..652fe5f 100644
|
||||
--- a/src/tmpfiles/tmpfiles.c
|
||||
+++ b/src/tmpfiles/tmpfiles.c
|
||||
@@ -1746,9 +1746,11 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
|
||||
unsigned n;
|
||||
|
||||
for (n = 0; n < existing->count; n++) {
|
||||
- if (!item_compatible(existing->items + n, &i))
|
||||
+ if (!item_compatible(existing->items + n, &i)) {
|
||||
log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
|
||||
fname, line, i.path);
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
} else {
|
||||
existing = new0(ItemArray, 1);
|
||||
--
|
||||
2.3.2
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
From 1c73f3bc29111a00738569c9d40a989b161a0624 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Mon, 23 Feb 2015 23:19:54 -0500
|
||||
Subject: [PATCH] tmpfiles: avoid creating duplicate acl entries
|
||||
|
||||
https://bugs.freedesktop.org/show_bug.cgi?id=89202
|
||||
https://bugs.debian.org/778656
|
||||
|
||||
Status quo ante can be restored with:
|
||||
getfacl -p /var/log/journal/`cat /etc/machine-id`|grep -v '^#'|sort -u|sudo setfacl --set-file=- /var/log/journal/`cat /etc/machine-id`
|
||||
---
|
||||
src/shared/acl-util.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
src/shared/acl-util.h | 4 +++
|
||||
2 files changed, 81 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
|
||||
index 34707e6..36dc824 100644
|
||||
--- a/src/shared/acl-util.c
|
||||
+++ b/src/shared/acl-util.c
|
||||
@@ -281,6 +281,77 @@ int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int acl_entry_equal(acl_entry_t a, acl_entry_t b) {
|
||||
+ acl_tag_t tag_a, tag_b;
|
||||
+
|
||||
+ if (acl_get_tag_type(a, &tag_a) < 0)
|
||||
+ return -errno;
|
||||
+
|
||||
+ if (acl_get_tag_type(b, &tag_b) < 0)
|
||||
+ return -errno;
|
||||
+
|
||||
+ if (tag_a != tag_b)
|
||||
+ return false;
|
||||
+
|
||||
+ switch (tag_a) {
|
||||
+ case ACL_USER_OBJ:
|
||||
+ case ACL_GROUP_OBJ:
|
||||
+ case ACL_MASK:
|
||||
+ case ACL_OTHER:
|
||||
+ /* can have only one of those */
|
||||
+ return true;
|
||||
+ case ACL_USER: {
|
||||
+ _cleanup_(acl_free_uid_tpp) uid_t *uid_a, *uid_b;
|
||||
+
|
||||
+ uid_a = acl_get_qualifier(a);
|
||||
+ if (!uid_a)
|
||||
+ return -errno;
|
||||
+
|
||||
+ uid_b = acl_get_qualifier(b);
|
||||
+ if (!uid_b)
|
||||
+ return -errno;
|
||||
+
|
||||
+ return *uid_a == *uid_b;
|
||||
+ }
|
||||
+ case ACL_GROUP: {
|
||||
+ _cleanup_(acl_free_gid_tpp) gid_t *gid_a, *gid_b;
|
||||
+
|
||||
+ gid_a = acl_get_qualifier(a);
|
||||
+ if (!gid_a)
|
||||
+ return -errno;
|
||||
+
|
||||
+ gid_b = acl_get_qualifier(b);
|
||||
+ if (!gid_b)
|
||||
+ return -errno;
|
||||
+
|
||||
+ return *gid_a == *gid_b;
|
||||
+ }
|
||||
+ default:
|
||||
+ assert_not_reached("Unknown acl tag type");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int find_acl_entry(acl_t acl, acl_entry_t entry, acl_entry_t *out) {
|
||||
+ acl_entry_t i;
|
||||
+ int r;
|
||||
+
|
||||
+ for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
|
||||
+ r > 0;
|
||||
+ r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
+
|
||||
+ r = acl_entry_equal(i, entry);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r > 0) {
|
||||
+ *out = i;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+ if (r < 0)
|
||||
+ return -errno;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
|
||||
_cleanup_(acl_freep) acl_t old;
|
||||
acl_entry_t i;
|
||||
@@ -296,8 +367,12 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) {
|
||||
|
||||
acl_entry_t j;
|
||||
|
||||
- if (acl_create_entry(&old, &j) < 0)
|
||||
- return -errno;
|
||||
+ r = find_acl_entry(old, i, &j);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ if (acl_create_entry(&old, &j) < 0)
|
||||
+ return -errno;
|
||||
|
||||
if (acl_copy_entry(j, i) < 0)
|
||||
return -errno;
|
||||
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
|
||||
index 90e88ff..fdb9006 100644
|
||||
--- a/src/shared/acl-util.h
|
||||
+++ b/src/shared/acl-util.h
|
||||
@@ -41,5 +41,9 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(acl_t, acl_free);
|
||||
#define acl_free_charp acl_free
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, acl_free_charp);
|
||||
+#define acl_free_uid_tp acl_free
|
||||
+DEFINE_TRIVIAL_CLEANUP_FUNC(uid_t*, acl_free_uid_tp);
|
||||
+#define acl_free_gid_tp acl_free
|
||||
+DEFINE_TRIVIAL_CLEANUP_FUNC(gid_t*, acl_free_gid_tp);
|
||||
|
||||
#endif
|
||||
--
|
||||
2.3.2
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
From 5bd4b173605142c7be493aa4d958ebaef21f421d Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 25 Feb 2015 22:05:14 +0100
|
||||
Subject: [PATCH] unit: use weaker dependencies between mount and device units
|
||||
in --user mode
|
||||
|
||||
When running in user mode unmounting of mount units when a device
|
||||
vanishes is unlikely to work, and even if it would work is already done
|
||||
by PID 1 anyway. HEnce, when creating implicit dependencies between
|
||||
mount units and their backing devices, created a Wants= type dependency
|
||||
in --user mode, but leave a BindsTo= dependency in --system mode.
|
||||
---
|
||||
src/core/unit.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index ad5348b..875befa 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -2839,7 +2839,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true);
|
||||
+ r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
--
|
||||
2.3.5
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
From f2273101c21bc59a390379e182e53cd4f07a7e71 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Franzke <benjaminfranzke@googlemail.com>
|
||||
Date: Thu, 19 Feb 2015 20:47:28 +0100
|
||||
Subject: machined: use x-machine-unix prefix for the container bus on dbus1
|
||||
|
||||
This fixes "machinectl login" on systems configured with --disable-kdbus.
|
||||
|
||||
The error was:
|
||||
machinectl login foo
|
||||
Failed to get machine PTY: Input/output error
|
||||
|
||||
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
|
||||
index 15c9159..9e78a67 100644
|
||||
--- a/src/machine/machine-dbus.c
|
||||
+++ b/src/machine/machine-dbus.c
|
||||
@@ -511,7 +511,7 @@ int bus_machine_method_open_login(sd_bus *bus, sd_bus_message *message, void *us
|
||||
#ifdef ENABLE_KDBUS
|
||||
asprintf(&container_bus->address, "x-machine-kernel:pid=" PID_FMT ";x-machine-unix:pid=" PID_FMT, m->leader, m->leader);
|
||||
#else
|
||||
- asprintf(&container_bus->address, "x-machine-kernel:pid=" PID_FMT, m->leader);
|
||||
+ asprintf(&container_bus->address, "x-machine-unix:pid=" PID_FMT, m->leader);
|
||||
#endif
|
||||
if (!container_bus->address)
|
||||
return log_oom();
|
||||
--
|
||||
cgit v0.10.2
|
||||
|
||||
|
|
@ -1,282 +0,0 @@
|
|||
From 5bac5235934fabe5a3e6a9d47f4812f81034c427 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Gundersen <teg@jklm.no>
|
||||
Date: Thu, 22 Jan 2015 00:53:16 +0100
|
||||
Subject: sd-dhcp-client: use RFC4361-complient ClientID by default
|
||||
|
||||
In addition to the benefits listed in the RFC, this allows DHCP to work also in
|
||||
case several interfaces share the same MAC address on the same link (IPVLAN).
|
||||
|
||||
Note that this will make the ClientID (so probably the assigned IP address)
|
||||
change on upgrades. If it is desired to avoid that we would have to remember and
|
||||
write back the ID (which the library supports, but networkd currently does not).
|
||||
|
||||
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
|
||||
index 65e888a..5f90617 100644
|
||||
--- a/src/libsystemd-network/sd-dhcp-client.c
|
||||
+++ b/src/libsystemd-network/sd-dhcp-client.c
|
||||
@@ -36,9 +36,10 @@
|
||||
#include "dhcp-protocol.h"
|
||||
#include "dhcp-internal.h"
|
||||
#include "dhcp-lease-internal.h"
|
||||
+#include "dhcp-identifier.h"
|
||||
#include "sd-dhcp-client.h"
|
||||
|
||||
-#define MAX_CLIENT_ID_LEN 64 /* Arbitrary limit */
|
||||
+#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
|
||||
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
|
||||
|
||||
struct sd_dhcp_client {
|
||||
@@ -60,29 +61,31 @@ struct sd_dhcp_client {
|
||||
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
|
||||
size_t mac_addr_len;
|
||||
uint16_t arp_type;
|
||||
- union {
|
||||
- struct {
|
||||
- uint8_t type; /* 0: Generic (non-LL) (RFC 2132) */
|
||||
- uint8_t data[MAX_CLIENT_ID_LEN];
|
||||
- } _packed_ gen;
|
||||
- struct {
|
||||
- uint8_t type; /* 1: Ethernet Link-Layer (RFC 2132) */
|
||||
- uint8_t haddr[ETH_ALEN];
|
||||
- } _packed_ eth;
|
||||
- struct {
|
||||
- uint8_t type; /* 2 - 254: ARP/Link-Layer (RFC 2132) */
|
||||
- uint8_t haddr[0];
|
||||
- } _packed_ ll;
|
||||
- struct {
|
||||
- uint8_t type; /* 255: Node-specific (RFC 4361) */
|
||||
- uint8_t iaid[4];
|
||||
- uint8_t duid[MAX_CLIENT_ID_LEN - 4];
|
||||
- } _packed_ ns;
|
||||
- struct {
|
||||
- uint8_t type;
|
||||
- uint8_t data[MAX_CLIENT_ID_LEN];
|
||||
- } _packed_ raw;
|
||||
- } client_id;
|
||||
+ struct {
|
||||
+ uint8_t type;
|
||||
+ union {
|
||||
+ struct {
|
||||
+ /* 0: Generic (non-LL) (RFC 2132) */
|
||||
+ uint8_t data[MAX_CLIENT_ID_LEN];
|
||||
+ } _packed_ gen;
|
||||
+ struct {
|
||||
+ /* 1: Ethernet Link-Layer (RFC 2132) */
|
||||
+ uint8_t haddr[ETH_ALEN];
|
||||
+ } _packed_ eth;
|
||||
+ struct {
|
||||
+ /* 2 - 254: ARP/Link-Layer (RFC 2132) */
|
||||
+ uint8_t haddr[0];
|
||||
+ } _packed_ ll;
|
||||
+ struct {
|
||||
+ /* 255: Node-specific (RFC 4361) */
|
||||
+ uint32_t iaid;
|
||||
+ struct duid duid;
|
||||
+ } _packed_ ns;
|
||||
+ struct {
|
||||
+ uint8_t data[MAX_CLIENT_ID_LEN];
|
||||
+ } _packed_ raw;
|
||||
+ };
|
||||
+ } _packed_ client_id;
|
||||
size_t client_id_len;
|
||||
char *hostname;
|
||||
char *vendor_class_identifier;
|
||||
@@ -239,10 +242,9 @@ int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
|
||||
*data = NULL;
|
||||
*data_len = 0;
|
||||
if (client->client_id_len) {
|
||||
- *type = client->client_id.raw.type;
|
||||
+ *type = client->client_id.type;
|
||||
*data = client->client_id.raw.data;
|
||||
- *data_len = client->client_id_len -
|
||||
- sizeof (client->client_id.raw.type);
|
||||
+ *data_len = client->client_id_len - sizeof(client->client_id.type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -270,8 +272,8 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
|
||||
break;
|
||||
}
|
||||
|
||||
- if (client->client_id_len == data_len + sizeof (client->client_id.raw.type) &&
|
||||
- client->client_id.raw.type == type &&
|
||||
+ if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
|
||||
+ client->client_id.type == type &&
|
||||
memcmp(&client->client_id.raw.data, data, data_len) == 0)
|
||||
return 0;
|
||||
|
||||
@@ -282,9 +284,9 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
|
||||
client_stop(client, DHCP_EVENT_STOP);
|
||||
}
|
||||
|
||||
- client->client_id.raw.type = type;
|
||||
+ client->client_id.type = type;
|
||||
memcpy(&client->client_id.raw.data, data, data_len);
|
||||
- client->client_id_len = data_len + sizeof (client->client_id.raw.type);
|
||||
+ client->client_id_len = data_len + sizeof (client->client_id.type);
|
||||
|
||||
if (need_restart && client->state != DHCP_STATE_STOPPED)
|
||||
sd_dhcp_client_start(client);
|
||||
@@ -461,12 +463,21 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
||||
if (client->arp_type == ARPHRD_ETHER)
|
||||
memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
|
||||
|
||||
- /* If no client identifier exists, construct one from an ethernet
|
||||
- address if present */
|
||||
- if (client->client_id_len == 0 && client->arp_type == ARPHRD_ETHER) {
|
||||
- client->client_id.eth.type = ARPHRD_ETHER;
|
||||
- memcpy(&client->client_id.eth.haddr, &client->mac_addr, ETH_ALEN);
|
||||
- client->client_id_len = sizeof (client->client_id.eth);
|
||||
+ /* If no client identifier exists, construct an RFC 4361-compliant one */
|
||||
+ if (client->client_id_len == 0) {
|
||||
+ size_t duid_len;
|
||||
+
|
||||
+ client->client_id.type = 255;
|
||||
+
|
||||
+ r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len;
|
||||
}
|
||||
|
||||
/* Some DHCP servers will refuse to issue an DHCP lease if the Client
|
||||
@@ -475,7 +486,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
||||
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
|
||||
DHCP_OPTION_CLIENT_IDENTIFIER,
|
||||
client->client_id_len,
|
||||
- &client->client_id.raw);
|
||||
+ &client->client_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -1031,7 +1042,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
|
||||
|
||||
if (client->client_id_len) {
|
||||
r = dhcp_lease_set_client_id(lease,
|
||||
- (uint8_t *) &client->client_id.raw,
|
||||
+ (uint8_t *) &client->client_id,
|
||||
client->client_id_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1098,7 +1109,7 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
|
||||
|
||||
if (client->client_id_len) {
|
||||
r = dhcp_lease_set_client_id(lease,
|
||||
- (uint8_t *) &client->client_id.raw,
|
||||
+ (uint8_t *) &client->client_id,
|
||||
client->client_id_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
|
||||
index 0515440..a3d69f3 100644
|
||||
--- a/src/libsystemd-network/test-dhcp-client.c
|
||||
+++ b/src/libsystemd-network/test-dhcp-client.c
|
||||
@@ -32,17 +32,16 @@
|
||||
#include "sd-event.h"
|
||||
#include "event-util.h"
|
||||
|
||||
+#include "dhcp-identifier.h"
|
||||
#include "dhcp-protocol.h"
|
||||
#include "dhcp-internal.h"
|
||||
#include "sd-dhcp-client.h"
|
||||
|
||||
-static struct ether_addr mac_addr = {
|
||||
- .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
|
||||
-};
|
||||
+static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
|
||||
|
||||
typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
|
||||
|
||||
-static bool verbose = false;
|
||||
+static bool verbose = true;
|
||||
static int test_fd[2];
|
||||
static test_callback_recv_t callback_recv;
|
||||
static be32_t xid;
|
||||
@@ -136,10 +135,22 @@ static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
|
||||
{
|
||||
switch(code) {
|
||||
case DHCP_OPTION_CLIENT_IDENTIFIER:
|
||||
- assert_se(len == 7);
|
||||
- assert_se(option[0] == 0x01);
|
||||
- assert_se(memcmp(&option[1], &mac_addr, ETH_ALEN) == 0);
|
||||
+ {
|
||||
+ uint32_t iaid;
|
||||
+ struct duid duid;
|
||||
+ size_t duid_len;
|
||||
+
|
||||
+ assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0);
|
||||
+ assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, &iaid) >= 0);
|
||||
+
|
||||
+ assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
|
||||
+ assert_se(len == 19);
|
||||
+ assert_se(option[0] == 0xff);
|
||||
+
|
||||
+ assert_se(memcmp(&option[1], &iaid, sizeof(iaid)) == 0);
|
||||
+ assert_se(memcmp(&option[5], &duid, duid_len) == 0);
|
||||
break;
|
||||
+ }
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -185,8 +196,7 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
|
||||
assert_se(ip_check == 0xffff);
|
||||
|
||||
assert_se(discover->dhcp.xid);
|
||||
- assert_se(memcmp(discover->dhcp.chaddr,
|
||||
- &mac_addr.ether_addr_octet, 6) == 0);
|
||||
+ assert_se(memcmp(discover->dhcp.chaddr, &mac_addr, ETH_ALEN) == 0);
|
||||
|
||||
size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
|
||||
|
||||
@@ -246,10 +256,7 @@ static void test_discover_message(sd_event *e)
|
||||
assert_se(r >= 0);
|
||||
|
||||
assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
|
||||
- assert_se(sd_dhcp_client_set_mac(client,
|
||||
- (const uint8_t *) &mac_addr,
|
||||
- sizeof (mac_addr),
|
||||
- ARPHRD_ETHER) >= 0);
|
||||
+ assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
|
||||
|
||||
assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
|
||||
|
||||
@@ -404,8 +411,7 @@ static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
|
||||
|
||||
memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
|
||||
memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
|
||||
- memcpy(&test_addr_acq_ack[56], &mac_addr.ether_addr_octet,
|
||||
- ETHER_ADDR_LEN);
|
||||
+ memcpy(&test_addr_acq_ack[56], &mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
callback_recv = NULL;
|
||||
|
||||
@@ -436,8 +442,7 @@ static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
|
||||
|
||||
memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
|
||||
memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
|
||||
- memcpy(&test_addr_acq_offer[56], &mac_addr.ether_addr_octet,
|
||||
- ETHER_ADDR_LEN);
|
||||
+ memcpy(&test_addr_acq_offer[56], &mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
callback_recv = test_addr_acq_recv_request;
|
||||
|
||||
@@ -467,10 +472,7 @@ static void test_addr_acq(sd_event *e) {
|
||||
assert_se(r >= 0);
|
||||
|
||||
assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
|
||||
- assert_se(sd_dhcp_client_set_mac(client,
|
||||
- (const uint8_t *) &mac_addr,
|
||||
- sizeof (mac_addr),
|
||||
- ARPHRD_ETHER) >= 0);
|
||||
+ assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
|
||||
|
||||
assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e)
|
||||
>= 0);
|
||||
--
|
||||
cgit v0.10.2
|
||||
|
|
@ -3,82 +3,64 @@
|
|||
|
||||
# ALARM: Kevin Mihelich <kevin@archlinuxarm.org>
|
||||
# - disable optimization, currently breaks many things
|
||||
# - v5: revert 5bac523 until the issue with it can be figured out
|
||||
# - removed makedepend on gnu-efi-libs, --enable-gnuefi configure option
|
||||
|
||||
pkgbase=systemd
|
||||
pkgname=('systemd' 'libsystemd' 'systemd-sysvcompat')
|
||||
pkgver=219
|
||||
pkgrel=6
|
||||
pkgver=221
|
||||
pkgrel=1
|
||||
arch=('i686' 'x86_64')
|
||||
url="http://www.freedesktop.org/wiki/Software/systemd"
|
||||
makedepends=('acl' 'cryptsetup' 'docbook-xsl' 'gobject-introspection' 'gperf'
|
||||
'gtk-doc' 'intltool' 'iptables' 'kmod' 'libcap' 'libidn' 'libgcrypt'
|
||||
'libmicrohttpd' 'libxslt' 'util-linux' 'linux-api-headers' 'lz4' 'pam'
|
||||
'python' 'python-lxml' 'quota-tools' 'shadow' 'xz')
|
||||
makedepends=('acl' 'cryptsetup' 'docbook-xsl' 'gperf' 'lz4' 'xz' 'pam'
|
||||
'intltool' 'iptables' 'kmod' 'libcap' 'libidn' 'libgcrypt'
|
||||
'libmicrohttpd' 'libxslt' 'util-linux' 'linux-api-headers'
|
||||
'python' 'python-lxml' 'quota-tools' 'shadow' 'git')
|
||||
options=('strip' 'debug')
|
||||
source=("http://www.freedesktop.org/software/$pkgname/$pkgname-$pkgver.tar.xz"
|
||||
source=("git://github.com/systemd/systemd.git#tag=v$pkgver"
|
||||
'initcpio-hook-udev'
|
||||
'initcpio-install-systemd'
|
||||
'initcpio-install-udev'
|
||||
'0001-tmpfiles-avoid-creating-duplicate-acl-entries.patch'
|
||||
'0001-nspawn-when-connected-to-pipes-for-stdin-stdout-pass.patch'
|
||||
'0001-core-shared-in-deserializing-match-same-files-reache.patch'
|
||||
'0001-tmpfiles-Fix-handling-of-duplicate-lines.patch'
|
||||
'0001-core-do-not-spawn-jobs-or-touch-other-units-during-c.patch'
|
||||
'0001-use-x-machine-unix-prefix-for-the-container-bus-on-dbus1.patch'
|
||||
'0001-unit-use-weaker-dependencies-between-mount-and-devic.patch'
|
||||
'0001-core-rework-device-state-logic.patch'
|
||||
'0001-core-don-t-change-removed-devices-to-state-tentative.patch'
|
||||
'5bac5235934fabe5a3e6a9d47f4812f81034c427.patch')
|
||||
md5sums=('e0d6c9a4b4f69f66932d2230298c9a34'
|
||||
'arch.conf'
|
||||
'loader.conf'
|
||||
'splash-arch.bmp')
|
||||
md5sums=('SKIP'
|
||||
'90ea67a7bb237502094914622a39e281'
|
||||
'58af51bd4c0464f195b3433b4e17cf6c'
|
||||
'8516a7bd65157d0115c113118c10c3f3'
|
||||
'bde43090d4ac0ef048e3eaee8202a407'
|
||||
'7cdefc73bf61934c353e4450e280e551'
|
||||
'cb8550749cd52b5902ed6fdf0eb465ec'
|
||||
'9d46aebfc04cc849fd4295f449b239a2'
|
||||
'c4c9c0f0a06314450563ed571962881e'
|
||||
'6b9d611dffd92c94641360c3ef2659c1'
|
||||
'3a0fc672b34ced18ca1364edf8644165'
|
||||
'cd2719e8e93ad662c00bf9f195fdce66'
|
||||
'12e01f00c91e54680098a799517698f2'
|
||||
'd0aa4e5ec598063eab2e79fb95bceece'
|
||||
'a168ea8a805ee16c1dd1cfe6f5893558')
|
||||
'20ead378f5d6df4b2a3e670301510a7d'
|
||||
'ddaef54f68f6c86c6c07835fc668f62a'
|
||||
'1e2f9a8b0fa32022bf0a8f39123e5f4e')
|
||||
|
||||
prepare() {
|
||||
cd "$pkgname-$pkgver"
|
||||
cd "$pkgname"
|
||||
|
||||
patch -Np1 <../0001-tmpfiles-avoid-creating-duplicate-acl-entries.patch
|
||||
patch -Np1 <../0001-nspawn-when-connected-to-pipes-for-stdin-stdout-pass.patch
|
||||
patch -Np1 <../0001-core-shared-in-deserializing-match-same-files-reache.patch
|
||||
patch -Np1 <../0001-tmpfiles-Fix-handling-of-duplicate-lines.patch
|
||||
patch -Np1 <../0001-core-do-not-spawn-jobs-or-touch-other-units-during-c.patch
|
||||
patch -Np1 <../0001-use-x-machine-unix-prefix-for-the-container-bus-on-dbus1.patch
|
||||
patch -Np1 <../0001-unit-use-weaker-dependencies-between-mount-and-devic.patch
|
||||
patch -Np1 <../0001-core-rework-device-state-logic.patch
|
||||
patch -Np1 <../0001-core-don-t-change-removed-devices-to-state-tentative.patch
|
||||
[[ $CARCH == "arm" ]] && patch -Rp1 -i ../5bac5235934fabe5a3e6a9d47f4812f81034c427.patch || true
|
||||
# pam_systemd: Properly check kdbus availability
|
||||
# https://github.com/systemd/systemd/commit/c5d452bb228e
|
||||
git cherry-pick -n c5d452bb228e
|
||||
|
||||
# udevd: suppress warning if we don't find cgroup
|
||||
# https://github.com/systemd/systemd/commit/11b9fb15be96
|
||||
git cherry-pick -n 11b9fb15be96
|
||||
|
||||
./autogen.sh
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$pkgname-$pkgver"
|
||||
cd "$pkgname"
|
||||
|
||||
local timeservers=({0..3}.arch.pool.ntp.org)
|
||||
|
||||
CFLAGS=`echo $CFLAGS | sed -e 's/-O2/-O0/'` && CXXFLAGS="$CFLAGS"
|
||||
unset CPPFLAGS
|
||||
|
||||
local timeservers=({0..3}.arch.pool.ntp.org)
|
||||
|
||||
./configure \
|
||||
--libexecdir=/usr/lib \
|
||||
--localstatedir=/var \
|
||||
--sysconfdir=/etc \
|
||||
--enable-introspection \
|
||||
--enable-gtk-doc \
|
||||
--enable-lz4 \
|
||||
--enable-compat-libs \
|
||||
--disable-audit \
|
||||
--disable-ima \
|
||||
--disable-kdbus \
|
||||
--with-sysvinit-path= \
|
||||
--with-sysvrcnd-path= \
|
||||
--with-ntp-servers="${timeservers[*]}"
|
||||
|
@ -88,7 +70,7 @@ build() {
|
|||
|
||||
package_systemd() {
|
||||
pkgdesc="system and service manager"
|
||||
license=('GPL2' 'LGPL2.1' 'MIT')
|
||||
license=('GPL2' 'LGPL2.1')
|
||||
depends=('acl' 'bash' 'dbus' 'glib2' 'iptables' 'kbd' 'kmod' 'hwids' 'libcap'
|
||||
'libgcrypt' 'libsystemd' 'libidn' 'lz4' 'pam' 'libseccomp' 'util-linux'
|
||||
'xz')
|
||||
|
@ -123,7 +105,7 @@ package_systemd() {
|
|||
etc/udev/udev.conf)
|
||||
install="systemd.install"
|
||||
|
||||
make -C "$pkgname-$pkgver" DESTDIR="$pkgdir" install
|
||||
make -C "$pkgname" DESTDIR="$pkgdir" install
|
||||
|
||||
# don't write units to /etc by default. some of these will be re-enabled on
|
||||
# post_install.
|
||||
|
@ -133,7 +115,7 @@ package_systemd() {
|
|||
rm -r "$pkgdir/usr/lib/rpm"
|
||||
|
||||
# add back tmpfiles.d/legacy.conf
|
||||
install -m644 "systemd-$pkgver/tmpfiles.d/legacy.conf" "$pkgdir/usr/lib/tmpfiles.d"
|
||||
install -m644 "$pkgname/tmpfiles.d/legacy.conf" "$pkgdir/usr/lib/tmpfiles.d"
|
||||
|
||||
# Replace dialout/tape/cdrom group in rules with uucp/storage/optical group
|
||||
sed -i 's#GROUP="dialout"#GROUP="uucp"#g;
|
||||
|
@ -171,18 +153,19 @@ package_systemd() {
|
|||
rm -rf "$srcdir/_libsystemd"
|
||||
install -dm755 "$srcdir"/_libsystemd/usr/lib
|
||||
cd "$srcdir"/_libsystemd
|
||||
mv "$pkgdir"/usr/lib/lib{systemd,{g,}udev}*.so* usr/lib
|
||||
mv "$pkgdir"/usr/lib/lib{systemd,udev}*.so* usr/lib
|
||||
|
||||
# include MIT license, since it's technically custom
|
||||
install -Dm644 "$srcdir/$pkgname-$pkgver/LICENSE.MIT" \
|
||||
"$pkgdir/usr/share/licenses/systemd/LICENSE.MIT"
|
||||
# add example bootctl configuration
|
||||
install -Dm644 "$srcdir/arch.conf" "$pkgdir"/usr/share/systemd/bootctl/arch.conf
|
||||
install -Dm644 "$srcdir/loader.conf" "$pkgdir"/usr/share/systemd/bootctl/loader.conf
|
||||
install -Dm644 "$srcdir/splash-arch.bmp" "$pkgdir"/usr/share/systemd/bootctl/splash-arch.bmp
|
||||
}
|
||||
|
||||
package_libsystemd() {
|
||||
pkgdesc="systemd client libraries"
|
||||
depends=('glib2' 'glibc' 'libgcrypt' 'lz4' 'xz')
|
||||
license=('GPL2')
|
||||
provides=('libgudev-1.0.so' 'libsystemd.so' 'libsystemd-daemon.so' 'libsystemd-id128.so'
|
||||
provides=('libsystemd.so' 'libsystemd-daemon.so' 'libsystemd-id128.so'
|
||||
'libsystemd-journal.so' 'libsystemd-login.so' 'libudev.so')
|
||||
|
||||
mv "$srcdir/_libsystemd"/* "$pkgdir"
|
||||
|
|
7
core/systemd/arch.conf
Normal file
7
core/systemd/arch.conf
Normal file
|
@ -0,0 +1,7 @@
|
|||
## This is just an example config file.
|
||||
## Please edit the paths and kernel parameters according to your system.
|
||||
|
||||
title Arch Linux
|
||||
linux /vmlinuz-linux
|
||||
initrd /initramfs-linux.img
|
||||
options root=PARTUUID=XXXX rootfstype=XXXX add_efi_memmap
|
|
@ -34,6 +34,7 @@ add_udev_rule() {
|
|||
strip_quotes 'value'
|
||||
# just take the first word as the binary name
|
||||
binary=${value%% *}
|
||||
[[ ${binary:0:1} == '$' ]] && continue
|
||||
if [[ ${binary:0:1} != '/' ]]; then
|
||||
binary=$(PATH=/usr/lib/udev:/lib/udev type -P "$binary")
|
||||
fi
|
||||
|
|
1
core/systemd/loader.conf
Normal file
1
core/systemd/loader.conf
Normal file
|
@ -0,0 +1 @@
|
|||
default arch
|
BIN
core/systemd/splash-arch.bmp
Executable file
BIN
core/systemd/splash-arch.bmp
Executable file
Binary file not shown.
After Width: | Height: | Size: 369 KiB |
Loading…
Reference in a new issue