aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-01-18 20:44:34 -0800
committerPaul Eggert2013-01-18 20:44:34 -0800
commit9fe43ff672d02d6f43bd5bc7b08f40823c7a1851 (patch)
tree89f42a987eff9a5559c4735c19b37d06994c342a /src
parentfa705c9927b57158e8973cd950419a2ac0f72c53 (diff)
downloademacs-9fe43ff672d02d6f43bd5bc7b08f40823c7a1851.tar.gz
emacs-9fe43ff672d02d6f43bd5bc7b08f40823c7a1851.zip
Work around bug in CIFS and vboxsf file systems.
The bug was observed on Ubuntu operating inside a virtual machine, editing files mounted via CIFS or vboxsf from the MS Windows 7 host. The workaround introduces a race condition on non-buggy hosts, but it's an unlikely race and anyway there's a nearly identical nearby race that can't be fixed. * fileio.c (valid_timestamp_file_system, timestamp_file_system): New static vars. (Fwrite_region): Test for file system time stamp bug. (init_fileio): New function. * lisp.h (init_fileio): Declare it. * emacs.c (main): Call it. Fixes: debbugs:13149
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog13
-rw-r--r--src/emacs.c1
-rw-r--r--src/fileio.c53
-rw-r--r--src/lisp.h1
4 files changed, 68 insertions, 0 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 4cd417868a1..2954df9d6b8 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,18 @@
12013-01-19 Paul Eggert <eggert@cs.ucla.edu> 12013-01-19 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Work around bug in CIFS and vboxsf file systems (Bug#13149).
4 The bug was observed on Ubuntu operating inside a virtual machine,
5 editing files mounted via CIFS or vboxsf from the MS Windows 7 host.
6 The workaround introduces a race condition on non-buggy hosts,
7 but it's an unlikely race and anyway there's a nearly identical
8 nearby race that can't be fixed.
9 * fileio.c (valid_timestamp_file_system, timestamp_file_system):
10 New static vars.
11 (Fwrite_region): Test for file system time stamp bug.
12 (init_fileio): New function.
13 * lisp.h (init_fileio): Declare it.
14 * emacs.c (main): Call it.
15
3 * fileio.c (Finsert_file_contents): Simplify new diagnostic 16 * fileio.c (Finsert_file_contents): Simplify new diagnostic
4 and make it more consistent with other stat-failure diagnostics. 17 and make it more consistent with other stat-failure diagnostics.
5 18
diff --git a/src/emacs.c b/src/emacs.c
index 91a7ce6390d..6536c3708af 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1317,6 +1317,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1317 } 1317 }
1318 1318
1319 init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */ 1319 init_callproc (); /* Must follow init_cmdargs but not init_sys_modes. */
1320 init_fileio ();
1320 init_lread (); 1321 init_lread ();
1321#ifdef WINDOWSNT 1322#ifdef WINDOWSNT
1322 /* Check to see if Emacs has been installed correctly. */ 1323 /* Check to see if Emacs has been installed correctly. */
diff --git a/src/fileio.c b/src/fileio.c
index bd845c2f1e0..616f1c50f91 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -103,6 +103,11 @@ static mode_t auto_save_mode_bits;
103/* Set by auto_save_1 if an error occurred during the last auto-save. */ 103/* Set by auto_save_1 if an error occurred during the last auto-save. */
104static bool auto_save_error_occurred; 104static bool auto_save_error_occurred;
105 105
106/* If VALID_TIMESTAMP_FILE_SYSTEM, then TIMESTAMP_FILE_SYSTEM is the device
107 number of a file system where time stamps were observed to to work. */
108static bool valid_timestamp_file_system;
109static dev_t timestamp_file_system;
110
106/* The symbol bound to coding-system-for-read when 111/* The symbol bound to coding-system-for-read when
107 insert-file-contents is called for recovering a file. This is not 112 insert-file-contents is called for recovering a file. This is not
108 an actual coding system name, but just an indicator to tell 113 an actual coding system name, but just an indicator to tell
@@ -4971,6 +4976,48 @@ This calls `write-region-annotate-functions' at the start, and
4971 /* Discard the unwind protect for close_file_unwind. */ 4976 /* Discard the unwind protect for close_file_unwind. */
4972 specpdl_ptr = specpdl + count1; 4977 specpdl_ptr = specpdl + count1;
4973 4978
4979 /* Some file systems have a bug where st_mtime is not updated
4980 properly after a write. For example, CIFS might not see the
4981 st_mtime change until after the file is opened again.
4982
4983 Attempt to detect this file system bug, and update MODTIME to the
4984 newer st_mtime if the bug appears to be present. This introduces
4985 a race condition, so to avoid most instances of the race condition
4986 on non-buggy file systems, skip this check if the most recently
4987 encountered non-buggy file system was the current file system.
4988
4989 A race condition can occur if some other process modifies the
4990 file between the fstat above and the fstat below, but the race is
4991 unlikely and a similar race between the last write and the fstat
4992 above cannot possibly be closed anyway. */
4993
4994 if (EMACS_TIME_VALID_P (modtime)
4995 && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system))
4996 {
4997 int desc1 = emacs_open (fn, O_WRONLY, 0);
4998 if (0 <= desc1)
4999 {
5000 struct stat st1;
5001 if (fstat (desc1, &st1) == 0
5002 && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino)
5003 {
5004 EMACS_TIME modtime1 = get_stat_mtime (&st1);
5005 if (EMACS_TIME_EQ (modtime, modtime1)
5006 && st.st_size == st1.st_size)
5007 {
5008 timestamp_file_system = st.st_dev;
5009 valid_timestamp_file_system = 1;
5010 }
5011 else
5012 {
5013 st.st_size = st1.st_size;
5014 modtime = modtime1;
5015 }
5016 }
5017 emacs_close (desc1);
5018 }
5019 }
5020
4974 /* Call write-region-post-annotation-function. */ 5021 /* Call write-region-post-annotation-function. */
4975 while (CONSP (Vwrite_region_annotation_buffers)) 5022 while (CONSP (Vwrite_region_annotation_buffers))
4976 { 5023 {
@@ -5768,6 +5815,12 @@ Fread_file_name (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filena
5768 5815
5769 5816
5770void 5817void
5818init_fileio (void)
5819{
5820 valid_timestamp_file_system = 0;
5821}
5822
5823void
5771syms_of_fileio (void) 5824syms_of_fileio (void)
5772{ 5825{
5773 DEFSYM (Qoperations, "operations"); 5826 DEFSYM (Qoperations, "operations");
diff --git a/src/lisp.h b/src/lisp.h
index 5c81bc5dd8a..48fba653203 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3299,6 +3299,7 @@ extern _Noreturn void report_file_error (const char *, Lisp_Object);
3299extern bool internal_delete_file (Lisp_Object); 3299extern bool internal_delete_file (Lisp_Object);
3300extern bool file_directory_p (const char *); 3300extern bool file_directory_p (const char *);
3301extern bool file_accessible_directory_p (const char *); 3301extern bool file_accessible_directory_p (const char *);
3302extern void init_fileio (void);
3302extern void syms_of_fileio (void); 3303extern void syms_of_fileio (void);
3303extern Lisp_Object make_temp_name (Lisp_Object, bool); 3304extern Lisp_Object make_temp_name (Lisp_Object, bool);
3304extern Lisp_Object Qdelete_file; 3305extern Lisp_Object Qdelete_file;