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)
committerJeremy Allison <jra@samba.org>
Tue, 6 May 2008 22:46:34 +0000 (15:46 -0700)
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
source/lib/recvfile.c

index a07b5b4aacddad6328f2ee6ceb698bfdeb34efa7..bbce8b65e877f337dd388ec360625cf1b9927acc 100644 (file)
@@ -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 <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 f9788fdefb607457d267a003d0460014a1040781..6e2093335033576e08122ec82ffd7931793bc18c 100644 (file)
@@ -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,