Issue
Scenario:
Task code (error checking omitted):
// open, write and close
fd = open(name);
write(fd, buf, len);
close(fd);
< more code here **not** issuing read/writes to name but maybe open()ing it >
// open again and fsync
fd = open(name);
fsync(fd);
No more tasks accessing name
concurrently in the system.
Is it defined, and more important, will it sync possible outstanding writes on the inode referred by name
? ie, will I read back buf
from the file after the fsync?
From POSIX http://pubs.opengroup.org/onlinepubs/009695399/functions/fsync.html I would say it seems legit ...
Thanks.
Edit may 18: Thanks for the answers and research. I took this question (in 2016) to one of the extfs lead developers (Ted) and got this answer: "It's not guaranteed by Posix, but in practice it should work on most file systems, including ext4. The key wording in the Posix specification is:
The
fsync()
function shall request that all data for the open file descriptor named byfildes
is to be transferred to the storage device associated with the file described byfildes
.
It does not say "all data for the file described by fildes
...." it
says "all data for the open file descriptor". So technically data
written by another file descriptor is not guaranteed to be synced to
disk.
In practice, file systems don't try dirty data by which fd it came in on, so you don't need to worry. And an OS which writes more than what is strictly required is standards compliant, and so that's what you will find in general, even if it isn't guaranteed." This is less specific than "exact same durabily guarrantees" but is quite authoritative, even though maybe outdated.
What I was trying to do was a 'sync' command that worked on single files. Like fsync /some/file without having to sync the whole filesystem, to use it in shell scripts for example. Now (since a few years ago) gnu coreutils 'sync' works on single files and does exactly this (open/fsync). commit: https://github.com/coreutils/coreutils/commit/8b2bf5295f353016d4f5e6a2317d55b6a8e7fd00
Solution
No, close()
+re-open()
+fsync()
does not provide the same guarantees as fsync()
+close()
.
Source: I took this question to the linux-fsdevel
mailing list and got the answer:
Does a sequence of close()/re-open()/fsync() provide the same durability guarantees as fsync()/close()?
The short answer is no, the latter provides a better guaranty. The longer answer is that durability guarantees depends on kernel version, because situation has been changing in v4.13, v4.14 and now again in v4.17-rc and stable kernels.
Further relevant links are:
- https://wiki.postgresql.org/wiki/Fsync_Errors ("fsyncgate")
- Mailing list entry PostgreSQL's handling of fsync() errors is unsafe and risks data loss at least on XFS
- Writing programs to cope with I/O errors causing lost writes on Linux from the same author
In particular, the latter links describe how
- after closing an FD, you lose all ways to enforce durability
- after an
fsync()
fails, you cannot callfsync()
again in the hope that now your data would be written - you must re-do/confirm all writing work if that happens
Answered By - nh2 Answer Checked By - Mildred Charles (WPSolving Admin)