Skip to content

Commit 97169cd

Browse files
ddissnathanchance
authored andcommitted
gen_init_cpio: attempt copy_file_range for file data
The copy_file_range syscall can improve copy performance by cloning extents between cpio archive source and destination files. Existing read / write based copy logic is retained for fallback in case the copy_file_range syscall is unsupported or unavailable due to cross-filesystem EXDEV, etc. Clone or reflink, as opposed to copy, of source file extents into the output cpio archive may (e.g. on Btrfs and XFS) require alignment of the output to the filesystem block size. This could be achieved by inserting padding entries into the cpio archive manifest. Signed-off-by: David Disseldorp <ddiss@suse.de> Reviewed-by: Nicolas Schier <nsc@kernel.org> Link: https://lore.kernel.org/r/20250819032607.28727-4-ddiss@suse.de Signed-off-by: Nathan Chancellor <nathan@kernel.org>
1 parent ae18b94 commit 97169cd

1 file changed

Lines changed: 12 additions & 1 deletion

File tree

usr/gen_init_cpio.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ static int cpio_mkfile(const char *name, const char *location,
354354
int namesize;
355355
unsigned int i;
356356
uint32_t csum = 0;
357+
ssize_t this_read;
357358

358359
mode |= S_IFREG;
359360

@@ -429,9 +430,19 @@ static int cpio_mkfile(const char *name, const char *location,
429430
push_pad(padlen(offset, 4)) < 0)
430431
goto error;
431432

433+
if (size) {
434+
this_read = copy_file_range(file, NULL, outfd, NULL, size, 0);
435+
if (this_read > 0) {
436+
if (this_read > size)
437+
goto error;
438+
offset += this_read;
439+
size -= this_read;
440+
}
441+
/* short or failed copy falls back to read/write... */
442+
}
443+
432444
while (size) {
433445
unsigned char filebuf[65536];
434-
ssize_t this_read;
435446
size_t this_size = MIN(size, sizeof(filebuf));
436447

437448
this_read = read(file, filebuf, this_size);

0 commit comments

Comments
 (0)