[Bug 11521] New: rsync does not use high-resolution timestamps to determine file differences

samba-bugs at samba.org samba-bugs at samba.org
Mon Sep 14 21:37:34 UTC 2015


https://bugzilla.samba.org/show_bug.cgi?id=11521

            Bug ID: 11521
           Summary: rsync does not use high-resolution timestamps to
                    determine file differences
           Product: rsync
           Version: 3.1.2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P5
         Component: core
          Assignee: wayned at samba.org
          Reporter: michael.mccracken at gmail.com
        QA Contact: rsync-qa at samba.org

The sub-second timestamps available on many filesystems are preserved when
requested across copies, but aren't used to determine file differences.

If a file exists at both origin and destination and its contents the same size
in each place, and the timestamps only differ in the sub-second resolution,
rsync will treat the files as the same (unless you use --checksum).

So if a file is created, and then a snapshot of its dir is taken, then the
origin file is modified (but the size is preserved) within the same second, an
attempt to update that snapshot using rsync will fail to copy the change.

Here's a script that reproduces the issue with high reliability for me:

#!/bin/bash                                                                     

set -x

DIR=$(mktemp -d -p $(pwd))

mkdir $DIR/d1
mkdir $DIR/d2

echo dummy > $DIR/d1/dummy
echo dummy > $DIR/d2/dummy

echo one > $DIR/d1/afile
sleep 0.1
echo two > $DIR/d2/afile

/usr/bin/stat $DIR/d1/afile | grep Mod
/usr/bin/stat $DIR/d2/afile | grep Mod

~/packages/rsync/rsync --delete -a -HAX -vii $DIR/d2/ $DIR/d1

diff -r $DIR/d1 $DIR/d2

/usr/bin/stat $DIR/d1/afile | grep Mod
/usr/bin/stat $DIR/d2/afile | grep Mod



If the diff shows a difference, then the rsync didn't copy afile's contents
over. However, note the stat info from the last two lines - the updated modify
timestamp *will* be synced, making an inconsistent sync.

The following patch adds a check of the high-res timestamp to unchanged_file.
This solves the problem for me, and I've guarded it so it shouldn't break on
systems with no high-res timestamp. Please let me know if I can be helpful in
testing it further or making it more robust.



diff --git a/generator.c b/generator.c
index 3a4504f..2f64f5d 100644
--- a/generator.c
+++ b/generator.c
@@ -588,7 +588,11 @@ int unchanged_file(char *fn, struct file_struct *file,
STRUCT_STAT *st)
        if (ignore_times)
                return 0;

-       return cmp_time(st->st_mtime, file->modtime) == 0;
+       return cmp_time(st->st_mtime, file->modtime) == 0
+#ifdef ST_MTIME_NSEC
+               && st->ST_MTIME_NSEC == F_MOD_NSEC(file)
+#endif
+               ;
 }

-- 
You are receiving this mail because:
You are the QA Contact for the bug.



More information about the rsync mailing list