Only fsync if the existing file is > 0 bytes
authorAlexander Larsson <alexl@redhat.com>
Tue, 11 Aug 2009 18:22:51 +0000 (20:22 +0200)
committerAlexander Larsson <alexl@redhat.com>
Tue, 11 Aug 2009 18:26:12 +0000 (20:26 +0200)
This means we don't sync in the case where we created an (empty)
temp file and now replace it with the data.

This fixes (among other things) the performance of trashing files.

glib/gfileutils.c

index 4f5c669bd45a7c453b20ec2abae5b31eea431490..13f8627acad287174903810d795a98cb62b5abad 100644 (file)
@@ -961,29 +961,34 @@ write_to_temp_file (const gchar  *contents,
     }
   
 #ifdef HAVE_FSYNC
-  errno = 0;
-  /* If the final destination exists, we want to sync the newly written
-   * file to ensure the data is on disk when we rename over the destination.
-   * otherwise if we get a system crash we can lose both the new and the
-   * old file on some filesystems. (I.E. those that don't guarantee the
-   * data is written to the disk before the metadata.)
-   */
-  if (g_file_test (dest_file, G_FILE_TEST_EXISTS) &&
-      fsync (fileno (file)) != 0)
-    { 
-      save_errno = errno;
-      
-      g_set_error (err,
-                  G_FILE_ERROR,
-                  g_file_error_from_errno (save_errno),
-                  _("Failed to write file '%s': fsync() failed: %s"),
-                  display_name, 
-                  g_strerror (save_errno));
+  {
+    struct stat statbuf;
+
+    errno = 0;
+    /* If the final destination exists and is > 0 bytes, we want to sync the
+     * newly written file to ensure the data is on disk when we rename over
+     * the destination. Otherwise if we get a system crash we can lose both
+     * the new and the old file on some filesystems. (I.E. those that don't
+     * guarantee the data is written to the disk before the metadata.)
+     */
+    if (g_lstat (dest_file, &statbuf) == 0 &&
+       statbuf.st_size > 0 &&
+       fsync (fileno (file)) != 0)
+      {
+       save_errno = errno;
+
+       g_set_error (err,
+                    G_FILE_ERROR,
+                    g_file_error_from_errno (save_errno),
+                    _("Failed to write file '%s': fsync() failed: %s"),
+                    display_name,
+                    g_strerror (save_errno));
 
-      g_unlink (tmp_name);
-      
-      goto out;
-    }
+       g_unlink (tmp_name);
+
+       goto out;
+      }
+  }
 #endif
   
   errno = 0;