Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH v4] file_copy: use sendfile return value to measure bytes copied (bug 635126)
Date: Tue, 24 Oct 2017 10:53:01
Message-Id: 20171024104827.17687-1-zmedico@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH] file_copy: use sendfile return value to measure bytes copied (bug 635126) by Zac Medico
1 The sendfile *offset parameter refers to the input file offest, so
2 it cannot be used in the same way as the copy_file_range *off_out
3 parameter. Therefore, add sf_wrapper function which implements the
4 *off_out behavior for sendfile.
5
6 Bug: https://bugs.gentoo.org/635126
7 ---
8 [PATCH v4] ensures that both input and output file offsets are aligned
9 prior to the sendfile call
10
11 src/portage_util_file_copy_reflink_linux.c | 43 +++++++++++++++++++++++++-----
12 1 file changed, 37 insertions(+), 6 deletions(-)
13
14 diff --git a/src/portage_util_file_copy_reflink_linux.c b/src/portage_util_file_copy_reflink_linux.c
15 index 4be9e0568..9d00ae733 100644
16 --- a/src/portage_util_file_copy_reflink_linux.c
17 +++ b/src/portage_util_file_copy_reflink_linux.c
18 @@ -56,7 +56,7 @@ initreflink_linux(void)
19
20 /**
21 * cfr_wrapper - A copy_file_range syscall wrapper function, having a
22 - * function signature that is compatible with sendfile.
23 + * function signature that is compatible with sf_wrapper.
24 * @fd_out: output file descriptor
25 * @fd_in: input file descriptor
26 * @off_out: offset of the output file
27 @@ -79,6 +79,37 @@ cfr_wrapper(int fd_out, int fd_in, off_t *off_out, size_t len)
28 }
29
30 /**
31 + * sf_wrapper - A sendfile wrapper function, having a function signature
32 + * that is compatible with cfr_wrapper.
33 + * @fd_out: output file descriptor
34 + * @fd_in: input file descriptor
35 + * @off_out: offset of the output file
36 + * @len: number of bytes to copy between the file descriptors
37 + *
38 + * Return: Number of bytes written to out_fd on success, -1 on failure
39 + * (errno is set appropriately).
40 + */
41 +static ssize_t
42 +sf_wrapper(int fd_out, int fd_in, off_t *off_out, size_t len)
43 +{
44 + ssize_t ret;
45 + /* The sendfile docs do not guarantee that the offset of fd_in
46 + * will be adjusted by the number of bytes written. Therefore,
47 + * prior to each sendfile call, always use lseek to ensure that
48 + * both file offsets are in alignment.
49 + */
50 + if (lseek(fd_in, *off_out, SEEK_SET) < 0)
51 + return -1;
52 + if (lseek(fd_out, *off_out, SEEK_SET) < 0)
53 + return -1;
54 + ret = sendfile(fd_out, fd_in, NULL, len);
55 + if (ret > 0)
56 + *off_out += ret;
57 + return ret;
58 +}
59 +
60 +
61 +/**
62 * do_lseek_data - Adjust file offsets to the next location containing
63 * data, creating sparse empty blocks in the output file as needed.
64 * @fd_in: input file descriptor
65 @@ -250,7 +281,7 @@ _reflink_linux_file_copy(PyObject *self, PyObject *args)
66 * syscall is not available (less than Linux 4.5).
67 */
68 error = 0;
69 - copyfunc = sendfile;
70 + copyfunc = sf_wrapper;
71 copyfunc_ret = copyfunc(fd_out,
72 fd_in,
73 &offset_out,
74 @@ -293,10 +324,10 @@ _reflink_linux_file_copy(PyObject *self, PyObject *args)
75 error = errno;
76 } else {
77 while (offset_out < stat_in.st_size) {
78 - copyfunc_ret = sendfile(fd_out,
79 - fd_in,
80 - &offset_out,
81 - stat_in.st_size - offset_out);
82 + copyfunc_ret = sf_wrapper(fd_out,
83 + fd_in,
84 + &offset_out,
85 + stat_in.st_size - offset_out);
86
87 if (copyfunc_ret < 0) {
88 error = errno;
89 --
90 2.13.5