forked from mirrors/nixpkgs
c34953ed24
Before: $ time journalctl > /dev/null real 6m12.470s user 5m51.439s sys 0m19.265s After: real 0m40.067s user 0m37.717s sys 0m2.383s Before: $ time journalctl --since '2015-08-01' _TRANSPORT=kernel real 1m9.817s user 0m13.318s sys 0m56.626s After: real 0m0.689s user 0m0.521s sys 0m0.221s
2533 lines
97 KiB
Diff
2533 lines
97 KiB
Diff
diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in
|
|
index e30d9a8..a3d399b 100644
|
|
--- a/rules/99-systemd.rules.in
|
|
+++ b/rules/99-systemd.rules.in
|
|
@@ -14,10 +14,6 @@ KERNEL=="vport*", TAG+="systemd"
|
|
SUBSYSTEM=="block", KERNEL!="ram*", TAG+="systemd"
|
|
SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0"
|
|
|
|
-# Ignore encrypted devices with no identified superblock on it, since
|
|
-# we are probably still calling mke2fs or mkswap on it.
|
|
-SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0"
|
|
-
|
|
# Ignore raid devices that are not yet assembled and started
|
|
SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0"
|
|
SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0"
|
|
diff --git a/src/core/job.c b/src/core/job.c
|
|
index eaa4bb1..db44fee 100644
|
|
--- a/src/core/job.c
|
|
+++ b/src/core/job.c
|
|
@@ -352,6 +352,9 @@ bool job_type_is_redundant(JobType a, UnitActiveState b) {
|
|
return
|
|
b == UNIT_ACTIVATING;
|
|
|
|
+ case JOB_NOP:
|
|
+ return true;
|
|
+
|
|
default:
|
|
assert_not_reached("Invalid job type");
|
|
}
|
|
diff --git a/src/core/job.h b/src/core/job.h
|
|
index 1e7c61b..ee8e54a 100644
|
|
--- a/src/core/job.h
|
|
+++ b/src/core/job.h
|
|
@@ -49,9 +49,11 @@ enum JobType {
|
|
_JOB_TYPE_MAX_MERGING,
|
|
|
|
/* JOB_NOP can enter into a transaction, but as it won't pull in
|
|
- * any dependencies, it won't have to merge with anything.
|
|
- * job_install() avoids the problem of merging JOB_NOP too (it's
|
|
- * special-cased, only merges with other JOB_NOPs). */
|
|
+ * any dependencies and it uses the special 'nop_job' slot in Unit,
|
|
+ * it won't have to merge with anything (except possibly into another
|
|
+ * JOB_NOP, previously installed). JOB_NOP is special-cased in
|
|
+ * job_type_is_*() functions so that the transaction can be
|
|
+ * activated. */
|
|
JOB_NOP = _JOB_TYPE_MAX_MERGING, /* do nothing */
|
|
|
|
_JOB_TYPE_MAX_IN_TRANSACTION,
|
|
@@ -190,11 +192,15 @@ _pure_ static inline bool job_type_is_mergeable(JobType a, JobType b) {
|
|
}
|
|
|
|
_pure_ static inline bool job_type_is_conflicting(JobType a, JobType b) {
|
|
- return !job_type_is_mergeable(a, b);
|
|
+ return a != JOB_NOP && b != JOB_NOP && !job_type_is_mergeable(a, b);
|
|
}
|
|
|
|
_pure_ static inline bool job_type_is_superset(JobType a, JobType b) {
|
|
/* Checks whether operation a is a "superset" of b in its actions */
|
|
+ if (b == JOB_NOP)
|
|
+ return true;
|
|
+ if (a == JOB_NOP)
|
|
+ return false;
|
|
return a == job_type_lookup_merge(a, b);
|
|
}
|
|
|
|
diff --git a/src/core/manager.c b/src/core/manager.c
|
|
index d427d88..256d6f7 100644
|
|
--- a/src/core/manager.c
|
|
+++ b/src/core/manager.c
|
|
@@ -662,9 +662,11 @@ static int manager_setup_notify(Manager *m) {
|
|
return -errno;
|
|
}
|
|
|
|
- if (m->running_as == SYSTEMD_SYSTEM)
|
|
+ if (m->running_as == SYSTEMD_SYSTEM) {
|
|
m->notify_socket = strdup("/run/systemd/notify");
|
|
- else {
|
|
+ if (!m->notify_socket)
|
|
+ return log_oom();
|
|
+ } else {
|
|
const char *e;
|
|
|
|
e = getenv("XDG_RUNTIME_DIR");
|
|
@@ -674,9 +676,11 @@ static int manager_setup_notify(Manager *m) {
|
|
}
|
|
|
|
m->notify_socket = strappend(e, "/systemd/notify");
|
|
+ if (!m->notify_socket)
|
|
+ return log_oom();
|
|
+
|
|
+ mkdir_parents_label(m->notify_socket, 0755);
|
|
}
|
|
- if (!m->notify_socket)
|
|
- return log_oom();
|
|
|
|
strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1);
|
|
r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
|
|
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
|
|
index 20cf526..03cfddc 100644
|
|
--- a/src/core/shutdown.c
|
|
+++ b/src/core/shutdown.c
|
|
@@ -75,7 +75,9 @@ static int parse_argv(int argc, char *argv[]) {
|
|
assert(argc >= 1);
|
|
assert(argv);
|
|
|
|
- while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
|
|
+ /* "-" prevents getopt from permuting argv[] and moving the verb away
|
|
+ * from argv[1]. Our interface to initrd promises it'll be there. */
|
|
+ while ((c = getopt_long(argc, argv, "-", options, NULL)) >= 0)
|
|
switch (c) {
|
|
|
|
case ARG_LOG_LEVEL:
|
|
@@ -113,6 +115,13 @@ static int parse_argv(int argc, char *argv[]) {
|
|
|
|
break;
|
|
|
|
+ case '\001':
|
|
+ if (!arg_verb)
|
|
+ arg_verb = optarg;
|
|
+ else
|
|
+ log_error("Excess arguments, ignoring");
|
|
+ break;
|
|
+
|
|
case '?':
|
|
return -EINVAL;
|
|
|
|
@@ -120,15 +129,11 @@ static int parse_argv(int argc, char *argv[]) {
|
|
assert_not_reached("Unhandled option code.");
|
|
}
|
|
|
|
- if (optind >= argc) {
|
|
+ if (!arg_verb) {
|
|
log_error("Verb argument missing.");
|
|
return -EINVAL;
|
|
}
|
|
|
|
- arg_verb = argv[optind];
|
|
-
|
|
- if (optind + 1 < argc)
|
|
- log_error("Excess arguments, ignoring");
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
|
|
index 5eed615..c2678cb 100644
|
|
--- a/src/core/snapshot.c
|
|
+++ b/src/core/snapshot.c
|
|
@@ -208,7 +208,7 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e,
|
|
return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s lacks snapshot suffix.", name);
|
|
|
|
if (manager_get_unit(m, name))
|
|
- sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
|
|
+ return sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
|
|
|
|
} else {
|
|
|
|
diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in
|
|
index d5b86bf..9c66e7b 100644
|
|
--- a/src/core/systemd.pc.in
|
|
+++ b/src/core/systemd.pc.in
|
|
@@ -14,8 +14,8 @@ systemduserunitdir=@userunitdir@
|
|
systemduserpresetdir=@userpresetdir@
|
|
systemdsystemconfdir=@pkgsysconfdir@/system
|
|
systemduserconfdir=@pkgsysconfdir@/user
|
|
-systemdsystemunitpath=${systemdsystemconfdir}:/etc/systemd/system:/run/systemd/system:/usr/local/lib/systemd/system:${systemdsystemunitdir}:/usr/lib/systemd/system:/lib/systemd/system
|
|
-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
|
|
+systemdsystemunitpath=${systemdsystemconfdir}:/etc/systemd/system:/etc/systemd-mutable/system:/nix/var/nix/profiles/default/lib/systemd/user:/run/systemd/system:${systemdsystemunitdir}
|
|
+systemduserunitpath=${systemduserconfdir}:/etc/systemd/user:/etc/systemd-mutable/user:/nix/var/nix/profiles/default/lib/systemd/system:/run/systemd/user:${systemduserunitdir}
|
|
systemdsystemgeneratordir=@systemgeneratordir@
|
|
systemdusergeneratordir=@usergeneratordir@
|
|
systemdsleepdir=@systemsleepdir@
|
|
diff --git a/src/core/timer.c b/src/core/timer.c
|
|
index a3713e2..5c4e9f9 100644
|
|
--- a/src/core/timer.c
|
|
+++ b/src/core/timer.c
|
|
@@ -521,6 +521,7 @@ fail:
|
|
|
|
static int timer_start(Unit *u) {
|
|
Timer *t = TIMER(u);
|
|
+ TimerValue *v;
|
|
|
|
assert(t);
|
|
assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
|
|
@@ -530,6 +531,11 @@ static int timer_start(Unit *u) {
|
|
|
|
t->last_trigger = DUAL_TIMESTAMP_NULL;
|
|
|
|
+ /* Reenable all timers that depend on unit activation time */
|
|
+ LIST_FOREACH(value, v, t->values)
|
|
+ if (v->base == TIMER_ACTIVE)
|
|
+ v->disabled = false;
|
|
+
|
|
if (t->stamp_path) {
|
|
struct stat st;
|
|
|
|
diff --git a/src/core/umount.c b/src/core/umount.c
|
|
index cffa453..4d1a9ff 100644
|
|
--- a/src/core/umount.c
|
|
+++ b/src/core/umount.c
|
|
@@ -385,6 +385,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
|
|
* anyway, since we are running from it. They have
|
|
* already been remounted ro. */
|
|
if (path_equal(m->path, "/")
|
|
+ || path_equal(m->path, "/nix")
|
|
+ || path_equal(m->path, "/nix/store")
|
|
#ifndef HAVE_SPLIT_USR
|
|
|| path_equal(m->path, "/usr")
|
|
#endif
|
|
diff --git a/src/delta/delta.c b/src/delta/delta.c
|
|
index 25c4a0b..e1f2d6d 100644
|
|
--- a/src/delta/delta.c
|
|
+++ b/src/delta/delta.c
|
|
@@ -487,7 +487,7 @@ static int parse_flags(const char *flag_str, int flags) {
|
|
const char *word, *state;
|
|
size_t l;
|
|
|
|
- FOREACH_WORD(word, l, flag_str, state) {
|
|
+ FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state) {
|
|
if (strneq("masked", word, l))
|
|
flags |= SHOW_MASKED;
|
|
else if (strneq ("equivalent", word, l))
|
|
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
|
|
index 70a5918..a5661e8 100644
|
|
--- a/src/fsck/fsck.c
|
|
+++ b/src/fsck/fsck.c
|
|
@@ -315,8 +315,7 @@ int main(int argc, char *argv[]) {
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
- cmdline[i++] = "/sbin/fsck";
|
|
- cmdline[i++] = arg_repair;
|
|
+ cmdline[i++] = "/run/current-system/sw/bin/fsck";
|
|
cmdline[i++] = "-T";
|
|
|
|
/*
|
|
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
|
|
index e257c12..1e04553 100644
|
|
--- a/src/fstab-generator/fstab-generator.c
|
|
+++ b/src/fstab-generator/fstab-generator.c
|
|
@@ -485,7 +485,7 @@ static int add_usr_mount(void) {
|
|
return log_oom();
|
|
}
|
|
|
|
- if (!arg_usr_what || !arg_usr_options)
|
|
+ if (!arg_usr_what)
|
|
return 0;
|
|
|
|
what = fstab_node_to_udev_node(arg_usr_what);
|
|
@@ -494,7 +494,13 @@ static int add_usr_mount(void) {
|
|
return -1;
|
|
}
|
|
|
|
- opts = arg_usr_options;
|
|
+ if (!arg_usr_options)
|
|
+ opts = arg_root_rw > 0 ? "rw" : "ro";
|
|
+ else if (!mount_test_option(arg_usr_options, "ro") &&
|
|
+ !mount_test_option(arg_usr_options, "rw"))
|
|
+ opts = strappenda(arg_usr_options, ",", arg_root_rw > 0 ? "rw" : "ro");
|
|
+ else
|
|
+ opts = arg_usr_options;
|
|
|
|
log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));
|
|
return add_mount(what,
|
|
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
|
|
index e487369..ff4e9c9 100644
|
|
--- a/src/hostname/hostnamectl.c
|
|
+++ b/src/hostname/hostnamectl.c
|
|
@@ -536,5 +536,5 @@ int main(int argc, char *argv[]) {
|
|
r = hostnamectl_main(bus, argc, argv);
|
|
|
|
finish:
|
|
- return r < 0 ? EXIT_FAILURE : r;
|
|
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
}
|
|
diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c
|
|
index 7dd8878..70a9a13 100644
|
|
--- a/src/journal-remote/journal-remote-parse.c
|
|
+++ b/src/journal-remote/journal-remote-parse.c
|
|
@@ -344,22 +344,25 @@ int process_data(RemoteSource *source) {
|
|
LLLLLLLL0011223344...\n
|
|
*/
|
|
sep = memchr(line, '=', n);
|
|
- if (sep)
|
|
+ if (sep) {
|
|
/* chomp newline */
|
|
n--;
|
|
- else
|
|
+
|
|
+ r = iovw_put(&source->iovw, line, n);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ } else {
|
|
/* replace \n with = */
|
|
line[n-1] = '=';
|
|
- log_trace("Received: %.*s", (int) n, line);
|
|
|
|
- r = iovw_put(&source->iovw, line, n);
|
|
- if (r < 0) {
|
|
- log_error("Failed to put line in iovect");
|
|
- return r;
|
|
+ source->field_len = n;
|
|
+ source->state = STATE_DATA_START;
|
|
+
|
|
+ /* we cannot put the field in iovec until we have all data */
|
|
}
|
|
|
|
- if (!sep)
|
|
- source->state = STATE_DATA_START;
|
|
+ log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary");
|
|
+
|
|
return 0; /* continue */
|
|
}
|
|
|
|
@@ -382,6 +385,7 @@ int process_data(RemoteSource *source) {
|
|
|
|
case STATE_DATA: {
|
|
void *data;
|
|
+ char *field;
|
|
|
|
assert(source->data_size > 0);
|
|
|
|
@@ -396,11 +400,12 @@ int process_data(RemoteSource *source) {
|
|
|
|
assert(data);
|
|
|
|
- r = iovw_put(&source->iovw, data, source->data_size);
|
|
- if (r < 0) {
|
|
- log_error("failed to put binary buffer in iovect");
|
|
+ field = (char*) data - sizeof(uint64_t) - source->field_len;
|
|
+ memmove(field + sizeof(uint64_t), field, source->field_len);
|
|
+
|
|
+ r = iovw_put(&source->iovw, field + sizeof(uint64_t), source->field_len + source->data_size);
|
|
+ if (r < 0)
|
|
return r;
|
|
- }
|
|
|
|
source->state = STATE_DATA_FINISH;
|
|
|
|
diff --git a/src/journal-remote/journal-remote-parse.h b/src/journal-remote/journal-remote-parse.h
|
|
index 8499f4e..22db550 100644
|
|
--- a/src/journal-remote/journal-remote-parse.h
|
|
+++ b/src/journal-remote/journal-remote-parse.h
|
|
@@ -42,7 +42,9 @@ typedef struct RemoteSource {
|
|
size_t offset; /* offset to the beginning of live data in the buffer */
|
|
size_t scanned; /* number of bytes since the beginning of data without a newline */
|
|
size_t filled; /* total number of bytes in the buffer */
|
|
- size_t data_size; /* size of the binary data chunk being processed */
|
|
+
|
|
+ size_t field_len; /* used for binary fields: the field name length */
|
|
+ size_t data_size; /* and the size of the binary data chunk being processed */
|
|
|
|
struct iovec_wrapper iovw;
|
|
|
|
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
|
|
index 5ab1982..1f980ee 100644
|
|
--- a/src/journal/journal-authenticate.c
|
|
+++ b/src/journal/journal-authenticate.c
|
|
@@ -229,7 +229,7 @@ int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
|
|
return 0;
|
|
}
|
|
|
|
-int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p) {
|
|
+int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p) {
|
|
int r;
|
|
|
|
assert(f);
|
|
@@ -246,7 +246,7 @@ int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p
|
|
if (r < 0)
|
|
return r;
|
|
} else {
|
|
- if (type >= 0 && o->object.type != type)
|
|
+ if (type > OBJECT_UNUSED && o->object.type != type)
|
|
return -EBADMSG;
|
|
}
|
|
|
|
diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h
|
|
index 0aaf836..565fe84 100644
|
|
--- a/src/journal/journal-authenticate.h
|
|
+++ b/src/journal/journal-authenticate.h
|
|
@@ -33,7 +33,7 @@ int journal_file_append_first_tag(JournalFile *f);
|
|
int journal_file_hmac_setup(JournalFile *f);
|
|
int journal_file_hmac_start(JournalFile *f);
|
|
int journal_file_hmac_put_header(JournalFile *f);
|
|
-int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p);
|
|
+int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p);
|
|
|
|
int journal_file_fss_load(JournalFile *f);
|
|
int journal_file_parse_verification_key(JournalFile *f, const char *key);
|
|
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
|
|
index e55fa19..ab089cb 100644
|
|
--- a/src/journal/journal-def.h
|
|
+++ b/src/journal/journal-def.h
|
|
@@ -52,8 +52,8 @@ typedef struct HashItem HashItem;
|
|
typedef struct FSSHeader FSSHeader;
|
|
|
|
/* Object types */
|
|
-enum {
|
|
- OBJECT_UNUSED,
|
|
+typedef enum ObjectType {
|
|
+ OBJECT_UNUSED, /* also serves as "any type" or "additional context" */
|
|
OBJECT_DATA,
|
|
OBJECT_FIELD,
|
|
OBJECT_ENTRY,
|
|
@@ -62,7 +62,7 @@ enum {
|
|
OBJECT_ENTRY_ARRAY,
|
|
OBJECT_TAG,
|
|
_OBJECT_TYPE_MAX
|
|
-};
|
|
+} ObjectType;
|
|
|
|
/* Object flags */
|
|
enum {
|
|
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
|
|
index 8a2c0fc..c55a4dc 100644
|
|
--- a/src/journal/journal-file.c
|
|
+++ b/src/journal/journal-file.c
|
|
@@ -374,7 +374,13 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
|
|
return 0;
|
|
}
|
|
|
|
-static int journal_file_move_to(JournalFile *f, int context, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
|
|
+static unsigned type_to_context(ObjectType type) {
|
|
+ /* One context for each type, plus one catch-all for the rest */
|
|
+ assert_cc(_OBJECT_TYPE_MAX <= MMAP_CACHE_MAX_CONTEXTS);
|
|
+ return type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX ? type : 0;
|
|
+}
|
|
+
|
|
+static int journal_file_move_to(JournalFile *f, ObjectType type, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
|
|
assert(f);
|
|
assert(ret);
|
|
|
|
@@ -391,7 +397,7 @@ static int journal_file_move_to(JournalFile *f, int context, bool keep_always, u
|
|
return -EADDRNOTAVAIL;
|
|
}
|
|
|
|
- return mmap_cache_get(f->mmap, f->fd, f->prot, context, keep_always, offset, size, &f->last_stat, ret, NULL);
|
|
+ return mmap_cache_get(f->mmap, f->fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret);
|
|
}
|
|
|
|
static uint64_t minimum_header_size(Object *o) {
|
|
@@ -412,7 +418,7 @@ static uint64_t minimum_header_size(Object *o) {
|
|
return table[o->object.type];
|
|
}
|
|
|
|
-int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret) {
|
|
+int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret) {
|
|
int r;
|
|
void *t;
|
|
Object *o;
|
|
@@ -425,7 +431,7 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec
|
|
if (!VALID64(offset))
|
|
return -EFAULT;
|
|
|
|
- r = journal_file_move_to(f, type_to_context(type), false, offset, sizeof(ObjectHeader), &t);
|
|
+ r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
@@ -441,11 +447,11 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec
|
|
if (s < minimum_header_size(o))
|
|
return -EBADMSG;
|
|
|
|
- if (type > 0 && o->object.type != type)
|
|
+ if (type > OBJECT_UNUSED && o->object.type != type)
|
|
return -EBADMSG;
|
|
|
|
if (s > sizeof(ObjectHeader)) {
|
|
- r = journal_file_move_to(f, o->object.type, false, offset, s, &t);
|
|
+ r = journal_file_move_to(f, type, false, offset, s, &t);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
@@ -482,14 +488,14 @@ static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) {
|
|
return r;
|
|
}
|
|
|
|
-int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) {
|
|
+int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset) {
|
|
int r;
|
|
uint64_t p;
|
|
Object *tail, *o;
|
|
void *t;
|
|
|
|
assert(f);
|
|
- assert(type > 0 && type < _OBJECT_TYPE_MAX);
|
|
+ assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX);
|
|
assert(size >= sizeof(ObjectHeader));
|
|
assert(offset);
|
|
assert(ret);
|
|
@@ -502,7 +508,7 @@ int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object *
|
|
if (p == 0)
|
|
p = le64toh(f->header->header_size);
|
|
else {
|
|
- r = journal_file_move_to_object(f, -1, p, &tail);
|
|
+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
@@ -1657,7 +1663,7 @@ static int generic_array_bisect(
|
|
}
|
|
}
|
|
|
|
- if (k > n) {
|
|
+ if (k >= n) {
|
|
if (direction == DIRECTION_UP) {
|
|
i = n;
|
|
subtract_one = true;
|
|
@@ -1793,23 +1799,6 @@ _pure_ static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle
|
|
return TEST_RIGHT;
|
|
}
|
|
|
|
-int journal_file_move_to_entry_by_offset(
|
|
- JournalFile *f,
|
|
- uint64_t p,
|
|
- direction_t direction,
|
|
- Object **ret,
|
|
- uint64_t *offset) {
|
|
-
|
|
- return generic_array_bisect(f,
|
|
- le64toh(f->header->entry_array_offset),
|
|
- le64toh(f->header->n_entries),
|
|
- p,
|
|
- test_object_offset,
|
|
- direction,
|
|
- ret, offset, NULL);
|
|
-}
|
|
-
|
|
-
|
|
static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) {
|
|
Object *o;
|
|
int r;
|
|
@@ -1939,9 +1928,81 @@ int journal_file_move_to_entry_by_monotonic(
|
|
ret, offset, NULL);
|
|
}
|
|
|
|
+void journal_file_reset_location(JournalFile *f) {
|
|
+ f->location_type = LOCATION_HEAD;
|
|
+ f->current_offset = 0;
|
|
+ f->current_seqnum = 0;
|
|
+ f->current_realtime = 0;
|
|
+ f->current_monotonic = 0;
|
|
+ zero(f->current_boot_id);
|
|
+ f->current_xor_hash = 0;
|
|
+}
|
|
+
|
|
+void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) {
|
|
+ f->location_type = LOCATION_SEEK;
|
|
+ f->current_offset = offset;
|
|
+ f->current_seqnum = le64toh(o->entry.seqnum);
|
|
+ f->current_realtime = le64toh(o->entry.realtime);
|
|
+ f->current_monotonic = le64toh(o->entry.monotonic);
|
|
+ f->current_boot_id = o->entry.boot_id;
|
|
+ f->current_xor_hash = le64toh(o->entry.xor_hash);
|
|
+}
|
|
+
|
|
+int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
|
|
+ assert(af);
|
|
+ assert(bf);
|
|
+ assert(af->location_type == LOCATION_SEEK);
|
|
+ assert(bf->location_type == LOCATION_SEEK);
|
|
+
|
|
+ /* If contents and timestamps match, these entries are
|
|
+ * identical, even if the seqnum does not match */
|
|
+ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) &&
|
|
+ af->current_monotonic == bf->current_monotonic &&
|
|
+ af->current_realtime == bf->current_realtime &&
|
|
+ af->current_xor_hash == bf->current_xor_hash)
|
|
+ return 0;
|
|
+
|
|
+ if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
|
|
+
|
|
+ /* If this is from the same seqnum source, compare
|
|
+ * seqnums */
|
|
+ if (af->current_seqnum < bf->current_seqnum)
|
|
+ return -1;
|
|
+ if (af->current_seqnum > bf->current_seqnum)
|
|
+ return 1;
|
|
+
|
|
+ /* Wow! This is weird, different data but the same
|
|
+ * seqnums? Something is borked, but let's make the
|
|
+ * best of it and compare by time. */
|
|
+ }
|
|
+
|
|
+ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) {
|
|
+
|
|
+ /* If the boot id matches, compare monotonic time */
|
|
+ if (af->current_monotonic < bf->current_monotonic)
|
|
+ return -1;
|
|
+ if (af->current_monotonic > bf->current_monotonic)
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ /* Otherwise, compare UTC time */
|
|
+ if (af->current_realtime < bf->current_realtime)
|
|
+ return -1;
|
|
+ if (af->current_realtime > bf->current_realtime)
|
|
+ return 1;
|
|
+
|
|
+ /* Finally, compare by contents */
|
|
+ if (af->current_xor_hash < bf->current_xor_hash)
|
|
+ return -1;
|
|
+ if (af->current_xor_hash > bf->current_xor_hash)
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int journal_file_next_entry(
|
|
JournalFile *f,
|
|
- Object *o, uint64_t p,
|
|
+ uint64_t p,
|
|
direction_t direction,
|
|
Object **ret, uint64_t *offset) {
|
|
|
|
@@ -1949,18 +2010,14 @@ int journal_file_next_entry(
|
|
int r;
|
|
|
|
assert(f);
|
|
- assert(p > 0 || !o);
|
|
|
|
n = le64toh(f->header->n_entries);
|
|
if (n <= 0)
|
|
return 0;
|
|
|
|
- if (!o)
|
|
+ if (p == 0)
|
|
i = direction == DIRECTION_DOWN ? 0 : n - 1;
|
|
else {
|
|
- if (o->object.type != OBJECT_ENTRY)
|
|
- return -EINVAL;
|
|
-
|
|
r = generic_array_bisect(f,
|
|
le64toh(f->header->entry_array_offset),
|
|
le64toh(f->header->n_entries),
|
|
@@ -2006,55 +2063,6 @@ int journal_file_next_entry(
|
|
return 1;
|
|
}
|
|
|
|
-int journal_file_skip_entry(
|
|
- JournalFile *f,
|
|
- Object *o, uint64_t p,
|
|
- int64_t skip,
|
|
- Object **ret, uint64_t *offset) {
|
|
-
|
|
- uint64_t i, n;
|
|
- int r;
|
|
-
|
|
- assert(f);
|
|
- assert(o);
|
|
- assert(p > 0);
|
|
-
|
|
- if (o->object.type != OBJECT_ENTRY)
|
|
- return -EINVAL;
|
|
-
|
|
- r = generic_array_bisect(f,
|
|
- le64toh(f->header->entry_array_offset),
|
|
- le64toh(f->header->n_entries),
|
|
- p,
|
|
- test_object_offset,
|
|
- DIRECTION_DOWN,
|
|
- NULL, NULL,
|
|
- &i);
|
|
- if (r <= 0)
|
|
- return r;
|
|
-
|
|
- /* Calculate new index */
|
|
- if (skip < 0) {
|
|
- if ((uint64_t) -skip >= i)
|
|
- i = 0;
|
|
- else
|
|
- i = i - (uint64_t) -skip;
|
|
- } else
|
|
- i += (uint64_t) skip;
|
|
-
|
|
- n = le64toh(f->header->n_entries);
|
|
- if (n <= 0)
|
|
- return -EBADMSG;
|
|
-
|
|
- if (i >= n)
|
|
- i = n-1;
|
|
-
|
|
- return generic_array_get(f,
|
|
- le64toh(f->header->entry_array_offset),
|
|
- i,
|
|
- ret, offset);
|
|
-}
|
|
-
|
|
int journal_file_next_entry_for_data(
|
|
JournalFile *f,
|
|
Object *o, uint64_t p,
|
|
@@ -2289,7 +2297,7 @@ void journal_file_dump(JournalFile *f) {
|
|
|
|
p = le64toh(f->header->header_size);
|
|
while (p != 0) {
|
|
- r = journal_file_move_to_object(f, -1, p, &o);
|
|
+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
|
|
if (r < 0)
|
|
goto fail;
|
|
|
|
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
|
|
index 211e121..ca17c97 100644
|
|
--- a/src/journal/journal-file.h
|
|
+++ b/src/journal/journal-file.h
|
|
@@ -48,6 +48,20 @@ typedef enum direction {
|
|
DIRECTION_DOWN
|
|
} direction_t;
|
|
|
|
+typedef enum LocationType {
|
|
+ /* The first and last entries, resp. */
|
|
+ LOCATION_HEAD,
|
|
+ LOCATION_TAIL,
|
|
+
|
|
+ /* We already read the entry we currently point to, and the
|
|
+ * next one to read should probably not be this one again. */
|
|
+ LOCATION_DISCRETE,
|
|
+
|
|
+ /* We should seek to the precise location specified, and
|
|
+ * return it, as we haven't read it yet. */
|
|
+ LOCATION_SEEK
|
|
+} LocationType;
|
|
+
|
|
typedef struct JournalFile {
|
|
int fd;
|
|
|
|
@@ -63,6 +77,8 @@ typedef struct JournalFile {
|
|
bool tail_entry_monotonic_valid:1;
|
|
|
|
direction_t last_direction;
|
|
+ LocationType location_type;
|
|
+ uint64_t last_n_entries;
|
|
|
|
char *path;
|
|
struct stat last_stat;
|
|
@@ -72,6 +88,11 @@ typedef struct JournalFile {
|
|
HashItem *field_hash_table;
|
|
|
|
uint64_t current_offset;
|
|
+ uint64_t current_seqnum;
|
|
+ uint64_t current_realtime;
|
|
+ uint64_t current_monotonic;
|
|
+ sd_id128_t current_boot_id;
|
|
+ uint64_t current_xor_hash;
|
|
|
|
JournalMetrics metrics;
|
|
MMapCache *mmap;
|
|
@@ -160,13 +181,13 @@ static inline bool VALID_EPOCH(uint64_t u) {
|
|
#define JOURNAL_HEADER_COMPRESSED_LZ4(h) \
|
|
(!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_LZ4))
|
|
|
|
-int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret);
|
|
+int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret);
|
|
|
|
uint64_t journal_file_entry_n_items(Object *o) _pure_;
|
|
uint64_t journal_file_entry_array_n_items(Object *o) _pure_;
|
|
uint64_t journal_file_hash_table_n_items(Object *o) _pure_;
|
|
|
|
-int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset);
|
|
+int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset);
|
|
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);
|
|
|
|
int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset);
|
|
@@ -175,12 +196,13 @@ int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, ui
|
|
int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset);
|
|
int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset);
|
|
|
|
-int journal_file_next_entry(JournalFile *f, Object *o, uint64_t p, direction_t direction, Object **ret, uint64_t *offset);
|
|
-int journal_file_skip_entry(JournalFile *f, Object *o, uint64_t p, int64_t skip, Object **ret, uint64_t *offset);
|
|
+void journal_file_reset_location(JournalFile *f);
|
|
+void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset);
|
|
+int journal_file_compare_locations(JournalFile *af, JournalFile *bf);
|
|
+int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *offset);
|
|
|
|
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);
|
|
|
|
-int journal_file_move_to_entry_by_offset(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
|
|
int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset);
|
|
int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset);
|
|
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);
|
|
@@ -205,21 +227,3 @@ int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *
|
|
int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to);
|
|
|
|
bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec);
|
|
-
|
|
-
|
|
-static unsigned type_to_context(int type) {
|
|
- /* One context for each type, plus one catch-all for the rest */
|
|
- return type > 0 && type < _OBJECT_TYPE_MAX ? type : 0;
|
|
-}
|
|
-
|
|
-static inline int journal_file_object_keep(JournalFile *f, Object *o, uint64_t offset, void **release_cookie) {
|
|
- unsigned context = type_to_context(o->object.type);
|
|
- uint64_t s = le64toh(o->object.size);
|
|
-
|
|
- return mmap_cache_get(f->mmap, f->fd, f->prot, context, true,
|
|
- offset, s, &f->last_stat, NULL, release_cookie);
|
|
-}
|
|
-
|
|
-static inline int journal_file_object_release(JournalFile *f, void *release_cookie) {
|
|
- return mmap_cache_release(f->mmap, f->fd, release_cookie);
|
|
-}
|
|
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
|
|
index 70847db..e99050c 100644
|
|
--- a/src/journal/journal-internal.h
|
|
+++ b/src/journal/journal-internal.h
|
|
@@ -57,20 +57,6 @@ struct Match {
|
|
LIST_HEAD(Match, matches);
|
|
};
|
|
|
|
-typedef enum LocationType {
|
|
- /* The first and last entries, resp. */
|
|
- LOCATION_HEAD,
|
|
- LOCATION_TAIL,
|
|
-
|
|
- /* We already read the entry we currently point to, and the
|
|
- * next one to read should probably not be this one again. */
|
|
- LOCATION_DISCRETE,
|
|
-
|
|
- /* We should seek to the precise location specified, and
|
|
- * return it, as we haven't read it yet. */
|
|
- LOCATION_SEEK
|
|
-} LocationType;
|
|
-
|
|
struct Location {
|
|
LocationType type;
|
|
|
|
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
|
|
index f74adcb..5baa22d 100644
|
|
--- a/src/journal/journal-verify.c
|
|
+++ b/src/journal/journal-verify.c
|
|
@@ -368,7 +368,7 @@ static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
|
|
|
|
c = (a + b) / 2;
|
|
|
|
- r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z, NULL);
|
|
+ r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
@@ -865,7 +865,7 @@ int journal_file_verify(
|
|
if (show_progress)
|
|
draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
|
|
|
|
- r = journal_file_move_to_object(f, -1, p, &o);
|
|
+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
|
|
if (r < 0) {
|
|
error(p, "invalid object");
|
|
goto fail;
|
|
@@ -1085,11 +1085,11 @@ int journal_file_verify(
|
|
q = last_tag;
|
|
|
|
while (q <= p) {
|
|
- r = journal_file_move_to_object(f, -1, q, &o);
|
|
+ r = journal_file_move_to_object(f, OBJECT_UNUSED, q, &o);
|
|
if (r < 0)
|
|
goto fail;
|
|
|
|
- r = journal_file_hmac_put_object(f, -1, o, q);
|
|
+ r = journal_file_hmac_put_object(f, OBJECT_UNUSED, o, q);
|
|
if (r < 0)
|
|
goto fail;
|
|
|
|
@@ -1097,7 +1097,7 @@ int journal_file_verify(
|
|
}
|
|
|
|
/* Position might have changed, let's reposition things */
|
|
- r = journal_file_move_to_object(f, -1, p, &o);
|
|
+ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
|
|
if (r < 0)
|
|
goto fail;
|
|
|
|
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
|
|
index f50faf4..03579fd 100644
|
|
--- a/src/journal/journalctl.c
|
|
+++ b/src/journal/journalctl.c
|
|
@@ -682,7 +682,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|
assert_not_reached("Unhandled option");
|
|
}
|
|
|
|
- if (arg_follow && !arg_no_tail && arg_lines == ARG_LINES_DEFAULT)
|
|
+ if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT)
|
|
arg_lines = 10;
|
|
|
|
if (!!arg_directory + !!arg_file + !!arg_machine > 1) {
|
|
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
|
|
index a635202..655e2dd 100644
|
|
--- a/src/journal/journald-native.c
|
|
+++ b/src/journal/journald-native.c
|
|
@@ -132,8 +132,8 @@ void server_process_native_message(
|
|
|
|
/* A property follows */
|
|
|
|
- /* n received properties, +1 for _TRANSPORT */
|
|
- if (!GREEDY_REALLOC(iovec, m, n + 1 + N_IOVEC_META_FIELDS + !!object_pid * N_IOVEC_OBJECT_FIELDS)) {
|
|
+ /* n existing properties, 1 new, +1 for _TRANSPORT */
|
|
+ if (!GREEDY_REALLOC(iovec, m, n + 2 + N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS)) {
|
|
log_oom();
|
|
break;
|
|
}
|
|
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
|
|
index 12735c4..08b143b 100644
|
|
--- a/src/journal/journald-server.c
|
|
+++ b/src/journal/journald-server.c
|
|
@@ -1655,6 +1655,7 @@ void server_done(Server *s) {
|
|
free(s->buffer);
|
|
free(s->tty_path);
|
|
free(s->cgroup_root);
|
|
+ free(s->hostname_field);
|
|
|
|
if (s->mmap)
|
|
mmap_cache_unref(s->mmap);
|
|
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
|
|
index b7db6f1..f6f669d 100644
|
|
--- a/src/journal/mmap-cache.c
|
|
+++ b/src/journal/mmap-cache.c
|
|
@@ -38,7 +38,7 @@ typedef struct FileDescriptor FileDescriptor;
|
|
struct Window {
|
|
MMapCache *cache;
|
|
|
|
- unsigned keep_always;
|
|
+ bool keep_always;
|
|
bool in_unused;
|
|
|
|
int prot;
|
|
@@ -76,7 +76,7 @@ struct MMapCache {
|
|
|
|
|
|
Hashmap *fds;
|
|
- Hashmap *contexts;
|
|
+ Context *contexts[MMAP_CACHE_MAX_CONTEXTS];
|
|
|
|
LIST_HEAD(Window, unused);
|
|
Window *last_unused;
|
|
@@ -185,7 +185,7 @@ static void context_detach_window(Context *c) {
|
|
c->window = NULL;
|
|
LIST_REMOVE(by_window, w->contexts, c);
|
|
|
|
- if (!w->contexts && w->keep_always == 0) {
|
|
+ if (!w->contexts && !w->keep_always) {
|
|
/* Not used anymore? */
|
|
LIST_PREPEND(unused, c->cache->unused, w);
|
|
if (!c->cache->last_unused)
|
|
@@ -219,18 +219,13 @@ static void context_attach_window(Context *c, Window *w) {
|
|
|
|
static Context *context_add(MMapCache *m, unsigned id) {
|
|
Context *c;
|
|
- int r;
|
|
|
|
assert(m);
|
|
|
|
- c = hashmap_get(m->contexts, UINT_TO_PTR(id + 1));
|
|
+ c = m->contexts[id];
|
|
if (c)
|
|
return c;
|
|
|
|
- r = hashmap_ensure_allocated(&m->contexts, NULL);
|
|
- if (r < 0)
|
|
- return NULL;
|
|
-
|
|
c = new0(Context, 1);
|
|
if (!c)
|
|
return NULL;
|
|
@@ -238,11 +233,8 @@ static Context *context_add(MMapCache *m, unsigned id) {
|
|
c->cache = m;
|
|
c->id = id;
|
|
|
|
- r = hashmap_put(m->contexts, UINT_TO_PTR(id + 1), c);
|
|
- if (r < 0) {
|
|
- free(c);
|
|
- return NULL;
|
|
- }
|
|
+ assert(!m->contexts[id]);
|
|
+ m->contexts[id] = c;
|
|
|
|
return c;
|
|
}
|
|
@@ -252,8 +244,10 @@ static void context_free(Context *c) {
|
|
|
|
context_detach_window(c);
|
|
|
|
- if (c->cache)
|
|
- assert_se(hashmap_remove(c->cache->contexts, UINT_TO_PTR(c->id + 1)));
|
|
+ if (c->cache) {
|
|
+ assert(c->cache->contexts[c->id] == c);
|
|
+ c->cache->contexts[c->id] = NULL;
|
|
+ }
|
|
|
|
free(c);
|
|
}
|
|
@@ -302,15 +296,14 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) {
|
|
}
|
|
|
|
static void mmap_cache_free(MMapCache *m) {
|
|
- Context *c;
|
|
FileDescriptor *f;
|
|
+ int i;
|
|
|
|
assert(m);
|
|
|
|
- while ((c = hashmap_first(m->contexts)))
|
|
- context_free(c);
|
|
-
|
|
- hashmap_free(m->contexts);
|
|
+ for (i = 0; i < MMAP_CACHE_MAX_CONTEXTS; i++)
|
|
+ if (m->contexts[i])
|
|
+ context_free(m->contexts[i]);
|
|
|
|
while ((f = hashmap_first(m->fds)))
|
|
fd_free(f);
|
|
@@ -352,8 +345,7 @@ static int try_context(
|
|
bool keep_always,
|
|
uint64_t offset,
|
|
size_t size,
|
|
- void **ret,
|
|
- void **release_cookie) {
|
|
+ void **ret) {
|
|
|
|
Context *c;
|
|
|
|
@@ -361,8 +353,9 @@ static int try_context(
|
|
assert(m->n_ref > 0);
|
|
assert(fd >= 0);
|
|
assert(size > 0);
|
|
+ assert(ret);
|
|
|
|
- c = hashmap_get(m->contexts, UINT_TO_PTR(context+1));
|
|
+ c = m->contexts[context];
|
|
if (!c)
|
|
return 0;
|
|
|
|
@@ -378,12 +371,9 @@ static int try_context(
|
|
return 0;
|
|
}
|
|
|
|
- c->window->keep_always += keep_always;
|
|
+ c->window->keep_always |= keep_always;
|
|
|
|
- if (ret)
|
|
- *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
|
|
- if (keep_always && release_cookie)
|
|
- *release_cookie = c->window;
|
|
+ *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
|
|
return 1;
|
|
}
|
|
|
|
@@ -395,8 +385,7 @@ static int find_mmap(
|
|
bool keep_always,
|
|
uint64_t offset,
|
|
size_t size,
|
|
- void **ret,
|
|
- void **release_cookie) {
|
|
+ void **ret) {
|
|
|
|
FileDescriptor *f;
|
|
Window *w;
|
|
@@ -427,10 +416,7 @@ static int find_mmap(
|
|
context_attach_window(c, w);
|
|
w->keep_always += keep_always;
|
|
|
|
- if (ret)
|
|
- *ret = (uint8_t*) w->ptr + (offset - w->offset);
|
|
- if (keep_always && release_cookie)
|
|
- *release_cookie = c->window;
|
|
+ *ret = (uint8_t*) w->ptr + (offset - w->offset);
|
|
return 1;
|
|
}
|
|
|
|
@@ -443,8 +429,7 @@ static int add_mmap(
|
|
uint64_t offset,
|
|
size_t size,
|
|
struct stat *st,
|
|
- void **ret,
|
|
- void **release_cookie) {
|
|
+ void **ret) {
|
|
|
|
uint64_t woffset, wsize;
|
|
Context *c;
|
|
@@ -457,6 +442,7 @@ static int add_mmap(
|
|
assert(m->n_ref > 0);
|
|
assert(fd >= 0);
|
|
assert(size > 0);
|
|
+ assert(ret);
|
|
|
|
woffset = offset & ~((uint64_t) page_size() - 1ULL);
|
|
wsize = size + (offset - woffset);
|
|
@@ -526,10 +512,7 @@ static int add_mmap(
|
|
c->window = w;
|
|
LIST_PREPEND(by_window, w->contexts, c);
|
|
|
|
- if (ret)
|
|
- *ret = (uint8_t*) w->ptr + (offset - w->offset);
|
|
- if (keep_always && release_cookie)
|
|
- *release_cookie = c->window;
|
|
+ *ret = (uint8_t*) w->ptr + (offset - w->offset);
|
|
return 1;
|
|
|
|
outofmem:
|
|
@@ -546,8 +529,7 @@ int mmap_cache_get(
|
|
uint64_t offset,
|
|
size_t size,
|
|
struct stat *st,
|
|
- void **ret,
|
|
- void **release_cookie) {
|
|
+ void **ret) {
|
|
|
|
int r;
|
|
|
|
@@ -555,16 +537,18 @@ int mmap_cache_get(
|
|
assert(m->n_ref > 0);
|
|
assert(fd >= 0);
|
|
assert(size > 0);
|
|
+ assert(ret);
|
|
+ assert(context < MMAP_CACHE_MAX_CONTEXTS);
|
|
|
|
/* Check whether the current context is the right one already */
|
|
- r = try_context(m, fd, prot, context, keep_always, offset, size, ret, release_cookie);
|
|
+ r = try_context(m, fd, prot, context, keep_always, offset, size, ret);
|
|
if (r != 0) {
|
|
m->n_hit ++;
|
|
return r;
|
|
}
|
|
|
|
/* Search for a matching mmap */
|
|
- r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret, release_cookie);
|
|
+ r = find_mmap(m, fd, prot, context, keep_always, offset, size, ret);
|
|
if (r != 0) {
|
|
m->n_hit ++;
|
|
return r;
|
|
@@ -573,39 +557,7 @@ int mmap_cache_get(
|
|
m->n_missed++;
|
|
|
|
/* Create a new mmap */
|
|
- return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret, release_cookie);
|
|
-}
|
|
-
|
|
-int mmap_cache_release(
|
|
- MMapCache *m,
|
|
- int fd,
|
|
- void *release_cookie) {
|
|
-
|
|
- FileDescriptor *f;
|
|
- Window *w;
|
|
-
|
|
- assert(m);
|
|
- assert(m->n_ref > 0);
|
|
- assert(fd >= 0);
|
|
-
|
|
- f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
|
|
- if (!f)
|
|
- return -EBADF;
|
|
-
|
|
- assert(f->fd == fd);
|
|
-
|
|
- LIST_FOREACH(by_fd, w, f->windows)
|
|
- if (w == release_cookie)
|
|
- break;
|
|
-
|
|
- if (!w)
|
|
- return -ENOENT;
|
|
-
|
|
- if (w->keep_always == 0)
|
|
- return -ENOLCK;
|
|
-
|
|
- w->keep_always -= 1;
|
|
- return 0;
|
|
+ return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret);
|
|
}
|
|
|
|
void mmap_cache_close_fd(MMapCache *m, int fd) {
|
|
@@ -621,18 +573,6 @@ void mmap_cache_close_fd(MMapCache *m, int fd) {
|
|
fd_free(f);
|
|
}
|
|
|
|
-void mmap_cache_close_context(MMapCache *m, unsigned context) {
|
|
- Context *c;
|
|
-
|
|
- assert(m);
|
|
-
|
|
- c = hashmap_get(m->contexts, UINT_TO_PTR(context + 1));
|
|
- if (!c)
|
|
- return;
|
|
-
|
|
- context_free(c);
|
|
-}
|
|
-
|
|
unsigned mmap_cache_get_hit(MMapCache *m) {
|
|
assert(m);
|
|
|
|
diff --git a/src/journal/mmap-cache.h b/src/journal/mmap-cache.h
|
|
index 76e5316..fe2c83d 100644
|
|
--- a/src/journal/mmap-cache.h
|
|
+++ b/src/journal/mmap-cache.h
|
|
@@ -25,6 +25,8 @@
|
|
#include <stdbool.h>
|
|
#include <sys/stat.h>
|
|
|
|
+#define MMAP_CACHE_MAX_CONTEXTS 8
|
|
+
|
|
typedef struct MMapCache MMapCache;
|
|
|
|
MMapCache* mmap_cache_new(void);
|
|
@@ -40,14 +42,8 @@ int mmap_cache_get(
|
|
uint64_t offset,
|
|
size_t size,
|
|
struct stat *st,
|
|
- void **ret,
|
|
- void **release_cookie);
|
|
-int mmap_cache_release(
|
|
- MMapCache *m,
|
|
- int fd,
|
|
- void *release_cookie);
|
|
+ void **ret);
|
|
void mmap_cache_close_fd(MMapCache *m, int fd);
|
|
-void mmap_cache_close_context(MMapCache *m, unsigned context);
|
|
|
|
unsigned mmap_cache_get_hit(MMapCache *m);
|
|
unsigned mmap_cache_get_missed(MMapCache *m);
|
|
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
|
|
index cf21c4d..cb7fc32 100644
|
|
--- a/src/journal/sd-journal.c
|
|
+++ b/src/journal/sd-journal.c
|
|
@@ -87,7 +87,7 @@ static void detach_location(sd_journal *j) {
|
|
j->current_field = 0;
|
|
|
|
ORDERED_HASHMAP_FOREACH(f, j->files, i)
|
|
- f->current_offset = 0;
|
|
+ journal_file_reset_location(f);
|
|
}
|
|
|
|
static void reset_location(sd_journal *j) {
|
|
@@ -114,20 +114,19 @@ static void init_location(Location *l, LocationType type, JournalFile *f, Object
|
|
l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
|
|
}
|
|
|
|
-static void set_location(sd_journal *j, LocationType type, JournalFile *f, Object *o,
|
|
- direction_t direction, uint64_t offset) {
|
|
+static void set_location(sd_journal *j, JournalFile *f, Object *o) {
|
|
assert(j);
|
|
- assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
|
|
assert(f);
|
|
assert(o);
|
|
|
|
- init_location(&j->current_location, type, f, o);
|
|
+ init_location(&j->current_location, LOCATION_DISCRETE, f, o);
|
|
|
|
j->current_file = f;
|
|
j->current_field = 0;
|
|
|
|
- f->last_direction = direction;
|
|
- f->current_offset = offset;
|
|
+ /* Let f know its candidate entry was picked. */
|
|
+ assert(f->location_type == LOCATION_SEEK);
|
|
+ f->location_type = LOCATION_DISCRETE;
|
|
}
|
|
|
|
static int match_is_valid(const void *data, size_t size) {
|
|
@@ -413,144 +412,51 @@ _public_ void sd_journal_flush_matches(sd_journal *j) {
|
|
detach_location(j);
|
|
}
|
|
|
|
-static int compare_entry_order(JournalFile *af, Object *_ao,
|
|
- JournalFile *bf, uint64_t bp) {
|
|
-
|
|
- uint64_t a, b;
|
|
- Object *ao, *bo;
|
|
- int r;
|
|
-
|
|
- assert(af);
|
|
- assert(bf);
|
|
- assert(_ao);
|
|
-
|
|
- /* The mmap cache might invalidate the object from the first
|
|
- * file if we look at the one from the second file. Hence
|
|
- * temporarily copy the header of the first one, and look at
|
|
- * that only. */
|
|
- ao = alloca(offsetof(EntryObject, items));
|
|
- memcpy(ao, _ao, offsetof(EntryObject, items));
|
|
-
|
|
- r = journal_file_move_to_object(bf, OBJECT_ENTRY, bp, &bo);
|
|
- if (r < 0)
|
|
- return strcmp(af->path, bf->path);
|
|
-
|
|
- /* We operate on two different files here, hence we can access
|
|
- * two objects at the same time, which we normally can't.
|
|
- *
|
|
- * If contents and timestamps match, these entries are
|
|
- * identical, even if the seqnum does not match */
|
|
-
|
|
- if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id) &&
|
|
- ao->entry.monotonic == bo->entry.monotonic &&
|
|
- ao->entry.realtime == bo->entry.realtime &&
|
|
- ao->entry.xor_hash == bo->entry.xor_hash)
|
|
- return 0;
|
|
-
|
|
- if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
|
|
-
|
|
- /* If this is from the same seqnum source, compare
|
|
- * seqnums */
|
|
- a = le64toh(ao->entry.seqnum);
|
|
- b = le64toh(bo->entry.seqnum);
|
|
-
|
|
- if (a < b)
|
|
- return -1;
|
|
- if (a > b)
|
|
- return 1;
|
|
-
|
|
- /* Wow! This is weird, different data but the same
|
|
- * seqnums? Something is borked, but let's make the
|
|
- * best of it and compare by time. */
|
|
- }
|
|
-
|
|
- if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id)) {
|
|
-
|
|
- /* If the boot id matches, compare monotonic time */
|
|
- a = le64toh(ao->entry.monotonic);
|
|
- b = le64toh(bo->entry.monotonic);
|
|
-
|
|
- if (a < b)
|
|
- return -1;
|
|
- if (a > b)
|
|
- return 1;
|
|
- }
|
|
-
|
|
- /* Otherwise, compare UTC time */
|
|
- a = le64toh(ao->entry.realtime);
|
|
- b = le64toh(bo->entry.realtime);
|
|
-
|
|
- if (a < b)
|
|
- return -1;
|
|
- if (a > b)
|
|
- return 1;
|
|
-
|
|
- /* Finally, compare by contents */
|
|
- a = le64toh(ao->entry.xor_hash);
|
|
- b = le64toh(bo->entry.xor_hash);
|
|
-
|
|
- if (a < b)
|
|
- return -1;
|
|
- if (a > b)
|
|
- return 1;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-_pure_ static int compare_with_location(JournalFile *af, Object *ao, Location *l) {
|
|
- uint64_t a;
|
|
-
|
|
- assert(af);
|
|
- assert(ao);
|
|
+_pure_ static int compare_with_location(JournalFile *f, Location *l) {
|
|
+ assert(f);
|
|
assert(l);
|
|
+ assert(f->location_type == LOCATION_SEEK);
|
|
assert(l->type == LOCATION_DISCRETE || l->type == LOCATION_SEEK);
|
|
|
|
if (l->monotonic_set &&
|
|
- sd_id128_equal(ao->entry.boot_id, l->boot_id) &&
|
|
+ sd_id128_equal(f->current_boot_id, l->boot_id) &&
|
|
l->realtime_set &&
|
|
- le64toh(ao->entry.realtime) == l->realtime &&
|
|
+ f->current_realtime == l->realtime &&
|
|
l->xor_hash_set &&
|
|
- le64toh(ao->entry.xor_hash) == l->xor_hash)
|
|
+ f->current_xor_hash == l->xor_hash)
|
|
return 0;
|
|
|
|
if (l->seqnum_set &&
|
|
- sd_id128_equal(af->header->seqnum_id, l->seqnum_id)) {
|
|
-
|
|
- a = le64toh(ao->entry.seqnum);
|
|
+ sd_id128_equal(f->header->seqnum_id, l->seqnum_id)) {
|
|
|
|
- if (a < l->seqnum)
|
|
+ if (f->current_seqnum < l->seqnum)
|
|
return -1;
|
|
- if (a > l->seqnum)
|
|
+ if (f->current_seqnum > l->seqnum)
|
|
return 1;
|
|
}
|
|
|
|
if (l->monotonic_set &&
|
|
- sd_id128_equal(ao->entry.boot_id, l->boot_id)) {
|
|
+ sd_id128_equal(f->current_boot_id, l->boot_id)) {
|
|
|
|
- a = le64toh(ao->entry.monotonic);
|
|
-
|
|
- if (a < l->monotonic)
|
|
+ if (f->current_monotonic < l->monotonic)
|
|
return -1;
|
|
- if (a > l->monotonic)
|
|
+ if (f->current_monotonic > l->monotonic)
|
|
return 1;
|
|
}
|
|
|
|
if (l->realtime_set) {
|
|
|
|
- a = le64toh(ao->entry.realtime);
|
|
-
|
|
- if (a < l->realtime)
|
|
+ if (f->current_realtime < l->realtime)
|
|
return -1;
|
|
- if (a > l->realtime)
|
|
+ if (f->current_realtime > l->realtime)
|
|
return 1;
|
|
}
|
|
|
|
if (l->xor_hash_set) {
|
|
- a = le64toh(ao->entry.xor_hash);
|
|
|
|
- if (a < l->xor_hash)
|
|
+ if (f->current_xor_hash < l->xor_hash)
|
|
return -1;
|
|
- if (a > l->xor_hash)
|
|
+ if (f->current_xor_hash > l->xor_hash)
|
|
return 1;
|
|
}
|
|
|
|
@@ -766,9 +672,9 @@ static int find_location_with_matches(
|
|
/* No matches is simple */
|
|
|
|
if (j->current_location.type == LOCATION_HEAD)
|
|
- return journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, ret, offset);
|
|
+ return journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset);
|
|
if (j->current_location.type == LOCATION_TAIL)
|
|
- return journal_file_next_entry(f, NULL, 0, DIRECTION_UP, ret, offset);
|
|
+ return journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset);
|
|
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
|
|
return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
|
|
if (j->current_location.monotonic_set) {
|
|
@@ -779,7 +685,7 @@ static int find_location_with_matches(
|
|
if (j->current_location.realtime_set)
|
|
return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset);
|
|
|
|
- return journal_file_next_entry(f, NULL, 0, direction, ret, offset);
|
|
+ return journal_file_next_entry(f, 0, direction, ret, offset);
|
|
} else
|
|
return find_location_for_match(j, j->level0, f, direction, ret, offset);
|
|
}
|
|
@@ -791,49 +697,61 @@ static int next_with_matches(
|
|
Object **ret,
|
|
uint64_t *offset) {
|
|
|
|
- Object *c;
|
|
- uint64_t cp;
|
|
-
|
|
assert(j);
|
|
assert(f);
|
|
assert(ret);
|
|
assert(offset);
|
|
|
|
- c = *ret;
|
|
- cp = *offset;
|
|
-
|
|
/* No matches is easy. We simple advance the file
|
|
* pointer by one. */
|
|
if (!j->level0)
|
|
- return journal_file_next_entry(f, c, cp, direction, ret, offset);
|
|
+ return journal_file_next_entry(f, f->current_offset, direction, ret, offset);
|
|
|
|
/* If we have a match then we look for the next matching entry
|
|
* with an offset at least one step larger */
|
|
- return next_for_match(j, j->level0, f, direction == DIRECTION_DOWN ? cp+1 : cp-1, direction, ret, offset);
|
|
+ return next_for_match(j, j->level0, f,
|
|
+ direction == DIRECTION_DOWN ? f->current_offset + 1
|
|
+ : f->current_offset - 1,
|
|
+ direction, ret, offset);
|
|
}
|
|
|
|
-static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) {
|
|
+static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction) {
|
|
Object *c;
|
|
- uint64_t cp;
|
|
+ uint64_t cp, n_entries;
|
|
int r;
|
|
|
|
assert(j);
|
|
assert(f);
|
|
|
|
- if (f->last_direction == direction && f->current_offset > 0) {
|
|
- cp = f->current_offset;
|
|
+ n_entries = le64toh(f->header->n_entries);
|
|
|
|
- r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c);
|
|
- if (r < 0)
|
|
- return r;
|
|
+ /* If we hit EOF before, we don't need to look into this file again
|
|
+ * unless direction changed or new entries appeared. */
|
|
+ if (f->last_direction == direction && f->location_type == LOCATION_TAIL &&
|
|
+ n_entries == f->last_n_entries)
|
|
+ return 0;
|
|
|
|
- r = next_with_matches(j, f, direction, &c, &cp);
|
|
- if (r <= 0)
|
|
- return r;
|
|
+ f->last_n_entries = n_entries;
|
|
+
|
|
+ if (f->last_direction == direction && f->current_offset > 0) {
|
|
+ /* LOCATION_SEEK here means we did the work in a previous
|
|
+ * iteration and the current location already points to a
|
|
+ * candidate entry. */
|
|
+ if (f->location_type != LOCATION_SEEK) {
|
|
+ r = next_with_matches(j, f, direction, &c, &cp);
|
|
+ if (r <= 0)
|
|
+ return r;
|
|
+
|
|
+ journal_file_save_location(f, c, cp);
|
|
+ }
|
|
} else {
|
|
+ f->last_direction = direction;
|
|
+
|
|
r = find_location_with_matches(j, f, direction, &c, &cp);
|
|
if (r <= 0)
|
|
return r;
|
|
+
|
|
+ journal_file_save_location(f, c, cp);
|
|
}
|
|
|
|
/* OK, we found the spot, now let's advance until an entry
|
|
@@ -848,30 +766,25 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
|
|
if (j->current_location.type == LOCATION_DISCRETE) {
|
|
int k;
|
|
|
|
- k = compare_with_location(f, c, &j->current_location);
|
|
+ k = compare_with_location(f, &j->current_location);
|
|
|
|
found = direction == DIRECTION_DOWN ? k > 0 : k < 0;
|
|
} else
|
|
found = true;
|
|
|
|
- if (found) {
|
|
- if (ret)
|
|
- *ret = c;
|
|
- if (offset)
|
|
- *offset = cp;
|
|
+ if (found)
|
|
return 1;
|
|
- }
|
|
|
|
r = next_with_matches(j, f, direction, &c, &cp);
|
|
if (r <= 0)
|
|
return r;
|
|
+
|
|
+ journal_file_save_location(f, c, cp);
|
|
}
|
|
}
|
|
|
|
static int real_journal_next(sd_journal *j, direction_t direction) {
|
|
JournalFile *f, *new_file = NULL;
|
|
- uint64_t new_offset = 0;
|
|
- uint64_t p = 0;
|
|
Iterator i;
|
|
Object *o;
|
|
int r;
|
|
@@ -882,38 +795,38 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
|
|
ORDERED_HASHMAP_FOREACH(f, j->files, i) {
|
|
bool found;
|
|
|
|
- r = next_beyond_location(j, f, direction, &o, &p);
|
|
+ r = next_beyond_location(j, f, direction);
|
|
if (r < 0) {
|
|
log_debug("Can't iterate through %s, ignoring: %s", f->path, strerror(-r));
|
|
remove_file_real(j, f);
|
|
continue;
|
|
- } else if (r == 0)
|
|
+ } else if (r == 0) {
|
|
+ f->location_type = LOCATION_TAIL;
|
|
continue;
|
|
+ }
|
|
|
|
if (!new_file)
|
|
found = true;
|
|
else {
|
|
int k;
|
|
|
|
- k = compare_entry_order(f, o, new_file, new_offset);
|
|
+ k = journal_file_compare_locations(f, new_file);
|
|
|
|
found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
|
|
}
|
|
|
|
- if (found) {
|
|
+ if (found)
|
|
new_file = f;
|
|
- new_offset = p;
|
|
- }
|
|
}
|
|
|
|
if (!new_file)
|
|
return 0;
|
|
|
|
- r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_offset, &o);
|
|
+ r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_file->current_offset, &o);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
- set_location(j, LOCATION_DISCRETE, new_file, o, direction, new_offset);
|
|
+ set_location(j, new_file, o);
|
|
|
|
return 1;
|
|
}
|
|
@@ -2526,7 +2439,6 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
|
|
size_t ol;
|
|
bool found;
|
|
int r;
|
|
- void *release_cookie;
|
|
|
|
/* Proceed to next data object in the field's linked list */
|
|
if (j->unique_offset == 0) {
|
|
@@ -2552,10 +2464,10 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
|
|
continue;
|
|
}
|
|
|
|
- /* We do not use the type context here, but 0 instead,
|
|
- * so that we can look at this data object at the same
|
|
+ /* We do not use OBJECT_DATA context here, but OBJECT_UNUSED
|
|
+ * instead, so that we can look at this data object at the same
|
|
* time as one on another file */
|
|
- r = journal_file_move_to_object(j->unique_file, 0, j->unique_offset, &o);
|
|
+ r = journal_file_move_to_object(j->unique_file, OBJECT_UNUSED, j->unique_offset, &o);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
@@ -2567,10 +2479,6 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
|
|
return -EBADMSG;
|
|
}
|
|
|
|
- r = journal_file_object_keep(j->unique_file, o, j->unique_offset, &release_cookie);
|
|
- if (r < 0)
|
|
- return r;
|
|
-
|
|
r = return_data(j, j->unique_file, o, &odata, &ol);
|
|
if (r < 0)
|
|
return r;
|
|
@@ -2615,10 +2523,6 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
|
|
found = true;
|
|
}
|
|
|
|
- r = journal_file_object_release(j->unique_file, release_cookie);
|
|
- if (r < 0)
|
|
- return r;
|
|
-
|
|
if (found)
|
|
continue;
|
|
|
|
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
|
|
index 372f3ed..d56ee51 100644
|
|
--- a/src/libsystemd-network/network-internal.c
|
|
+++ b/src/libsystemd-network/network-internal.c
|
|
@@ -392,10 +392,12 @@ void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *route
|
|
|
|
fprintf(f, "%s=", key);
|
|
|
|
- for (i = 0; i < size; i++)
|
|
- fprintf(f, "%s/%" PRIu8 ",%s%s", inet_ntoa(routes[i].dst_addr),
|
|
- routes[i].dst_prefixlen, inet_ntoa(routes[i].gw_addr),
|
|
+ for (i = 0; i < size; i++) {
|
|
+ fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
|
|
+ routes[i].dst_prefixlen);
|
|
+ fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
|
|
(i < (size - 1)) ? " ": "");
|
|
+ }
|
|
|
|
fputs("\n", f);
|
|
}
|
|
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
|
|
index 0eba4c3..9986b52 100644
|
|
--- a/src/libsystemd-network/sd-dhcp-client.c
|
|
+++ b/src/libsystemd-network/sd-dhcp-client.c
|
|
@@ -68,7 +68,6 @@ struct sd_dhcp_client {
|
|
uint32_t mtu;
|
|
uint32_t xid;
|
|
usec_t start_time;
|
|
- uint16_t secs;
|
|
unsigned int attempt;
|
|
usec_t request_sent;
|
|
sd_event_source *timeout_t1;
|
|
@@ -321,10 +320,12 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
|
_cleanup_free_ DHCPPacket *packet;
|
|
size_t optlen, optoffset, size;
|
|
be16_t max_size;
|
|
+ usec_t time_now;
|
|
+ uint16_t secs;
|
|
int r;
|
|
|
|
assert(client);
|
|
- assert(client->secs);
|
|
+ assert(client->start_time);
|
|
assert(ret);
|
|
assert(_optlen);
|
|
assert(_optoffset);
|
|
@@ -344,7 +345,15 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
|
|
|
/* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
|
|
refuse to issue an DHCP lease if 'secs' is set to zero */
|
|
- packet->dhcp.secs = htobe16(client->secs);
|
|
+ r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ assert(time_now >= client->start_time);
|
|
+
|
|
+ /* seconds between sending first and last DISCOVER
|
|
+ * must always be strictly positive to deal with broken servers */
|
|
+ secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
|
|
+ packet->dhcp.secs = htobe16(secs);
|
|
|
|
/* RFC2132 section 4.1
|
|
A client that cannot receive unicast IP datagrams until its protocol
|
|
@@ -441,24 +450,12 @@ static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
|
|
static int client_send_discover(sd_dhcp_client *client) {
|
|
_cleanup_free_ DHCPPacket *discover = NULL;
|
|
size_t optoffset, optlen;
|
|
- usec_t time_now;
|
|
int r;
|
|
|
|
assert(client);
|
|
assert(client->state == DHCP_STATE_INIT ||
|
|
client->state == DHCP_STATE_SELECTING);
|
|
|
|
- /* See RFC2131 section 4.4.1 */
|
|
-
|
|
- r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
|
|
- if (r < 0)
|
|
- return r;
|
|
- assert(time_now >= client->start_time);
|
|
-
|
|
- /* seconds between sending first and last DISCOVER
|
|
- * must always be strictly positive to deal with broken servers */
|
|
- client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
|
|
-
|
|
r = client_message_init(client, &discover, DHCP_DISCOVER,
|
|
&optlen, &optoffset);
|
|
if (r < 0)
|
|
@@ -875,10 +872,8 @@ static int client_start(sd_dhcp_client *client) {
|
|
}
|
|
client->fd = r;
|
|
|
|
- if (client->state == DHCP_STATE_INIT) {
|
|
+ if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
|
|
client->start_time = now(clock_boottime_or_monotonic());
|
|
- client->secs = 0;
|
|
- }
|
|
|
|
return client_initialize_events(client, client_receive_message_raw);
|
|
}
|
|
@@ -1269,6 +1264,9 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
|
|
if (r >= 0) {
|
|
client->timeout_resend =
|
|
sd_event_source_unref(client->timeout_resend);
|
|
+ client->receive_message =
|
|
+ sd_event_source_unref(client->receive_message);
|
|
+ client->fd = asynchronous_close(client->fd);
|
|
|
|
if (IN_SET(client->state, DHCP_STATE_REQUESTING,
|
|
DHCP_STATE_REBOOTING))
|
|
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
|
|
index 4fb01c0..b7c9a07 100644
|
|
--- a/src/libsystemd-network/sd-dhcp-lease.c
|
|
+++ b/src/libsystemd-network/sd-dhcp-lease.c
|
|
@@ -50,7 +50,7 @@ int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
|
|
|
|
int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
|
|
assert_return(lease, -EINVAL);
|
|
- assert_return(lease, -EINVAL);
|
|
+ assert_return(lifetime, -EINVAL);
|
|
|
|
*lifetime = lease->lifetime;
|
|
|
|
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
|
|
index fa4f9b5..dbec1a2 100644
|
|
--- a/src/libsystemd-network/sd-dhcp6-client.c
|
|
+++ b/src/libsystemd-network/sd-dhcp6-client.c
|
|
@@ -200,19 +200,19 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
|
|
|
|
switch (type) {
|
|
case DHCP6_DUID_LLT:
|
|
- if (duid_len <= sizeof(client->duid.llt))
|
|
+ if (duid_len <= sizeof(client->duid.llt) - 2)
|
|
return -EINVAL;
|
|
break;
|
|
case DHCP6_DUID_EN:
|
|
- if (duid_len != sizeof(client->duid.en))
|
|
+ if (duid_len != sizeof(client->duid.en) - 2)
|
|
return -EINVAL;
|
|
break;
|
|
case DHCP6_DUID_LL:
|
|
- if (duid_len <= sizeof(client->duid.ll))
|
|
+ if (duid_len <= sizeof(client->duid.ll) - 2)
|
|
return -EINVAL;
|
|
break;
|
|
case DHCP6_DUID_UUID:
|
|
- if (duid_len != sizeof(client->duid.uuid))
|
|
+ if (duid_len != sizeof(client->duid.uuid) - 2)
|
|
return -EINVAL;
|
|
break;
|
|
default:
|
|
@@ -222,7 +222,7 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
|
|
|
|
client->duid.raw.type = htobe16(type);
|
|
memcpy(&client->duid.raw.data, duid, duid_len);
|
|
- client->duid_len = duid_len;
|
|
+ client->duid_len = duid_len + 2; /* +2 for sizeof(type) */
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
|
|
index 18afe0f..5658c61 100644
|
|
--- a/src/libsystemd/sd-bus/bus-match.c
|
|
+++ b/src/libsystemd/sd-bus/bus-match.c
|
|
@@ -537,7 +537,7 @@ static int bus_match_find_compare_value(
|
|
else if (BUS_MATCH_CAN_HASH(t))
|
|
n = hashmap_get(c->compare.children, value_str);
|
|
else {
|
|
- for (n = c->child; !value_node_same(n, t, value_u8, value_str); n = n->next)
|
|
+ for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next)
|
|
;
|
|
}
|
|
|
|
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
|
|
index 0ab1119..6c3230a 100644
|
|
--- a/src/libsystemd/sd-bus/bus-objects.c
|
|
+++ b/src/libsystemd/sd-bus/bus-objects.c
|
|
@@ -617,6 +617,9 @@ static int property_get_set_callbacks_run(
|
|
return r;
|
|
|
|
} else {
|
|
+ const char *signature = NULL;
|
|
+ char type = 0;
|
|
+
|
|
if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
|
|
return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member);
|
|
|
|
@@ -628,6 +631,13 @@ static int property_get_set_callbacks_run(
|
|
|
|
c->last_iteration = bus->iteration_counter;
|
|
|
|
+ r = sd_bus_message_peek_type(m, &type, &signature);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+
|
|
+ if (type != 'v' || !streq(strempty(signature), strempty(c->vtable->x.property.signature)))
|
|
+ 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));
|
|
+
|
|
r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
|
|
if (r < 0)
|
|
return r;
|
|
diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
|
|
index b501a52..740133a 100644
|
|
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
|
|
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
|
|
@@ -36,6 +36,8 @@
|
|
#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
|
|
#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
|
|
|
|
+#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
|
|
+
|
|
static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
|
|
sd_rtnl_message *m;
|
|
|
|
@@ -566,8 +568,8 @@ int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const
|
|
size = (size_t)r;
|
|
|
|
if (size) {
|
|
- length = strnlen(data, size);
|
|
- if (length >= size)
|
|
+ length = strnlen(data, size+1);
|
|
+ if (length > size)
|
|
return -EINVAL;
|
|
} else
|
|
length = strlen(data);
|
|
@@ -1066,7 +1068,7 @@ int rtnl_message_parse(sd_rtnl_message *m,
|
|
*rta_tb_size = max + 1;
|
|
|
|
for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
|
|
- type = rta->rta_type;
|
|
+ type = RTA_TYPE(rta);
|
|
|
|
/* if the kernel is newer than the headers we used
|
|
when building, we ignore out-of-range attributes
|
|
@@ -1222,7 +1224,7 @@ int socket_read_message(sd_rtnl *rtnl) {
|
|
}
|
|
}
|
|
|
|
- for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
|
|
+ for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
|
|
_cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
|
|
const NLType *nl_type;
|
|
|
|
@@ -1237,7 +1239,8 @@ int socket_read_message(sd_rtnl *rtnl) {
|
|
if (new_msg->nlmsg_type == NLMSG_DONE) {
|
|
/* finished reading multi-part message */
|
|
done = true;
|
|
- break;
|
|
+
|
|
+ continue;
|
|
}
|
|
|
|
/* check that we support this message type */
|
|
diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
|
|
index 2699374..e2afcb8 100644
|
|
--- a/src/libudev/libudev-device.c
|
|
+++ b/src/libudev/libudev-device.c
|
|
@@ -730,8 +730,13 @@ _public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, con
|
|
return NULL;
|
|
} else {
|
|
/* everything else just needs to be a directory */
|
|
- if (stat(path, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
|
|
+ if (stat(path, &statbuf) != 0)
|
|
return NULL;
|
|
+
|
|
+ if (!S_ISDIR(statbuf.st_mode)) {
|
|
+ errno = EISDIR;
|
|
+ return NULL;
|
|
+ }
|
|
}
|
|
|
|
udev_device = udev_device_new(udev);
|
|
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
|
|
index b6d9bc6..759794f 100644
|
|
--- a/src/nspawn/nspawn.c
|
|
+++ b/src/nspawn/nspawn.c
|
|
@@ -758,7 +758,7 @@ static int mount_binds(const char *dest, char **l, bool ro) {
|
|
* and char devices. */
|
|
if (S_ISDIR(source_st.st_mode)) {
|
|
r = mkdir_label(where, 0755);
|
|
- if (r < 0) {
|
|
+ if (r < 0 && errno != EEXIST) {
|
|
log_error("Failed to create mount point %s: %s", where, strerror(-r));
|
|
|
|
return r;
|
|
@@ -818,7 +818,7 @@ static int mount_tmpfs(const char *dest) {
|
|
return log_oom();
|
|
|
|
r = mkdir_label(where, 0755);
|
|
- if (r < 0) {
|
|
+ if (r < 0 && errno != EEXIST) {
|
|
log_error("creating mount point for tmpfs %s failed: %s", where, strerror(-r));
|
|
|
|
return r;
|
|
@@ -3073,6 +3073,7 @@ int main(int argc, char *argv[]) {
|
|
goto finish;
|
|
}
|
|
} else {
|
|
+#if 0
|
|
const char *p;
|
|
|
|
p = strappenda(arg_directory,
|
|
@@ -3082,6 +3083,7 @@ int main(int argc, char *argv[]) {
|
|
goto finish;
|
|
|
|
}
|
|
+#endif
|
|
}
|
|
} else {
|
|
char template[] = "/tmp/nspawn-root-XXXXXX";
|
|
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
|
|
index 7375f77..ec8efcc 100644
|
|
--- a/src/resolve/resolved-dns-packet.c
|
|
+++ b/src/resolve/resolved-dns-packet.c
|
|
@@ -866,7 +866,7 @@ fail:
|
|
|
|
int dns_packet_read_name(DnsPacket *p, char **_ret,
|
|
bool allow_compression, size_t *start) {
|
|
- size_t saved_rindex, after_rindex = 0;
|
|
+ size_t saved_rindex, after_rindex = 0, jump_barrier;
|
|
_cleanup_free_ char *ret = NULL;
|
|
size_t n = 0, allocated = 0;
|
|
bool first = true;
|
|
@@ -876,6 +876,7 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
|
|
assert(_ret);
|
|
|
|
saved_rindex = p->rindex;
|
|
+ jump_barrier = p->rindex;
|
|
|
|
for (;;) {
|
|
uint8_t c, d;
|
|
@@ -922,7 +923,7 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
|
|
goto fail;
|
|
|
|
ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
|
|
- if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= saved_rindex) {
|
|
+ if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
|
|
r = -EBADMSG;
|
|
goto fail;
|
|
}
|
|
@@ -930,9 +931,13 @@ int dns_packet_read_name(DnsPacket *p, char **_ret,
|
|
if (after_rindex == 0)
|
|
after_rindex = p->rindex;
|
|
|
|
+ /* Jumps are limited to a "prior occurence" (RFC-1035 4.1.4) */
|
|
+ jump_barrier = ptr;
|
|
p->rindex = ptr;
|
|
- } else
|
|
+ } else {
|
|
+ r = -EBADMSG;
|
|
goto fail;
|
|
+ }
|
|
}
|
|
|
|
if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
|
|
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
|
|
index 7d258c9..6dd4cad 100644
|
|
--- a/src/resolve/resolved.c
|
|
+++ b/src/resolve/resolved.c
|
|
@@ -108,7 +108,7 @@ int main(int argc, char *argv[]) {
|
|
|
|
finish:
|
|
sd_notify(false,
|
|
- "STOPPIN=1\n"
|
|
+ "STOPPING=1\n"
|
|
"STATUS=Shutting down...");
|
|
|
|
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
diff --git a/src/run/run.c b/src/run/run.c
|
|
index e3b6293..dcefb5c 100644
|
|
--- a/src/run/run.c
|
|
+++ b/src/run/run.c
|
|
@@ -573,9 +573,12 @@ int main(int argc, char* argv[]) {
|
|
if (r <= 0)
|
|
goto finish;
|
|
|
|
- r = find_binary(argv[optind], &command);
|
|
+ r = find_binary(argv[optind], arg_transport == BUS_TRANSPORT_LOCAL, &command);
|
|
if (r < 0) {
|
|
- log_error("Failed to find executable %s: %s", argv[optind], strerror(-r));
|
|
+ log_error("Failed to find executable %s%s: %s",
|
|
+ argv[optind],
|
|
+ arg_transport == BUS_TRANSPORT_LOCAL ? "" : " on local system",
|
|
+ strerror(-r));
|
|
goto finish;
|
|
}
|
|
argv[optind] = command;
|
|
diff --git a/src/shared/install.c b/src/shared/install.c
|
|
index 035b44c..cab93e8 100644
|
|
--- a/src/shared/install.c
|
|
+++ b/src/shared/install.c
|
|
@@ -1620,12 +1620,10 @@ int unit_file_enable(
|
|
STRV_FOREACH(i, files) {
|
|
UnitFileState state;
|
|
|
|
+ /* We only want to know if this unit is masked, so we ignore
|
|
+ * errors from unit_file_get_state, deferring other checks.
|
|
+ * This allows templated units to be enabled on the fly. */
|
|
state = unit_file_get_state(scope, root_dir, *i);
|
|
- if (state < 0) {
|
|
- log_error("Failed to get unit file state for %s: %s", *i, strerror(-state));
|
|
- return state;
|
|
- }
|
|
-
|
|
if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
|
|
log_error("Failed to enable unit: Unit %s is masked", *i);
|
|
return -ENOTSUP;
|
|
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
|
|
index 8f75a8e..c800e01 100644
|
|
--- a/src/shared/path-lookup.c
|
|
+++ b/src/shared/path-lookup.c
|
|
@@ -86,17 +86,14 @@ static char** user_dirs(
|
|
const char * const config_unit_paths[] = {
|
|
USER_CONFIG_UNIT_PATH,
|
|
"/etc/systemd/user",
|
|
+ "/etc/systemd-mutable/user",
|
|
NULL
|
|
};
|
|
|
|
const char * const runtime_unit_path = "/run/systemd/user";
|
|
|
|
const char * const data_unit_paths[] = {
|
|
- "/usr/local/lib/systemd/user",
|
|
- "/usr/local/share/systemd/user",
|
|
USER_DATA_UNIT_PATH,
|
|
- "/usr/lib/systemd/user",
|
|
- "/usr/share/systemd/user",
|
|
NULL
|
|
};
|
|
|
|
@@ -260,13 +257,11 @@ int lookup_paths_init(
|
|
STRV_IFNOTNULL(generator_early),
|
|
USER_CONFIG_UNIT_PATH,
|
|
"/etc/systemd/user",
|
|
+ "/etc/systemd-mutable/user",
|
|
+ "/nix/var/nix/profiles/default/lib/systemd/user",
|
|
"/run/systemd/user",
|
|
STRV_IFNOTNULL(generator),
|
|
- "/usr/local/lib/systemd/user",
|
|
- "/usr/local/share/systemd/user",
|
|
USER_DATA_UNIT_PATH,
|
|
- "/usr/lib/systemd/user",
|
|
- "/usr/share/systemd/user",
|
|
STRV_IFNOTNULL(generator_late),
|
|
NULL);
|
|
} else
|
|
@@ -276,14 +271,11 @@ int lookup_paths_init(
|
|
STRV_IFNOTNULL(generator_early),
|
|
SYSTEM_CONFIG_UNIT_PATH,
|
|
"/etc/systemd/system",
|
|
+ "/etc/systemd-mutable/system",
|
|
+ "/nix/var/nix/profiles/default/lib/systemd/system",
|
|
"/run/systemd/system",
|
|
STRV_IFNOTNULL(generator),
|
|
- "/usr/local/lib/systemd/system",
|
|
SYSTEM_DATA_UNIT_PATH,
|
|
- "/usr/lib/systemd/system",
|
|
-#ifdef HAVE_SPLIT_USR
|
|
- "/lib/systemd/system",
|
|
-#endif
|
|
STRV_IFNOTNULL(generator_late),
|
|
NULL);
|
|
|
|
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
|
|
index 67566bc..be03695 100644
|
|
--- a/src/shared/path-util.c
|
|
+++ b/src/shared/path-util.c
|
|
@@ -563,11 +563,11 @@ int path_is_os_tree(const char *path) {
|
|
return r >= 0;
|
|
}
|
|
|
|
-int find_binary(const char *name, char **filename) {
|
|
+int find_binary(const char *name, bool local, char **filename) {
|
|
assert(name);
|
|
|
|
if (is_path(name)) {
|
|
- if (access(name, X_OK) < 0)
|
|
+ if (local && access(name, X_OK) < 0)
|
|
return -errno;
|
|
|
|
if (filename) {
|
|
@@ -657,7 +657,7 @@ int fsck_exists(const char *fstype) {
|
|
|
|
checker = strappenda("fsck.", fstype);
|
|
|
|
- r = find_binary(checker, &p);
|
|
+ r = find_binary(checker, true, &p);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
|
|
index 8d171a5..bd0d324 100644
|
|
--- a/src/shared/path-util.h
|
|
+++ b/src/shared/path-util.h
|
|
@@ -55,7 +55,7 @@ int path_is_mount_point(const char *path, bool allow_symlink);
|
|
int path_is_read_only_fs(const char *path);
|
|
int path_is_os_tree(const char *path);
|
|
|
|
-int find_binary(const char *name, char **filename);
|
|
+int find_binary(const char *name, bool local, char **filename);
|
|
|
|
bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
|
|
|
|
diff --git a/src/shared/virt.c b/src/shared/virt.c
|
|
index f9c4e67..f10baab 100644
|
|
--- a/src/shared/virt.c
|
|
+++ b/src/shared/virt.c
|
|
@@ -293,8 +293,26 @@ int detect_container(const char **id) {
|
|
|
|
r = read_one_line_file("/run/systemd/container", &m);
|
|
if (r == -ENOENT) {
|
|
- r = 0;
|
|
- goto finish;
|
|
+
|
|
+ /* Fallback for cases where PID 1 was not
|
|
+ * systemd (for example, cases where
|
|
+ * init=/bin/sh is used. */
|
|
+
|
|
+ r = getenv_for_pid(1, "container", &m);
|
|
+ if (r <= 0) {
|
|
+
|
|
+ /* If that didn't work, give up,
|
|
+ * assume no container manager.
|
|
+ *
|
|
+ * Note: This means we still cannot
|
|
+ * detect containers if init=/bin/sh
|
|
+ * is passed but privileges dropped,
|
|
+ * as /proc/1/environ is only readable
|
|
+ * with privileges. */
|
|
+
|
|
+ r = 0;
|
|
+ goto finish;
|
|
+ }
|
|
}
|
|
if (r < 0)
|
|
return r;
|
|
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
|
index 28eaa6a..3866308 100644
|
|
--- a/src/systemctl/systemctl.c
|
|
+++ b/src/systemctl/systemctl.c
|
|
@@ -2651,7 +2651,7 @@ static int start_unit_one(
|
|
|
|
log_debug("Adding %s to the set", p);
|
|
r = set_consume(s, p);
|
|
- if (r < 0)
|
|
+ if (r < 0 && r != -EEXIST)
|
|
return log_oom();
|
|
}
|
|
|
|
@@ -6917,8 +6917,13 @@ done:
|
|
|
|
static int halt_now(enum action a) {
|
|
|
|
-/* Make sure C-A-D is handled by the kernel from this
|
|
- * point on... */
|
|
+ /* The kernel will automaticall flush ATA disks and suchlike
|
|
+ * on reboot(), but the file systems need to be synce'd
|
|
+ * explicitly in advance. */
|
|
+ sync();
|
|
+
|
|
+ /* Make sure C-A-D is handled by the kernel from this point
|
|
+ * on... */
|
|
reboot(RB_ENABLE_CAD);
|
|
|
|
switch (a) {
|
|
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
|
|
index eb24372..00237a2 100644
|
|
--- a/src/systemd/sd-journal.h
|
|
+++ b/src/systemd/sd-journal.h
|
|
@@ -138,13 +138,15 @@ int sd_journal_reliable_fd(sd_journal *j);
|
|
int sd_journal_get_catalog(sd_journal *j, char **text);
|
|
int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **text);
|
|
|
|
+/* the inverse condition avoids ambiguity of danling 'else' after the macro */
|
|
#define SD_JOURNAL_FOREACH(j) \
|
|
- if (sd_journal_seek_head(j) >= 0) \
|
|
- while (sd_journal_next(j) > 0)
|
|
+ if (sd_journal_seek_head(j) < 0) { } \
|
|
+ else while (sd_journal_next(j) > 0)
|
|
|
|
+/* the inverse condition avoids ambiguity of danling 'else' after the macro */
|
|
#define SD_JOURNAL_FOREACH_BACKWARDS(j) \
|
|
- if (sd_journal_seek_tail(j) >= 0) \
|
|
- while (sd_journal_previous(j) > 0)
|
|
+ if (sd_journal_seek_tail(j) < 0) { } \
|
|
+ else while (sd_journal_previous(j) > 0)
|
|
|
|
#define SD_JOURNAL_FOREACH_DATA(j, data, l) \
|
|
for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
|
|
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
|
|
index 63d64b2..57264de 100644
|
|
--- a/src/test/test-path-util.c
|
|
+++ b/src/test/test-path-util.c
|
|
@@ -85,29 +85,30 @@ static void test_path(void) {
|
|
}
|
|
}
|
|
|
|
-static void test_find_binary(const char *self) {
|
|
+static void test_find_binary(const char *self, bool local) {
|
|
char *p;
|
|
|
|
- assert_se(find_binary("/bin/sh", &p) == 0);
|
|
+ assert_se(find_binary("/bin/sh", local, &p) == 0);
|
|
puts(p);
|
|
assert_se(streq(p, "/bin/sh"));
|
|
free(p);
|
|
|
|
- assert_se(find_binary(self, &p) == 0);
|
|
+ assert_se(find_binary(self, local, &p) == 0);
|
|
puts(p);
|
|
assert_se(endswith(p, "/test-path-util"));
|
|
assert_se(path_is_absolute(p));
|
|
free(p);
|
|
|
|
- assert_se(find_binary("sh", &p) == 0);
|
|
+ assert_se(find_binary("sh", local, &p) == 0);
|
|
puts(p);
|
|
assert_se(endswith(p, "/sh"));
|
|
assert_se(path_is_absolute(p));
|
|
free(p);
|
|
|
|
- assert_se(find_binary("xxxx-xxxx", &p) == -ENOENT);
|
|
+ assert_se(find_binary("xxxx-xxxx", local, &p) == -ENOENT);
|
|
|
|
- assert_se(find_binary("/some/dir/xxxx-xxxx", &p) == -ENOENT);
|
|
+ assert_se(find_binary("/some/dir/xxxx-xxxx", local, &p) ==
|
|
+ (local ? -ENOENT : 0));
|
|
}
|
|
|
|
static void test_prefixes(void) {
|
|
@@ -244,7 +245,8 @@ static void test_strv_resolve(void) {
|
|
|
|
int main(int argc, char **argv) {
|
|
test_path();
|
|
- test_find_binary(argv[0]);
|
|
+ test_find_binary(argv[0], true);
|
|
+ test_find_binary(argv[0], false);
|
|
test_prefixes();
|
|
test_path_join();
|
|
test_fsck_exists();
|
|
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
|
|
index 2e6c713..193702c 100644
|
|
--- a/src/udev/udevd.c
|
|
+++ b/src/udev/udevd.c
|
|
@@ -994,9 +994,9 @@ static void kernel_cmdline_options(struct udev *udev) {
|
|
if (r < 0)
|
|
log_warning("Invalid udev.exec-delay ignored: %s", opt + 16);
|
|
} else if (startswith(opt, "udev.event-timeout=")) {
|
|
- r = safe_atou64(opt + 16, &arg_event_timeout_usec);
|
|
+ r = safe_atou64(opt + 19, &arg_event_timeout_usec);
|
|
if (r < 0) {
|
|
- log_warning("Invalid udev.event-timeout ignored: %s", opt + 16);
|
|
+ log_warning("Invalid udev.event-timeout ignored: %s", opt + 19);
|
|
break;
|
|
}
|
|
arg_event_timeout_usec *= USEC_PER_SEC;
|
|
diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4.in
|
|
index 8ac51a4..cae9fb5 100644
|
|
--- a/units/console-getty.service.m4.in
|
|
+++ b/units/console-getty.service.m4.in
|
|
@@ -15,7 +15,6 @@ After=rc-local.service
|
|
Before=getty.target
|
|
|
|
[Service]
|
|
-ExecStart=-/sbin/agetty --noclear --keep-baud console 115200,38400,9600 $TERM
|
|
Type=idle
|
|
Restart=always
|
|
RestartSec=0
|
|
diff --git a/units/container-getty@.service.m4.in b/units/container-getty@.service.m4.in
|
|
index 4f7794b..6dfc2e9 100644
|
|
--- a/units/container-getty@.service.m4.in
|
|
+++ b/units/container-getty@.service.m4.in
|
|
@@ -14,9 +14,9 @@ After=rc-local.service
|
|
)m4_dnl
|
|
Before=getty.target
|
|
IgnoreOnIsolate=yes
|
|
+ConditionPathExists=/dev/pts/%I
|
|
|
|
[Service]
|
|
-ExecStart=-/sbin/agetty --noclear --keep-baud pts/%I 115200,38400,9600 $TERM
|
|
Type=idle
|
|
Restart=always
|
|
RestartSec=0
|
|
diff --git a/units/emergency.service.in b/units/emergency.service.in
|
|
index 18973e7..3a99660 100644
|
|
--- a/units/emergency.service.in
|
|
+++ b/units/emergency.service.in
|
|
@@ -16,7 +16,6 @@ Before=shutdown.target
|
|
[Service]
|
|
Environment=HOME=/root
|
|
WorkingDirectory=/root
|
|
-ExecStartPre=-/bin/plymouth quit
|
|
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.'
|
|
ExecStart=-/bin/sh -c "/sbin/sulogin; @SYSTEMCTL@ --fail --no-block default"
|
|
Type=idle
|
|
diff --git a/units/getty@.service.m4 b/units/getty@.service.m4
|
|
index 46164ab..f194a31 100644
|
|
--- a/units/getty@.service.m4
|
|
+++ b/units/getty@.service.m4
|
|
@@ -23,11 +23,12 @@ IgnoreOnIsolate=yes
|
|
# On systems without virtual consoles, don't start any getty. Note
|
|
# that serial gettys are covered by serial-getty@.service, not this
|
|
# unit.
|
|
-ConditionPathExists=/dev/tty0
|
|
+ConditionPathExists=|/dev/tty0
|
|
+ConditionVirtualization=|lxc
|
|
+ConditionVirtualization=|lxc-libvirt
|
|
|
|
[Service]
|
|
# the VT is cleared by TTYVTDisallocate
|
|
-ExecStart=-/sbin/agetty --noclear %I $TERM
|
|
Type=idle
|
|
Restart=always
|
|
RestartSec=0
|
|
diff --git a/units/kmod-static-nodes.service.in b/units/kmod-static-nodes.service.in
|
|
index 0934a87..7e30c9e 100644
|
|
--- a/units/kmod-static-nodes.service.in
|
|
+++ b/units/kmod-static-nodes.service.in
|
|
@@ -10,7 +10,6 @@ Description=Create list of required static device nodes for the current kernel
|
|
DefaultDependencies=no
|
|
Before=sysinit.target systemd-tmpfiles-setup-dev.service
|
|
ConditionCapability=CAP_SYS_MODULE
|
|
-ConditionPathExists=/lib/modules/%v/modules.devname
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
diff --git a/units/local-fs.target b/units/local-fs.target
|
|
index d2e5429..d26984b 100644
|
|
--- a/units/local-fs.target
|
|
+++ b/units/local-fs.target
|
|
@@ -13,3 +13,5 @@ Conflicts=shutdown.target
|
|
After=local-fs-pre.target
|
|
OnFailure=emergency.target
|
|
OnFailureJobMode=replace-irreversibly
|
|
+
|
|
+X-StopOnReconfiguration=yes
|
|
diff --git a/units/remote-fs.target b/units/remote-fs.target
|
|
index 43ffa5c..156a681 100644
|
|
--- a/units/remote-fs.target
|
|
+++ b/units/remote-fs.target
|
|
@@ -12,5 +12,7 @@ After=remote-fs-pre.target
|
|
DefaultDependencies=no
|
|
Conflicts=shutdown.target
|
|
|
|
+X-StopOnReconfiguration=yes
|
|
+
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
diff --git a/units/rescue.service.in b/units/rescue.service.in
|
|
index fc93f1e..3c87cf8 100644
|
|
--- a/units/rescue.service.in
|
|
+++ b/units/rescue.service.in
|
|
@@ -16,7 +16,6 @@ Before=shutdown.target
|
|
[Service]
|
|
Environment=HOME=/root
|
|
WorkingDirectory=/root
|
|
-ExecStartPre=-/bin/plymouth quit
|
|
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.'
|
|
ExecStart=-/bin/sh -c "/sbin/sulogin; @SYSTEMCTL@ --fail --no-block default"
|
|
Type=idle
|
|
diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4
|
|
index 4522d0d..96daa5c 100644
|
|
--- a/units/serial-getty@.service.m4
|
|
+++ b/units/serial-getty@.service.m4
|
|
@@ -22,7 +22,6 @@ Before=getty.target
|
|
IgnoreOnIsolate=yes
|
|
|
|
[Service]
|
|
-ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM
|
|
Type=idle
|
|
Restart=always
|
|
UtmpIdentifier=%I
|
|
diff --git a/units/sysinit.target b/units/sysinit.target
|
|
index ec33503..4ac47b9 100644
|
|
--- a/units/sysinit.target
|
|
+++ b/units/sysinit.target
|
|
@@ -9,5 +9,4 @@
|
|
Description=System Initialization
|
|
Documentation=man:systemd.special(7)
|
|
Conflicts=emergency.service emergency.target
|
|
-Wants=local-fs.target swap.target
|
|
-After=local-fs.target swap.target emergency.service emergency.target
|
|
+After=emergency.service emergency.target
|
|
diff --git a/units/systemd-backlight@.service.in b/units/systemd-backlight@.service.in
|
|
index ecf3de4..7e83446 100644
|
|
--- a/units/systemd-backlight@.service.in
|
|
+++ b/units/systemd-backlight@.service.in
|
|
@@ -19,3 +19,4 @@ Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecStart=@rootlibexecdir@/systemd-backlight load %i
|
|
ExecStop=@rootlibexecdir@/systemd-backlight save %i
|
|
+X-RestartIfChanged=false
|
|
diff --git a/units/systemd-journal-flush.service.in b/units/systemd-journal-flush.service.in
|
|
index 699670b..ba22c6d 100644
|
|
--- a/units/systemd-journal-flush.service.in
|
|
+++ b/units/systemd-journal-flush.service.in
|
|
@@ -10,8 +10,10 @@ Description=Trigger Flushing of Journal to Persistent Storage
|
|
Documentation=man:systemd-journald.service(8) man:journald.conf(5)
|
|
DefaultDependencies=no
|
|
Requires=systemd-journald.service
|
|
-After=systemd-journald.service local-fs.target remote-fs.target
|
|
+After=systemd-journald.service
|
|
+After=systemd-remount-fs.service
|
|
Before=systemd-user-sessions.service systemd-tmpfiles-setup.service
|
|
+RequiresMountsFor=/var/log/journal
|
|
|
|
[Service]
|
|
ExecStart=@rootbindir@/journalctl --flush
|
|
diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
|
|
index 4de38fa..2f23c13 100644
|
|
--- a/units/systemd-journald.service.in
|
|
+++ b/units/systemd-journald.service.in
|
|
@@ -14,6 +14,7 @@ After=systemd-journald.socket systemd-journald-dev-log.socket syslog.socket
|
|
Before=sysinit.target
|
|
|
|
[Service]
|
|
+Type=notify
|
|
Sockets=systemd-journald.socket systemd-journald-dev-log.socket
|
|
ExecStart=@rootlibexecdir@/systemd-journald
|
|
Restart=always
|
|
@@ -26,3 +27,8 @@ WatchdogSec=1min
|
|
# Increase the default a bit in order to allow many simultaneous
|
|
# services being run since we keep one fd open per service.
|
|
LimitNOFILE=16384
|
|
+
|
|
+# Don't restart journald, since that causes services connected to
|
|
+# journald to stop logging (see
|
|
+# https://bugs.freedesktop.org/show_bug.cgi?id=56043).
|
|
+X-RestartIfChanged=no
|
|
diff --git a/units/systemd-random-seed.service.in b/units/systemd-random-seed.service.in
|
|
index b55844b..3ef9fc6 100644
|
|
--- a/units/systemd-random-seed.service.in
|
|
+++ b/units/systemd-random-seed.service.in
|
|
@@ -19,3 +19,4 @@ Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecStart=@rootlibexecdir@/systemd-random-seed load
|
|
ExecStop=@rootlibexecdir@/systemd-random-seed save
|
|
+X-RestartIfChanged=false
|
|
diff --git a/units/systemd-rfkill@.service.in b/units/systemd-rfkill@.service.in
|
|
index 0e9851b..9f8fa0d 100644
|
|
--- a/units/systemd-rfkill@.service.in
|
|
+++ b/units/systemd-rfkill@.service.in
|
|
@@ -19,3 +19,4 @@ Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecStart=@rootlibexecdir@/systemd-rfkill load %I
|
|
ExecStop=@rootlibexecdir@/systemd-rfkill save %I
|
|
+X-RestartIfChanged=false
|
|
diff --git a/units/systemd-tmpfiles-setup.service.in b/units/systemd-tmpfiles-setup.service.in
|
|
index e895cda..194146f 100644
|
|
--- a/units/systemd-tmpfiles-setup.service.in
|
|
+++ b/units/systemd-tmpfiles-setup.service.in
|
|
@@ -11,7 +11,7 @@ Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
|
|
DefaultDependencies=no
|
|
Conflicts=shutdown.target
|
|
After=local-fs.target systemd-sysusers.service
|
|
-Before=sysinit.target shutdown.target
|
|
+Before=shutdown.target
|
|
RefuseManualStop=yes
|
|
|
|
[Service]
|
|
diff --git a/units/systemd-update-utmp.service.in b/units/systemd-update-utmp.service.in
|
|
index 163eccd..7357c12 100644
|
|
--- a/units/systemd-update-utmp.service.in
|
|
+++ b/units/systemd-update-utmp.service.in
|
|
@@ -11,7 +11,7 @@ Documentation=man:systemd-update-utmp.service(8) man:utmp(5)
|
|
DefaultDependencies=no
|
|
RequiresMountsFor=/var/log/wtmp
|
|
Conflicts=shutdown.target
|
|
-After=systemd-remount-fs.service systemd-tmpfiles-setup.service auditd.service
|
|
+After=systemd-remount-fs.service auditd.service
|
|
Before=sysinit.target shutdown.target
|
|
|
|
[Service]
|
|
@@ -19,3 +19,4 @@ Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecStart=@rootlibexecdir@/systemd-update-utmp reboot
|
|
ExecStop=@rootlibexecdir@/systemd-update-utmp shutdown
|
|
+X-RestartIfChanged=false
|
|
diff --git a/units/systemd-user-sessions.service.in b/units/systemd-user-sessions.service.in
|
|
index 0869e73..b6ed958 100644
|
|
--- a/units/systemd-user-sessions.service.in
|
|
+++ b/units/systemd-user-sessions.service.in
|
|
@@ -15,3 +15,6 @@ Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecStart=@rootlibexecdir@/systemd-user-sessions start
|
|
ExecStop=@rootlibexecdir@/systemd-user-sessions stop
|
|
+
|
|
+# Restart kills all active sessions.
|
|
+X-RestartIfChanged=no
|