ldconfig: Call fsync on temporary files before renaming them [BZ #20890]
Commit Message
If the system crashes before the file data has been written to disk, the
file system recovery upon the next mount may restore a partially
rewritten temporary file under the non-temporary (final) name (after the
rename operation).
Some file systems perform an implicit fsync before renaming a file over
another one, but XFS does not, for example.
2018-01-12 Florian Weimer <fweimer@redhat.com>
[BZ #20890]
* elf/cache.c (save_cache): Call fsync on temporary file before
renaming it.
(save_aux_cache): Likewise.
Comments
On Fri, Jan 12, 2018 at 12:07:57PM +0100, Florian Weimer wrote:
> If the system crashes before the file data has been written to disk, the
> file system recovery upon the next mount may restore a partially
> rewritten temporary file under the non-temporary (final) name (after the
> rename operation).
>
> Some file systems perform an implicit fsync before renaming a file over
> another one, but XFS does not, for example.
At least on Linux no file system performs an actual fsync equivalent.
A few do start a writeout, but don't actually wait on it.
On 01/12/2018 12:37 PM, Christoph Hellwig wrote:
> On Fri, Jan 12, 2018 at 12:07:57PM +0100, Florian Weimer wrote:
>> If the system crashes before the file data has been written to disk, the
>> file system recovery upon the next mount may restore a partially
>> rewritten temporary file under the non-temporary (final) name (after the
>> rename operation).
>>
>> Some file systems perform an implicit fsync before renaming a file over
>> another one, but XFS does not, for example.
>
> At least on Linux no file system performs an actual fsync equivalent.
> A few do start a writeout, but don't actually wait on it.
Oh. I'll drop the last paragraph from the commit message, then.
Thanks,
Florian
Florian Weimer wrote:
> if (write (fd, strings, total_strlen) != (ssize_t) total_strlen
> - || close (fd))
> + || fsync (fd) != 0
> + || close (fd) != 0)
> error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
Would fdatasync suffice, instead of fsync?
@@ -449,7 +449,8 @@ save_cache (const char *cache_name)
}
if (write (fd, strings, total_strlen) != (ssize_t) total_strlen
- || close (fd))
+ || fsync (fd) != 0
+ || close (fd) != 0)
error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
/* Make sure user can always read cache file */
@@ -812,7 +813,8 @@ save_aux_cache (const char *aux_cache_name)
if (write (fd, file_entries, file_entries_size + total_strlen)
!= (ssize_t) (file_entries_size + total_strlen)
- || close (fd))
+ || fsync (fd) != 0
+ || close (fd) != 0)
{
unlink (temp_name);
goto out_fail;