From 63d110098d08409f7012373f55848c113a67ccb8 Mon Sep 17 00:00:00 2001 From: Meta11ic0 Date: Fri, 28 Aug 2026 17:50:35 +0800 Subject: [PATCH v2] pg_upgrade: Make --copy-file-range check use the copy loop. check_copy_file_range() issued a single copy_file_range() call, which succeeds on kernels such as Linux 4.19 where a later call at a non-zero offset with SSIZE_MAX fails with EINVAL. Run the same do-while loop as copyFileByRange() so --check exercises the contract the transfer path depends on. Discussion: https://postgr.es/m/CAJh1VjasvNHhLoJu7WX55f2eW2i424MPRKMUF9hVt3YxDdMNAw@mail.gmail.com --- src/bin/pg_upgrade/file.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index af82c0de490..f6353d8ead4 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -246,6 +246,7 @@ check_copy_file_range(void) { int src_fd; int dest_fd; + ssize_t nbytes; if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0) pg_fatal("could not open file \"%s\": %m", @@ -256,8 +257,13 @@ check_copy_file_range(void) pg_fatal("could not create file \"%s\": %m", new_link_file); - if (copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0) < 0) - pg_fatal("could not copy file range between old and new data directories: %m"); + do + { + nbytes = copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0); + if (nbytes < 0) + pg_fatal("could not copy file range between old and new data directories: %m"); + } + while (nbytes > 0); close(src_fd); close(dest_fd); -- 2.43.0