From 2b784748e37c975d4b05d394b772d668a85da4ff Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Wed, 9 Sep 2026 16:00:33 +0200 Subject: [PATCH] Propagate final writeback errors from advise_close --- cmdline/handle.c | 26 +++++++++++++++++++------- cmdline/import.c | 13 ++++++++++++- cmdline/parity.c | 22 +++++++++++++++++++--- cmdline/support.c | 27 +++++++++++++++++++++++---- cmdline/support.h | 2 +- 5 files changed, 74 insertions(+), 16 deletions(-) diff --git a/cmdline/handle.c b/cmdline/handle.c index a9620ff5..1172e67a 100644 --- a/cmdline/handle.c +++ b/cmdline/handle.c @@ -329,21 +329,29 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int int handle_close(struct snapraid_handle* handle) { - int ret; + int f_ret = 0; + int f_errno = 0; /* close if open */ if (handle->f != -1) { - advise_close(&handle->advise, handle->f); + int ret = advise_close(&handle->advise, handle->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + f_ret = -1; + f_errno = errno; + log_fatal(errno, "Error advising file '%s'. %s.\n", handle->path, strerror(errno)); + /* LCOV_EXCL_STOP */ + } ret = close(handle->f); if (ret != 0) { /* LCOV_EXCL_START */ + if (f_ret == 0) { + f_ret = -1; + f_errno = errno; + } log_fatal(errno, "Error closing file '%s'. %s.\n", handle->path, strerror(errno)); - /* invalidate for error */ - handle->file = 0; - handle->f = -1; - return -1; /* LCOV_EXCL_STOP */ } } @@ -353,7 +361,10 @@ int handle_close(struct snapraid_handle* handle) handle->f = -1; handle->readonly_errno = 0; - return 0; + if (f_ret != 0) + errno = f_errno; + + return f_ret; } ssize_t handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, log_ptr* out_missing) @@ -572,3 +583,4 @@ struct snapraid_handle* handle_mapping(struct snapraid_state* state, unsigned* h *handlemax = size; return handle; } + diff --git a/cmdline/import.c b/cmdline/import.c index 6644209f..79d641bf 100644 --- a/cmdline/import.c +++ b/cmdline/import.c @@ -47,6 +47,7 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t ssize_t ret; int f; int flags; + int advise_errno; unsigned block_size = state->block_size; struct advise_struct advise; block_off_t blockmax; @@ -149,9 +150,19 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t size -= read_size; } - advise_close(&advise, f); + ret = advise_close(&advise, f); + advise_errno = ret != 0 ? errno : 0; ret = close(f); + + if (advise_errno != 0) { + /* LCOV_EXCL_START */ + errno = advise_errno; + log_fatal(errno, "Error advising file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (ret != 0) { /* LCOV_EXCL_START */ log_fatal(errno, "Error closing file '%s'. %s.\n", path, strerror(errno)); diff --git a/cmdline/parity.c b/cmdline/parity.c index 27521b2d..89bb34ec 100644 --- a/cmdline/parity.c +++ b/cmdline/parity.c @@ -1001,23 +1001,35 @@ int parity_close(struct snapraid_parity_handle* handle) { unsigned s; int f_ret = 0; + int f_errno = 0; for (s = 0; s < handle->split_mac; ++s) { struct snapraid_split_handle* split = &handle->split_map[s]; - int ret; - advise_close(&split->advise, split->f); + int ret = advise_close(&split->advise, split->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + if (f_ret == 0) { + f_ret = -1; + f_errno = errno; + } + log_fatal(errno, "Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); + /* LCOV_EXCL_STOP */ + } ret = close(split->f); if (ret != 0) { /* LCOV_EXCL_START */ + if (f_ret == 0) { + f_ret = -1; + f_errno = errno; + } /* * This is a serious error, as it may be the result of a failed write * identified at later time. * In a normal file-system (not NFS) it should never happen */ log_fatal(errno, "Error closing parity file '%s'. %s.\n", split->path, strerror(errno)); - f_ret = -1; /* LCOV_EXCL_STOP */ /* continue to close the others */ @@ -1027,6 +1039,9 @@ int parity_close(struct snapraid_parity_handle* handle) split->f = -1; } + if (f_ret != 0) + errno = f_errno; + return f_ret; } @@ -1217,3 +1232,4 @@ int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned return block_size; } + diff --git a/cmdline/support.c b/cmdline/support.c index 3eb7f103..dd5fe9e4 100644 --- a/cmdline/support.c +++ b/cmdline/support.c @@ -1802,7 +1802,7 @@ int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off return 0; } -void advise_close(struct advise_struct* advise, int f) +int advise_close(struct advise_struct* advise, int f) { data_off_t flush_offset; data_off_t flush_size; @@ -1835,8 +1835,15 @@ void advise_close(struct advise_struct* advise, int f) #if HAVE_SYNC_FILE_RANGE if (flush_size != 0) { + int ret; + /* start writing immediately */ - sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE); + ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE); + if (ret != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } } #endif @@ -1848,17 +1855,29 @@ void advise_close(struct advise_struct* advise, int f) ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER); if (ret != 0) { /* LCOV_EXCL_START */ - return; + return -1; /* LCOV_EXCL_STOP */ } /* flush the data from the cache */ - posix_fadvise_wrapper(f, discard_offset, discard_size, POSIX_FADV_DONTNEED); + ret = posix_fadvise_wrapper(f, discard_offset, discard_size, POSIX_FADV_DONTNEED); + if (ret == ENOSYS) { + /* call is not supported */ + ret = 0; + } + if (ret != 0) { + /* LCOV_EXCL_START */ + errno = ret; /* posix_fadvise return the error code */ + return -1; + /* LCOV_EXCL_STOP */ + } } #endif advise->dirty_begin = 0; advise->dirty_end = 0; + + return 0; } /****************************************************************************/ diff --git a/cmdline/support.h b/cmdline/support.h index 5c70eda5..e997b7e0 100644 --- a/cmdline/support.h +++ b/cmdline/support.h @@ -429,7 +429,7 @@ int advise_flags(struct advise_struct* advise); int advise_open(struct advise_struct* advise, int f); int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size); int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size); -void advise_close(struct advise_struct* advise, int f); +int advise_close(struct advise_struct* advise, int f); /****************************************************************************/ /* smartctl */