mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Extend parent directory fsync after content file rename to all platforms
This commit is contained in:
parent
6d4c4925f4
commit
15831064a1
2 changed files with 45 additions and 4 deletions
|
|
@ -4871,7 +4871,26 @@ static void state_rename_content(struct snapraid_state* state)
|
|||
{
|
||||
tommy_node* i;
|
||||
|
||||
#if defined(__linux__) /* this sequence is linux specific */
|
||||
#ifndef _WIN32
|
||||
/*
|
||||
* This sequence relies on POSIX file-system semantics.
|
||||
*
|
||||
* The temporary content file has already been flushed and fsync'ed.
|
||||
* rename()/renameat() atomically replaces the old content file, but the
|
||||
* directory entry update is not necessarily durable when the rename
|
||||
* returns.
|
||||
*
|
||||
* Open and fsync the parent directory after the rename to ensure that the
|
||||
* new content file name is persisted before state_write() returns. This
|
||||
* ordering is required for crash consistency because parity modifications
|
||||
* may start only after the pre-sync content state has been durably
|
||||
* published.
|
||||
*
|
||||
* When renameat() is available, perform the rename relative to the same
|
||||
* directory descriptor that is subsequently fsync'ed. Use O_DIRECTORY
|
||||
* when available, while retaining compatibility with POSIX systems where
|
||||
* O_DIRECTORY is not defined.
|
||||
*/
|
||||
i = tommy_list_head(&state->contentlist);
|
||||
while (i) {
|
||||
struct snapraid_content* content = i->data;
|
||||
|
|
@ -4888,8 +4907,13 @@ static void state_rename_content(struct snapraid_state* state)
|
|||
else
|
||||
pathcpy(dir, sizeof(dir), ".");
|
||||
|
||||
int flags = O_RDONLY;
|
||||
#ifdef O_DIRECTORY
|
||||
flags |= O_DIRECTORY;
|
||||
#endif
|
||||
|
||||
/* open the directory to get the handle */
|
||||
handle = open(dir, O_RDONLY | O_DIRECTORY);
|
||||
handle = open(dir, flags);
|
||||
if (handle < 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Error opening the directory '%s'. %s.\n", dir, strerror(errno));
|
||||
|
|
@ -4899,17 +4923,33 @@ static void state_rename_content(struct snapraid_state* state)
|
|||
|
||||
/* now rename the just written copy with the correct name */
|
||||
pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
|
||||
if (rename(tmp, content->content) != 0) {
|
||||
#if HAVE_RENAMEAT
|
||||
const char* content_name = slash ? content->content + (slash - dir) + 1 : content->content;
|
||||
char tmp_name[PATH_MAX];
|
||||
|
||||
pathprint(tmp_name, sizeof(tmp_name), "%s.tmp", content_name);
|
||||
if (renameat(handle, tmp_name, handle, content_name) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Error renaming the content file '%s' to '%s'. %s.\n", tmp, content->content, strerror(errno));
|
||||
close(handle);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#else
|
||||
if (rename(tmp, content->content) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Error renaming the content file '%s' to '%s'. %s.\n", tmp, content->content, strerror(errno));
|
||||
close(handle);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* sync the directory */
|
||||
if (fsync(handle) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Error syncing the directory '%s'. %s.\n", dir, strerror(errno));
|
||||
close(handle);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
|
@ -6240,3 +6280,4 @@ void state_snapshot_cleanup(struct snapraid_state* state)
|
|||
fssnapshot_unmount(&disk->fss);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ AC_CHECK_FUNCS([ftruncate fallocate access])
|
|||
AC_CHECK_FUNCS([fsync posix_fadvise sync_file_range syncfs])
|
||||
AC_CHECK_FUNCS([getc_unlocked ferror_unlocked])
|
||||
AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat])
|
||||
AC_CHECK_FUNCS([fstatat flock])
|
||||
AC_CHECK_FUNCS([fstatat flock renameat])
|
||||
AC_CHECK_FUNCS([mach_absolute_time])
|
||||
AC_CHECK_FUNCS([backtrace backtrace_symbols])
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue