Просмотр исходного кода

dpkg: On Linux finish writeback before fsync

The second sync_file_range() call, with the operation
SYNC_FILE_RANGE_WAIT_BEFORE, will block until the previously
initiated writeback has completed.

We finish the writeback for all files before calling fsync. This
basically ensures that the delayed allocation has been resolved;
that is, the data blocks have been allocated and written, and the
inode updated (in memory), but not necessarily pushed out to disk.
So that later fsync can become no-ops, minimizing the number of
(costly) jbd2 commits.

Suggested-by: Ted Ts'o <tytso@mit.edu>
Based-on-patch-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Guillem Jover <guillem@debian.org>
Guillem Jover лет назад: 15
Родитель
Сommit
2921e80c2f
1 измененных файлов с 36 добавлено и 0 удалено
  1. 36 0
      src/archives.c

+ 36 - 0
src/archives.c

@@ -860,6 +860,40 @@ tarobject(void *ctx, struct tar_entry *ti)
   return 0;
 }
 
+#if defined(SYNC_FILE_RANGE_WAIT_BEFORE)
+static void
+tar_writeback_barrier(struct fileinlist *files, struct pkginfo *pkg)
+{
+  struct fileinlist *cfile;
+
+  for (cfile = files; cfile; cfile = cfile->next) {
+    struct filenamenode *usenode;
+    const char *usename;
+    int fd;
+
+    if (!(cfile->namenode->flags & fnnf_deferred_fsync))
+      continue;
+
+    usenode = namenodetouse(cfile->namenode, pkg);
+    usename = usenode->name + 1; /* Skip the leading '/'. */
+
+    setupfnamevbs(usename);
+
+    fd = open(fnamenewvb.buf, O_WRONLY);
+    if (fd < 0)
+      ohshite(_("unable to open '%.255s'"), fnamenewvb.buf);
+    sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WAIT_BEFORE);
+    if (close(fd))
+      ohshite(_("error closing/writing `%.255s'"), fnamenewvb.buf);
+  }
+}
+#else
+static void
+tar_writeback_barrier(struct fileinlist *files, struct pkginfo *pkg)
+{
+}
+#endif
+
 void
 tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg)
 {
@@ -871,6 +905,8 @@ tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg)
   debug(dbg_general, "deferred extract mass sync");
   if (!fc_unsafe_io)
     sync();
+#else
+  tar_writeback_barrier(files, pkg);
 #endif
 
   for (cfile = files; cfile; cfile = cfile->next) {