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 v2] file_copy: use sendfile return value to measure bytes copied (bug 635126)
Date: Mon, 23 Oct 2017 07:25:43
Message-Id: 20171023072224.2621-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 v2] updates sf_wrapper to guarantee that the offset of
9 fd_in is in sync with *off_out on success
10
11 src/portage_util_file_copy_reflink_linux.c | 41 +++++++++++++++++++++++++-----
12 1 file changed, 35 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..3e97730df 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,35 @@ 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 + ret = sendfile(fd_out, fd_in, NULL, len);
46 + if (ret > 0) {
47 + /* The sendfile docs do not guarantee that the offset of fd_in
48 + * will be adjusted by the number of bytes written, so use
49 + * lseek to guarantee it.
50 + */
51 + if (lseek(fd_in, (*off_out) + ret, SEEK_SET) < 0)
52 + return -1;
53 + (*off_out) += ret;
54 + }
55 + return ret;
56 +}
57 +
58 +
59 +/**
60 * do_lseek_data - Adjust file offsets to the next location containing
61 * data, creating sparse empty blocks in the output file as needed.
62 * @fd_in: input file descriptor
63 @@ -250,7 +279,7 @@ _reflink_linux_file_copy(PyObject *self, PyObject *args)
64 * syscall is not available (less than Linux 4.5).
65 */
66 error = 0;
67 - copyfunc = sendfile;
68 + copyfunc = sf_wrapper;
69 copyfunc_ret = copyfunc(fd_out,
70 fd_in,
71 &offset_out,
72 @@ -293,10 +322,10 @@ _reflink_linux_file_copy(PyObject *self, PyObject *args)
73 error = errno;
74 } else {
75 while (offset_out < stat_in.st_size) {
76 - copyfunc_ret = sendfile(fd_out,
77 - fd_in,
78 - &offset_out,
79 - stat_in.st_size - offset_out);
80 + copyfunc_ret = sf_wrapper(fd_out,
81 + fd_in,
82 + &offset_out,
83 + stat_in.st_size - offset_out);
84
85 if (copyfunc_ret < 0) {
86 error = errno;
87 --
88 2.13.5