From 21ac419d37f307fee4ba88d37c0bf1da0c591bac Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 1 Apr 2025 11:07:51 +0100 Subject: [PATCH] file: Hard error if sync_file_range fails After discussion with Dave Chinner, it appears that I/O errors can be returned by sync_file_range, ie. it is not merely a hint to start the eviction. Therefore return a hard error if any of the sync_file_range calls fails. Thanks: Dave Chinner Updates: commit d35f0636373e6a58c8f3fcfcf505af248e27c574 (cherry picked from commit d2ed6a839c3ed50b417f45dc13e5b811ecdc4e74) --- plugins/file/file.c | 53 ++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/plugins/file/file.c b/plugins/file/file.c index 0271a56b..aa552037 100644 --- a/plugins/file/file.c +++ b/plugins/file/file.c @@ -118,7 +118,7 @@ struct write_window { static pthread_mutex_t window_lock = PTHREAD_MUTEX_INITIALIZER; static struct write_window window[NR_WINDOWS]; -static void +static int evict_writes (int fd, uint64_t offset, size_t len) { ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&window_lock); @@ -127,31 +127,32 @@ evict_writes (int fd, uint64_t offset, size_t len) * (asynchronously). */ if (sync_file_range (fd, offset, len, SYNC_FILE_RANGE_WRITE) == -1) { - /* sync_file_range to start the write failed */ - nbdkit_debug ("sync_file_range: write: (ignored): %m"); + nbdkit_error ("sync_file_range: cache=none: starting eviction: %m"); + return -1; } - else { - /* sync_file_range to start the write succeeded, so - * evict the oldest window from the page cache. - */ - if (window[0].len > 0) { - if (sync_file_range (window[0].fd, window[0].offset, window[0].len, - SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| - SYNC_FILE_RANGE_WAIT_AFTER) == -1) - nbdkit_debug ("sync_file_range: wait: (ignored): %m"); - if (posix_fadvise (window[0].fd, window[0].offset, window[0].len, - POSIX_FADV_DONTNEED) == -1) - nbdkit_debug ("posix_fadvise: POSIX_FADV_DONTNEED: (ignored): %m"); + + /* Evict the oldest window from the page cache. */ + if (window[0].len > 0) { + if (sync_file_range (window[0].fd, window[0].offset, window[0].len, + SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| + SYNC_FILE_RANGE_WAIT_AFTER) == -1) { + nbdkit_error ("sync_file_range: cache=none: evicting oldest window: %m"); + return -1; } - - /* Move the Nth window to N-1. */ - memmove (&window[0], &window[1], sizeof window[0] * (NR_WINDOWS-1)); - - /* Add the range to the newest end of the list of windows. */ - window[NR_WINDOWS-1].fd = fd; - window[NR_WINDOWS-1].offset = offset; - window[NR_WINDOWS-1].len = len; + if (posix_fadvise (window[0].fd, window[0].offset, window[0].len, + POSIX_FADV_DONTNEED) == -1) + nbdkit_debug ("posix_fadvise: POSIX_FADV_DONTNEED: (ignored): %m"); } + + /* Move the Nth window to N-1. */ + memmove (&window[0], &window[1], sizeof window[0] * (NR_WINDOWS-1)); + + /* Add the range to the newest end of the list of windows. */ + window[NR_WINDOWS-1].fd = fd; + window[NR_WINDOWS-1].offset = offset; + window[NR_WINDOWS-1].len = len; + + return 0; } /* When we close the handle we must remove any windows which are still @@ -920,8 +921,10 @@ file_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset, return -1; #if EVICT_WRITES - if (cache_mode == cache_none) - evict_writes (h->fd, orig_offset, orig_count); + if (cache_mode == cache_none) { + if (evict_writes (h->fd, orig_offset, orig_count) == -1) + return -1; + } #endif return 0; -- 2.47.1