From bad2c3f1c817a94b7638bbf6456ff862829aed76 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 May 2008 15:46:34 -0700 Subject: [PATCH] Enable tests for splice on Linux. Add a static (vl, I hate this) so we can detect broken Linux recvfile splice and correctly fall back. Karolin, I think this should be pulled into 3.2-stable even though it's a feature change as otherwise there's no way for 3.2 to use recvfile zerocopy, which is an advertised feature. Others please comment. Jeremy. --- source/configure.in | 20 ++++++++++++++++++++ source/lib/recvfile.c | 21 +++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/source/configure.in b/source/configure.in index a07b5b4aacd..bbce8b65e87 100644 --- a/source/configure.in +++ b/source/configure.in @@ -5664,6 +5664,26 @@ if test x"$samba_cv_HAVE_POSIX_FADVISE" = x"yes"; then [Whether posix_fadvise is available]) fi +############################################ +# See if we have the Linux splice syscall. + +AC_CACHE_CHECK([for Linux splice], + samba_cv_HAVE_LINUX_SPLICE,[ + AC_TRY_LINK([ +#if defined(HAVE_UNISTD_H) +#include +#endif +#include ], + [long ret = splice(0,0,1,0,400,0);], + samba_cv_HAVE_LINUX_SPLICE=yes, + samba_cv_HAVE_LINUX_SPLICE=no)]) + +if test x"$samba_cv_HAVE_LINUX_SPLICE" = x"yes"; then + AC_DEFINE(HAVE_LINUX_SPLICE,1, + [Whether Linux splice is available]) +fi + +AC_HAVE_DECL(splice, [#include ]) ################################################# diff --git a/source/lib/recvfile.c b/source/lib/recvfile.c index f9788fdefb6..6e209333503 100644 --- a/source/lib/recvfile.c +++ b/source/lib/recvfile.c @@ -124,7 +124,7 @@ static ssize_t default_sys_recvfile(int fromfd, return (ssize_t)total_written; } -#if defined(HAVE_SPLICE_SYSCALL) +#if defined(HAVE_LINUX_SPLICE) /* * Try and use the Linux system call to do this. @@ -134,17 +134,33 @@ static ssize_t default_sys_recvfile(int fromfd, * from the network in the case of return != -1. */ + ssize_t sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset, size_t count) { + static bool try_splice_call = true; size_t total_written = 0; if (count == 0) { return 0; } + /* + * Older Linux kernels have splice for sendfile, + * but it fails for recvfile. Ensure we only try + * this once and always fall back to the userspace + * implementation if recvfile splice fails. JRA. + */ + + if (!try_splice_call) { + return default_sys_recvfile(fromfd, + tofd, + offset, + count); + } + while (total_written < count) { ssize_t ret = splice(fromfd, NULL, @@ -155,7 +171,8 @@ ssize_t sys_recvfile(int fromfd, if (ret == -1) { if (errno != EINTR) { if (total_written == 0 && - errno == EBADF || errno == EINVAL) { + (errno == EBADF || errno == EINVAL)) { + try_splice_call = false; return default_sys_recvfile(fromfd, tofd, offset, -- 2.34.1