Rev 6075: (jameinel) Bug #1075108, handle when fdatasync returns EOPNOTSUPP, in file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/2.4/

Patch Queue Manager pqm at pqm.ubuntu.com
Thu May 23 08:55:46 UTC 2013


At file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/2.4/

------------------------------------------------------------
revno: 6075 [merge]
revision-id: pqm at pqm.ubuntu.com-20130523085545-6kn9bzcpww7befjb
parent: pqm at pqm.ubuntu.com-20130523081746-2bsarcuxk0ihst5s
parent: john at arbash-meinel.com-20130523083009-9mw2908d0vrbetr5
committer: Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: 2.4
timestamp: Thu 2013-05-23 08:55:45 +0000
message:
  (jameinel) Bug #1075108, handle when fdatasync returns EOPNOTSUPP,
   which should be considered a non-fatal error. (John A Meinel)
modified:
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
  doc/en/release-notes/bzr-2.4.txt bzr2.4.txt-20110114053217-k7ym9jfz243fddjm-1
=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2011-11-29 20:20:02 +0000
+++ b/bzrlib/osutils.py	2013-05-23 08:25:07 +0000
@@ -2522,6 +2522,10 @@
 else:
     is_local_pid_dead = _posix_is_local_pid_dead
 
+_maybe_ignored = ['EAGAIN', 'EINTR', 'ENOTSUP', 'EOPNOTSUPP', 'EACCES']
+_fdatasync_ignored = [getattr(errno, name) for name in _maybe_ignored
+                      if getattr(errno, name, None) is not None]
+
 
 def fdatasync(fileno):
     """Flush file contents to disk if possible.
@@ -2531,7 +2535,16 @@
     """
     fn = getattr(os, 'fdatasync', getattr(os, 'fsync', None))
     if fn is not None:
-        fn(fileno)
+        try:
+            fn(fileno)
+        except IOError, e:
+            # See bug #1075108, on some platforms fdatasync exists, but can
+            # raise ENOTSUP. However, we are calling fdatasync to be helpful
+            # and reduce the chance of corruption-on-powerloss situations. It
+            # is not a mandatory call, so it is ok to suppress failures.
+            trace.mutter("ignoring error calling fdatasync: %s" % (e,))
+            if getattr(e, 'errno', None) not in _fdatasync_ignored:
+                raise
 
 
 def ensure_empty_directory_exists(path, exception_class):

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2011-10-04 18:43:55 +0000
+++ b/bzrlib/tests/test_osutils.py	2013-05-23 08:25:07 +0000
@@ -22,6 +22,7 @@
 import re
 import socket
 import sys
+import tempfile
 import time
 
 from bzrlib import (
@@ -426,6 +427,49 @@
         self.assertTrue(-eighteen_hours < offset < eighteen_hours)
 
 
+class TestFdatasync(tests.TestCaseInTempDir):
+
+    def do_fdatasync(self):
+        f = tempfile.NamedTemporaryFile()
+        osutils.fdatasync(f.fileno())
+        f.close()
+
+    @staticmethod
+    def raise_eopnotsupp(*args, **kwargs):
+        raise IOError(errno.EOPNOTSUPP, os.strerror(errno.EOPNOTSUPP))
+
+    @staticmethod
+    def raise_enotsup(*args, **kwargs):
+        raise IOError(errno.ENOTSUP, os.strerror(errno.ENOTSUP))
+
+    def test_fdatasync_handles_system_function(self):
+        self.overrideAttr(os, "fdatasync")
+        self.do_fdatasync()
+
+    def test_fdatasync_handles_no_fdatasync_no_fsync(self):
+        self.overrideAttr(os, "fdatasync")
+        self.overrideAttr(os, "fsync")
+        self.do_fdatasync()
+
+    def test_fdatasync_handles_no_EOPNOTSUPP(self):
+        self.overrideAttr(errno, "EOPNOTSUPP")
+        self.do_fdatasync()
+
+    def test_fdatasync_catches_ENOTSUP(self):
+        enotsup = getattr(errno, "ENOTSUP", None)
+        if enotsup is None:
+            raise tests.TestNotApplicable("No ENOTSUP on this platform")
+        self.overrideAttr(os, "fdatasync", self.raise_enotsup)
+        self.do_fdatasync()
+
+    def test_fdatasync_catches_EOPNOTSUPP(self):
+        enotsup = getattr(errno, "EOPNOTSUPP", None)
+        if enotsup is None:
+            raise tests.TestNotApplicable("No EOPNOTSUPP on this platform")
+        self.overrideAttr(os, "fdatasync", self.raise_eopnotsupp)
+        self.do_fdatasync()
+
+
 class TestLinks(tests.TestCaseInTempDir):
 
     def test_dereference_path(self):

=== modified file 'doc/en/release-notes/bzr-2.4.txt'
--- a/doc/en/release-notes/bzr-2.4.txt	2012-06-08 06:59:50 +0000
+++ b/doc/en/release-notes/bzr-2.4.txt	2013-05-23 08:30:09 +0000
@@ -35,6 +35,10 @@
 * Cope with Unix filesystems, such as smbfs, where chmod gives 'permission
   denied'.  (Martin Pool, #606537)
 
+* Fix a traceback when trying to checkout a tree that also has an entry
+  with file-id `TREE_ROOT` somewhere other than at the root directory.
+  (John Arbash Meinel, #830947)
+
 * When the ``limbo`` or ``pending-deletion`` directories exist, typically
   because of an interrupted tree update, but are empty, bzr no longer
   errors out, because there is nothing for the user to clean up.  Also,
@@ -55,6 +59,10 @@
 * Prevent a traceback being printed to stderr when logging has problems and
   accept utf-8 byte string without breaking. (Martin Packman, #714449)
 
+* Some filesystems give ``EOPNOTSUPP`` when trying to call ``fdatasync``.
+  This shouldn't be treated as a fatal error.
+  (John Arbash Meinel, #1075108)
+
 * Use ``encoding_type='exact'`` for ``bzr testament`` so that on Windows
   the sha hash of the long testament matches the sha hash in the short
   form. (John Arbash Meinel, #1010339)




More information about the bazaar-commits mailing list