bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/2] fdatasync: new module


From: Eric Blake
Subject: [PATCH 2/2] fdatasync: new module
Date: Fri, 16 Sep 2011 11:25:45 -0600

At least libvirt would like to use the lighter-weight fdatasync
on platforms where it is supported, while still guaranteeing full
sync (via the heavy-weight fsync fallback) on all platforms.

I've got an open question to the Austin Group, since the POSIX 2008
wording is self-contradictory (unlike fsync, fdatasync requires
EBADF on non-writable fds, but still mentions that read() errors
must be propagated).  I can see how fsync() would affect atime after
read() while fdatasync() can skip that, explaining why fdatasync()
might have the EBADF requirement, but on the other hand, that prevents
an implementation (like ours) where fdatasync is a straight alias of
fsync.  At any rate, glibc allows fdatasync on read-only fds.

* modules/fsync (Description): Document difference to fdatasync.
* modules/fdatasync: New module.
* m4/fdatasync.m4 (gl_FUNC_FDATASYNC): New file.
* lib/fdatasync.c (fdatasync): Likewise.
* m4/unistd_h.m4 (gl_UNISTD_H, gl_UNISTD_H_DEFAULTS): Set up
defaults.
* modules/unistd (Makefile.am): Set witnesses.
* lib/unistd.in.h (fdatasync): Declare.
* MODULES.html.sh: Document it.
* doc/posix-functions/fdatasync.texi (fdatasync): Likewise.
* modules/fdatasync-tests: New test.
* tests/test-fdatasync.c: Likewise.

Signed-off-by: Eric Blake <address@hidden>
---

I've tested this on Linux (both fsync, fdatasync present),
mingw (neither present), and MacOS (fsync but not fdatasync).

I just noticed that Solaris man page documents that fdatasync
requires -lrt (unlike fsync), so I'll have to fix that in a
followup patch.

 ChangeLog                          |   16 +++++++++
 MODULES.html.sh                    |    1 +
 doc/posix-functions/fdatasync.texi |    8 ++--
 lib/fdatasync.c                    |   25 ++++++++++++++
 lib/unistd.in.h                    |   21 +++++++++++-
 m4/fdatasync.m4                    |   14 ++++++++
 m4/unistd_h.m4                     |    6 ++-
 modules/fdatasync                  |   28 ++++++++++++++++
 modules/fdatasync-tests            |   13 +++++++
 modules/fsync                      |    2 +-
 modules/unistd                     |    2 +
 tests/test-fdatasync.c             |   64 ++++++++++++++++++++++++++++++++++++
 12 files changed, 192 insertions(+), 8 deletions(-)
 create mode 100644 lib/fdatasync.c
 create mode 100644 m4/fdatasync.m4
 create mode 100644 modules/fdatasync
 create mode 100644 modules/fdatasync-tests
 create mode 100644 tests/test-fdatasync.c

diff --git a/ChangeLog b/ChangeLog
index e1f97a0..469037c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2011-09-16  Eric Blake  <address@hidden>

+       fdatasync: new module
+       * modules/fsync (Description): Document difference to fdatasync.
+       * modules/fdatasync: New module.
+       * m4/fdatasync.m4 (gl_FUNC_FDATASYNC): New file.
+       * lib/fdatasync.c (fdatasync): Likewise.
+       * m4/unistd_h.m4 (gl_UNISTD_H, gl_UNISTD_H_DEFAULTS): Set up
+       defaults.
+       * modules/unistd (Makefile.am): Set witnesses.
+       * lib/unistd.in.h (fdatasync): Declare.
+       * MODULES.html.sh: Document it.
+       * doc/posix-functions/fdatasync.texi (fdatasync): Likewise.
+       * modules/fdatasync-tests: New test.
+       * tests/test-fdatasync.c: Likewise.
+
+2011-09-16  Eric Blake  <address@hidden>
+
        test-fsync: enhance tests
        * modules/fsync-tests (Depends-on): Add errno, for mingw.
        * tests/test-fsync.c (main): Enhance test.
diff --git a/MODULES.html.sh b/MODULES.html.sh
index 8785ff2..8273faa 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2356,6 +2356,7 @@ func_all_modules ()
   func_module fclose
   func_module fcntl-h
   func_module fcntl
+  func_module fdatasync
   func_module flock
   func_module fopen
   func_module fprintf-posix
