                          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

         reboot(RB_ENABLE_CAD);
 
         switch (a) {
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

                 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
