On Thu, May 28, 2015 at 9:54 PM, Philip Martin
> Stefan Fuhrmann <stefan.fuhrmann_at_wandisco.com> writes:
>> In the future, we should implement step 1 as simple
>> non-fsync'ing file operations. Then explicitly sync every
>> file, and on POSIX the folders, once. Step 2 does not
>> have any atomicity requirements. Finally, do the 'current'
>> rename. This also only requires a single fsync b/c
>> the temp file will be in the same folder.
>> On top of that, all operations in step 2 can be run
>> concurrently. I did that for FSX on Linux using aio_fsync
>> and it got 3x as fast. Windows can do something similar.
>> I wrapped that functionality into a "batch_fsync" object
>> with a few methods on it. You simply push paths into it,
>> it drops duplicates, and finally you ask it to fsync all.
> fsync() works on file descriptors rather than files, do we need to keep
> the original file descriptors open in order to fsync()?
We could b/c there are at most 7 (4 files, 3 folders) of them for a
FSFS commit, but this is not necessary. Since it would imply
keeping them open during renames, we could no longer use
plain APR calls - i.e. extra code churn.
If your interpretation was correct, fsync'ing a directory would
only work if you modified that directory file through its descriptor -
which you simply can't. Also, it would mean that our protorev
file handling was broken: We open & close that file for every
PUT, re-open it during commit, append the structure data and
fsync only through the last file handle.
> The POSIX description is
> The fsync() function shall request that all data for the open file
> descriptor named by fildes is to be transferred to the storage device
> associated with the file described by fildes. The nature of the
> transfer is implementation-defined.
My reading of this paragraph is: "all data for the open file descriptor"
means "all data accessible through the open file descriptor", not
just the parts that it might have modified itself. The following
paragraph for serialized I/O makes this clearer:
> If _POSIX_SYNCHRONIZED_IO is defined, the fsync() function
> shall force all currently queued I/O operations associated with the
> file indicated by file descriptor fildes to the synchronized I/O completion
> state. ...
So, it requires the file object to be flushed not just some sub-set
manipulated through the given descriptor. If _POSIX_SYNCHRONIZED_IO
is not defined, the behaviour is configuration dependent and fsync
may simply be ineffective.
Received on 2015-05-29 09:08:08 CEST