mirror of
https://github.com/systemd/systemd.git
synced 2025-02-03 17:47:28 +03:00
basic/copy: use copy_file_range()
For btrfs, c_f_r() is like BTRFS_IOC_CLONE which we already used, but also works when max_bytes is set. We do call copy_bytes in coredump code with max_bytes set, and for large files, so we might see some benefit from using c_f_r() on btrfs. For other filesystems, c_f_r() falls back to do_splice_direct(), the same as sendfile, which we already call, so there shouldn't be much difference. Tested with test-copy and systemd-coredump on Linux 4.3 (w/o c_f_r) and 4.5 (w/ c_f_r).
This commit is contained in:
parent
1d4b557d1b
commit
a44202e98b
2
TODO
2
TODO
@ -49,8 +49,6 @@ Features:
|
||||
|
||||
* cache sd_event_now() result from before the first iteration...
|
||||
|
||||
* support for the new copy_file_range() syscall
|
||||
|
||||
* add systemctl stop --job-mode=triggering that follows TRIGGERED_BY deps and adds them to the same transaction
|
||||
|
||||
* Maybe add a way how users can "pin" units into memory, so that they are not subject to automatic GC?
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "io-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
@ -48,10 +49,29 @@
|
||||
|
||||
#define COPY_BUFFER_SIZE (16*1024u)
|
||||
|
||||
static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
|
||||
int fd_out, loff_t *off_out,
|
||||
size_t len,
|
||||
unsigned int flags) {
|
||||
static int have = -1;
|
||||
ssize_t r;
|
||||
|
||||
if (have == false)
|
||||
return -ENOSYS;
|
||||
|
||||
r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
|
||||
if (_unlikely_(have < 0))
|
||||
have = r >= 0 || errno != ENOSYS;
|
||||
if (r >= 0)
|
||||
return r;
|
||||
else
|
||||
return -errno;
|
||||
}
|
||||
|
||||
int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
|
||||
bool try_sendfile = true, try_splice = true;
|
||||
bool try_cfr = true, try_sendfile = true, try_splice = true;
|
||||
int r;
|
||||
size_t m = SSIZE_MAX; /* that the maximum that sendfile accepts */
|
||||
size_t m = SSIZE_MAX; /* that the maximum that sendfile and c_f_r accept */
|
||||
|
||||
assert(fdf >= 0);
|
||||
assert(fdt >= 0);
|
||||
@ -78,6 +98,22 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
|
||||
m = (size_t) max_bytes;
|
||||
}
|
||||
|
||||
/* First try copy_file_range(), unless we already tried */
|
||||
if (try_cfr) {
|
||||
n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
|
||||
if (n < 0) {
|
||||
if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV))
|
||||
return n;
|
||||
|
||||
try_cfr = false;
|
||||
/* use fallback below */
|
||||
} else if (n == 0) /* EOF */
|
||||
break;
|
||||
else
|
||||
/* Success! */
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* First try sendfile(), unless we already tried */
|
||||
if (try_sendfile) {
|
||||
n = sendfile(fdt, fdf, NULL, m);
|
||||
|
Loading…
x
Reference in New Issue
Block a user