Explorar o código

dpkg: On Linux use sync() instead of an fsync() per file

Due to the performance degradation on ext4 file systems, as a
workaround on Linux, we use sync() which is synchronous, before
rename() to make sure it's truly atomic.

Closes: #578635
Guillem Jover %!s(int64=16) %!d(string=hai) anos
pai
achega
0ff43ca667
Modificáronse 4 ficheiros con 26 adicións e 0 borrados
  1. 1 0
      configure.ac
  2. 2 0
      debian/changelog
  3. 16 0
      m4/dpkg-funcs.m4
  4. 7 0
      src/archives.c

+ 1 - 0
configure.ac

@@ -118,6 +118,7 @@ DPKG_DECL_SYS_SIGLIST
 # Checks for library functions.
 DPKG_FUNC_VA_COPY
 DPKG_FUNC_C99_SNPRINTF
+DPKG_FUNC_ASYNC_SYNC
 DPKG_CHECK_DECL([offsetof], [stddef.h])
 DPKG_CHECK_DECL([WCOREDUMP], [sys/wait.h])
 DPKG_CHECK_COMPAT_FUNCS([getopt getopt_long obstack_free \

+ 2 - 0
debian/changelog

@@ -35,6 +35,8 @@ dpkg (1.15.7.2) UNRELEASED; urgency=low
     Kyle Moffett <Kyle.D.Moffett@boeing.com>. Closes: #568123, #575158
   * Fix dpkg --root by properly stripping again the root directory from the
     path of the maintainer script to execute. Closes: #580984
+  * On Linux use sync() instead of an fsync() per file on deferred extraction,
+    to workaround performance degradation on ext4. Closes: #578635
 
   [ Gerfried Fuchs ]
   * Fix syntax error in dpkg-name. Closes: #581315

+ 16 - 0
m4/dpkg-funcs.m4

@@ -68,6 +68,22 @@ AS_IF([test "x$dpkg_cv_c99_snprintf" = "xyes"],
 AM_CONDITIONAL(HAVE_C99_SNPRINTF, [test "x$dpkg_cv_c99_snprintf" = "xyes"])
 ])# DPKG_FUNC_C99_SNPRINTF
 
+# DPKG_FUNC_ASYNC_SYNC
+# --------------------
+# Define HAVE_ASYNC_SYNC if sync() is asynchronous
+AC_DEFUN([DPKG_FUNC_ASYNC_SYNC],
+[
+  AC_CANONICAL_HOST
+  AC_MSG_CHECKING([whether sync is asynchronous])
+  AS_CASE([$host_os],
+          [linux-*], [dpkg_cv_async_sync=no],
+          [dpkg_cv_async_sync=yes])
+  AS_IF([test "x$dpkg_cv_async_sync" = "xyes"],
+        [AC_DEFINE([HAVE_ASYNC_SYNC], 1,
+                   [Define to 1 if the 'sync' function is asynchronous])])
+  AC_MSG_RESULT([$dpkg_cv_async_sync])
+])# DPKG_FUNC_ASYNC_SYNC
+
 # DPKG_CHECK_COMPAT_FUNCS(LIST)
 # -----------------------
 # Check each function and define an automake conditional

+ 7 - 0
src/archives.c

@@ -816,6 +816,11 @@ tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg)
   struct filenamenode *usenode;
   const char *usename;
 
+#if !defined(HAVE_ASYNC_SYNC)
+  debug(dbg_general, "deferred extract mass sync");
+  sync();
+#endif
+
   for (cfile = files; cfile; cfile = cfile->next) {
     debug(dbg_eachfile, "deferred extract of '%.255s'", cfile->namenode->name);
 
@@ -829,6 +834,7 @@ tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg)
 
     setupfnamevbs(usename);
 
+#if defined(HAVE_ASYNC_SYNC)
     if (cfile->namenode->flags & fnnf_deferred_fsync) {
       int fd;
 
@@ -844,6 +850,7 @@ tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg)
 
       cfile->namenode->flags &= ~fnnf_deferred_fsync;
     }
+#endif
 
     if (rename(fnamenewvb.buf, fnamevb.buf))
       ohshite(_("unable to install new version of `%.255s'"),