summaryrefslogtreecommitdiff
path: root/mysys/my_sync.c
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2012-08-30 10:53:49 +0200
committerunknown <knielsen@knielsen-hq.org>2012-08-30 10:53:49 +0200
commit10802c4d9046fd54bf1a27cb7611c182ecde93fb (patch)
tree7dd0f391ecde085d8f47990da25869298d14969c /mysys/my_sync.c
parent0536c506ff7c3ed261abc3d02fb787bfdd228abb (diff)
downloadmariadb-git-10802c4d9046fd54bf1a27cb7611c182ecde93fb.tar.gz
MDEV-381: fdatasync() does not correctly flush growing binlog file.
When we append data to the binlog file, we use fdatasync() to ensure the data gets to disk so that crash recovery can work. Unfortunately there seems to be a bug in ext3/ext4 on linux, so that fdatasync() does not correctly sync all data when the size of a file is increased. This causes crash recovery to not work correctly (it loses transactions from the binlog). As a work-around, use fsync() for the binlog, not fdatasync(). Since we are increasing the file size, (correct) fdatasync() will most likely not be faster than fsync() on any file system, and fsync() does work correctly on ext3/ext4. This avoids the need to try to detect if we are running on buggy ext3/ext4.
Diffstat (limited to 'mysys/my_sync.c')
-rw-r--r--mysys/my_sync.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index d8973244620..33033ff1045 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -39,6 +39,13 @@ ulong my_sync_count; /* Count number of sync calls */
(which is correct behaviour, if we know that the other thread synced the
file before closing)
+ MY_SYNC_FILESIZE is useful when syncing a file after it has been extended.
+ On Linux, fdatasync() on ext3/ext4 file systems does not properly flush
+ to disk the inode data required to preserve the added data across a crash
+ (this looks to be a bug). But when a file is extended, inode data will most
+ likely need flushing in any case, so passing MY_SYNC_FILESIZE as flags
+ is not likely to be any slower, and will be crash safe on Linux ext3/ext4.
+
RETURN
0 ok
-1 error
@@ -67,8 +74,12 @@ int my_sync(File fd, myf my_flags)
DBUG_PRINT("info",("fcntl(F_FULLFSYNC) failed, falling back"));
#endif
#if defined(HAVE_FDATASYNC) && HAVE_DECL_FDATASYNC
- res= fdatasync(fd);
-#elif defined(HAVE_FSYNC)
+ if (!(my_flags & MY_SYNC_FILESIZE))
+ res= fdatasync(fd);
+ else
+ {
+#endif
+#if defined(HAVE_FSYNC)
res= fsync(fd);
if (res == -1 && errno == ENOLCK)
res= 0; /* Result Bug in Old FreeBSD */
@@ -78,6 +89,9 @@ int my_sync(File fd, myf my_flags)
#error Cannot find a way to sync a file, durability in danger
res= 0; /* No sync (strange OS) */
#endif
+#if defined(HAVE_FDATASYNC) && HAVE_DECL_FDATASYNC
+ }
+#endif
} while (res == -1 && errno == EINTR);
if (res)