[ostree] bootloader: fdatasync() bootloader configuration



commit 829e0382ab2a2ad1a741bbabeb5ef9a7fd7cfb75
Author: Colin Walters <walters verbum org>
Date:   Thu Apr 3 22:20:59 2014 -0400

    bootloader: fdatasync() bootloader configuration
    
    Let's be a bit more conservative here and actually fdatasync() the
    configurations we're generating.
    
    I'm seeing an issue at the moment where syslinux isn't finding the
    config sometimes, and while I don't think this is the issue, let's try
    it.

 src/libostree/ostree-bootloader-syslinux.c |   15 ++++---
 src/libostree/ostree-bootloader-uboot.c    |   13 ++++--
 src/libotutil/ot-gio-utils.c               |   61 ++++++++++++++++++++++++++++
 src/libotutil/ot-gio-utils.h               |    5 ++
 4 files changed, 83 insertions(+), 11 deletions(-)
---
diff --git a/src/libostree/ostree-bootloader-syslinux.c b/src/libostree/ostree-bootloader-syslinux.c
index 4327381..0934bb8 100644
--- a/src/libostree/ostree-bootloader-syslinux.c
+++ b/src/libostree/ostree-bootloader-syslinux.c
@@ -236,12 +236,15 @@ _ostree_bootloader_syslinux_write_config (OstreeBootloader          *bootloader,
     goto out;
 
   new_config_contents = _ostree_sysroot_join_lines (new_lines);
-
-  if (!g_file_replace_contents (new_config_path, new_config_contents,
-                                strlen (new_config_contents), 
-                                NULL, FALSE, G_FILE_CREATE_NONE,
-                                NULL, cancellable, error))
-    goto out;
+  {
+    gs_unref_bytes GBytes *new_config_contents_bytes =
+      g_bytes_new_static (new_config_contents,
+                          strlen (new_config_contents));
+
+    if (!ot_gfile_replace_contents_fsync (new_config_path, new_config_contents_bytes,
+                                          cancellable, error))
+      goto out;
+  }
   
   ret = TRUE;
  out:
diff --git a/src/libostree/ostree-bootloader-uboot.c b/src/libostree/ostree-bootloader-uboot.c
index c56d5ac..cd25e56 100644
--- a/src/libostree/ostree-bootloader-uboot.c
+++ b/src/libostree/ostree-bootloader-uboot.c
@@ -124,12 +124,15 @@ _ostree_bootloader_uboot_write_config (OstreeBootloader          *bootloader,
     return FALSE;
 
   new_config_contents = _ostree_sysroot_join_lines (new_lines);
+  {
+    gs_unref_bytes GBytes *new_config_contents_bytes =
+      g_bytes_new_static (new_config_contents,
+                          strlen (new_config_contents));
 
-  if (!g_file_replace_contents (new_config_path, new_config_contents,
-                                strlen (new_config_contents),
-                                NULL, FALSE, G_FILE_CREATE_NONE,
-                                NULL, cancellable, error))
-    return FALSE;
+    if (!ot_gfile_replace_contents_fsync (new_config_path, new_config_contents_bytes,
+                                          cancellable, error))
+      return FALSE;
+  }
 
   return TRUE;
 }
diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c
index f250f15..da895fb 100644
--- a/src/libotutil/ot-gio-utils.c
+++ b/src/libotutil/ot-gio-utils.c
@@ -25,6 +25,7 @@
 #include <gio/gio.h>
 #include <gio/gunixinputstream.h>
 #include <gio/gunixoutputstream.h>
+#include <gio/gfiledescriptorbased.h>
 
 #include <string.h>
 
@@ -272,6 +273,66 @@ ot_gfile_load_contents_utf8_allow_noent (GFile          *path,
 }
 
 /**
+ * ot_gfile_replace_contents_fsync:
+ * 
+ * Like g_file_replace_contents(), except always uses fdatasync().
+ */
+gboolean
+ot_gfile_replace_contents_fsync (GFile          *path,
+                                 GBytes         *contents,
+                                 GCancellable   *cancellable,
+                                 GError        **error)
+{
+  gboolean ret = FALSE;
+  int fd;
+  gs_unref_object GFile *parent = NULL;
+  gs_unref_object GFile *tmpfile = NULL;
+  gs_unref_object GOutputStream *stream = NULL;
+  gs_unref_object GInputStream *instream = NULL;
+
+  parent = g_file_get_parent (path);
+
+  if (!gs_file_open_in_tmpdir (parent, 0644, &tmpfile, &stream,
+                               cancellable, error))
+    goto out;
+
+  g_assert (G_IS_FILE_DESCRIPTOR_BASED (stream));
+  fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (stream));
+
+  instream = g_memory_input_stream_new_from_bytes (contents);
+
+  if (posix_fallocate (fd, 0, g_bytes_get_size (contents)) != 0)
+    {
+      ot_util_set_error_from_errno (error, errno);
+      goto out;
+    }
+
+  if (g_output_stream_splice (stream, instream, 0,
+                              cancellable, error) < 0)
+    goto out;
+
+  if (fdatasync (fd) != 0)
+    {
+      ot_util_set_error_from_errno (error, errno);
+      goto out;
+    }
+
+  if (!g_output_stream_close (stream, cancellable, error))
+    goto out;
+
+  if (!gs_file_rename (tmpfile, path, cancellable, error))
+    goto out;
+
+  g_clear_object (&tmpfile);
+
+  ret = TRUE;
+ out:
+  if (tmpfile)
+    (void) gs_file_unlink (tmpfile, NULL, NULL);
+  return ret;
+}
+
+/**
  * ot_gfile_ensure_unlinked:
  *
  * Like gs_file_unlink(), but return successfully if the file doesn't
diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h
index 184c770..2d585ba 100644
--- a/src/libotutil/ot-gio-utils.h
+++ b/src/libotutil/ot-gio-utils.h
@@ -69,6 +69,11 @@ gboolean ot_gfile_load_contents_utf8_allow_noent (GFile          *path,
                                                   GCancellable   *cancellable,
                                                   GError        **error);
 
+gboolean ot_gfile_replace_contents_fsync (GFile          *path,
+                                          GBytes         *contents,
+                                          GCancellable   *cancellable,
+                                          GError        **error);
+
 gboolean ot_gfile_ensure_unlinked (GFile         *path,
                                    GCancellable  *cancellable,
                                    GError       **error);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]