Add new --sync-per-filesystem to use FS_IOC_SYNCFS on unpack
To avoid mismatched data and metadata on file systems (like XFS, ext4,
btrfs, and ubifs) that delay allocation of blocks for new files,
current dpkg calls fsync for each file it unpacks before renaming it.
Unfortunately that results in an unpleasant and seeky I/O pattern, as
each file is flushed out one at a time.
The alternative of using sync generally has acceptable performance,
except it provokes I/O on unrelated filesystems (think: networked
/home or flash /media/thumb). Unfortunately there does not seem to be
a convenient system call between the two extremes of fsync and sync.
The proposed FS_IOC_SYNCFS ioctl fills that gap: when called, it syncs
the filesystem containing the given fd. This patch teaches dpkg a
--sync-per-filesystem to use that ioctl in place of fsync for the
first file associated to a given device and to skip the remaining
fsyncs for that device.
If the ioctl fails (for example due to lack of kernel support), the
--sync-per-filesystem flag is cleared and dpkg returns to the old
behavior.
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
That's the end of the series. Thanks for reading.
# Checks for typedefs, structures, and compiler characteristics.
AC_C_BIGENDIAN
diff --git a/man/dpkg.1 b/man/dpkg.1
index 68146f8..c1f0ffa 100644
--- a/man/dpkg.1
+++ b/man/dpkg.1
@@ -626,6 +626,13 @@ or keep.
fB--no-debsigfP
Do not try to verify package signatures.
.TP
+.B --sync-per-filesystem
+Use FS_IOC_SYNCFS ioctl if available when unpacking. This means each
+file system touched in the course of unpacking is sync'd all at once,
+which tends to result in a faster I/O pattern than syncing files one
+at a time. To disable the syncs altogether, use the
+--force-unsafe-io option instead.
+.TP
fB--no-triggersfP
Do not run any triggers in this run (activations will still be recorded).
If used with fB--configurefP fIpackagefP or
diff --git a/src/archives.c b/src/archives.c
index d68f9d6..d75d6a9 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -56,6 +56,14 @@
#include <selinux/selinux.h>
#endif
for (cfile = files; cfile; cfile = cfile->next) {
@@ -884,7 +971,7 @@ tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg)
fd = open(fnamenewvb.buf, O_WRONLY);
if (fd < 0)
ohshite(_("unable to open '%.255s'"), fnamenewvb.buf);
- if (fsync(fd))
+ if (fsync_or_sync_filesystem(&synched, fd))
ohshite(_("unable to sync file '%.255s'"), fnamenewvb.buf);
if (close(fd))
ohshite(_("error closing/writing `%.255s'"), fnamenewvb.buf);
@@ -912,6 +999,7 @@ tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg)
debug(dbg_eachfiledetail, "deferred extract done and installed");
}
+ device_list_free(synched);
}
/**
diff --git a/src/main.c b/src/main.c
index 880ed75..eace76e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -136,6 +136,7 @@ usage(const struct cmdinfo *ci, const char *value)
" -G|--refuse-downgrade Skip packages with earlier version than installed.
"
" -B|--auto-deconfigure Install even if it would break some other package.
"
" --[no-]triggers Skip or force consequential trigger processing.
"
+" --sync-per-filesystem Use sync_filesystem instead of fsync if available.
"
" --no-debsig Do not try to verify package signatures.
"
" --no-act|--dry-run|--simulate
"
" Just say what we would do - don't do it.
"
@@ -178,7 +179,7 @@ const char printforhelp[]= N_(
extern int f_pending, f_recursive, f_alsoselect, f_skipsame, f_noact;
extern int f_autodeconf, f_nodebsig;
-extern int f_triggers;
+extern int f_triggers, f_syncperfs;
extern unsigned long f_debug;
extern int fc_downgrade, fc_configureany, fc_hold, fc_removereinstreq, fc_overwrite;
extern int fc_removeessential, fc_conflicts, fc_depends, fc_dependsversion;
--
1.7.2.3
--
To UNSUBSCRIBE, email to debian-dpkg-REQUEST@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org
Archive: 20101127214718.GC26283@burratino">http://lists.debian.org/20101127214718.GC26283@burratino