journal: when creating a new journal file, fsync() the directory it is created in too
authorLennart Poettering <lennart@poettering.net>
Tue, 26 Apr 2016 13:47:55 +0000 (15:47 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 29 Apr 2016 10:23:34 +0000 (12:23 +0200)
Fixes: #2831

src/basic/fd-util.c
src/journal/journal-file.c

index 9130d02..8b466cf 100644 (file)
@@ -361,8 +361,14 @@ bool fdname_is_valid(const char *s) {
 
 int fd_get_path(int fd, char **ret) {
         char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+        int r;
 
         xsprintf(procfs_path, "/proc/self/fd/%i", fd);
 
-        return readlink_malloc(procfs_path, ret);
+        r = readlink_malloc(procfs_path, ret);
+
+        if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
+                return -EBADF;
+
+        return r;
 }
index 35f4aba..a58079b 100644 (file)
@@ -439,6 +439,39 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) {
         return 0;
 }
 
+static int fsync_directory_of_file(int fd) {
+        _cleanup_free_ char *path = NULL, *dn = NULL;
+        _cleanup_close_ int dfd = -1;
+        struct stat st;
+        int r;
+
+        if (fstat(fd, &st) < 0)
+                return -errno;
+
+        if (!S_ISREG(st.st_mode))
+                return -EBADFD;
+
+        r = fd_get_path(fd, &path);
+        if (r < 0)
+                return r;
+
+        if (!path_is_absolute(path))
+                return -EINVAL;
+
+        dn = dirname_malloc(path);
+        if (!dn)
+                return -ENOMEM;
+
+        dfd = open(dn, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
+        if (dfd < 0)
+                return -errno;
+
+        if (fsync(dfd) < 0)
+                return -errno;
+
+        return 0;
+}
+
 static int journal_file_refresh_header(JournalFile *f) {
         sd_id128_t boot_id;
         int r;
@@ -464,6 +497,9 @@ static int journal_file_refresh_header(JournalFile *f) {
         /* Sync the online state to disk */
         (void) fsync(f->fd);
 
+        /* We likely just created a new file, also sync the directory this file is located in. */
+        (void) fsync_directory_of_file(f->fd);
+
         return r;
 }