summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBranko Čibej <brane@apache.org>2020-11-12 09:43:00 +0000
committerBranko Čibej <brane@apache.org>2020-11-12 09:43:00 +0000
commit22920927cd8b358fb1afbeb0b29fef92dcb34e46 (patch)
tree967288719a7b3d6c50313a5030b95f12fec5d6d0
parentc19ce4081713f876edaf7ced04f79b2c0cdc1f3b (diff)
downloadapr-22920927cd8b358fb1afbeb0b29fef92dcb34e46.tar.gz
Backport r1883340:
Follow up to r1790200: fall back to fsync() if F_FULLFSYNC is not supported by the file descriptor, filesystem or underlying device. See, e.g.: https://github.com/vim/vim/pull/4025 git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.7.x@1883341 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--file_io/unix/readwrite.c12
-rw-r--r--test/testfile.c37
2 files changed, 46 insertions, 3 deletions
diff --git a/file_io/unix/readwrite.c b/file_io/unix/readwrite.c
index 0759495af..ee204ab45 100644
--- a/file_io/unix/readwrite.c
+++ b/file_io/unix/readwrite.c
@@ -373,6 +373,7 @@ APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile)
APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
{
apr_status_t rv = APR_SUCCESS;
+ int os_status = 0;
file_lock(thefile);
@@ -386,12 +387,17 @@ APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
}
#ifdef HAVE_FDATASYNC
- if (fdatasync(thefile->filedes)) {
+ os_status = fdatasync(thefile->filedes);
#elif defined(F_FULLFSYNC)
- if (fcntl(thefile->filedes, F_FULLFSYNC)) {
+ os_status = fcntl(thefile->filedes, F_FULLFSYNC);
+ if (os_status) {
+ /* Fall back to fsync() if the device doesn't support F_FULLFSYNC. */
+ os_status = fsync(thefile->filedes);
+ }
#else
- if (fsync(thefile->filedes)) {
+ os_status = fsync(thefile->filedes);
#endif
+ if (os_status) {
rv = apr_get_os_error();
}
diff --git a/test/testfile.c b/test/testfile.c
index 36ab4f0d8..f90ca92ba 100644
--- a/test/testfile.c
+++ b/test/testfile.c
@@ -1219,6 +1219,41 @@ static void test_xthread(abts_case *tc, void *data)
apr_file_close(f);
}
+static void test_datasync_on_file(abts_case *tc, void *data)
+{
+ apr_status_t rv;
+ apr_file_t *f;
+ const char *fname = DIRNAME "/testtest_datasync.dat";
+ apr_size_t bytes_written;
+
+ apr_file_remove(fname, p);
+
+ rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE,
+ APR_FPROT_OS_DEFAULT, p);
+ APR_ASSERT_SUCCESS(tc, "open test file for writing", rv);
+ rv = apr_file_write_full(f, "abcdef", 6, &bytes_written);
+ APR_ASSERT_SUCCESS(tc, "write to file", rv);
+ rv = apr_file_datasync(f);
+ APR_ASSERT_SUCCESS(tc, "sync file contents", rv);
+ apr_file_close(f);
+
+ apr_file_remove(fname, p);
+}
+
+static void test_datasync_on_stream(abts_case *tc, void *data)
+{
+ apr_status_t rv;
+ apr_file_t *f;
+ apr_size_t bytes_written;
+
+ rv = apr_file_open_stdout(&f, p);
+ APR_ASSERT_SUCCESS(tc, "open stdout", rv);
+ rv = apr_file_write_full(f, "abcdef\b\b\b\b\b\b\b", 12, &bytes_written);
+ APR_ASSERT_SUCCESS(tc, "write to stdout", rv);
+ rv = apr_file_datasync(f);
+ APR_ASSERT_SUCCESS(tc, "sync stdout", rv);
+}
+
abts_suite *testfile(abts_suite *suite)
{
suite = ADD_SUITE(suite)
@@ -1263,6 +1298,8 @@ abts_suite *testfile(abts_suite *suite)
abts_run_test(suite, test_fail_read_flush, NULL);
abts_run_test(suite, test_buffer_set_get, NULL);
abts_run_test(suite, test_xthread, NULL);
+ abts_run_test(suite, test_datasync_on_file, NULL);
+ abts_run_test(suite, test_datasync_on_stream, NULL);
return suite;
}