diff --git a/0001-copy-Stable-sort-in-tests.patch b/0001-copy-Stable-sort-in-tests.patch index 24a2f73..93b3ecd 100644 --- a/0001-copy-Stable-sort-in-tests.patch +++ b/0001-copy-Stable-sort-in-tests.patch @@ -1,7 +1,7 @@ From 8b20bbd329c07941f3e4aa00e14c05ed27b25435 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 2 Mar 2021 22:20:49 +0000 -Subject: [PATCH 1/3] copy: Stable sort in tests. +Subject: [PATCH 1/5] copy: Stable sort in tests. When running the tests in Koji they behaved differently from running locally (under a UTF-8 locale). This turned out to be a difference in diff --git a/0002-copy-Nicer-sort.patch b/0002-copy-Nicer-sort.patch index 8f632e1..7ea1409 100644 --- a/0002-copy-Nicer-sort.patch +++ b/0002-copy-Nicer-sort.patch @@ -1,7 +1,7 @@ From bae7c41a5126c56da4ee77bce39955036fca8b5f Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 2 Mar 2021 16:31:39 -0600 -Subject: [PATCH 2/3] copy: Nicer sort +Subject: [PATCH 2/5] copy: Nicer sort Tell sort where the numbers live, so we can get columns in ascending numeric order. Improves 8b20bbd329. diff --git a/0003-Revert-copy-file-ops.c-Remove-unneeded-check.patch b/0003-Revert-copy-file-ops.c-Remove-unneeded-check.patch index 5ff29b9..b45d880 100644 --- a/0003-Revert-copy-file-ops.c-Remove-unneeded-check.patch +++ b/0003-Revert-copy-file-ops.c-Remove-unneeded-check.patch @@ -1,7 +1,7 @@ From 4e456ff6363580177ceffdad79b8fc1e8c7f35eb Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 3 Mar 2021 10:12:31 +0000 -Subject: [PATCH 3/3] Revert "copy: file-ops.c: Remove unneeded check" +Subject: [PATCH 3/5] Revert "copy: file-ops.c: Remove unneeded check" This reverts commit 0f6e4f38bc440fc52c20a3a448ef031f806ec5e2. diff --git a/0004-copy-file-ops.c-Remove-unneeded-check.patch b/0004-copy-file-ops.c-Remove-unneeded-check.patch new file mode 100644 index 0000000..7c5cc03 --- /dev/null +++ b/0004-copy-file-ops.c-Remove-unneeded-check.patch @@ -0,0 +1,67 @@ +From 94a78764d80b6dc41ff2ae8a0e5f1b35c2fd8e78 Mon Sep 17 00:00:00 2001 +From: Nir Soffer +Date: Sat, 27 Feb 2021 05:36:38 +0200 +Subject: [PATCH 4/5] copy: file-ops.c: Remove unneeded check + +This function is called only from page_cache_evict(), which already +check that we could map the cached pages. Add an assert to document this +assumption. + +Signed-off-by: Nir Soffer +--- + copy/file-ops.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/copy/file-ops.c b/copy/file-ops.c +index ea725a4..47ec768 100644 +--- a/copy/file-ops.c ++++ b/copy/file-ops.c +@@ -102,7 +102,7 @@ page_size_init (void) + /* Load the page cache map for a particular file into + * rwf->cached_pages. Only used when reading files. This doesn't + * fail: if a system call fails then rwf->cached_pages.size will be +- * zero which is handled in page_was_cached. ++ * zero which is handled in page_cache_evict. + */ + static inline void + page_cache_map (struct rw_file *rwf) +@@ -126,19 +126,16 @@ page_cache_map (struct rw_file *rwf) + munmap (ptr, rwf->rw.size); + } + +-/* Test if a single page of the file was cached before nbdcopy ran. */ ++/* Test if a single page of the file was cached before nbdcopy ran. ++ * Valid only if we mapped the cached pages. ++ */ + static inline bool + page_was_cached (struct rw_file *rwf, uint64_t offset) + { + uint64_t page = offset / page_size; +- if (page < rwf->cached_pages.size) +- return (rwf->cached_pages.ptr[page] & 1) != 0; +- else +- /* This path is taken if we didn't manage to map the input file +- * for any reason. In this case assume that pages were mapped so +- * we will not evict them: essentially fall back to doing nothing. +- */ +- return true; ++ assert (page < rwf->cached_pages.size); ++ ++ return (rwf->cached_pages.ptr[page] & 1) != 0; + } + + /* Evict file contents from the page cache if they were not present in +@@ -150,6 +147,10 @@ page_cache_evict (struct rw_file *rwf, uint64_t orig_offset, size_t orig_len) + uint64_t offset, n; + size_t len; + ++ /* If we didn't manage to map the input file for any reason, assume ++ * that pages were mapped so we will not evict them: essentially fall ++ * back to doing nothing. ++ */ + if (rwf->cached_pages.size == 0) return; + + /* Only bother with whole pages. */ +-- +2.29.0.rc2 + diff --git a/0005-copy-file-ops.c-Fix-page-eviction-when-len-page_size.patch b/0005-copy-file-ops.c-Fix-page-eviction-when-len-page_size.patch new file mode 100644 index 0000000..9430c05 --- /dev/null +++ b/0005-copy-file-ops.c-Fix-page-eviction-when-len-page_size.patch @@ -0,0 +1,32 @@ +From 107eb605cfb75238020332b5a5461d0e09d62bec Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Wed, 3 Mar 2021 12:51:51 +0100 +Subject: [PATCH 5/5] copy/file-ops.c: Fix page eviction when len < page_size. + +On Fedora ppc64le at the moment page size is 64K. When asked to evict +a range with length < 64K the length calculation wrapped around and it +tried to evict a huge number of pages beyond the end of the file. + +With Nir's commit 0f6e4f38b this (correctly) resulted in an assertion +failure. + +Fix this by checking for the overflow and returning early. +--- + copy/file-ops.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/copy/file-ops.c b/copy/file-ops.c +index 47ec768..6bad50c 100644 +--- a/copy/file-ops.c ++++ b/copy/file-ops.c +@@ -155,6 +155,7 @@ page_cache_evict (struct rw_file *rwf, uint64_t orig_offset, size_t orig_len) + + /* Only bother with whole pages. */ + offset = ROUND_UP (orig_offset, page_size); ++ if (orig_len < offset - orig_offset) return; + len = orig_len - (offset - orig_offset); + len = ROUND_DOWN (len, page_size); + +-- +2.29.0.rc2 + diff --git a/libnbd.spec b/libnbd.spec index 79eca68..785c0d7 100644 --- a/libnbd.spec +++ b/libnbd.spec @@ -29,6 +29,8 @@ Source3: copy-patches.sh Patch0001: 0001-copy-Stable-sort-in-tests.patch Patch0002: 0002-copy-Nicer-sort.patch Patch0003: 0003-Revert-copy-file-ops.c-Remove-unneeded-check.patch +Patch0004: 0004-copy-file-ops.c-Remove-unneeded-check.patch +Patch0005: 0005-copy-file-ops.c-Fix-page-eviction-when-len-page_size.patch %if 0%{patches_touch_autotools} BuildRequires: autoconf, automake, libtool