summaryrefslogtreecommitdiff
path: root/src/hwdb
diff options
context:
space:
mode:
authorAlan Jenkins <alan.christopher.jenkins@gmail.com>2017-08-17 17:09:44 +0100
committerAlan Jenkins <alan.christopher.jenkins@gmail.com>2017-08-17 20:26:36 +0100
commit0675e94ab53237ad27bfba929c7490bdd2215cf1 (patch)
treeffcd2233a70ae8464b000c1b5e8d52304fa160b6 /src/hwdb
parentdce892acef1c5316fb98f7f5ea287bc74f935ca3 (diff)
downloadsystemd-0675e94ab53237ad27bfba929c7490bdd2215cf1.tar.gz
systemd-0675e94ab53237ad27bfba929c7490bdd2215cf1.tar.bz2
systemd-0675e94ab53237ad27bfba929c7490bdd2215cf1.zip
"Don't fear the fsync()"
For files which are vital to boot 1. Avoid opening any window where power loss will zero them out or worse. I know app developers all coded to the ext3 implementation, but the only formal documentation we have says we're broken if we actually rely on it. E.g. * `man mount`, search for `auto_da_alloc`. * http://www.linux-mtd.infradead.org/faq/ubifs.html#L_atomic_change * https://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/ 2. If we tell the kernel we're interested in writing them to disk, it will tell us if that fails. So at minimum, this means we play our part in notifying the user about errors. I refactored error-handling in `udevadm-hwdb` a little. It turns out I did exactly the same as had already been done in the `systemd-hwdb` version, i.e. commit d702dcd.
Diffstat (limited to 'src/hwdb')
-rw-r--r--src/hwdb/hwdb.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index 793398ca68..ead4e1770b 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -403,14 +403,14 @@ static int trie_store(struct trie *trie, const char *filename) {
t.strings_off = sizeof(struct trie_header_f);
trie_store_nodes_size(&t, trie->root);
- r = fopen_temporary(filename , &t.f, &filename_tmp);
+ r = fopen_temporary(filename, &t.f, &filename_tmp);
if (r < 0)
return r;
fchmod(fileno(t.f), 0444);
/* write nodes */
if (fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET) < 0)
- goto error;
+ goto error_fclose;
root_off = trie_store_nodes(&t, trie->root);
h.nodes_root_off = htole64(root_off);
@@ -425,13 +425,20 @@ static int trie_store(struct trie *trie, const char *filename) {
size = ftello(t.f);
h.file_size = htole64(size);
if (fseeko(t.f, 0, SEEK_SET) < 0)
- goto error;
-
+ goto error_fclose;
fwrite(&h, sizeof(struct trie_header_f), 1, t.f);
- if (fclose(t.f) < 0 || rename(filename_tmp, filename) < 0) {
- unlink_noerrno(filename_tmp);
- return -errno;
- }
+
+ if (ferror(t.f))
+ goto error_fclose;
+ if (fflush(t.f) < 0)
+ goto error_fclose;
+ if (fsync(fileno(t.f)) < 0)
+ goto error_fclose;
+ if (rename(filename_tmp, filename) < 0)
+ goto error_fclose;
+
+ /* write succeeded */
+ fclose(t.f);
log_debug("=== trie on-disk ===");
log_debug("size: %8"PRIi64" bytes", size);
@@ -446,7 +453,7 @@ static int trie_store(struct trie *trie, const char *filename) {
log_debug("strings start: %8"PRIu64, t.strings_off);
return 0;
- error:
+ error_fclose:
r = -errno;
fclose(t.f);
unlink(filename_tmp);