aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel')
-rw-r--r--lib/kernel/doc/src/file.xml27
-rw-r--r--lib/kernel/src/file.erl12
-rw-r--r--lib/kernel/src/file_io_server.erl8
-rw-r--r--lib/kernel/src/ram_file.erl5
-rw-r--r--lib/kernel/test/file_SUITE.erl28
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl22
6 files changed, 96 insertions, 6 deletions
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 50f9722a1c..c94df62d1f 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -1641,6 +1641,33 @@ f.txt: {person, "kalle", 25}.
</desc>
</func>
<func>
+ <name>datasync(IoDevice) -> ok | {error, Reason}</name>
+ <fsummary>Synchronizes the in-memory data of a file, ignoring most of its metadata, with that on the physical medium</fsummary>
+ <type>
+ <v>IoDevice = io_device()</v>
+ <v>Reason = ext_posix() | terminated</v>
+ </type>
+ <desc>
+ <p>Makes sure that any buffers kept by the operating system
+ (not by the Erlang runtime system) are written to disk. In
+ many ways it's resembles fsync but it not requires to update
+ some of file's metadata such as the access time. On
+ some platforms, this function might have no effect.</p>
+ <p>Applications that access databases or log files often write
+ a tiny data fragment (e.g., one line in a log file) and then
+ call fsync() immediately in order to ensure that the written
+ data is physically stored on the harddisk. Unfortunately, fsync()
+ will always initiate two write operations: one for the newly
+ written data and another one in order to update the modification
+ time stored in the inode. If the modification time is not a part
+ of the transaction concept fdatasync() can be used to avoid
+ unnecessary inode disk write operations.</p>
+ <p>Available only in some POSIX systems. This call results in a
+ call to fsync(), or has no effect, in systems not implementing
+ the fdatasync syscall.</p>
+ </desc>
+ </func>
+ <func>
<name>truncate(IoDevice) -> ok | {error, Reason}</name>
<fsummary>Truncate a file</fsummary>
<type>
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 46ffa9d708..5da359fdf1 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -40,7 +40,7 @@
read/2, write/2,
pread/2, pread/3, pwrite/2, pwrite/3,
read_line/1,
- position/2, truncate/1, sync/1,
+ position/2, truncate/1, datasync/1, sync/1,
copy/2, copy/3]).
%% High level operations
-export([consult/1, path_consult/2]).
@@ -472,6 +472,16 @@ pwrite(#file_descriptor{module = Module} = Handle, Offs, Bytes) ->
pwrite(_, _, _) ->
{error, badarg}.
+-spec datasync(File :: io_device()) -> 'ok' | {'error', posix()}.
+
+datasync(File) when is_pid(File) ->
+ R = file_request(File, datasync),
+ wait_file_reply(File, R);
+datasync(#file_descriptor{module = Module} = Handle) ->
+ Module:datasync(Handle);
+datasync(_) ->
+ {error, badarg}.
+
-spec sync(File :: io_device()) -> 'ok' | {'error', posix()}.
sync(File) when is_pid(File) ->
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index 3ac35a209d..d0b30192b3 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -219,6 +219,14 @@ file_request({pwrite,At,Data},
Reply ->
std_reply(Reply, State)
end;
+file_request(datasync,
+ #state{handle=Handle}=State) ->
+ case ?PRIM_FILE:datasync(Handle) of
+ {error,_}=Reply ->
+ {stop,normal,Reply,State};
+ Reply ->
+ {reply,Reply,State}
+ end;
file_request(sync,
#state{handle=Handle}=State) ->
case ?PRIM_FILE:sync(Handle) of
diff --git a/lib/kernel/src/ram_file.erl b/lib/kernel/src/ram_file.erl
index d996650948..0230cb4e0a 100644
--- a/lib/kernel/src/ram_file.erl
+++ b/lib/kernel/src/ram_file.erl
@@ -24,7 +24,7 @@
-export([open/2, close/1]).
-export([write/2, read/2, copy/3,
pread/2, pread/3, pwrite/2, pwrite/3,
- position/2, truncate/1, sync/1]).
+ position/2, truncate/1, datasync/1, sync/1]).
%% Specialized file operations
-export([get_size/1, get_file/1, set_file/2, get_file_close/1]).
@@ -60,6 +60,7 @@
-define(RAM_FILE_TRUNCATE, 14).
-define(RAM_FILE_PREAD, 17).
-define(RAM_FILE_PWRITE, 18).
+-define(RAM_FILE_FDATASYNC, 19).
%% Other operations
-define(RAM_FILE_GET, 30).
@@ -167,6 +168,8 @@ copy(#file_descriptor{module = ?MODULE} = Source,
%% XXX Should be moved down to the driver for optimization.
file:copy_opened(Source, Dest, Length).
+datasync(#file_descriptor{module = ?MODULE, data = Port}) ->
+ call_port(Port, <<?RAM_FILE_FDATASYNC>>).
sync(#file_descriptor{module = ?MODULE, data = Port}) ->
call_port(Port, <<?RAM_FILE_FSYNC>>).
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 1d170790a3..2e6c3aba16 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -52,7 +52,7 @@
old_modes/1, new_modes/1, path_open/1, open_errors/1]).
-export([file_info/1, file_info_basic_file/1, file_info_basic_directory/1,
file_info_bad/1, file_info_times/1, file_write_file_info/1]).
--export([rename/1, access/1, truncate/1, sync/1,
+-export([rename/1, access/1, truncate/1, datasync/1, sync/1,
read_write/1, pread_write/1, append/1]).
-export([errors/1, e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
-export([otp_5814/1]).
@@ -377,7 +377,7 @@ win_cur_dir_1(_Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-files(suite) -> [open,pos,file_info,consult,eval,script,truncate,sync].
+files(suite) -> [open,pos,file_info,consult,eval,script,truncate,sync,datasync].
open(suite) -> [open1,old_modes,new_modes,path_open,close,access,read_write,
pread_write,append,open_errors].
@@ -1355,6 +1355,30 @@ truncate(Config) when is_list(Config) ->
ok.
+datasync(suite) -> [];
+datasync(doc) -> "Tests that ?FILE_MODULE:datasync/1 at least doesn't crash.";
+datasync(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(5)),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Sync = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_sync.fil"),
+
+ %% Raw open.
+ ?line {ok, Fd} = ?FILE_MODULE:open(Sync, [write, raw]),
+ ?line ok = ?FILE_MODULE:datasync(Fd),
+ ?line ok = ?FILE_MODULE:close(Fd),
+
+ %% Ordinary open.
+ ?line {ok, Fd2} = ?FILE_MODULE:open(Sync, [write]),
+ ?line ok = ?FILE_MODULE:datasync(Fd2),
+ ?line ok = ?FILE_MODULE:close(Fd2),
+
+ ?line [] = flush(),
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+
sync(suite) -> [];
sync(doc) -> "Tests that ?FILE_MODULE:sync/1 at least doesn't crash.";
sync(Config) when is_list(Config) ->
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index 6badbb5090..842945e83c 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -34,7 +34,7 @@
file_info_times_a/1, file_info_times_b/1,
file_write_file_info_a/1, file_write_file_info_b/1]).
-export([rename_a/1, rename_b/1,
- access/1, truncate/1, sync/1,
+ access/1, truncate/1, datasync/1, sync/1,
read_write/1, pread_write/1, append/1]).
-export([errors/1, e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
@@ -380,7 +380,7 @@ win_cur_dir_1(_Config, Handle) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-files(suite) -> [open,pos,file_info,truncate,sync].
+files(suite) -> [open,pos,file_info,truncate,sync,datasync].
open(suite) -> [open1,modes,close,access,read_write,
pread_write,append].
@@ -1064,6 +1064,24 @@ truncate(Config) when is_list(Config) ->
ok.
+datasync(suite) -> [];
+datasync(doc) -> "Tests that ?PRIM_FILE:datasync/1 at least doesn't crash.";
+datasync(Config) when is_list(Config) ->
+ ?line Dog = test_server:timetrap(test_server:seconds(5)),
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Sync = filename:join(PrivDir,
+ atom_to_list(?MODULE)
+ ++"_sync.fil"),
+
+ %% Raw open.
+ ?line {ok, Fd} = ?PRIM_FILE:open(Sync, [write]),
+ ?line ok = ?PRIM_FILE:datasync(Fd),
+ ?line ok = ?PRIM_FILE:close(Fd),
+
+ ?line test_server:timetrap_cancel(Dog),
+ ok.
+
+
sync(suite) -> [];
sync(doc) -> "Tests that ?PRIM_FILE:sync/1 at least doesn't crash.";
sync(Config) when is_list(Config) ->