1diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in
2index e30d9a8..a3d399b 100644
3--- a/rules/99-systemd.rules.in
4+++ b/rules/99-systemd.rules.in
5@@ -14,10 +14,6 @@ KERNEL=="vport*", TAG+="systemd"
6 SUBSYSTEM=="block", KERNEL!="ram*", TAG+="systemd"
7 SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
8
9-# Ignore encrypted devices with no identified superblock on it, since
10-# we are probably still calling mke2fs or mkswap on it.
11-SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0"
12-
13 # Ignore raid devices that are not yet assembled and started
14 SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0"
15 SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0"
16diff --git a/src/core/job.c b/src/core/job.c
17index eaa4bb1..db44fee 100644
18--- a/src/core/job.c
19+++ b/src/core/job.c
20@@ -352,6 +352,9 @@ bool job_type_is_redundant(JobType a, UnitActiveState b) {
21 return
22 b == UNIT_ACTIVATING;
23
24+ case JOB_NOP:
25+ return true;
26+
27 default:
28 assert_not_reached("Invalid job type");
29 }
30diff --git a/src/core/job.h b/src/core/job.h
31index 1e7c61b..ee8e54a 100644
32--- a/src/core/job.h
33+++ b/src/core/job.h
34@@ -49,9 +49,11 @@ enum JobType {
35 _JOB_TYPE_MAX_MERGING,
36
37 /* JOB_NOP can enter into a transaction, but as it won't pull in
38- * any dependencies, it won't have to merge with anything.
39- * job_install() avoids the problem of merging JOB_NOP too (it's
40- * special-cased, only merges with other JOB_NOPs). */
41+ * any dependencies and it uses the special 'nop_job' slot in Unit,
42+ * it won't have to merge with anything (except possibly into another
43+ * JOB_NOP, previously installed). JOB_NOP is special-cased in
44+ * job_type_is_*() functions so that the transaction can be
45+ * activated. */
46 JOB_NOP = _JOB_TYPE_MAX_MERGING, /* do nothing */
47
48 _JOB_TYPE_MAX_IN_TRANSACTION,
49@@ -190,11 +192,15 @@ _pure_ static inline bool job_type_is_mergeable(JobType a, JobType b) {
50 }
51
52 _pure_ static inline bool job_type_is_conflicting(JobType a, JobType b) {
53- return !job_type_is_mergeable(a, b);
54+ return a != JOB_NOP && b != JOB_NOP && !job_type_is_mergeable(a, b);
55 }
56
57 _pure_ static inline bool job_type_is_superset(JobType a, JobType b) {
58 /* Checks whether operation a is a "superset" of b in its actions */
59+ if (b == JOB_NOP)
60+ return true;
61+ if (a == JOB_NOP)
62+ return false;
63 return a == job_type_lookup_merge(a, b);
64 }
65
66diff --git a/src/core/manager.c b/src/core/manager.c
67index d427d88..256d6f7 100644
68--- a/src/core/manager.c
69+++ b/src/core/manager.c
70@@ -662,9 +662,11 @@ static int manager_setup_notify(Manager *m) {
71 return -errno;
72 }
73
74- if (m->running_as == SYSTEMD_SYSTEM)
75+ if (m->running_as == SYSTEMD_SYSTEM) {
76 m->notify_socket = strdup("/run/systemd/notify");
77- else {
78+ if (!m->notify_socket)
79+ return log_oom();
80+ } else {
81 const char *e;
82
83 e = getenv("XDG_RUNTIME_DIR");
84@@ -674,9 +676,11 @@ static int manager_setup_notify(Manager *m) {
85 }
86
87 m->notify_socket = strappend(e, "/systemd/notify");
88+ if (!m->notify_socket)
89+ return log_oom();
90+
91+ mkdir_parents_label(m->notify_socket, 0755);
92 }
93- if (!m->notify_socket)
94- return log_oom();
95
96 strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1);
97 r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
98diff --git a/src/core/shutdown.c b/src/core/shutdown.c
99index 20cf526..03cfddc 100644
100--- a/src/core/shutdown.c
101+++ b/src/core/shutdown.c
102@@ -75,7 +75,9 @@ static int parse_argv(int argc, char *argv[]) {
103 assert(argc >= 1);
104 assert(argv);
105
106- while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
107+ /* "-" prevents getopt from permuting argv[] and moving the verb away
108+ * from argv[1]. Our interface to initrd promises it'll be there. */
109+ while ((c = getopt_long(argc, argv, "-", options, NULL)) >= 0)
110 switch (c) {
111
112 case ARG_LOG_LEVEL:
113@@ -113,6 +115,13 @@ static int parse_argv(int argc, char *argv[]) {
114
115 break;
116
117+ case '\001':
118+ if (!arg_verb)
119+ arg_verb = optarg;
120+ else
121+ log_error("Excess arguments, ignoring");
122+ break;
123+
124 case '?':
125 return -EINVAL;
126
127@@ -120,15 +129,11 @@ static int parse_argv(int argc, char *argv[]) {
128 assert_not_reached("Unhandled option code.");
129 }
130
131- if (optind >= argc) {
132+ if (!arg_verb) {
133 log_error("Verb argument missing.");
134 return -EINVAL;
135 }
136
137- arg_verb = argv[optind];
138-
139- if (optind + 1 < argc)
140- log_error("Excess arguments, ignoring");
141 return 0;
142 }
143
144diff --git a/src/core/snapshot.c b/src/core/snapshot.c
145index 5eed615..c2678cb 100644
146--- a/src/core/snapshot.c
147+++ b/src/core/snapshot.c
148@@ -208,7 +208,7 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e,
149 return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s lacks snapshot suffix.", name);
150
151 if (manager_get_unit(m, name))
152- sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
153+ return sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
154
155 } else {
156
157diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in
158index d5b86bf..9c66e7b 100644
159--- a/src/core/systemd.pc.in
160+++ b/src/core/systemd.pc.in
161@@ -14,8 +14,8 @@ systemduserunitdir=@userunitdir@
162 systemduserpresetdir=@userpresetdir@
163 systemdsystemconfdir=@pkgsysconfdir@/system
164 systemduserconfdir=@pkgsysconfdir@/user
165-systemdsystemunitpath=${systemdsystemconfdir}:/etc/systemd/system:/run/systemd/system:/usr/local/lib/systemd/system:${systemdsystemunitdir}:/usr/lib/systemd/system:/lib/systemd/system
166-systemduserunitpath=${systemduserconfdir}:/etc/systemd/user:/run/systemd/user:/usr/local/lib/systemd/user:/usr/local/share/systemd/user:${systemduserunitdir}:/usr/lib/systemd/user:/usr/share/systemd/user
167+systemdsystemunitpath=${systemdsystemconfdir}:/etc/systemd/system:/etc/systemd-mutable/system:/nix/var/nix/profiles/default/lib/systemd/user:/run/systemd/system:${systemdsystemunitdir}
168+systemduserunitpath=${systemduserconfdir}:/etc/systemd/user:/etc/systemd-mutable/user:/nix/var/nix/profiles/default/lib/systemd/system:/run/systemd/user:${systemduserunitdir}
169 systemdsystemgeneratordir=@systemgeneratordir@
170 systemdusergeneratordir=@usergeneratordir@
171 systemdsleepdir=@systemsleepdir@
172diff --git a/src/core/timer.c b/src/core/timer.c
173index a3713e2..5c4e9f9 100644
174--- a/src/core/timer.c
175+++ b/src/core/timer.c
176@@ -521,6 +521,7 @@ fail:
177
178 static int timer_start(Unit *u) {
179 Timer *t = TIMER(u);
180+ TimerValue *v;
181
182 assert(t);
183 assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
184@@ -530,6 +531,11 @@ static int timer_start(Unit *u) {
185
186 t->last_trigger = DUAL_TIMESTAMP_NULL;
187
188+ /* Reenable all timers that depend on unit activation time */
189+ LIST_FOREACH(value, v, t->values)
190+ if (v->base == TIMER_ACTIVE)
191+ v->disabled = false;
192+
193 if (t->stamp_path) {
194 struct stat st;
195
196diff --git a/src/core/umount.c b/src/core/umount.c
197index cffa453..4d1a9ff 100644
198--- a/src/core/umount.c
199+++ b/src/core/umount.c
200@@ -385,6 +385,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
201 * anyway, since we are running from it. They have
202 * already been remounted ro. */
203 if (path_equal(m->path, "/")
204+ || path_equal(m->path, "/nix")
205+ || path_equal(m->path, "/nix/store")
206 #ifndef HAVE_SPLIT_USR
207 || path_equal(m->path, "/usr")
208 #endif
209diff --git a/src/delta/delta.c b/src/delta/delta.c
210index 25c4a0b..e1f2d6d 100644
211--- a/src/delta/delta.c
212+++ b/src/delta/delta.c
213@@ -487,7 +487,7 @@ static int parse_flags(const char *flag_str, int flags) {
214 const char *word, *state;
215 size_t l;
216
217- FOREACH_WORD(word, l, flag_str, state) {
218+ FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state) {
219 if (strneq("masked", word, l))
220 flags |= SHOW_MASKED;
221 else if (strneq ("equivalent", word, l))
222diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
223index 70a5918..a5661e8 100644
224--- a/src/fsck/fsck.c
225+++ b/src/fsck/fsck.c
226@@ -315,8 +315,7 @@ int main(int argc, char *argv[]) {
227 return EXIT_FAILURE;
228 }
229
230- cmdline[i++] = "/sbin/fsck";
231- cmdline[i++] = arg_repair;
232+ cmdline[i++] = "/run/current-system/sw/bin/fsck";
233 cmdline[i++] = "-T";
234
235 /*
236diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
237index e257c12..1e04553 100644
238--- a/src/fstab-generator/fstab-generator.c
239+++ b/src/fstab-generator/fstab-generator.c
240@@ -485,7 +485,7 @@ static int add_usr_mount(void) {
241 return log_oom();
242 }
243
244- if (!arg_usr_what || !arg_usr_options)
245+ if (!arg_usr_what)
246 return 0;
247
248 what = fstab_node_to_udev_node(arg_usr_what);
249@@ -494,7 +494,13 @@ static int add_usr_mount(void) {
250 return -1;
251 }
252
253- opts = arg_usr_options;
254+ if (!arg_usr_options)
255+ opts = arg_root_rw > 0 ? "rw" : "ro";
256+ else if (!mount_test_option(arg_usr_options, "ro") &&
257+ !mount_test_option(arg_usr_options, "rw"))
258+ opts = strappenda(arg_usr_options, ",", arg_root_rw > 0 ? "rw" : "ro");
259+ else
260+ opts = arg_usr_options;
261
262 log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));
263 return add_mount(what,
264diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
265index e487369..ff4e9c9 100644
266--- a/src/hostname/hostnamectl.c
267+++ b/src/hostname/hostnamectl.c
268@@ -536,5 +536,5 @@ int main(int argc, char *argv[]) {
269 r = hostnamectl_main(bus, argc, argv);
270
271 finish:
272- return r < 0 ? EXIT_FAILURE : r;
273+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
274 }
275diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c
276index 7dd8878..70a9a13 100644
277--- a/src/journal-remote/journal-remote-parse.c
278+++ b/src/journal-remote/journal-remote-parse.c
279@@ -344,22 +344,25 @@ int process_data(RemoteSource *source) {
280 LLLLLLLL0011223344...\n
281 */
282 sep = memchr(line, '=', n);
283- if (sep)
284+ if (sep) {
285 /* chomp newline */
286 n--;
287- else
288+
289+ r = iovw_put(&source->iovw, line, n);
290+ if (r < 0)
291+ return r;
292+ } else {
293 /* replace \n with = */
294 line[n-1] = '=';
295- log_trace("Received: %.*s", (int) n, line);
296
297- r = iovw_put(&source->iovw, line, n);
298- if (r < 0) {
299- log_error("Failed to put line in iovect");
300- return r;
301+ source->field_len = n;
302+ source->state = STATE_DATA_START;
303+
304+ /* we cannot put the field in iovec until we have all data */
305 }
306
307- if (!sep)
308- source->state = STATE_DATA_START;
309+ log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary");
310+
311 return 0; /* continue */
312 }
313
314@@ -382,6 +385,7 @@ int process_data(RemoteSource *source) {
315
316 case STATE_DATA: {
317 void *data;
318+ char *field;
319
320 assert(source->data_size > 0);
321
322@@ -396,11 +400,12 @@ int process_data(RemoteSource *source) {
323
324 assert(data);
325
326- r = iovw_put(&source->iovw, data, source->data_size);
327- if (r < 0) {
328- log_error("failed to put binary buffer in iovect");
329+ field = (char*) data - sizeof(uint64_t) - source->field_len;
330+ memmove(field + sizeof(uint64_t), field, source->field_len);
331+
332+ r = iovw_put(&source->iovw, field + sizeof(uint64_t), source->field_len + source->data_size);
333+ if (r < 0)
334 return r;
335- }
336
337 source->state = STATE_DATA_FINISH;
338
339diff --git a/src/journal-remote/journal-remote-parse.h b/src/journal-remote/journal-remote-parse.h
340index 8499f4e..22db550 100644
341--- a/src/journal-remote/journal-remote-parse.h
342+++ b/src/journal-remote/journal-remote-parse.h
343@@ -42,7 +42,9 @@ typedef struct RemoteSource {
344 size_t offset; /* offset to the beginning of live data in the buffer */
345 size_t scanned; /* number of bytes since the beginning of data without a newline */
346 size_t filled; /* total number of bytes in the buffer */
347- size_t data_size; /* size of the binary data chunk being processed */
348+
349+ size_t field_len; /* used for binary fields: the field name length */
350+ size_t data_size; /* and the size of the binary data chunk being processed */
351
352 struct iovec_wrapper iovw;
353
354diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
355index 5ab1982..1f980ee 100644
356--- a/src/journal/journal-authenticate.c
357+++ b/src/journal/journal-authenticate.c
358@@ -229,7 +229,7 @@ int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
359 return 0;
360 }
361
362-int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p) {
363+int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p) {
364 int r;
365
366 assert(f);
367@@ -246,7 +246,7 @@ int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p
368 if (r < 0)
369 return r;
370 } else {
371- if (type >= 0 && o->object.type != type)
372+ if (type > OBJECT_UNUSED && o->object.type != type)
373 return -EBADMSG;
374 }
375
376diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h
377index 0aaf836..565fe84 100644
378--- a/src/journal/journal-authenticate.h
379+++ b/src/journal/journal-authenticate.h
380@@ -33,7 +33,7 @@ int journal_file_append_first_tag(JournalFile *f);
381 int journal_file_hmac_setup(JournalFile *f);
382 int journal_file_hmac_start(JournalFile *f);
383 int journal_file_hmac_put_header(JournalFile *f);
384-int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p);
385+int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p);
386
387 int journal_file_fss_load(JournalFile *f);
388 int journal_file_parse_verification_key(JournalFile *f, const char *key);
389diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
390index e55fa19..ab089cb 100644
391--- a/src/journal/journal-def.h
392+++ b/src/journal/journal-def.h
393@@ -52,8 +52,8 @@ typedef struct HashItem HashItem;
394 typedef struct FSSHeader FSSHeader;
395
396 /* Object types */
397-enum {
398- OBJECT_UNUSED,
399+typedef enum ObjectType {
400+ OBJECT_UNUSED, /* also serves as "any type" or "additional context" */
401 OBJECT_DATA,
402 OBJECT_FIELD,
403 OBJECT_ENTRY,
404@@ -62,7 +62,7 @@ enum {
405 OBJECT_ENTRY_ARRAY,
406 OBJECT_TAG,
407 _OBJECT_TYPE_MAX
408-};
409+} ObjectType;
410
411 /* Object flags */
412 enum {
413diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
414index 8a2c0fc..c55a4dc 100644
415--- a/src/journal/journal-file.c
416+++ b/src/journal/journal-file.c
417@@ -374,7 +374,13 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
418 return 0;
419 }
420
421-static int journal_file_move_to(JournalFile *f, int context, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
422+static unsigned type_to_context(ObjectType type) {
423+ /* One context for each type, plus one catch-all for the rest */
424+ assert_cc(_OBJECT_TYPE_MAX <= MMAP_CACHE_MAX_CONTEXTS);
425+ return type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX ? type : 0;
426+}
427+
428+static int journal_file_move_to(JournalFile *f, ObjectType type, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
429 assert(f);
430 assert(ret);
431
432@@ -391,7 +397,7 @@ static int journal_file_move_to(JournalFile *f, int context, bool keep_always, u
433 return -EADDRNOTAVAIL;
434 }
435
436- return mmap_cache_get(f->mmap, f->fd, f->prot, context, keep_always, offset, size, &f->last_stat, ret, NULL);
437+ return mmap_cache_get(f->mmap, f->fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret);
438 }
439
440 static uint64_t minimum_header_size(Object *o) {
441@@ -412,7 +418,7 @@ static uint64_t minimum_header_size(Object *o) {
442 return table[o->object.type];
443 }
444
445-int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret) {
446+int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret) {
447 int r;
448 void *t;
449 Object *o;
450@@ -425,7 +431,7 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec
451 if (!VALID64(offset))
452 return -EFAULT;
453
454- r = journal_file_move_to(f, type_to_context(type), false, offset, sizeof(ObjectHeader), &t);
455+ r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t);
456 if (r < 0)
457 return r;
458
459@@ -441,11 +447,11 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec
460 if (s < minimum_header_size(o))
461 return -EBADMSG;
462
463- if (type > 0 && o->object.type != type)
464+ if (type > OBJECT_UNUSED && o->object.type != type)
465 return -EBADMSG;
466
467 if (s > sizeof(ObjectHeader)) {
468- r = journal_file_move_to(f, o->object.type, false, offset, s, &t);
469+ r = journal_file_move_to(f, type, false, offset, s, &t);
470 if (r < 0)
471 return r;
472
473@@ -482,14 +488,14 @@ static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) {
474 return r;
475 }
476
477-int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) {
478+int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset) {
479 int r;
480 uint64_t p;
481 Object *tail, *o;
482 void *t;
483
484 assert(f);
485- assert(type > 0 && type < _OBJECT_TYPE_MAX);
486+ assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX);
487 assert(size >= sizeof(ObjectHeader));
488 assert(offset);
489 assert(ret);
490@@ -502,7 +508,7 @@ int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object *
491 if (p == 0)
492 p = le64toh(f->header->header_size);
493 else {
494- r = journal_file_move_to_object(f, -1, p, &tail);
495+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
496 if (r < 0)
497 return r;
498
499@@ -1657,7 +1663,7 @@ static int generic_array_bisect(
500 }
501 }
502
503- if (k > n) {
504+ if (k >= n) {
505 if (direction == DIRECTION_UP) {
506 i = n;
507 subtract_one = true;
508@@ -1793,23 +1799,6 @@ _pure_ static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle
509 return TEST_RIGHT;
510 }
511
512-int journal_file_move_to_entry_by_offset(
513- JournalFile *f,
514- uint64_t p,
515- direction_t direction,
516- Object **ret,
517- uint64_t *offset) {
518-
519- return generic_array_bisect(f,
520- le64toh(f->header->entry_array_offset),
521- le64toh(f->header->n_entries),
522- p,
523- test_object_offset,
524- direction,
525- ret, offset, NULL);
526-}
527-
528-
529 static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) {
530 Object *o;
531 int r;
532@@ -1939,9 +1928,81 @@ int journal_file_move_to_entry_by_monotonic(
533 ret, offset, NULL);
534 }
535
536+void journal_file_reset_location(JournalFile *f) {
537+ f->location_type = LOCATION_HEAD;
538+ f->current_offset = 0;
539+ f->current_seqnum = 0;
540+ f->current_realtime = 0;
541+ f->current_monotonic = 0;
542+ zero(f->current_boot_id);
543+ f->current_xor_hash = 0;
544+}
545+
546+void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) {
547+ f->location_type = LOCATION_SEEK;
548+ f->current_offset = offset;
549+ f->current_seqnum = le64toh(o->entry.seqnum);
550+ f->current_realtime = le64toh(o->entry.realtime);
551+ f->current_monotonic = le64toh(o->entry.monotonic);
552+ f->current_boot_id = o->entry.boot_id;
553+ f->current_xor_hash = le64toh(o->entry.xor_hash);
554+}
555+
556+int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
557+ assert(af);
558+ assert(bf);
559+ assert(af->location_type == LOCATION_SEEK);
560+ assert(bf->location_type == LOCATION_SEEK);
561+
562+ /* If contents and timestamps match, these entries are
563+ * identical, even if the seqnum does not match */
564+ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) &&
565+ af->current_monotonic == bf->current_monotonic &&
566+ af->current_realtime == bf->current_realtime &&
567+ af->current_xor_hash == bf->current_xor_hash)
568+ return 0;
569+
570+ if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
571+
572+ /* If this is from the same seqnum source, compare
573+ * seqnums */
574+ if (af->current_seqnum < bf->current_seqnum)
575+ return -1;
576+ if (af->current_seqnum > bf->current_seqnum)
577+ return 1;
578+
579+ /* Wow! This is weird, different data but the same
580+ * seqnums? Something is borked, but let's make the
581+ * best of it and compare by time. */
582+ }
583+
584+ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) {
585+
586+ /* If the boot id matches, compare monotonic time */
587+ if (af->current_monotonic < bf->current_monotonic)
588+ return -1;
589+ if (af->current_monotonic > bf->current_monotonic)
590+ return 1;
591+ }
592+
593+ /* Otherwise, compare UTC time */
594+ if (af->current_realtime < bf->current_realtime)
595+ return -1;
596+ if (af->current_realtime > bf->current_realtime)
597+ return 1;
598+
599+ /* Finally, compare by contents */
600+ if (af->current_xor_hash < bf->current_xor_hash)
601+ return -1;
602+ if (af->current_xor_hash > bf->current_xor_hash)
603+ return 1;
604+
605+ return 0;
606+}
607+
608 int journal_file_next_entry(
609 JournalFile *f,
610- Object *o, uint64_t p,
611+ uint64_t p,
612 direction_t direction,
613 Object **ret, uint64_t *offset) {
614
615@@ -1949,18 +2010,14 @@ int journal_file_next_entry(
616 int r;
617
618 assert(f);
619- assert(p > 0 || !o);
620
621 n = le64toh(f->header->n_entries);
622 if (n <= 0)
623 return 0;
624
625- if (!o)
626+ if (p == 0)
627 i = direction == DIRECTION_DOWN ? 0 : n - 1;
628 else {
629- if (o->object.type != OBJECT_ENTRY)
630- return -EINVAL;
631-
632 r = generic_array_bisect(f,
633 le64toh(f->header->entry_array_offset),
634 le64toh(f->header->n_entries),
635@@ -2006,55 +2063,6 @@ int journal_file_next_entry(
636 return 1;
637 }
638
639-int journal_file_skip_entry(
640- JournalFile *f,
641- Object *o, uint64_t p,
642- int64_t skip,
643- Object **ret, uint64_t *offset) {
644-
645- uint64_t i, n;
646- int r;
647-
648- assert(f);
649- assert(o);
650- assert(p > 0);
651-
652- if (o->object.type != OBJECT_ENTRY)
653- return -EINVAL;
654-
655- r = generic_array_bisect(f,
656- le64toh(f->header->entry_array_offset),
657- le64toh(f->header->n_entries),
658- p,
659- test_object_offset,
660- DIRECTION_DOWN,
661- NULL, NULL,
662- &i);
663- if (r <= 0)
664- return r;
665-
666- /* Calculate new index */
667- if (skip < 0) {
668- if ((uint64_t) -skip >= i)
669- i = 0;
670- else
671- i = i - (uint64_t) -skip;
672- } else
673- i += (uint64_t) skip;
674-
675- n = le64toh(f->header->n_entries);
676- if (n <= 0)
677- return -EBADMSG;
678-
679- if (i >= n)
680- i = n-1;
681-
682- return generic_array_get(f,
683- le64toh(f->header->entry_array_offset),
684- i,
685- ret, offset);
686-}
687-
688 int journal_file_next_entry_for_data(
689 JournalFile *f,
690 Object *o, uint64_t p,
691@@ -2289,7 +2297,7 @@ void journal_file_dump(JournalFile *f) {
692
693 p = le64toh(f->header->header_size);
694 while (p != 0) {
695- r = journal_file_move_to_object(f, -1, p, &o);
696+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
697 if (r < 0)
698 goto fail;
699
700diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
701index 211e121..ca17c97 100644
702--- a/src/journal/journal-file.h
703+++ b/src/journal/journal-file.h
704@@ -48,6 +48,20 @@ typedef enum direction {
705 DIRECTION_DOWN
706 } direction_t;
707
708+typedef enum LocationType {
709+ /* The first and last entries, resp. */
710+ LOCATION_HEAD,
711+ LOCATION_TAIL,
712+
713+ /* We already read the entry we currently point to, and the
714+ * next one to read should probably not be this one again. */
715+ LOCATION_DISCRETE,
716+
717+ /* We should seek to the precise location specified, and
718+ * return it, as we haven't read it yet. */
719+ LOCATION_SEEK
720+} LocationType;
721+
722 typedef struct JournalFile {
723 int fd;
724
725@@ -63,6 +77,8 @@ typedef struct JournalFile {
726 bool tail_entry_monotonic_valid:1;
727
728 direction_t last_direction;
729+ LocationType location_type;
730+ uint64_t last_n_entries;
731
732 char *path;
733 struct stat last_stat;
734@@ -72,6 +88,11 @@ typedef struct JournalFile {
735 HashItem *field_hash_table;
736
737 uint64_t current_offset;
738+ uint64_t current_seqnum;
739+ uint64_t current_realtime;
740+ uint64_t current_monotonic;
741+ sd_id128_t current_boot_id;
742+ uint64_t current_xor_hash;
743
744 JournalMetrics metrics;
745 MMapCache *mmap;
746@@ -160,13 +181,13 @@ static inline bool VALID_EPOCH(uint64_t u) {
747 #define JOURNAL_HEADER_COMPRESSED_LZ4(h) \
748 (!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_LZ4))
749
750-int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret);
751+int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret);
752
753 uint64_t journal_file_entry_n_items(Object *o) _pure_;
754 uint64_t journal_file_entry_array_n_items(Object *o) _pure_;
755 uint64_t journal_file_hash_table_n_items(Object *o) _pure_;
756
757-int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset);
758+int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset);
759 int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset);
760
761 int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset);
762@@ -175,12 +196,13 @@ int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, ui
763 int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset);
764 int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset);
765
766-int journal_file_next_entry(JournalFile *f, Object *o, uint64_t p, direction_t direction, Object **ret, uint64_t *offset);
767-int journal_file_skip_entry(JournalFile *f, Object *o, uint64_t p, int64_t skip, Object **ret, uint64_t *offset);
768+void journal_file_reset_location(JournalFile *f);
769+void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset);
770+int journal_file_compare_locations(JournalFile *af, JournalFile *bf);
771+int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *offset);
772
773 int journal_file_next_entry_for_data(JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset);
774
775-int journal_file_move_to_entry_by_offset(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
776 int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
777 int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);
778 int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset);
779@@ -205,21 +227,3 @@ int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *
780 int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to);
781
782 bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec);
783-
784-
785-static unsigned type_to_context(int type) {
786- /* One context for each type, plus one catch-all for the rest */
787- return type > 0 && type < _OBJECT_TYPE_MAX ? type : 0;
788-}
789-
790-static inline int journal_file_object_keep(JournalFile *f, Object *o, uint64_t offset, void **release_cookie) {
791- unsigned context = type_to_context(o->object.type);
792- uint64_t s = le64toh(o->object.size);
793-
794- return mmap_cache_get(f->mmap, f->fd, f->prot, context, true,
795- offset, s, &f->last_stat, NULL, release_cookie);
796-}
797-
798-static inline int journal_file_object_release(JournalFile *f, void *release_cookie) {
799- return mmap_cache_release(f->mmap, f->fd, release_cookie);
800-}
801diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
802index 70847db..e99050c 100644
803--- a/src/journal/journal-internal.h
804+++ b/src/journal/journal-internal.h
805@@ -57,20 +57,6 @@ struct Match {
806 LIST_HEAD(Match, matches);
807 };
808
809-typedef enum LocationType {
810- /* The first and last entries, resp. */
811- LOCATION_HEAD,
812- LOCATION_TAIL,
813-
814- /* We already read the entry we currently point to, and the
815- * next one to read should probably not be this one again. */
816- LOCATION_DISCRETE,
817-
818- /* We should seek to the precise location specified, and
819- * return it, as we haven't read it yet. */
820- LOCATION_SEEK
821-} LocationType;
822-
823 struct Location {
824 LocationType type;
825
826diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
827index f74adcb..5baa22d 100644
828--- a/src/journal/journal-verify.c
829+++ b/src/journal/journal-verify.c
830@@ -368,7 +368,7 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
831
832 c = (a + b) / 2;
833
834- r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z, NULL);
835+ r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
836 if (r < 0)
837 return r;
838
839@@ -865,7 +865,7 @@ int journal_file_verify(
840 if (show_progress)
841 draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
842
843- r = journal_file_move_to_object(f, -1, p, &o);
844+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
845 if (r < 0) {
846 error(p, "invalid object");
847 goto fail;
848@@ -1085,11 +1085,11 @@ int journal_file_verify(
849 q = last_tag;
850
851 while (q <= p) {
852- r = journal_file_move_to_object(f, -1, q, &o);
853+ r = journal_file_move_to_object(f, OBJECT_UNUSED, q, &o);
854 if (r < 0)
855 goto fail;
856
857- r = journal_file_hmac_put_object(f, -1, o, q);
858+ r = journal_file_hmac_put_object(f, OBJECT_UNUSED, o, q);
859 if (r < 0)
860 goto fail;
861
862@@ -1097,7 +1097,7 @@ int journal_file_verify(
863 }
864
865 /* Position might have changed, let's reposition things */
866- r = journal_file_move_to_object(f, -1, p, &o);
867+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
868 if (r < 0)
869 goto fail;
870
871diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
872index f50faf4..03579fd 100644
873--- a/src/journal/journalctl.c
874+++ b/src/journal/journalctl.c
875@@ -682,7 +682,7 @@ static int parse_argv(int argc, char *argv[]) {
876 assert_not_reached("Unhandled option");
877 }
878
879- if (arg_follow && !arg_no_tail && arg_lines == ARG_LINES_DEFAULT)
880+ if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT)
881 arg_lines = 10;
882
883 if (!!arg_directory + !!arg_file + !!arg_machine > 1) {
884diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
885index a635202..655e2dd 100644
886--- a/src/journal/journald-native.c
887+++ b/src/journal/journald-native.c
888@@ -132,8 +132,8 @@ void server_process_native_message(
889
890 /* A property follows */
891
892- /* n received properties, +1 for _TRANSPORT */
893- if (!GREEDY_REALLOC(iovec, m, n + 1 + N_IOVEC_META_FIELDS + !!object_pid * N_IOVEC_OBJECT_FIELDS)) {
894+ /* n existing properties, 1 new, +1 for _TRANSPORT */
895+ if (!GREEDY_REALLOC(iovec, m, n + 2 + N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS)) {
896 log_oom();
897 break;
898 }
899diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
900index 12735c4..08b143b 100644
901--- a/src/journal/journald-server.c
902+++ b/src/journal/journald-server.c
903@@ -1655,6 +1655,7 @@ void server_done(Server *s) {
904 free(s->buffer);
905 free(s->tty_path);
906 free(s->cgroup_root);
907+ free(s->hostname_field);
908
909 if (s->mmap)
910 mmap_cache_unref(s->mmap);
911diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
912index b7db6f1..f6f669d 100644
913--- a/src/journal/mmap-cache.c
914+++ b/src/journal/mmap-cache.c
915@@ -38,7 +38,7 @@ typedef struct FileDescriptor FileDescriptor;
916 struct Window {
917 MMapCache *cache;
918
919- unsigned keep_always;
920+ bool keep_always;
921 bool in_unused;
922
923 int prot;
924@@ -76,7 +76,7 @@ struct MMapCache {
925
926
927 Hashmap *fds;
928- Hashmap *contexts;
929+ Context *contexts[MMAP_CACHE_MAX_CONTEXTS];
930
931 LIST_HEAD(Window, unused);
932 Window *last_unused;
933@@ -185,7 +185,7 @@ static void context_detach_window(Context *c) {
934 c->window = NULL;
935 LIST_REMOVE(by_window, w->contexts, c);
936
937- if (!w->contexts && w->keep_always == 0) {
938+ if (!w->contexts && !w->keep_always) {
939 /* Not used anymore? */
940 LIST_PREPEND(unused, c->cache->unused, w);
941 if (!c->cache->last_unused)
942@@ -219,18 +219,13 @@ static void context_attach_window(Context *c, Window *w) {
943
944 static Context *context_add(MMapCache *m, unsigned id) {
945 Context *c;
946- int r;
947
948 assert(m);
949
950- c = hashmap_get(m->contexts, UINT_TO_PTR(id + 1));
951+ c = m->contexts[id];
952 if (c)
953 return c;
954
955- r = hashmap_ensure_allocated(&m->contexts, NULL);
956- if (r < 0)
957- return NULL;
958-
959 c = new0(Context, 1);
960 if (!c)
961 return NULL;
962@@ -238,11 +233,8 @@ static Context *context_add(MMapCache *m, unsigned id) {
963 c->cache = m;
964 c->id = id;
965
966- r = hashmap_put(m->contexts, UINT_TO_PTR(id + 1), c);
967- if (r < 0) {
968- free(c);
969- return NULL;
970- }
971+ assert(!m->contexts[id]);
972+ m->contexts[id] = c;
973
974 return c;
975 }
976@@ -252,8 +244,10 @@ static void context_free(Context *c) {
977
978 context_detach_window(c);
979
980- if (c->cache)
981- assert_se(hashmap_remove(c->cache->contexts, UINT_TO_PTR(c->id + 1)));
982+ if (c->cache) {
983+ assert(c->cache->contexts[c->id] == c);
984+ c->cache->contexts[c->id] = NULL;
985+ }
986
987 free(c);
988 }
989@@ -302,15 +296,14 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) {
990 }
991
992 static void mmap_cache_free(MMapCache *m) {
993- Context *c;
994 FileDescriptor *f;
995+ int i;
996
997 assert(m);
998
999- while ((c = hashmap_first(m->contexts)))
1000- context_free(c);
1001-
1002- hashmap_free(m->contexts);
1003+ for (i = 0; i < MMAP_CACHE_MAX_CONTEXTS; i++)
1004+ if (m->contexts[i])
1005+ context_free(m->contexts[i]);
1006
1007 while ((f = hashmap_first(m->fds)))
1008 fd_free(f);
1009@@ -352,8 +345,7 @@ static int try_context(
1010 bool keep_always,
1011 uint64_t offset,
1012 size_t size,
1013- void **ret,
1014- void **release_cookie) {
1015+ void **ret) {
1016
1017 Context *c;
1018
1019@@ -361,8 +353,9 @@ static int try_context(
1020 assert(m->n_ref > 0);
1021 assert(fd >= 0);
1022 assert(size > 0);
1023+ assert(ret);
1024
1025- c = hashmap_get(m->contexts, UINT_TO_PTR(context+1));
1026+ c = m->contexts[context];
1027 if (!c)
1028 return 0;
1029
1030@@ -378,12 +371,9 @@ static int try_context(
1031 return 0;
1032 }
1033
1034- c->window->keep_always += keep_always;
1035+ c->window->keep_always |= keep_always;
1036
1037- if (ret)
1038- *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
1039- if (keep_always && release_cookie)
1040- *release_cookie = c->window;
1041+ *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
1042 return 1;
1043 }
1044
1045@@ -395,8 +385,7 @@ static int find_mmap(
1046 bool keep_always,
1047 uint64_t offset,
1048 size_t size,
1049- void **ret,
1050- void **release_cookie) {
1051+ void **ret) {
1052
1053 FileDescriptor *f;
1054 Window *w;
1055@@ -427,10 +416,7 @@ static int find_mmap(
1056 context_attach_window(c, w);
1057 w->keep_always += keep_always;
1058
1059- if (ret)
1060- *ret = (uint8_t*) w->ptr + (offset - w->offset);
1061- if (keep_always && release_cookie)
1062- *release_cookie = c->window;
1063+ *ret = (uint8_t*) w->ptr + (offset - w->offset);
1064 return 1;
1065 }
1066
1067@@ -443,8 +429,7 @@ static int add_mmap(
1068 uint64_t offset,
1069 size_t size,
1070 struct stat *st,
1071- void **ret,
1072- void **release_cookie) {
1073+ void **ret) {
1074
1075 uint64_t woffset, wsize;
1076 Context *c;
1077@@ -457,6 +442,7 @@ static int add_mmap(
1078 assert(m->n_ref > 0);
1079 assert(fd >= 0);
1080 assert(size > 0);
1081+ assert(ret);
1082
1083 woffset = offset & ~((uint64_t) page_size() - 1ULL);
1084 wsize = size + (offset - woffset);
1085@@ -526,10 +512,7 @@ static int add_mmap(
1086 c->window = w;
1087 LIST_PREPEND(by_window, w->contexts, c);
1088
1089- if (ret)
1090- *ret = (uint8_t*) w->ptr + (offset - w->offset);
1091- if (keep_always && release_cookie)
1092- *release_cookie = c->window;
1093+ *ret = (uint8_t*) w->ptr + (offset - w->offset);
1094 return 1;
1095
1096 outofmem:
1097@@ -546,8 +529,7 @@ int mmap_cache_get(
1098 uint64_t offset,
1099 size_t size,
1100 struct stat *st,
1101- void **ret,
1102- void **release_cookie) {
1103+ void **ret) {
1104
1105 int r;
1106
1107@@ -555,16 +537,18 @@ int mmap_cache_get(
1108 assert(m->n_ref > 0);
1109 assert(fd >= 0);
1110 assert(size > 0);
1111+ assert(ret);
1112+ assert(context < MMAP_CACHE_MAX_CONTEXTS);
1113
1114 /* Check whether the current context is the right one already */
1115- r = try_context(m, fd, prot, context, keep_always, offset, size, ret, release_cookie);
1116+ r = try_context(m, fd, prot, context, keep_always, offset, size, ret);
1117 if (r != 0) {
1118 m->n_hit ++;
1119 return r;
1120 }
1121
1122 /* Search for a matching mmap */
1123- r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret, release_cookie);
1124+ r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret);
1125 if (r != 0) {
1126 m->n_hit ++;
1127 return r;
1128@@ -573,39 +557,7 @@ int mmap_cache_get(
1129 m->n_missed++;
1130
1131 /* Create a new mmap */
1132- return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret, release_cookie);
1133-}
1134-
1135-int mmap_cache_release(
1136- MMapCache *m,
1137- int fd,
1138- void *release_cookie) {
1139-
1140- FileDescriptor *f;
1141- Window *w;
1142-
1143- assert(m);
1144- assert(m->n_ref > 0);
1145- assert(fd >= 0);
1146-
1147- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
1148- if (!f)
1149- return -EBADF;
1150-
1151- assert(f->fd == fd);
1152-
1153- LIST_FOREACH(by_fd, w, f->windows)
1154- if (w == release_cookie)
1155- break;
1156-
1157- if (!w)
1158- return -ENOENT;
1159-
1160- if (w->keep_always == 0)
1161- return -ENOLCK;
1162-
1163- w->keep_always -= 1;
1164- return 0;
1165+ return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret);
1166 }
1167
1168 void mmap_cache_close_fd(MMapCache *m, int fd) {
1169@@ -621,18 +573,6 @@ void mmap_cache_close_fd(MMapCache *m, int fd) {
1170 fd_free(f);
1171 }
1172
1173-void mmap_cache_close_context(MMapCache *m, unsigned context) {
1174- Context *c;
1175-
1176- assert(m);
1177-
1178- c = hashmap_get(m->contexts, UINT_TO_PTR(context + 1));
1179- if (!c)
1180- return;
1181-
1182- context_free(c);
1183-}
1184-
1185 unsigned mmap_cache_get_hit(MMapCache *m) {
1186 assert(m);
1187
1188diff --git a/src/journal/mmap-cache.h b/src/journal/mmap-cache.h
1189index 76e5316..fe2c83d 100644
1190--- a/src/journal/mmap-cache.h
1191+++ b/src/journal/mmap-cache.h
1192@@ -25,6 +25,8 @@
1193 #include <stdbool.h>
1194 #include <sys/stat.h>
1195
1196+#define MMAP_CACHE_MAX_CONTEXTS 8
1197+
1198 typedef struct MMapCache MMapCache;
1199
1200 MMapCache* mmap_cache_new(void);
1201@@ -40,14 +42,8 @@ int mmap_cache_get(
1202 uint64_t offset,
1203 size_t size,
1204 struct stat *st,
1205- void **ret,
1206- void **release_cookie);
1207-int mmap_cache_release(
1208- MMapCache *m,
1209- int fd,
1210- void *release_cookie);
1211+ void **ret);
1212 void mmap_cache_close_fd(MMapCache *m, int fd);
1213-void mmap_cache_close_context(MMapCache *m, unsigned context);
1214
1215 unsigned mmap_cache_get_hit(MMapCache *m);
1216 unsigned mmap_cache_get_missed(MMapCache *m);
1217diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
1218index cf21c4d..cb7fc32 100644
1219--- a/src/journal/sd-journal.c
1220+++ b/src/journal/sd-journal.c
1221@@ -87,7 +87,7 @@ static void detach_location(sd_journal *j) {
1222 j->current_field = 0;
1223
1224 ORDERED_HASHMAP_FOREACH(f, j->files, i)
1225- f->current_offset = 0;
1226+ journal_file_reset_location(f);
1227 }
1228
1229 static void reset_location(sd_journal *j) {
1230@@ -114,20 +114,19 @@ static void init_location(Location *l, LocationType type, JournalFile *f, Object
1231 l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
1232 }
1233
1234-static void set_location(sd_journal *j, LocationType type, JournalFile *f, Object *o,
1235- direction_t direction, uint64_t offset) {
1236+static void set_location(sd_journal *j, JournalFile *f, Object *o) {
1237 assert(j);
1238- assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
1239 assert(f);
1240 assert(o);
1241
1242- init_location(&j->current_location, type, f, o);
1243+ init_location(&j->current_location, LOCATION_DISCRETE, f, o);
1244
1245 j->current_file = f;
1246 j->current_field = 0;
1247
1248- f->last_direction = direction;
1249- f->current_offset = offset;
1250+ /* Let f know its candidate entry was picked. */
1251+ assert(f->location_type == LOCATION_SEEK);
1252+ f->location_type = LOCATION_DISCRETE;
1253 }
1254
1255 static int match_is_valid(const void *data, size_t size) {
1256@@ -413,144 +412,51 @@ _public_ void sd_journal_flush_matches(sd_journal *j) {
1257 detach_location(j);
1258 }
1259
1260-static int compare_entry_order(JournalFile *af, Object *_ao,
1261- JournalFile *bf, uint64_t bp) {
1262-
1263- uint64_t a, b;
1264- Object *ao, *bo;
1265- int r;
1266-
1267- assert(af);
1268- assert(bf);
1269- assert(_ao);
1270-
1271- /* The mmap cache might invalidate the object from the first
1272- * file if we look at the one from the second file. Hence
1273- * temporarily copy the header of the first one, and look at
1274- * that only. */
1275- ao = alloca(offsetof(EntryObject, items));
1276- memcpy(ao, _ao, offsetof(EntryObject, items));
1277-
1278- r = journal_file_move_to_object(bf, OBJECT_ENTRY, bp, &bo);
1279- if (r < 0)
1280- return strcmp(af->path, bf->path);
1281-
1282- /* We operate on two different files here, hence we can access
1283- * two objects at the same time, which we normally can't.
1284- *
1285- * If contents and timestamps match, these entries are
1286- * identical, even if the seqnum does not match */
1287-
1288- if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id) &&
1289- ao->entry.monotonic == bo->entry.monotonic &&
1290- ao->entry.realtime == bo->entry.realtime &&
1291- ao->entry.xor_hash == bo->entry.xor_hash)
1292- return 0;
1293-
1294- if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
1295-
1296- /* If this is from the same seqnum source, compare
1297- * seqnums */
1298- a = le64toh(ao->entry.seqnum);
1299- b = le64toh(bo->entry.seqnum);
1300-
1301- if (a < b)
1302- return -1;
1303- if (a > b)
1304- return 1;
1305-
1306- /* Wow! This is weird, different data but the same
1307- * seqnums? Something is borked, but let's make the
1308- * best of it and compare by time. */
1309- }
1310-
1311- if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id)) {
1312-
1313- /* If the boot id matches, compare monotonic time */
1314- a = le64toh(ao->entry.monotonic);
1315- b = le64toh(bo->entry.monotonic);
1316-
1317- if (a < b)
1318- return -1;
1319- if (a > b)
1320- return 1;
1321- }
1322-
1323- /* Otherwise, compare UTC time */
1324- a = le64toh(ao->entry.realtime);
1325- b = le64toh(bo->entry.realtime);
1326-
1327- if (a < b)
1328- return -1;
1329- if (a > b)
1330- return 1;
1331-
1332- /* Finally, compare by contents */
1333- a = le64toh(ao->entry.xor_hash);
1334- b = le64toh(bo->entry.xor_hash);
1335-
1336- if (a < b)
1337- return -1;
1338- if (a > b)
1339- return 1;
1340-
1341- return 0;
1342-}
1343-
1344-_pure_ static int compare_with_location(JournalFile *af, Object *ao, Location *l) {
1345- uint64_t a;
1346-
1347- assert(af);
1348- assert(ao);
1349+_pure_ static int compare_with_location(JournalFile *f, Location *l) {
1350+ assert(f);
1351 assert(l);
1352+ assert(f->location_type == LOCATION_SEEK);
1353 assert(l->type == LOCATION_DISCRETE || l->type == LOCATION_SEEK);
1354
1355 if (l->monotonic_set &&
1356- sd_id128_equal(ao->entry.boot_id, l->boot_id) &&
1357+ sd_id128_equal(f->current_boot_id, l->boot_id) &&
1358 l->realtime_set &&
1359- le64toh(ao->entry.realtime) == l->realtime &&
1360+ f->current_realtime == l->realtime &&
1361 l->xor_hash_set &&
1362- le64toh(ao->entry.xor_hash) == l->xor_hash)
1363+ f->current_xor_hash == l->xor_hash)
1364 return 0;
1365
1366 if (l->seqnum_set &&
1367- sd_id128_equal(af->header->seqnum_id, l->seqnum_id)) {
1368-
1369- a = le64toh(ao->entry.seqnum);
1370+ sd_id128_equal(f->header->seqnum_id, l->seqnum_id)) {
1371
1372- if (a < l->seqnum)
1373+ if (f->current_seqnum < l->seqnum)
1374 return -1;
1375- if (a > l->seqnum)
1376+ if (f->current_seqnum > l->seqnum)
1377 return 1;
1378 }
1379
1380 if (l->monotonic_set &&
1381- sd_id128_equal(ao->entry.boot_id, l->boot_id)) {
1382+ sd_id128_equal(f->current_boot_id, l->boot_id)) {
1383
1384- a = le64toh(ao->entry.monotonic);
1385-
1386- if (a < l->monotonic)
1387+ if (f->current_monotonic < l->monotonic)
1388 return -1;
1389- if (a > l->monotonic)
1390+ if (f->current_monotonic > l->monotonic)
1391 return 1;
1392 }
1393
1394 if (l->realtime_set) {
1395
1396- a = le64toh(ao->entry.realtime);
1397-
1398- if (a < l->realtime)
1399+ if (f->current_realtime < l->realtime)
1400 return -1;
1401- if (a > l->realtime)
1402+ if (f->current_realtime > l->realtime)
1403 return 1;
1404 }
1405
1406 if (l->xor_hash_set) {
1407- a = le64toh(ao->entry.xor_hash);
1408
1409- if (a < l->xor_hash)
1410+ if (f->current_xor_hash < l->xor_hash)
1411 return -1;
1412- if (a > l->xor_hash)
1413+ if (f->current_xor_hash > l->xor_hash)
1414 return 1;
1415 }
1416
1417@@ -766,9 +672,9 @@ static int find_location_with_matches(
1418 /* No matches is simple */
1419
1420 if (j->current_location.type == LOCATION_HEAD)
1421- return journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, ret, offset);
1422+ return journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset);
1423 if (j->current_location.type == LOCATION_TAIL)
1424- return journal_file_next_entry(f, NULL, 0, DIRECTION_UP, ret, offset);
1425+ return journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset);
1426 if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
1427 return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
1428 if (j->current_location.monotonic_set) {
1429@@ -779,7 +685,7 @@ static int find_location_with_matches(
1430 if (j->current_location.realtime_set)
1431 return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset);
1432
1433- return journal_file_next_entry(f, NULL, 0, direction, ret, offset);
1434+ return journal_file_next_entry(f, 0, direction, ret, offset);
1435 } else
1436 return find_location_for_match(j, j->level0, f, direction, ret, offset);
1437 }
1438@@ -791,49 +697,61 @@ static int next_with_matches(
1439 Object **ret,
1440 uint64_t *offset) {
1441
1442- Object *c;
1443- uint64_t cp;
1444-
1445 assert(j);
1446 assert(f);
1447 assert(ret);
1448 assert(offset);
1449
1450- c = *ret;
1451- cp = *offset;
1452-
1453 /* No matches is easy. We simple advance the file
1454 * pointer by one. */
1455 if (!j->level0)
1456- return journal_file_next_entry(f, c, cp, direction, ret, offset);
1457+ return journal_file_next_entry(f, f->current_offset, direction, ret, offset);
1458
1459 /* If we have a match then we look for the next matching entry
1460 * with an offset at least one step larger */
1461- return next_for_match(j, j->level0, f, direction == DIRECTION_DOWN ? cp+1 : cp-1, direction, ret, offset);
1462+ return next_for_match(j, j->level0, f,
1463+ direction == DIRECTION_DOWN ? f->current_offset + 1
1464+ : f->current_offset - 1,
1465+ direction, ret, offset);
1466 }
1467
1468-static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) {
1469+static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction) {
1470 Object *c;
1471- uint64_t cp;
1472+ uint64_t cp, n_entries;
1473 int r;
1474
1475 assert(j);
1476 assert(f);
1477
1478- if (f->last_direction == direction && f->current_offset > 0) {
1479- cp = f->current_offset;
1480+ n_entries = le64toh(f->header->n_entries);
1481
1482- r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c);
1483- if (r < 0)
1484- return r;
1485+ /* If we hit EOF before, we don't need to look into this file again
1486+ * unless direction changed or new entries appeared. */
1487+ if (f->last_direction == direction && f->location_type == LOCATION_TAIL &&
1488+ n_entries == f->last_n_entries)
1489+ return 0;
1490
1491- r = next_with_matches(j, f, direction, &c, &cp);
1492- if (r <= 0)
1493- return r;
1494+ f->last_n_entries = n_entries;
1495+
1496+ if (f->last_direction == direction && f->current_offset > 0) {
1497+ /* LOCATION_SEEK here means we did the work in a previous
1498+ * iteration and the current location already points to a
1499+ * candidate entry. */
1500+ if (f->location_type != LOCATION_SEEK) {
1501+ r = next_with_matches(j, f, direction, &c, &cp);
1502+ if (r <= 0)
1503+ return r;
1504+
1505+ journal_file_save_location(f, c, cp);
1506+ }
1507 } else {
1508+ f->last_direction = direction;
1509+
1510 r = find_location_with_matches(j, f, direction, &c, &cp);
1511 if (r <= 0)
1512 return r;
1513+
1514+ journal_file_save_location(f, c, cp);
1515 }
1516
1517 /* OK, we found the spot, now let's advance until an entry
1518@@ -848,30 +766,25 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
1519 if (j->current_location.type == LOCATION_DISCRETE) {
1520 int k;
1521
1522- k = compare_with_location(f, c, &j->current_location);
1523+ k = compare_with_location(f, &j->current_location);
1524
1525 found = direction == DIRECTION_DOWN ? k > 0 : k < 0;
1526 } else
1527 found = true;
1528
1529- if (found) {
1530- if (ret)
1531- *ret = c;
1532- if (offset)
1533- *offset = cp;
1534+ if (found)
1535 return 1;
1536- }
1537
1538 r = next_with_matches(j, f, direction, &c, &cp);
1539 if (r <= 0)
1540 return r;
1541+
1542+ journal_file_save_location(f, c, cp);
1543 }
1544 }
1545
1546 static int real_journal_next(sd_journal *j, direction_t direction) {
1547 JournalFile *f, *new_file = NULL;
1548- uint64_t new_offset = 0;
1549- uint64_t p = 0;
1550 Iterator i;
1551 Object *o;
1552 int r;
1553@@ -882,38 +795,38 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
1554 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1555 bool found;
1556
1557- r = next_beyond_location(j, f, direction, &o, &p);
1558+ r = next_beyond_location(j, f, direction);
1559 if (r < 0) {
1560 log_debug("Can't iterate through %s, ignoring: %s", f->path, strerror(-r));
1561 remove_file_real(j, f);
1562 continue;
1563- } else if (r == 0)
1564+ } else if (r == 0) {
1565+ f->location_type = LOCATION_TAIL;
1566 continue;
1567+ }
1568
1569 if (!new_file)
1570 found = true;
1571 else {
1572 int k;
1573
1574- k = compare_entry_order(f, o, new_file, new_offset);
1575+ k = journal_file_compare_locations(f, new_file);
1576
1577 found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
1578 }
1579
1580- if (found) {
1581+ if (found)
1582 new_file = f;
1583- new_offset = p;
1584- }
1585 }
1586
1587 if (!new_file)
1588 return 0;
1589
1590- r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_offset, &o);
1591+ r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_file->current_offset, &o);
1592 if (r < 0)
1593 return r;
1594
1595- set_location(j, LOCATION_DISCRETE, new_file, o, direction, new_offset);
1596+ set_location(j, new_file, o);
1597
1598 return 1;
1599 }
1600@@ -2526,7 +2439,6 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
1601 size_t ol;
1602 bool found;
1603 int r;
1604- void *release_cookie;
1605
1606 /* Proceed to next data object in the field's linked list */
1607 if (j->unique_offset == 0) {
1608@@ -2552,10 +2464,10 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
1609 continue;
1610 }
1611
1612- /* We do not use the type context here, but 0 instead,
1613- * so that we can look at this data object at the same
1614+ /* We do not use OBJECT_DATA context here, but OBJECT_UNUSED
1615+ * instead, so that we can look at this data object at the same
1616 * time as one on another file */
1617- r = journal_file_move_to_object(j->unique_file, 0, j->unique_offset, &o);
1618+ r = journal_file_move_to_object(j->unique_file, OBJECT_UNUSED, j->unique_offset, &o);
1619 if (r < 0)
1620 return r;
1621
1622@@ -2567,10 +2479,6 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
1623 return -EBADMSG;
1624 }
1625
1626- r = journal_file_object_keep(j->unique_file, o, j->unique_offset, &release_cookie);
1627- if (r < 0)
1628- return r;
1629-
1630 r = return_data(j, j->unique_file, o, &odata, &ol);
1631 if (r < 0)
1632 return r;
1633@@ -2615,10 +2523,6 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
1634 found = true;
1635 }
1636
1637- r = journal_file_object_release(j->unique_file, release_cookie);
1638- if (r < 0)
1639- return r;
1640-
1641 if (found)
1642 continue;
1643
1644diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
1645index 372f3ed..d56ee51 100644
1646--- a/src/libsystemd-network/network-internal.c
1647+++ b/src/libsystemd-network/network-internal.c
1648@@ -392,10 +392,12 @@ void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *route
1649
1650 fprintf(f, "%s=", key);
1651
1652- for (i = 0; i < size; i++)
1653- fprintf(f, "%s/%" PRIu8 ",%s%s", inet_ntoa(routes[i].dst_addr),
1654- routes[i].dst_prefixlen, inet_ntoa(routes[i].gw_addr),
1655+ for (i = 0; i < size; i++) {
1656+ fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
1657+ routes[i].dst_prefixlen);
1658+ fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
1659 (i < (size - 1)) ? " ": "");
1660+ }
1661
1662 fputs("\n", f);
1663 }
1664diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
1665index 0eba4c3..9986b52 100644
1666--- a/src/libsystemd-network/sd-dhcp-client.c
1667+++ b/src/libsystemd-network/sd-dhcp-client.c
1668@@ -68,7 +68,6 @@ struct sd_dhcp_client {
1669 uint32_t mtu;
1670 uint32_t xid;
1671 usec_t start_time;
1672- uint16_t secs;
1673 unsigned int attempt;
1674 usec_t request_sent;
1675 sd_event_source *timeout_t1;
1676@@ -321,10 +320,12 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
1677 _cleanup_free_ DHCPPacket *packet;
1678 size_t optlen, optoffset, size;
1679 be16_t max_size;
1680+ usec_t time_now;
1681+ uint16_t secs;
1682 int r;
1683
1684 assert(client);
1685- assert(client->secs);
1686+ assert(client->start_time);
1687 assert(ret);
1688 assert(_optlen);
1689 assert(_optoffset);
1690@@ -344,7 +345,15 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
1691
1692 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
1693 refuse to issue an DHCP lease if 'secs' is set to zero */
1694- packet->dhcp.secs = htobe16(client->secs);
1695+ r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1696+ if (r < 0)
1697+ return r;
1698+ assert(time_now >= client->start_time);
1699+
1700+ /* seconds between sending first and last DISCOVER
1701+ * must always be strictly positive to deal with broken servers */
1702+ secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
1703+ packet->dhcp.secs = htobe16(secs);
1704
1705 /* RFC2132 section 4.1
1706 A client that cannot receive unicast IP datagrams until its protocol
1707@@ -441,24 +450,12 @@ static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
1708 static int client_send_discover(sd_dhcp_client *client) {
1709 _cleanup_free_ DHCPPacket *discover = NULL;
1710 size_t optoffset, optlen;
1711- usec_t time_now;
1712 int r;
1713
1714 assert(client);
1715 assert(client->state == DHCP_STATE_INIT ||
1716 client->state == DHCP_STATE_SELECTING);
1717
1718- /* See RFC2131 section 4.4.1 */
1719-
1720- r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1721- if (r < 0)
1722- return r;
1723- assert(time_now >= client->start_time);
1724-
1725- /* seconds between sending first and last DISCOVER
1726- * must always be strictly positive to deal with broken servers */
1727- client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
1728-
1729 r = client_message_init(client, &discover, DHCP_DISCOVER,
1730 &optlen, &optoffset);
1731 if (r < 0)
1732@@ -875,10 +872,8 @@ static int client_start(sd_dhcp_client *client) {
1733 }
1734 client->fd = r;
1735
1736- if (client->state == DHCP_STATE_INIT) {
1737+ if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
1738 client->start_time = now(clock_boottime_or_monotonic());
1739- client->secs = 0;
1740- }
1741
1742 return client_initialize_events(client, client_receive_message_raw);
1743 }
1744@@ -1269,6 +1264,9 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1745 if (r >= 0) {
1746 client->timeout_resend =
1747 sd_event_source_unref(client->timeout_resend);
1748+ client->receive_message =
1749+ sd_event_source_unref(client->receive_message);
1750+ client->fd = asynchronous_close(client->fd);
1751
1752 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1753 DHCP_STATE_REBOOTING))
1754diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
1755index 4fb01c0..b7c9a07 100644
1756--- a/src/libsystemd-network/sd-dhcp-lease.c
1757+++ b/src/libsystemd-network/sd-dhcp-lease.c
1758@@ -50,7 +50,7 @@ int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
1759
1760 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
1761 assert_return(lease, -EINVAL);
1762- assert_return(lease, -EINVAL);
1763+ assert_return(lifetime, -EINVAL);
1764
1765 *lifetime = lease->lifetime;
1766
1767diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
1768index fa4f9b5..dbec1a2 100644
1769--- a/src/libsystemd-network/sd-dhcp6-client.c
1770+++ b/src/libsystemd-network/sd-dhcp6-client.c
1771@@ -200,19 +200,19 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
1772
1773 switch (type) {
1774 case DHCP6_DUID_LLT:
1775- if (duid_len <= sizeof(client->duid.llt))
1776+ if (duid_len <= sizeof(client->duid.llt) - 2)
1777 return -EINVAL;
1778 break;
1779 case DHCP6_DUID_EN:
1780- if (duid_len != sizeof(client->duid.en))
1781+ if (duid_len != sizeof(client->duid.en) - 2)
1782 return -EINVAL;
1783 break;
1784 case DHCP6_DUID_LL:
1785- if (duid_len <= sizeof(client->duid.ll))
1786+ if (duid_len <= sizeof(client->duid.ll) - 2)
1787 return -EINVAL;
1788 break;
1789 case DHCP6_DUID_UUID:
1790- if (duid_len != sizeof(client->duid.uuid))
1791+ if (duid_len != sizeof(client->duid.uuid) - 2)
1792 return -EINVAL;
1793 break;
1794 default:
1795@@ -222,7 +222,7 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
1796
1797 client->duid.raw.type = htobe16(type);
1798 memcpy(&client->duid.raw.data, duid, duid_len);
1799- client->duid_len = duid_len;
1800+ client->duid_len = duid_len + 2; /* +2 for sizeof(type) */
1801
1802 return 0;
1803 }
1804diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
1805index 18afe0f..5658c61 100644
1806--- a/src/libsystemd/sd-bus/bus-match.c
1807+++ b/src/libsystemd/sd-bus/bus-match.c
1808@@ -537,7 +537,7 @@ static int bus_match_find_compare_value(
1809 else if (BUS_MATCH_CAN_HASH(t))
1810 n = hashmap_get(c->compare.children, value_str);
1811 else {
1812- for (n = c->child; !value_node_same(n, t, value_u8, value_str); n = n->next)
1813+ for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next)
1814 ;
1815 }
1816
1817diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
1818index 0ab1119..6c3230a 100644
1819--- a/src/libsystemd/sd-bus/bus-objects.c
1820+++ b/src/libsystemd/sd-bus/bus-objects.c
1821@@ -617,6 +617,9 @@ static int property_get_set_callbacks_run(
1822 return r;
1823
1824 } else {
1825+ const char *signature = NULL;
1826+ char type = 0;
1827+
1828 if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
1829 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member);
1830
1831@@ -628,6 +631,13 @@ static int property_get_set_callbacks_run(
1832
1833 c->last_iteration = bus->iteration_counter;
1834
1835+ r = sd_bus_message_peek_type(m, &type, &signature);
1836+ if (r < 0)
1837+ return r;
1838+
1839+ if (type != 'v' || !streq(strempty(signature), strempty(c->vtable->x.property.signature)))
1840+ return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Incorrect parameters for property '%s', expected '%s', got '%s'.", c->member, strempty(c->vtable->x.property.signature), strempty(signature));
1841+
1842 r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
1843 if (r < 0)
1844 return r;
1845diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
1846index b501a52..740133a 100644
1847--- a/src/libsystemd/sd-rtnl/rtnl-message.c
1848+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
1849@@ -36,6 +36,8 @@
1850 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
1851 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
1852
1853+#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
1854+
1855 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
1856 sd_rtnl_message *m;
1857
1858@@ -566,8 +568,8 @@ int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const
1859 size = (size_t)r;
1860
1861 if (size) {
1862- length = strnlen(data, size);
1863- if (length >= size)
1864+ length = strnlen(data, size+1);
1865+ if (length > size)
1866 return -EINVAL;
1867 } else
1868 length = strlen(data);
1869@@ -1066,7 +1068,7 @@ int rtnl_message_parse(sd_rtnl_message *m,
1870 *rta_tb_size = max + 1;
1871
1872 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1873- type = rta->rta_type;
1874+ type = RTA_TYPE(rta);
1875
1876 /* if the kernel is newer than the headers we used
1877 when building, we ignore out-of-range attributes
1878@@ -1222,7 +1224,7 @@ int socket_read_message(sd_rtnl *rtnl) {
1879 }
1880 }
1881
1882- for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1883+ for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
1884 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1885 const NLType *nl_type;
1886
1887@@ -1237,7 +1239,8 @@ int socket_read_message(sd_rtnl *rtnl) {
1888 if (new_msg->nlmsg_type == NLMSG_DONE) {
1889 /* finished reading multi-part message */
1890 done = true;
1891- break;
1892+
1893+ continue;
1894 }
1895
1896 /* check that we support this message type */
1897diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
1898index 2699374..e2afcb8 100644
1899--- a/src/libudev/libudev-device.c
1900+++ b/src/libudev/libudev-device.c
1901@@ -730,8 +730,13 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
1902 return NULL;
1903 } else {
1904 /* everything else just needs to be a directory */
1905- if (stat(path, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
1906+ if (stat(path, &statbuf) != 0)
1907 return NULL;
1908+
1909+ if (!S_ISDIR(statbuf.st_mode)) {
1910+ errno = EISDIR;
1911+ return NULL;
1912+ }
1913 }
1914
1915 udev_device = udev_device_new(udev);
1916diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
1917index b6d9bc6..759794f 100644
1918--- a/src/nspawn/nspawn.c
1919+++ b/src/nspawn/nspawn.c
1920@@ -758,7 +758,7 @@ static int mount_binds(const char *dest, char **l, bool ro) {
1921 * and char devices. */
1922 if (S_ISDIR(source_st.st_mode)) {
1923 r = mkdir_label(where, 0755);
1924- if (r < 0) {
1925+ if (r < 0 && errno != EEXIST) {
1926 log_error("Failed to create mount point %s: %s", where, strerror(-r));
1927
1928 return r;
1929@@ -818,7 +818,7 @@ static int mount_tmpfs(const char *dest) {
1930 return log_oom();
1931
1932 r = mkdir_label(where, 0755);
1933- if (r < 0) {
1934+ if (r < 0 && errno != EEXIST) {
1935 log_error("creating mount point for tmpfs %s failed: %s", where, strerror(-r));
1936
1937 return r;
1938@@ -3073,6 +3073,7 @@ int main(int argc, char *argv[]) {
1939 goto finish;
1940 }
1941 } else {
1942+#if 0
1943 const char *p;
1944
1945 p = strappenda(arg_directory,
1946@@ -3082,6 +3083,7 @@ int main(int argc, char *argv[]) {
1947 goto finish;
1948
1949 }
1950+#endif
1951 }
1952 } else {
1953 char template[] = "/tmp/nspawn-root-XXXXXX";
1954diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
1955index 7375f77..ec8efcc 100644
1956--- a/src/resolve/resolved-dns-packet.c
1957+++ b/src/resolve/resolved-dns-packet.c
1958@@ -866,7 +866,7 @@ fail:
1959
1960 int dns_packet_read_name(DnsPacket *p, char **_ret,
1961 bool allow_compression, size_t *start) {
1962- size_t saved_rindex, after_rindex = 0;
1963+ size_t saved_rindex, after_rindex = 0, jump_barrier;
1964 _cleanup_free_ char *ret = NULL;
1965 size_t n = 0, allocated = 0;
1966 bool first = true;
1967@@ -876,6 +876,7 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
1968 assert(_ret);
1969
1970 saved_rindex = p->rindex;
1971+ jump_barrier = p->rindex;
1972
1973 for (;;) {
1974 uint8_t c, d;
1975@@ -922,7 +923,7 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
1976 goto fail;
1977
1978 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
1979- if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
1980+ if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
1981 r = -EBADMSG;
1982 goto fail;
1983 }
1984@@ -930,9 +931,13 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
1985 if (after_rindex == 0)
1986 after_rindex = p->rindex;
1987
1988+ /* Jumps are limited to a "prior occurence" (RFC-1035 4.1.4) */
1989+ jump_barrier = ptr;
1990 p->rindex = ptr;
1991- } else
1992+ } else {
1993+ r = -EBADMSG;
1994 goto fail;
1995+ }
1996 }
1997
1998 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
1999diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
2000index 7d258c9..6dd4cad 100644
2001--- a/src/resolve/resolved.c
2002+++ b/src/resolve/resolved.c
2003@@ -108,7 +108,7 @@ int main(int argc, char *argv[]) {
2004
2005 finish:
2006 sd_notify(false,
2007- "STOPPIN=1\n"
2008+ "STOPPING=1\n"
2009 "STATUS=Shutting down...");
2010
2011 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2012diff --git a/src/run/run.c b/src/run/run.c
2013index e3b6293..dcefb5c 100644
2014--- a/src/run/run.c
2015+++ b/src/run/run.c
2016@@ -573,9 +573,12 @@ int main(int argc, char* argv[]) {
2017 if (r <= 0)
2018 goto finish;
2019
2020- r = find_binary(argv[optind], &command);
2021+ r = find_binary(argv[optind], arg_transport == BUS_TRANSPORT_LOCAL, &command);
2022 if (r < 0) {
2023- log_error("Failed to find executable %s: %s", argv[optind], strerror(-r));
2024+ log_error("Failed to find executable %s%s: %s",
2025+ argv[optind],
2026+ arg_transport == BUS_TRANSPORT_LOCAL ? "" : " on local system",
2027+ strerror(-r));
2028 goto finish;
2029 }
2030 argv[optind] = command;
2031diff --git a/src/shared/install.c b/src/shared/install.c
2032index 035b44c..cab93e8 100644
2033--- a/src/shared/install.c
2034+++ b/src/shared/install.c
2035@@ -1620,12 +1620,10 @@ int unit_file_enable(
2036 STRV_FOREACH(i, files) {
2037 UnitFileState state;
2038
2039+ /* We only want to know if this unit is masked, so we ignore
2040+ * errors from unit_file_get_state, deferring other checks.
2041+ * This allows templated units to be enabled on the fly. */
2042 state = unit_file_get_state(scope, root_dir, *i);
2043- if (state < 0) {
2044- log_error("Failed to get unit file state for %s: %s", *i, strerror(-state));
2045- return state;
2046- }
2047-
2048 if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
2049 log_error("Failed to enable unit: Unit %s is masked", *i);
2050 return -ENOTSUP;
2051diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
2052index 8f75a8e..c800e01 100644
2053--- a/src/shared/path-lookup.c
2054+++ b/src/shared/path-lookup.c
2055@@ -86,17 +86,14 @@ static char** user_dirs(
2056 const char * const config_unit_paths[] = {
2057 USER_CONFIG_UNIT_PATH,
2058 "/etc/systemd/user",
2059+ "/etc/systemd-mutable/user",
2060 NULL
2061 };
2062
2063 const char * const runtime_unit_path = "/run/systemd/user";
2064
2065 const char * const data_unit_paths[] = {
2066- "/usr/local/lib/systemd/user",
2067- "/usr/local/share/systemd/user",
2068 USER_DATA_UNIT_PATH,
2069- "/usr/lib/systemd/user",
2070- "/usr/share/systemd/user",
2071 NULL
2072 };
2073
2074@@ -260,13 +257,11 @@ int lookup_paths_init(
2075 STRV_IFNOTNULL(generator_early),
2076 USER_CONFIG_UNIT_PATH,
2077 "/etc/systemd/user",
2078+ "/etc/systemd-mutable/user",
2079+ "/nix/var/nix/profiles/default/lib/systemd/user",
2080 "/run/systemd/user",
2081 STRV_IFNOTNULL(generator),
2082- "/usr/local/lib/systemd/user",
2083- "/usr/local/share/systemd/user",
2084 USER_DATA_UNIT_PATH,
2085- "/usr/lib/systemd/user",
2086- "/usr/share/systemd/user",
2087 STRV_IFNOTNULL(generator_late),
2088 NULL);
2089 } else
2090@@ -276,14 +271,11 @@ int lookup_paths_init(
2091 STRV_IFNOTNULL(generator_early),
2092 SYSTEM_CONFIG_UNIT_PATH,
2093 "/etc/systemd/system",
2094+ "/etc/systemd-mutable/system",
2095+ "/nix/var/nix/profiles/default/lib/systemd/system",
2096 "/run/systemd/system",
2097 STRV_IFNOTNULL(generator),
2098- "/usr/local/lib/systemd/system",
2099 SYSTEM_DATA_UNIT_PATH,
2100- "/usr/lib/systemd/system",
2101-#ifdef HAVE_SPLIT_USR
2102- "/lib/systemd/system",
2103-#endif
2104 STRV_IFNOTNULL(generator_late),
2105 NULL);
2106
2107diff --git a/src/shared/path-util.c b/src/shared/path-util.c
2108index 67566bc..be03695 100644
2109--- a/src/shared/path-util.c
2110+++ b/src/shared/path-util.c
2111@@ -563,11 +563,11 @@ int path_is_os_tree(const char *path) {
2112 return r >= 0;
2113 }
2114
2115-int find_binary(const char *name, char **filename) {
2116+int find_binary(const char *name, bool local, char **filename) {
2117 assert(name);
2118
2119 if (is_path(name)) {
2120- if (access(name, X_OK) < 0)
2121+ if (local && access(name, X_OK) < 0)
2122 return -errno;
2123
2124 if (filename) {
2125@@ -657,7 +657,7 @@ int fsck_exists(const char *fstype) {
2126
2127 checker = strappenda("fsck.", fstype);
2128
2129- r = find_binary(checker, &p);
2130+ r = find_binary(checker, true, &p);
2131 if (r < 0)
2132 return r;
2133
2134diff --git a/src/shared/path-util.h b/src/shared/path-util.h
2135index 8d171a5..bd0d324 100644
2136--- a/src/shared/path-util.h
2137+++ b/src/shared/path-util.h
2138@@ -55,7 +55,7 @@ int path_is_mount_point(const char *path, bool allow_symlink);
2139 int path_is_read_only_fs(const char *path);
2140 int path_is_os_tree(const char *path);
2141
2142-int find_binary(const char *name, char **filename);
2143+int find_binary(const char *name, bool local, char **filename);
2144
2145 bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
2146
2147diff --git a/src/shared/virt.c b/src/shared/virt.c
2148index f9c4e67..f3104d5 100644
2149--- a/src/shared/virt.c
2150+++ b/src/shared/virt.c
2151@@ -151,7 +151,7 @@ int detect_vm(const char **id) {
2152 _cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL;
2153 static thread_local int cached_found = -1;
2154 static thread_local const char *cached_id = NULL;
2155- const char *_id = NULL;
2156+ const char *_id = NULL, *_id_cpuid = NULL;
2157 int r;
2158
2159 if (_likely_(cached_found >= 0)) {
2160@@ -197,10 +197,26 @@ int detect_vm(const char **id) {
2161
2162 /* this will set _id to "other" and return 0 for unknown hypervisors */
2163 r = detect_vm_cpuid(&_id);
2164- if (r != 0)
2165+
2166+ /* finish when found a known hypervisor other than kvm */
2167+ if (r < 0 || (r > 0 && !streq(_id, "kvm")))
2168 goto finish;
2169
2170+ _id_cpuid = _id;
2171+
2172 r = detect_vm_dmi(&_id);
2173+
2174+ /* kvm with and without Virtualbox */
2175+ if (streq_ptr(_id_cpuid, "kvm")) {
2176+ if (r > 0 && streq(_id, "oracle"))
2177+ goto finish;
2178+
2179+ _id = _id_cpuid;
2180+ r = 1;
2181+ goto finish;
2182+ }
2183+
2184+ /* information from dmi */
2185 if (r != 0)
2186 goto finish;
2187
2188@@ -293,8 +309,26 @@ int detect_container(const char **id) {
2189
2190 r = read_one_line_file("/run/systemd/container", &m);
2191 if (r == -ENOENT) {
2192- r = 0;
2193- goto finish;
2194+
2195+ /* Fallback for cases where PID 1 was not
2196+ * systemd (for example, cases where
2197+ * init=/bin/sh is used. */
2198+
2199+ r = getenv_for_pid(1, "container", &m);
2200+ if (r <= 0) {
2201+
2202+ /* If that didn't work, give up,
2203+ * assume no container manager.
2204+ *
2205+ * Note: This means we still cannot
2206+ * detect containers if init=/bin/sh
2207+ * is passed but privileges dropped,
2208+ * as /proc/1/environ is only readable
2209+ * with privileges. */
2210+
2211+ r = 0;
2212+ goto finish;
2213+ }
2214 }
2215 if (r < 0)
2216 return r;
2217diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
2218index 28eaa6a..3866308 100644
2219--- a/src/systemctl/systemctl.c
2220+++ b/src/systemctl/systemctl.c
2221@@ -2651,7 +2651,7 @@ static int start_unit_one(
2222
2223 log_debug("Adding %s to the set", p);
2224 r = set_consume(s, p);
2225- if (r < 0)
2226+ if (r < 0 && r != -EEXIST)
2227 return log_oom();
2228 }
2229
2230@@ -6917,8 +6917,13 @@ done:
2231
2232 static int halt_now(enum action a) {
2233
2234-/* Make sure C-A-D is handled by the kernel from this
2235- * point on... */
2236+ /* The kernel will automaticall flush ATA disks and suchlike
2237+ * on reboot(), but the file systems need to be synce'd
2238+ * explicitly in advance. */
2239+ sync();
2240+
2241+ /* Make sure C-A-D is handled by the kernel from this point
2242+ * on... */
2243 reboot(RB_ENABLE_CAD);
2244
2245 switch (a) {
2246diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
2247index eb24372..00237a2 100644
2248--- a/src/systemd/sd-journal.h
2249+++ b/src/systemd/sd-journal.h
2250@@ -138,13 +138,15 @@ int sd_journal_reliable_fd(sd_journal *j);
2251 int sd_journal_get_catalog(sd_journal *j, char **text);
2252 int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **text);
2253
2254+/* the inverse condition avoids ambiguity of danling 'else' after the macro */
2255 #define SD_JOURNAL_FOREACH(j) \
2256- if (sd_journal_seek_head(j) >= 0) \
2257- while (sd_journal_next(j) > 0)
2258+ if (sd_journal_seek_head(j) < 0) { } \
2259+ else while (sd_journal_next(j) > 0)
2260
2261+/* the inverse condition avoids ambiguity of danling 'else' after the macro */
2262 #define SD_JOURNAL_FOREACH_BACKWARDS(j) \
2263- if (sd_journal_seek_tail(j) >= 0) \
2264- while (sd_journal_previous(j) > 0)
2265+ if (sd_journal_seek_tail(j) < 0) { } \
2266+ else while (sd_journal_previous(j) > 0)
2267
2268 #define SD_JOURNAL_FOREACH_DATA(j, data, l) \
2269 for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
2270diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
2271index 63d64b2..57264de 100644
2272--- a/src/test/test-path-util.c
2273+++ b/src/test/test-path-util.c
2274@@ -85,29 +85,30 @@ static void test_path(void) {
2275 }
2276 }
2277
2278-static void test_find_binary(const char *self) {
2279+static void test_find_binary(const char *self, bool local) {
2280 char *p;
2281
2282- assert_se(find_binary("/bin/sh", &p) == 0);
2283+ assert_se(find_binary("/bin/sh", local, &p) == 0);
2284 puts(p);
2285 assert_se(streq(p, "/bin/sh"));
2286 free(p);
2287
2288- assert_se(find_binary(self, &p) == 0);
2289+ assert_se(find_binary(self, local, &p) == 0);
2290 puts(p);
2291 assert_se(endswith(p, "/test-path-util"));
2292 assert_se(path_is_absolute(p));
2293 free(p);
2294
2295- assert_se(find_binary("sh", &p) == 0);
2296+ assert_se(find_binary("sh", local, &p) == 0);
2297 puts(p);
2298 assert_se(endswith(p, "/sh"));
2299 assert_se(path_is_absolute(p));
2300 free(p);
2301
2302- assert_se(find_binary("xxxx-xxxx", &p) == -ENOENT);
2303+ assert_se(find_binary("xxxx-xxxx", local, &p) == -ENOENT);
2304
2305- assert_se(find_binary("/some/dir/xxxx-xxxx", &p) == -ENOENT);
2306+ assert_se(find_binary("/some/dir/xxxx-xxxx", local, &p) ==
2307+ (local ? -ENOENT : 0));
2308 }
2309
2310 static void test_prefixes(void) {
2311@@ -244,7 +245,8 @@ static void test_strv_resolve(void) {
2312
2313 int main(int argc, char **argv) {
2314 test_path();
2315- test_find_binary(argv[0]);
2316+ test_find_binary(argv[0], true);
2317+ test_find_binary(argv[0], false);
2318 test_prefixes();
2319 test_path_join();
2320 test_fsck_exists();
2321diff --git a/src/udev/udevd.c b/src/udev/udevd.c
2322index 2e6c713..193702c 100644
2323--- a/src/udev/udevd.c
2324+++ b/src/udev/udevd.c
2325@@ -994,9 +994,9 @@ static void kernel_cmdline_options(struct udev *udev) {
2326 if (r < 0)
2327 log_warning("Invalid udev.exec-delay ignored: %s", opt + 16);
2328 } else if (startswith(opt, "udev.event-timeout=")) {
2329- r = safe_atou64(opt + 16, &arg_event_timeout_usec);
2330+ r = safe_atou64(opt + 19, &arg_event_timeout_usec);
2331 if (r < 0) {
2332- log_warning("Invalid udev.event-timeout ignored: %s", opt + 16);
2333+ log_warning("Invalid udev.event-timeout ignored: %s", opt + 19);
2334 break;
2335 }
2336 arg_event_timeout_usec *= USEC_PER_SEC;
2337diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4.in
2338index 8ac51a4..cae9fb5 100644
2339--- a/units/console-getty.service.m4.in
2340+++ b/units/console-getty.service.m4.in
2341@@ -15,7 +15,6 @@ After=rc-local.service
2342 Before=getty.target
2343
2344 [Service]
2345-ExecStart=-/sbin/agetty --noclear --keep-baud console 115200,38400,9600 $TERM
2346 Type=idle
2347 Restart=always
2348 RestartSec=0
2349diff --git a/units/container-getty@.service.m4.in b/units/container-getty@.service.m4.in
2350index 4f7794b..6dfc2e9 100644
2351--- a/units/container-getty@.service.m4.in
2352+++ b/units/container-getty@.service.m4.in
2353@@ -14,9 +14,9 @@ After=rc-local.service
2354 )m4_dnl
2355 Before=getty.target
2356 IgnoreOnIsolate=yes
2357+ConditionPathExists=/dev/pts/%I
2358
2359 [Service]
2360-ExecStart=-/sbin/agetty --noclear --keep-baud pts/%I 115200,38400,9600 $TERM
2361 Type=idle
2362 Restart=always
2363 RestartSec=0
2364diff --git a/units/emergency.service.in b/units/emergency.service.in
2365index 18973e7..3a99660 100644
2366--- a/units/emergency.service.in
2367+++ b/units/emergency.service.in
2368@@ -16,7 +16,6 @@ Before=shutdown.target
2369 [Service]
2370 Environment=HOME=/root
2371 WorkingDirectory=/root
2372-ExecStartPre=-/bin/plymouth quit
2373 ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\ntry again to boot into default mode.'
2374 ExecStart=-/bin/sh -c "/sbin/sulogin; @SYSTEMCTL@ --fail --no-block default"
2375 Type=idle
2376diff --git a/units/getty@.service.m4 b/units/getty@.service.m4
2377index 46164ab..f194a31 100644
2378--- a/units/getty@.service.m4
2379+++ b/units/getty@.service.m4
2380@@ -23,11 +23,12 @@ IgnoreOnIsolate=yes
2381 # On systems without virtual consoles, don't start any getty. Note
2382 # that serial gettys are covered by serial-getty@.service, not this
2383 # unit.
2384-ConditionPathExists=/dev/tty0
2385+ConditionPathExists=|/dev/tty0
2386+ConditionVirtualization=|lxc
2387+ConditionVirtualization=|lxc-libvirt
2388
2389 [Service]
2390 # the VT is cleared by TTYVTDisallocate
2391-ExecStart=-/sbin/agetty --noclear %I $TERM
2392 Type=idle
2393 Restart=always
2394 RestartSec=0
2395diff --git a/units/kmod-static-nodes.service.in b/units/kmod-static-nodes.service.in
2396index 0934a87..7e30c9e 100644
2397--- a/units/kmod-static-nodes.service.in
2398+++ b/units/kmod-static-nodes.service.in
2399@@ -10,7 +10,6 @@ Description=Create list of required static device nodes for the current kernel
2400 DefaultDependencies=no
2401 Before=sysinit.target systemd-tmpfiles-setup-dev.service
2402 ConditionCapability=CAP_SYS_MODULE
2403-ConditionPathExists=/lib/modules/%v/modules.devname
2404
2405 [Service]
2406 Type=oneshot
2407diff --git a/units/local-fs.target b/units/local-fs.target
2408index d2e5429..d26984b 100644
2409--- a/units/local-fs.target
2410+++ b/units/local-fs.target
2411@@ -13,3 +13,5 @@ Conflicts=shutdown.target
2412 After=local-fs-pre.target
2413 OnFailure=emergency.target
2414 OnFailureJobMode=replace-irreversibly
2415+
2416+X-StopOnReconfiguration=yes
2417diff --git a/units/remote-fs.target b/units/remote-fs.target
2418index 43ffa5c..156a681 100644
2419--- a/units/remote-fs.target
2420+++ b/units/remote-fs.target
2421@@ -12,5 +12,7 @@ After=remote-fs-pre.target
2422 DefaultDependencies=no
2423 Conflicts=shutdown.target
2424
2425+X-StopOnReconfiguration=yes
2426+
2427 [Install]
2428 WantedBy=multi-user.target
2429diff --git a/units/rescue.service.in b/units/rescue.service.in
2430index fc93f1e..3c87cf8 100644
2431--- a/units/rescue.service.in
2432+++ b/units/rescue.service.in
2433@@ -16,7 +16,6 @@ Before=shutdown.target
2434 [Service]
2435 Environment=HOME=/root
2436 WorkingDirectory=/root
2437-ExecStartPre=-/bin/plymouth quit
2438 ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" or ^D to\\nboot into default mode.'
2439 ExecStart=-/bin/sh -c "/sbin/sulogin; @SYSTEMCTL@ --fail --no-block default"
2440 Type=idle
2441diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4
2442index 4522d0d..96daa5c 100644
2443--- a/units/serial-getty@.service.m4
2444+++ b/units/serial-getty@.service.m4
2445@@ -22,7 +22,6 @@ Before=getty.target
2446 IgnoreOnIsolate=yes
2447
2448 [Service]
2449-ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM
2450 Type=idle
2451 Restart=always
2452 UtmpIdentifier=%I
2453diff --git a/units/sysinit.target b/units/sysinit.target
2454index ec33503..4ac47b9 100644
2455--- a/units/sysinit.target
2456+++ b/units/sysinit.target
2457@@ -9,5 +9,4 @@
2458 Description=System Initialization
2459 Documentation=man:systemd.special(7)
2460 Conflicts=emergency.service emergency.target
2461-Wants=local-fs.target swap.target
2462-After=local-fs.target swap.target emergency.service emergency.target
2463+After=emergency.service emergency.target
2464diff --git a/units/systemd-backlight@.service.in b/units/systemd-backlight@.service.in
2465index ecf3de4..7e83446 100644
2466--- a/units/systemd-backlight@.service.in
2467+++ b/units/systemd-backlight@.service.in
2468@@ -19,3 +19,4 @@ Type=oneshot
2469 RemainAfterExit=yes
2470 ExecStart=@rootlibexecdir@/systemd-backlight load %i
2471 ExecStop=@rootlibexecdir@/systemd-backlight save %i
2472+X-RestartIfChanged=false
2473diff --git a/units/systemd-journal-flush.service.in b/units/systemd-journal-flush.service.in
2474index 699670b..ba22c6d 100644
2475--- a/units/systemd-journal-flush.service.in
2476+++ b/units/systemd-journal-flush.service.in
2477@@ -10,8 +10,10 @@ Description=Trigger Flushing of Journal to Persistent Storage
2478 Documentation=man:systemd-journald.service(8) man:journald.conf(5)
2479 DefaultDependencies=no
2480 Requires=systemd-journald.service
2481-After=systemd-journald.service local-fs.target remote-fs.target
2482+After=systemd-journald.service
2483+After=systemd-remount-fs.service
2484 Before=systemd-user-sessions.service systemd-tmpfiles-setup.service
2485+RequiresMountsFor=/var/log/journal
2486
2487 [Service]
2488 ExecStart=@rootbindir@/journalctl --flush
2489diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
2490index 4de38fa..2f23c13 100644
2491--- a/units/systemd-journald.service.in
2492+++ b/units/systemd-journald.service.in
2493@@ -14,6 +14,7 @@ After=systemd-journald.socket systemd-journald-dev-log.socket syslog.socket
2494 Before=sysinit.target
2495
2496 [Service]
2497+Type=notify
2498 Sockets=systemd-journald.socket systemd-journald-dev-log.socket
2499 ExecStart=@rootlibexecdir@/systemd-journald
2500 Restart=always
2501@@ -26,3 +27,8 @@ WatchdogSec=1min
2502 # Increase the default a bit in order to allow many simultaneous
2503 # services being run since we keep one fd open per service.
2504 LimitNOFILE=16384
2505+
2506+# Don't restart journald, since that causes services connected to
2507+# journald to stop logging (see
2508+# https://bugs.freedesktop.org/show_bug.cgi?id=56043).
2509+X-RestartIfChanged=no
2510diff --git a/units/systemd-random-seed.service.in b/units/systemd-random-seed.service.in
2511index b55844b..3ef9fc6 100644
2512--- a/units/systemd-random-seed.service.in
2513+++ b/units/systemd-random-seed.service.in
2514@@ -19,3 +19,4 @@ Type=oneshot
2515 RemainAfterExit=yes
2516 ExecStart=@rootlibexecdir@/systemd-random-seed load
2517 ExecStop=@rootlibexecdir@/systemd-random-seed save
2518+X-RestartIfChanged=false
2519diff --git a/units/systemd-rfkill@.service.in b/units/systemd-rfkill@.service.in
2520index 0e9851b..9f8fa0d 100644
2521--- a/units/systemd-rfkill@.service.in
2522+++ b/units/systemd-rfkill@.service.in
2523@@ -19,3 +19,4 @@ Type=oneshot
2524 RemainAfterExit=yes
2525 ExecStart=@rootlibexecdir@/systemd-rfkill load %I
2526 ExecStop=@rootlibexecdir@/systemd-rfkill save %I
2527+X-RestartIfChanged=false
2528diff --git a/units/systemd-tmpfiles-setup.service.in b/units/systemd-tmpfiles-setup.service.in
2529index e895cda..194146f 100644
2530--- a/units/systemd-tmpfiles-setup.service.in
2531+++ b/units/systemd-tmpfiles-setup.service.in
2532@@ -11,7 +11,7 @@ Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
2533 DefaultDependencies=no
2534 Conflicts=shutdown.target
2535 After=local-fs.target systemd-sysusers.service
2536-Before=sysinit.target shutdown.target
2537+Before=shutdown.target
2538 RefuseManualStop=yes
2539
2540 [Service]
2541diff --git a/units/systemd-update-utmp.service.in b/units/systemd-update-utmp.service.in
2542index 163eccd..7357c12 100644
2543--- a/units/systemd-update-utmp.service.in
2544+++ b/units/systemd-update-utmp.service.in
2545@@ -11,7 +11,7 @@ Documentation=man:systemd-update-utmp.service(8) man:utmp(5)
2546 DefaultDependencies=no
2547 RequiresMountsFor=/var/log/wtmp
2548 Conflicts=shutdown.target
2549-After=systemd-remount-fs.service systemd-tmpfiles-setup.service auditd.service
2550+After=systemd-remount-fs.service auditd.service
2551 Before=sysinit.target shutdown.target
2552
2553 [Service]
2554@@ -19,3 +19,4 @@ Type=oneshot
2555 RemainAfterExit=yes
2556 ExecStart=@rootlibexecdir@/systemd-update-utmp reboot
2557 ExecStop=@rootlibexecdir@/systemd-update-utmp shutdown
2558+X-RestartIfChanged=false
2559diff --git a/units/systemd-user-sessions.service.in b/units/systemd-user-sessions.service.in
2560index 0869e73..b6ed958 100644
2561--- a/units/systemd-user-sessions.service.in
2562+++ b/units/systemd-user-sessions.service.in
2563@@ -15,3 +15,6 @@ Type=oneshot
2564 RemainAfterExit=yes
2565 ExecStart=@rootlibexecdir@/systemd-user-sessions start
2566 ExecStop=@rootlibexecdir@/systemd-user-sessions stop
2567+
2568+# Restart kills all active sessions.
2569+X-RestartIfChanged=no