[mod_webdav] use copy_file_range() if available
This commit is contained in:
parent
3f7779d247
commit
0d62b8657b
|
@ -386,6 +386,7 @@ if 1:
|
|||
'arc4random_buf',
|
||||
'chroot',
|
||||
'clock_gettime',
|
||||
'copy_file_range',
|
||||
'dup2',
|
||||
'epoll_ctl',
|
||||
'explicit_bzero',
|
||||
|
|
|
@ -1216,6 +1216,7 @@ AC_CHECK_FUNCS([\
|
|||
arc4random_buf \
|
||||
chroot \
|
||||
clock_gettime \
|
||||
copy_file_range \
|
||||
epoll_ctl \
|
||||
explicit_bzero \
|
||||
explicit_memset \
|
||||
|
|
|
@ -150,6 +150,7 @@ check_type_size(off_t SIZEOF_OFF_T)
|
|||
|
||||
check_function_exists(arc4random_buf HAVE_ARC4RANDOM_BUF)
|
||||
check_function_exists(chroot HAVE_CHROOT)
|
||||
check_function_exists(copy_file_range HAVE_COPY_FILE_RANGE)
|
||||
check_function_exists(epoll_ctl HAVE_EPOLL_CTL)
|
||||
check_function_exists(fork HAVE_FORK)
|
||||
check_function_exists(getloadavg HAVE_GETLOADAVG)
|
||||
|
|
|
@ -113,6 +113,7 @@ conf_data.set('SIZEOF_OFF_T', compiler.sizeof('off_t', args: defs))
|
|||
|
||||
conf_data.set('HAVE_ARC4RANDOM_BUF', compiler.has_function('arc4random_buf', args: defs))
|
||||
conf_data.set('HAVE_CHROOT', compiler.has_function('chroot', args: defs))
|
||||
conf_data.set('HAVE_COPY_FILE_RANGE', compiler.has_function('copy_file_range', args: defs))
|
||||
conf_data.set('HAVE_EPOLL_CTL', compiler.has_function('epoll_ctl', args: defs))
|
||||
conf_data.set('HAVE_FORK', compiler.has_function('fork', args: defs))
|
||||
conf_data.set('HAVE_GETLOADAVG', compiler.has_function('getloadavg', args: defs))
|
||||
|
|
|
@ -4369,11 +4369,11 @@ mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con,
|
|||
const char *num = h->ptr;
|
||||
off_t offset;
|
||||
char *err;
|
||||
if (0 != strncmp(num, "bytes", sizeof("bytes")-1)) {
|
||||
if (0 != strncmp(num, "bytes ", sizeof("bytes ")-1)) {
|
||||
http_status_set_error(con, 501); /* Not Implemented */
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
num += 5; /* +5 for "bytes" */
|
||||
num += sizeof("bytes ")-1; /* +6 for "bytes " */
|
||||
offset = strtoll(num, &err, 10); /*(strtoll() ignores leading whitespace)*/
|
||||
if (num == err || *err != '-' || offset < 0) {
|
||||
http_status_set_error(con, 501); /* Not Implemented */
|
||||
|
@ -4387,6 +4387,27 @@ mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con,
|
|||
return HANDLER_FINISHED;
|
||||
}
|
||||
|
||||
#ifdef HAVE_COPY_FILE_RANGE
|
||||
/* use Linux copy_file_range() if available
|
||||
* (Linux 4.5, but glibc 2.27 provides a user-space emulation)
|
||||
* fd_in and fd_out must be on same mount (handled in mod_webdav_put_prep())
|
||||
* check that reqbody is contained in single tempfile and open fd (expected)
|
||||
* (Note: copying might take some time, temporarily pausing server)
|
||||
*/
|
||||
chunkqueue * const cq = con->request_content_queue;
|
||||
chunk *c = cq->first;
|
||||
off_t cqlen = chunkqueue_length(cq);
|
||||
if (c->type == FILE_CHUNK && NULL == c->next && c->file.fd >= 0) {
|
||||
loff_t zoff = 0;
|
||||
loff_t ooff = offset;
|
||||
ssize_t wr;
|
||||
do {
|
||||
wr = copy_file_range(c->file.fd,&zoff,fd,&ooff,(size_t)cqlen, 0);
|
||||
} while (wr >= 0 && (cqlen -= wr));
|
||||
}
|
||||
if (0 != cqlen) /* fallback, retry if copy_file_range() did not finish */
|
||||
#endif
|
||||
{
|
||||
if (-1 == lseek(fd, offset, SEEK_SET)) {
|
||||
close(fd);
|
||||
http_status_set_error(con, 500); /* Internal Server Error */
|
||||
|
@ -4398,6 +4419,7 @@ mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con,
|
|||
* (Note: copying might take some time, temporarily pausing server)
|
||||
* (error status is set if error occurs) */
|
||||
mod_webdav_write_cq(con, con->request_content_queue, fd);
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (0 != con->conf.etag_flags && !http_status_is_set(con)) {
|
||||
|
|
Loading…
Reference in New Issue