|
|
1abbee |
From 283df68dbc1d90cad21beec6563215c26c69ec2c Mon Sep 17 00:00:00 2001
|
|
|
1abbee |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
1abbee |
Date: Fri, 24 Jul 2015 01:55:45 +0200
|
|
|
1abbee |
Subject: [PATCH] journal: avoid mapping empty data and field hash tables
|
|
|
1abbee |
|
|
|
1abbee |
When a new journal file is created we write the header first, then sync
|
|
|
1abbee |
and only then create the data and field hash tables in them. That means
|
|
|
1abbee |
to other processes it might appear that the files have a valid header
|
|
|
1abbee |
but not data and field hash tables. Our reader code should be able to
|
|
|
1abbee |
deal with this.
|
|
|
1abbee |
|
|
|
1abbee |
With this change we'll not map the two hash tables right-away after
|
|
|
1abbee |
opening a file for reading anymore (because that will of course fail if
|
|
|
1abbee |
the objects are missing), but delay this until the first time we access
|
|
|
1abbee |
them. On top of that, when we want to look something up in the hash
|
|
|
1abbee |
tables and we notice they aren't initialized yet, we consider them
|
|
|
1abbee |
empty.
|
|
|
1abbee |
|
|
|
1abbee |
This improves handling of some journal files reported in #487.
|
|
|
1abbee |
|
|
|
1abbee |
Cherry-picked from: dade37d403f1b8c1d7bb2efbe2361f2a3e999613
|
|
|
1abbee |
Related: #1350232
|
|
|
1abbee |
---
|
|
|
23b3cf |
src/journal/journal-file.c | 37 +++++++++++++++++++++++++-----------
|
|
|
1abbee |
src/journal/journal-file.h | 3 +++
|
|
|
1abbee |
src/journal/journal-verify.c | 14 ++++++++++++++
|
|
|
1abbee |
3 files changed, 43 insertions(+), 11 deletions(-)
|
|
|
1abbee |
|
|
|
1abbee |
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
|
|
|
181b3f |
index 892fe4734..ef1849787 100644
|
|
|
1abbee |
--- a/src/journal/journal-file.c
|
|
|
1abbee |
+++ b/src/journal/journal-file.c
|
|
|
1abbee |
@@ -656,13 +656,16 @@ static int journal_file_setup_field_hash_table(JournalFile *f) {
|
|
|
1abbee |
return 0;
|
|
|
1abbee |
}
|
|
|
1abbee |
|
|
|
1abbee |
-static int journal_file_map_data_hash_table(JournalFile *f) {
|
|
|
1abbee |
+int journal_file_map_data_hash_table(JournalFile *f) {
|
|
|
1abbee |
uint64_t s, p;
|
|
|
1abbee |
void *t;
|
|
|
1abbee |
int r;
|
|
|
1abbee |
|
|
|
1abbee |
assert(f);
|
|
|
1abbee |
|
|
|
1abbee |
+ if (f->data_hash_table)
|
|
|
1abbee |
+ return 0;
|
|
|
1abbee |
+
|
|
|
1abbee |
p = le64toh(f->header->data_hash_table_offset);
|
|
|
1abbee |
s = le64toh(f->header->data_hash_table_size);
|
|
|
1abbee |
|
|
|
1abbee |
@@ -678,13 +681,16 @@ static int journal_file_map_data_hash_table(JournalFile *f) {
|
|
|
1abbee |
return 0;
|
|
|
1abbee |
}
|
|
|
1abbee |
|
|
|
1abbee |
-static int journal_file_map_field_hash_table(JournalFile *f) {
|
|
|
1abbee |
+int journal_file_map_field_hash_table(JournalFile *f) {
|
|
|
1abbee |
uint64_t s, p;
|
|
|
1abbee |
void *t;
|
|
|
1abbee |
int r;
|
|
|
1abbee |
|
|
|
1abbee |
assert(f);
|
|
|
1abbee |
|
|
|
1abbee |
+ if (f->field_hash_table)
|
|
|
1abbee |
+ return 0;
|
|
|
1abbee |
+
|
|
|
1abbee |
p = le64toh(f->header->field_hash_table_offset);
|
|
|
1abbee |
s = le64toh(f->header->field_hash_table_size);
|
|
|
1abbee |
|
|
|
1abbee |
@@ -803,10 +809,18 @@ int journal_file_find_field_object_with_hash(
|
|
|
1abbee |
assert(f);
|
|
|
1abbee |
assert(field && size > 0);
|
|
|
1abbee |
|
|
|
1abbee |
+ /* If the field hash table is empty, we can't find anything */
|
|
|
1abbee |
+ if (le64toh(f->header->field_hash_table_size) <= 0)
|
|
|
1abbee |
+ return 0;
|
|
|
1abbee |
+
|
|
|
1abbee |
+ /* Map the field hash table, if it isn't mapped yet. */
|
|
|
1abbee |
+ r = journal_file_map_field_hash_table(f);
|
|
|
1abbee |
+ if (r < 0)
|
|
|
1abbee |
+ return r;
|
|
|
1abbee |
+
|
|
|
1abbee |
osize = offsetof(Object, field.payload) + size;
|
|
|
1abbee |
|
|
|
1abbee |
m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
|
|
|
1abbee |
-
|
|
|
1abbee |
if (m <= 0)
|
|
|
1abbee |
return -EBADMSG;
|
|
|
1abbee |
|
|
|
1abbee |
@@ -866,6 +880,15 @@ int journal_file_find_data_object_with_hash(
|
|
|
1abbee |
assert(f);
|
|
|
1abbee |
assert(data || size == 0);
|
|
|
1abbee |
|
|
|
1abbee |
+ /* If there's no data hash table, then there's no entry. */
|
|
|
1abbee |
+ if (le64toh(f->header->data_hash_table_size) <= 0)
|
|
|
1abbee |
+ return 0;
|
|
|
1abbee |
+
|
|
|
1abbee |
+ /* Map the data hash table, if it isn't mapped yet. */
|
|
|
1abbee |
+ r = journal_file_map_data_hash_table(f);
|
|
|
1abbee |
+ if (r < 0)
|
|
|
1abbee |
+ return r;
|
|
|
1abbee |
+
|
|
|
1abbee |
osize = offsetof(Object, data.payload) + size;
|
|
|
1abbee |
|
|
|
1abbee |
m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
|
|
|
1abbee |
@@ -2707,14 +2730,6 @@ int journal_file_open(
|
|
|
1abbee |
#endif
|
|
|
1abbee |
}
|
|
|
1abbee |
|
|
|
1abbee |
- r = journal_file_map_field_hash_table(f);
|
|
|
1abbee |
- if (r < 0)
|
|
|
1abbee |
- goto fail;
|
|
|
1abbee |
-
|
|
|
1abbee |
- r = journal_file_map_data_hash_table(f);
|
|
|
1abbee |
- if (r < 0)
|
|
|
1abbee |
- goto fail;
|
|
|
1abbee |
-
|
|
|
1abbee |
if (mmap_cache_got_sigbus(f->mmap, f->fd)) {
|
|
|
1abbee |
r = -EIO;
|
|
|
1abbee |
goto fail;
|
|
|
1abbee |
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
|
|
|
181b3f |
index 0f29b092b..c74ad5fc5 100644
|
|
|
1abbee |
--- a/src/journal/journal-file.h
|
|
|
1abbee |
+++ b/src/journal/journal-file.h
|
|
|
1abbee |
@@ -234,3 +234,6 @@ static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) {
|
|
|
1abbee |
assert(f);
|
|
|
1abbee |
return f->compress_xz || f->compress_lz4;
|
|
|
1abbee |
}
|
|
|
1abbee |
+
|
|
|
1abbee |
+int journal_file_map_data_hash_table(JournalFile *f);
|
|
|
1abbee |
+int journal_file_map_field_hash_table(JournalFile *f);
|
|
|
1abbee |
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
|
|
|
181b3f |
index 983217c1b..d2d5c400c 100644
|
|
|
1abbee |
--- a/src/journal/journal-verify.c
|
|
|
1abbee |
+++ b/src/journal/journal-verify.c
|
|
|
1abbee |
@@ -590,6 +590,13 @@ static int verify_hash_table(
|
|
|
1abbee |
assert(last_usec);
|
|
|
1abbee |
|
|
|
1abbee |
n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
|
|
|
1abbee |
+ if (n <= 0)
|
|
|
1abbee |
+ return 0;
|
|
|
1abbee |
+
|
|
|
1abbee |
+ r = journal_file_map_data_hash_table(f);
|
|
|
1abbee |
+ if (r < 0)
|
|
|
1abbee |
+ return log_error_errno(r, "Failed to map data hash table: %m");
|
|
|
1abbee |
+
|
|
|
1abbee |
for (i = 0; i < n; i++) {
|
|
|
1abbee |
uint64_t last = 0, p;
|
|
|
1abbee |
|
|
|
1abbee |
@@ -647,6 +654,13 @@ static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p)
|
|
|
1abbee |
assert(f);
|
|
|
1abbee |
|
|
|
1abbee |
n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
|
|
|
1abbee |
+ if (n <= 0)
|
|
|
1abbee |
+ return 0;
|
|
|
1abbee |
+
|
|
|
1abbee |
+ r = journal_file_map_data_hash_table(f);
|
|
|
1abbee |
+ if (r < 0)
|
|
|
1abbee |
+ return log_error_errno(r, "Failed to map data hash table: %m");
|
|
|
1abbee |
+
|
|
|
1abbee |
h = hash % n;
|
|
|
1abbee |
|
|
|
1abbee |
q = le64toh(f->data_hash_table[h].head_hash_offset);
|