Merge pull request #62 from giuseppe/use-sendfile-copyup

copyup: use sendfile(2) if available
This commit is contained in:
Daniel J Walsh 2019-04-03 09:38:41 -04:00 committed by GitHub
commit 9b6732407c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 21 deletions

View File

@ -12,7 +12,7 @@ AC_PROG_CC
gl_EARLY
gl_INIT
AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stddef.h stdint.h stdlib.h string.h unistd.h])
AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stddef.h stdint.h stdlib.h string.h unistd.h sys/sendfile.h])
AC_PROG_RANLIB

76
main.c
View File

@ -37,6 +37,9 @@
#include <errno.h>
#include <err.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_SENDFILE_H
# include <sys/sendfile.h>
#endif
#ifdef HAVE_ERROR_H
# include <error.h>
@ -1947,6 +1950,36 @@ create_node_directory (struct ovl_data *lo, struct ovl_node *src)
return ret;
}
static int
copy_fd_to_fd (int sfd, int dfd, char *buf, size_t buf_size)
{
int ret;
for (;;)
{
int written;
int nread;
nread = TEMP_FAILURE_RETRY (read (sfd, buf, buf_size));
if (nread < 0)
return nread;
if (nread == 0)
break;
written = 0;
{
ret = TEMP_FAILURE_RETRY (write (dfd, buf + written, nread));
if (ret < 0)
return ret;
written += ret;
nread -= ret;
}
while (nread);
}
return 0;
}
static int
copyup (struct ovl_data *lo, struct ovl_node *node)
{
@ -2038,30 +2071,33 @@ copyup (struct ovl_data *lo, struct ovl_node *node)
}
}
#ifdef HAVE_SYS_SENDFILE_H
if (! data_copied)
{
for (;;)
off_t copied = 0;
while (copied < st.st_size)
{
int written;
int nread;
off_t tocopy = st.st_size - copied;
ssize_t n = sendfile (dfd, sfd, NULL, tocopy > SIZE_MAX ? SIZE_MAX : (size_t) tocopy);
if (n < 0)
{
/* On failure, fallback to the read/write loop. */
ret = copy_fd_to_fd (sfd, dfd, buf, buf_size);
if (ret < 0)
goto exit;
}
copied += n;
}
data_copied = true;
}
#endif
nread = TEMP_FAILURE_RETRY (read (sfd, buf, buf_size));
if (nread < 0)
goto exit;
if (nread == 0)
break;
written = 0;
{
ret = TEMP_FAILURE_RETRY (write (dfd, buf + written, nread));
if (ret < 0)
goto exit;
written += ret;
nread -= ret;
}
while (nread);
}
if (! data_copied)
{
ret = copy_fd_to_fd (sfd, dfd, buf, buf_size);
if (ret < 0)
goto exit;
}
times[0] = st.st_atim;