Subject: Re: bug#13149: 24.3.50; Emacs thinks file was changed outside Emacs, but it was not

From: Paul Eggert <[email-masked]>
Date: Mon, 14 Jan 2013 22:45:31 -0800

On 01/14/2013 02:20 PM, Dmitry Gutov wrote:

> stat_mtime=1358201692.000000000
> stat_mtime=1358201692.912737000

That looks like a file system bug, I'm afraid.
Does the following work around the bug, if you
set the variable sloppy-file-time-stamps?

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2013-01-14 17:46:14 +0000
+++ src/ChangeLog	2013-01-15 05:38:42 +0000
@@ -1,3 +1,10 @@
+2013-01-15  Paul Eggert  <[email-masked]>
+
+	Add workaround for file system time stamp bug (Bug#13149).
+	Reported by Dmitry Gutov for Ubuntu vboxsf mounting MS Windows 7.
+	* fileio.c (syms_of_fileio) <sloppy-file-time-stamps>: New variable.
+	(Fverify_visited_file_modtime): Use it.
+
 2013-01-14  Paul Eggert  <[email-masked]>
 
 	Avoid needless casts with XSAVE_POINTER.

=== modified file 'src/fileio.c'
--- src/fileio.c	2013-01-14 17:46:14 +0000
+++ src/fileio.c	2013-01-15 05:38:42 +0000
@@ -5358,7 +5358,17 @@
   mtime = (stat (SSDATA (filename), &st) == 0
 	   ? get_stat_mtime (&st)
 	   : time_error_value (errno));
-  if (EMACS_TIME_EQ (mtime, b->modtime)
+
+  /* On a few buggy file systems, the fractional part of the time stamp,
+     or perhaps even the low order bit of the seconds part, can
+     spontaneously change even though the file has not changed.  If
+     SLOPPY_FILE_TIME_STAMPS, work around these bugs at the cost of
+     possibly missing some changes.  */
+  if ((EMACS_TIME_EQ (mtime, b->modtime)
+       || (sloppy_file_time_stamps
+	   && EMACS_TIME_VALID_P (mtime)
+	   && EMACS_TIME_VALID_P (b->modtime)
+	   && EMACS_SECS (mtime) >> 1 == EMACS_SECS (b->modtime) >> 1))
       && (b->modtime_size < 0
 	  || st.st_size == b->modtime_size))
     return Qt;
@@ -6036,6 +6046,13 @@
   write_region_inhibit_fsync = 0;
 #endif
 
+  DEFVAR_BOOL ("sloppy-file-time-stamps", sloppy_file_time_stamps,
+	       doc: /* Non-nil means file time stamps are sloppy.
+When non-nil, ignore low-order part of time stamp when inferring whether
+a file may have changed.  Although this suppresses bogus diagnostics
+on buggy file systems, it can also lose changes to files.  */);
+  sloppy_file_time_stamps = 0;
+
   DEFVAR_BOOL ("delete-by-moving-to-trash", delete_by_moving_to_trash,
                doc: /* Specifies whether to use the system's trash can.
 When non-nil, certain file deletion commands use the function