diff options
author | Alan Jenkins <alan.christopher.jenkins@gmail.com> | 2017-08-17 17:09:44 +0100 |
---|---|---|
committer | Alan Jenkins <alan.christopher.jenkins@gmail.com> | 2017-08-17 20:26:36 +0100 |
commit | 0675e94ab53237ad27bfba929c7490bdd2215cf1 (patch) | |
tree | ffcd2233a70ae8464b000c1b5e8d52304fa160b6 /src/udev/udevadm-hwdb.c | |
parent | dce892acef1c5316fb98f7f5ea287bc74f935ca3 (diff) | |
download | systemd-0675e94ab53237ad27bfba929c7490bdd2215cf1.tar.gz |
"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/udev/udevadm-hwdb.c')
-rw-r--r-- | src/udev/udevadm-hwdb.c | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index 69b0b9025c..7688f8192b 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -364,18 +364,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); - err = fopen_temporary(filename , &t.f, &filename_tmp); + err = fopen_temporary(filename, &t.f, &filename_tmp); if (err < 0) return err; fchmod(fileno(t.f), 0444); /* write nodes */ - err = fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET); - if (err < 0) { - fclose(t.f); - unlink_noerrno(filename_tmp); - return -errno; - } + if (fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET) < 0) + goto error_fclose; root_off = trie_store_nodes(&t, trie->root); h.nodes_root_off = htole64(root_off); pos = ftello(t.f); @@ -388,21 +384,21 @@ static int trie_store(struct trie *trie, const char *filename) { /* write header */ size = ftello(t.f); h.file_size = htole64(size); - err = fseeko(t.f, 0, SEEK_SET); - if (err < 0) { - fclose(t.f); - unlink_noerrno(filename_tmp); - return -errno; - } + if (fseeko(t.f, 0, SEEK_SET < 0)) + goto error_fclose; fwrite(&h, sizeof(struct trie_header_f), 1, t.f); - err = ferror(t.f); - if (err) - err = -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); - if (err < 0 || rename(filename_tmp, filename) < 0) { - unlink_noerrno(filename_tmp); - return err < 0 ? err : -errno; - } log_debug("=== trie on-disk ==="); log_debug("size: %8"PRIi64" bytes", size); @@ -417,6 +413,12 @@ static int trie_store(struct trie *trie, const char *filename) { log_debug("strings start: %8"PRIu64, t.strings_off); return 0; + + error_fclose: + err = -errno; + fclose(t.f); + unlink(filename_tmp); + return err; } static int insert_data(struct trie *trie, struct udev_list *match_list, |