diff --git a/doc/posix-functions/fdatasync.texi 
b/doc/posix-functions/fdatasync.texi
index 88a497c..8209ecd 100644
--- a/doc/posix-functions/fdatasync.texi
+++ b/doc/posix-functions/fdatasync.texi
@@ -4,15 +4,15 @@ fdatasync

 POSIX specification:@* 
@url{http://www.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html}

-Gnulib module: ---
+Gnulib module: fdatasync

 Portability problems fixed by Gnulib:
 @itemize
address@hidden
+This function is missing on some platforms:
+MacOS X 10.5, FreeBSD 6.0, OpenBSD 3.8, Minix 3.1.8, IRIX 5.3, Solaris 2.4, 
mingw, MSVC 9, Interix 3.5, BeOS.
 @end itemize

 Portability problems not fixed by Gnulib:
 @itemize
address@hidden
-This function is missing on some platforms:
-MacOS X 10.5, FreeBSD 6.0, OpenBSD 3.8, Minix 3.1.8, IRIX 5.3, Solaris 2.4, 
mingw, MSVC 9, Interix 3.5, BeOS.
 @end itemize
diff --git a/lib/fdatasync.c b/lib/fdatasync.c
new file mode 100644
index 0000000..54c10fd
--- /dev/null
+++ b/lib/fdatasync.c
@@ -0,0 +1,25 @@
+/* Emulate fdatasync on platforms that lack it.
+
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <unistd.h>
+
+int
+fdatasync (int fd)
+{
+  return fsync (fd);
+}
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index c1cfb54..3ad166c 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -484,10 +484,29 @@ _GL_WARN_ON_USE (fchownat, "fchownat is not portable - "
 #endif


-#if @GNULIB_FSYNC@
+#if @GNULIB_FDATASYNC@
 /* Synchronize changes to a file.
    Return 0 if successful, otherwise -1 and errno set.
    See POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/fdatasync.html>.  */
+# if address@hidden@
+_GL_FUNCDECL_SYS (fdatasync, int, (int fd));
+# endif
+_GL_CXXALIAS_SYS (fdatasync, int, (int fd));
+_GL_CXXALIASWARN (fdatasync);
+#elif defined GNULIB_POSIXCHECK
+# undef fdatasync
+# if HAVE_RAW_DECL_FDATASYNC
+_GL_WARN_ON_USE (fdatasync, "fdatasync is unportable - "
+                 "use gnulib module fdatasync for portability");
+# endif
+#endif
+
+
+#if @GNULIB_FSYNC@
+/* Synchronize changes, including metadata, to a file.
+   Return 0 if successful, otherwise -1 and errno set.
+   See POSIX:2001 specification
    <http://www.opengroup.org/susv3xsh/fsync.html>.  */
 # if address@hidden@
 _GL_FUNCDECL_SYS (fsync, int, (int fd));
diff --git a/m4/fdatasync.m4 b/m4/fdatasync.m4
new file mode 100644
index 0000000..8eceeb5
--- /dev/null
+++ b/m4/fdatasync.m4
@@ -0,0 +1,14 @@
+# fdatasync.m4 serial 1
+dnl Copyright (C) 2008-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FDATASYNC],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_CHECK_FUNCS_ONCE([fdatasync])
+  if test $ac_cv_func_fdatasync = no; then
+    HAVE_FDATASYNC=0
+  fi
+])
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index 33897ae..29f3947 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 58
+# unistd_h.m4 serial 59
 dnl Copyright (C) 2006-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -40,7 +40,7 @@ AC_DEFUN([gl_UNISTD_H],
 # endif
 #endif
     ]], [chown dup2 dup3 environ euidaccess faccessat fchdir fchownat
-    fsync ftruncate getcwd getdomainname getdtablesize getgroups
+    fdatasync fsync ftruncate getcwd getdomainname getdtablesize getgroups
     gethostname getlogin getlogin_r getpagesize getusershell setusershell
     endusershell group_member lchown link linkat lseek pipe pipe2 pread pwrite
     readlink readlinkat rmdir sleep symlink symlinkat ttyname_r unlink unlinkat
@@ -67,6 +67,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   GNULIB_FACCESSAT=0;            AC_SUBST([GNULIB_FACCESSAT])
   GNULIB_FCHDIR=0;               AC_SUBST([GNULIB_FCHDIR])
   GNULIB_FCHOWNAT=0;             AC_SUBST([GNULIB_FCHOWNAT])
+  GNULIB_FDATASYNC=0;            AC_SUBST([GNULIB_FDATASYNC])
   GNULIB_FSYNC=0;                AC_SUBST([GNULIB_FSYNC])
   GNULIB_FTRUNCATE=0;            AC_SUBST([GNULIB_FTRUNCATE])
   GNULIB_GETCWD=0;               AC_SUBST([GNULIB_GETCWD])
@@ -110,6 +111,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   HAVE_FACCESSAT=1;       AC_SUBST([HAVE_FACCESSAT])
   HAVE_FCHDIR=1;          AC_SUBST([HAVE_FCHDIR])
   HAVE_FCHOWNAT=1;        AC_SUBST([HAVE_FCHOWNAT])
+  HAVE_FDATASYNC=1;       AC_SUBST([HAVE_FDATASYNC])
   HAVE_FSYNC=1;           AC_SUBST([HAVE_FSYNC])
   HAVE_FTRUNCATE=1;       AC_SUBST([HAVE_FTRUNCATE])
   HAVE_GETDTABLESIZE=1;   AC_SUBST([HAVE_GETDTABLESIZE])
diff --git a/modules/fdatasync b/modules/fdatasync
new file mode 100644
index 0000000..7b78a80
--- /dev/null
+++ b/modules/fdatasync
@@ -0,0 +1,28 @@
+Description:
+fdatasync(2) function: synchronize writes to a file.
+
+Files:
+lib/fdatasync.c
+m4/fdatasync.m4
+
+Depends-on:
+fsync
+unistd
+
+configure.ac:
+gl_FUNC_FDATASYNC
+if test $HAVE_FDATASYNC = 0; then
+  AC_LIBOBJ([fdatasync])
+fi
+gl_UNISTD_MODULE_INDICATOR([fdatasync])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Eric Blake
diff --git a/modules/fdatasync-tests b/modules/fdatasync-tests
new file mode 100644
index 0000000..9afd058
--- /dev/null
+++ b/modules/fdatasync-tests
@@ -0,0 +1,13 @@
+Files:
+tests/test-fdatasync.c
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+errno
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-fdatasync
+check_PROGRAMS += test-fdatasync
diff --git a/modules/fsync b/modules/fsync
index 0092226..0f5b3fc 100644
--- a/modules/fsync
+++ b/modules/fsync
@@ -1,5 +1,5 @@
 Description:
-fsync(2) function: synchronize writes to a file.
+fsync(2) function: synchronize writes, including metadata, to a file.

 Files:
 lib/fsync.c
diff --git a/modules/unistd b/modules/unistd
index d6642a7..f843a2f 100644
--- a/modules/unistd
+++ b/modules/unistd
@@ -39,6 +39,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \
              -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \
              -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \
+             -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \
              -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \
              -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \
              -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \
@@ -82,6 +83,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \
              -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \
              -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \
+             -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|g' \
              -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \
              -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \
              -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \
diff --git a/tests/test-fdatasync.c b/tests/test-fdatasync.c
new file mode 100644
index 0000000..d23e6db
--- /dev/null
+++ b/tests/test-fdatasync.c
@@ -0,0 +1,64 @@
+/* Test of fdatasync() function.
+   Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (fdatasync, int, (int));
+
+#include <errno.h>
+#include <fcntl.h>
+
+#include "macros.h"
+
+int
+main (void)
+{
+  int fd;
+  const char *file = "test-fdatasync.txt";
+
+  if (fdatasync (STDOUT_FILENO) != 0)
+    {
+      ASSERT (errno == EINVAL /* POSIX */
+              || errno == ENOTSUP /* seen on MacOS X 10.5 */
+              || errno == EBADF /* seen on AIX 7.1 */
+              );
+    }
+  errno = 0;
+  ASSERT (fdatasync (-1) == -1);
+  ASSERT (errno == EBADF);
+  fd = open (file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+  ASSERT (0 <= fd);
+  ASSERT (write (fd, "hello", 5) == 5);
+  ASSERT (fdatasync (fd) == 0);
+  ASSERT (close (fd) == 0);
+#if 0
+  /* POSIX is self-contradictory on whether fdatasync must fail on
+     read-only file descriptors.  Glibc allows it, as does our
+     implementation if fsync allows it.  */
+  fd = open (file, O_RDONLY);
+  ASSERT (0 <= fd);
+  errno = 0;
+  ASSERT (fdatasync (fd) == -1);
+  ASSERT (errno == EBADF);
+  ASSERT (close (fd) == 0);
+#endif
+  ASSERT (unlink (file) == 0);
+
+  return 0;
+}
-- 
1.7.4.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]