Enable tests for splice on Linux. Add a static (vl, I hate this)
authorJeremy Allison <jra@samba.org>
Tue, 6 May 2008 22:46:34 +0000 (15:46 -0700)
committerKarolin Seeger <kseeger@samba.org>
Mon, 26 May 2008 09:21:30 +0000 (11:21 +0200)
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.
(cherry picked from commit bad2c3f1c817a94b7638bbf6456ff862829aed76)

source/configure.in
source/lib/recvfile.c

index a9d22afa130d96c5b65556b9f9f17ef3089638df..671ed63ffc8c31143099d78703818df3d752ec24 100644 (file)
@@ -5591,6 +5591,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 <unistd.h>
+#endif
+#include <fcntl.h>],
+    [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 <fcntl.h>])
 
 
 #################################################
index 07c1f682c8a11ddd535388e30870ee0e4262dba2..513742ce8f8edfa298ab3f0721fe85588d55ebd2 100644 (file)
@@ -129,7 +129,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.
@@ -139,11 +139,13 @@ 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;
 
        DEBUG(10,("sys_recvfile: from = %d, to = %d, "
@@ -155,6 +157,20 @@ ssize_t sys_recvfile(int fromfd,
                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,
@@ -165,7 +181,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,