This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author sdaoden
Recipients nadeem.vawda, neologix, pitrou, ronaldoussoren, santoso.wijaya, sdaoden, vstinner
Date 2011-05-21.12:22:51
SpamBayes Score 5.757632e-10
Marked as misclassified No
Message-id <20110521122242.GA34134@sherwood.local>
In-reply-to
Content
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -810,6 +810,35 @@
    Availability: Unix, and Windows.

+.. function:: fullfsync(fd)
+
+   The POSIX standart requires that :c:func:`fsync` must transfer the buffered
+   data to the storage device, not that the data is actually written by the
+   device itself.  It explicitely leaves it up to operating system implementors
+   whether users are given stronger guarantees on data integrity or not.  Some
+   systems also offer special functions which overtake the part of making such
+   stronger guarantees, i.e., Mac OS X and NetBSD.
+
+   This non-standart function is *optionally* made available to access such
+   special functionality when feasible.  It will force write of file buffers to
+   disk and the flush of disk caches of the file given by file descriptor *fd*.
+   To strive for best-possible data integrity, the following can be done::
+
+      # Force writeout of local buffer modifications
+      f.flush()
+      # Then synchronize the changes to physical backing store
+      if hasattr(os, 'fullfsync'):
+         os.fullfsync(f.fileno())
+      elif hasattr(os, 'fsync'):
+         os.fsync(f.fileno())
+
+   ..note::
+      Calling this function may take a long time, since it may block
+      until the disk reports that the transfer has been completed.
+
+   Availability: Unix.
+
+
 .. function:: ftruncate(fd, length)

    Truncate the file corresponding to file descriptor *fd*, so that it is at most
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -835,12 +835,12 @@

 class TestInvalidFD(unittest.TestCase):
     singles = ["fchdir", "dup", "fdopen", "fdatasync", "fstat",
-               "fstatvfs", "fsync", "tcgetpgrp", "ttyname"]
+               "fstatvfs", "fsync", "fullfsync", "tcgetpgrp", "ttyname"]
     #singles.append("close")
-    #We omit close because it doesn'r raise an exception on some platforms
+    # We omit close because it doesn't raise an exception on some platforms
     def get_single(f):
         def helper(self):
-            if  hasattr(os, f):
+            if hasattr(os, f):
                 self.check(getattr(os, f))
         return helper
     for f in singles:
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -174,6 +174,11 @@
 #endif /* ! __IBMC__ */

 #ifndef _MSC_VER
+  /* os.fullfsync()? */
+# if (defined HAVE_FSYNC && ((defined __APPLE__ && defined F_FULLFSYNC) || \
+                             (defined __NetBSD__ && defined FDISKSYNC)))
+#  define PROVIDE_FULLFSYNC
+# endif

 #if defined(__sgi)&&_COMPILER_VERSION>=700
 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
@@ -2129,6 +2134,41 @@
 {
     return posix_fildes(fdobj, fsync);
 }
+
+# ifdef PROVIDE_FULLFSYNC
+PyDoc_STRVAR(fullfsync__doc__,
+"fullfsync(fd)\n\n"
+"force write of file buffers to disk, and the flush of disk caches\n"
+"of the file given by file descriptor fd.");
+
+static PyObject *
+fullfsync(PyObject *self, PyObject *fdobj)
+{
+    /* See issue 11877 discussion */
+    int res, fd = PyObject_AsFileDescriptor(fdobj);
+    if (fd < 0)
+        return NULL;
+    if (!_PyVerify_fd(fd))
+        return posix_error();
+
+    Py_BEGIN_ALLOW_THREADS
+#  if defined __APPLE__
+    /* F_FULLFSYNC is not supported for all types of FDs/FSYSs;
+     * be on the safe side and test for inappropriate ioctl errors */
+    res = fcntl(fd, F_FULLFSYNC);
+    if (res < 0 && errno == ENOTTY)
+        res = fsync(fd);
+#  elif defined __NetBSD__
+    res = fsync_range(fd, FFILESYNC | FDISKSYNC, 0, 0);
+#  endif
+    Py_END_ALLOW_THREADS
+
+    if (res < 0)
+        return posix_error();
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+# endif /* PROVIDE_FULLFSYNC */
 #endif /* HAVE_FSYNC */

 #ifdef HAVE_SYNC
@@ -9473,6 +9513,9 @@
 #endif
 #ifdef HAVE_FSYNC
     {"fsync",       posix_fsync, METH_O, posix_fsync__doc__},
+# ifdef PROVIDE_FULLFSYNC
+    {"fullfsync",   fullfsync, METH_O, fullfsync__doc__},
+# endif
 #endif
 #ifdef HAVE_SYNC
     {"sync",        posix_sync, METH_NOARGS, posix_sync__doc__},
History
Date User Action Args
2011-05-21 12:22:58sdaodensetrecipients: + sdaoden, ronaldoussoren, pitrou, vstinner, nadeem.vawda, neologix, santoso.wijaya
2011-05-21 12:22:52sdaodenlinkissue11877 messages
2011-05-21 12:22:51sdaodencreate