summaryrefslogtreecommitdiff
path: root/mysys/my_sync.c
diff options
context:
space:
mode:
authorunknown <guilhem@gbichot3.local>2006-11-21 22:22:59 +0100
committerunknown <guilhem@gbichot3.local>2006-11-21 22:22:59 +0100
commita41ac15b960aee306e3464835b05a835fd98771d (patch)
treebac3eccdcb9906c3a529aa064ac3b9dcb8841edf /mysys/my_sync.c
parent3becab22e9dd774d58983e553b6fbbfb9960f852 (diff)
downloadmariadb-git-a41ac15b960aee306e3464835b05a835fd98771d.tar.gz
Maria - various fixes around durability of files:
1) on Mac OS X >=10.3, fcntl() is recommended over fsync (from the man page: "[With fsync()] the disk drive may also re-order the data so that later writes may be present while earlier writes are not. Applications such as databases that require a strict ordering of writes should use F_FULLFSYNC to ensure their data is written in the order they expect"). I have seen two other pieces of software changing from fsync to F_FULLFSYNC on Mac OS X. 2) to make a file creation/deletion/renaming durable on Linux (at least ext2 as I have tested) (see "man fsync"), a fsync() on the directory is needed: new functions to do that, and a flag MY_SYNC_DIR to do it in my_create/my_delete/my_rename. 3) now using this directory syncing when creating he frm if opt_sync_frm, and for Maria's control file when it is created. include/my_sys.h: new flag to my_create/my_delete/my_rename, which asks to sync the directory after the operation is done (currently does nothing except on Linux) libmysql/CMakeLists.txt: my_create() now depends on my_sync() so my_sync is needed for libmysql libmysql/Makefile.shared: my_create() now depends on my_sync() so my_sync is needed for libmysql mysys/my_create.c: my_create() can now sync the directory if asked for mysys/my_delete.c: my_delete() can now sync the directory if asked for mysys/my_open.c: it was a bug that my_close() is done on fd but a positive fd would still be returned, by my_register_filename(). mysys/my_rename.c: my_rename() can now sync the two directories (the one of "from" and the one of "to") if asked for. mysys/my_sync.c: On recent Mac OS X, fcntl(F_FULLFSYNC) is recommended over fsync() (see "man fsync" on Mac OS X 10.3). my_sync_dir(): to sync a directory after a file creation/deletion/ renaming; can be called directly or via MY_SYNC_DIR in my_create/ my_delete/my_rename(). No-op except on Linux (see "man fsync" on Linux). my_sync_dir_from_file(): same as above, just more practical when the caller has a file name but no directory name ready. Should the #warning even be a #error? I mean do we want to release binaries which don't guarantee any durability? sql/log.cc: a TODO for the future. sql/unireg.cc: If we sync the frm it makes sense to also sync its creation in the directory. storage/maria/ma_control_file.c: control file is vital, try to make it to disk
Diffstat (limited to 'mysys/my_sync.c')
-rw-r--r--mysys/my_sync.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index c557324b52c..eaa26ef07a7 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -49,6 +49,12 @@ int my_sync(File fd, myf my_flags)
do
{
+#if defined(F_FULLFSYNC)
+ /* Recent Mac OS X versions insist this call is safer than fsync() */
+ if (!(res= fcntl(fd, F_FULLFSYNC, 0)))
+ break; /* ok */
+ /* Some fs don't support F_FULLFSYNC and fail above, fallback: */
+#endif
#if defined(HAVE_FDATASYNC)
res= fdatasync(fd);
#elif defined(HAVE_FSYNC)
@@ -56,6 +62,7 @@ int my_sync(File fd, myf my_flags)
#elif defined(__WIN__)
res= _commit(fd);
#else
+#warning Cannot find a way to sync a file, durability in danger
res= 0; /* No sync (strange OS) */
#endif
} while (res == -1 && errno == EINTR);
@@ -74,3 +81,70 @@ int my_sync(File fd, myf my_flags)
DBUG_RETURN(res);
} /* my_sync */
+
+/*
+ Force directory information to disk. Only Linux is known to need this to
+ make sure a file creation/deletion/renaming in(from,to) this directory
+ durable.
+
+ SYNOPSIS
+ my_sync_dir()
+ dir_name the name of the directory
+ my_flags unused
+
+ RETURN
+ nothing (the sync may fail sometimes).
+*/
+void my_sync_dir(const char *dir_name, myf my_flags __attribute__((unused)))
+{
+#ifdef TARGET_OS_LINUX
+ DBUG_ENTER("my_sync_dir");
+ DBUG_PRINT("my",("Dir: '%s' my_flags: %d", dir_name, my_flags));
+ File dir_fd;
+ int error= 0;
+ /*
+ Syncing a dir does not work on all filesystems (e.g. tmpfs->EINVAL) :
+ ignore errors. But print them to the debug log.
+ */
+ if (((dir_fd= my_open(dir_name, O_RDONLY, MYF(0))) >= 0))
+ {
+ if (my_sync(dir_fd, MYF(0)))
+ {
+ error= errno;
+ DBUG_PRINT("info",("my_sync failed errno: %d", error));
+ }
+ my_close(dir_fd, MYF(0));
+ }
+ else
+ {
+ error= errno;
+ DBUG_PRINT("info",("my_open failed errno: %d", error));
+ }
+ DBUG_VOID_RETURN;
+#endif
+}
+
+
+/*
+ Force directory information to disk. Only Linux is known to need this to
+ make sure a file creation/deletion/renaming in(from,to) this directory
+ durable.
+
+ SYNOPSIS
+ my_sync_dir_by_file()
+ file_name the name of a file in the directory
+ my_flags unused
+
+ RETURN
+ nothing (the sync may fail sometimes).
+*/
+void my_sync_dir_by_file(const char *file_name,
+ myf my_flags __attribute__((unused)))
+{
+#ifdef TARGET_OS_LINUX
+ char dir_name[FN_REFLEN];
+ dirname_part(dir_name, file_name);
+ return my_sync_dir(dir_name, my_flags);
+#endif
+}
+