diff options
author | Branko Čibej <brane@apache.org> | 2020-11-12 09:43:00 +0000 |
---|---|---|
committer | Branko Čibej <brane@apache.org> | 2020-11-12 09:43:00 +0000 |
commit | 22920927cd8b358fb1afbeb0b29fef92dcb34e46 (patch) | |
tree | 967288719a7b3d6c50313a5030b95f12fec5d6d0 | |
parent | c19ce4081713f876edaf7ced04f79b2c0cdc1f3b (diff) | |
download | apr-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.c | 12 | ||||
-rw-r--r-- | test/testfile.c | 37 |
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; } |